finding boundaries of circle division by straight line - algorithm

Given a circle, I add a straight line that goes through the circle and intersects it at two points as well as intersects every previous line at one point.
I want to repeat this procedure (adding one straight line at a time) and figure out the points that make up the boundaries of the sections the circle is divided into.
For example the first time I do this (first line) it divides the circle into 2 pieces:
When I add a second line it will divide each of these 2 pieces of the circle into 4 pieces:
When I add a third line it will divide the circle into 7 pieces:
What is an efficient algorithm to get these points?
Every time I add a line I can compute all the points that line intersects the circle and the other previous lines but I have to somehow figure out which regions these points are the boundary to

Not sure I completely understand the question but:
1) line/line intersection is achieved by Cramer. http://en.wikipedia.org/wiki/Line%E2%80%93line_intersection
2) line/circle intersection is achieved by solving a quadratic equation http://mathworld.wolfram.com/Circle-LineIntersection.html
3) you can classify the points per region by considering all signs obtained when injecting the point coordinates in the parametric equation of the splitting lines (in other words, is the point on the left or on the right of the line); this gives you a binary labeling of all regions (some of the labels being impossible).
You can also consider a ternary notation if you need to handle points known to be exactly on a line.

Related

Greedy algorithm to find minimum number of lines that can intersect all circles in the plane

I have a problem from homework where I need to find an O(n.log(n))
greedy algorithm for the minimum number of lines required to intersect all circles in the plane, as shown with the example below.
The starting point of all the lines is (0,0) which is the origin point. The set C contains n circles, where each circle c_i has information about its radius r_i and its centre coordinate (x_i, y_i).
I have tried making greedy rules:
iterate over each circle in the set C and pick c_i
construct 3 lines from origin to c_i, where 2 lines are tangent lines that only intersect 1 point in the circle, and 1 line is secant line that goes through the circle via its center.
iterate over other remaining circles c_j (j != i) and look how many circles intersect with these lines
choose the line L_i and remove the circles that intersect with it from the plane.
continue until the plane is empty.
But I don't think that this greedy rule will achieve the optimum solution and its complexity won't be O(n.log(n)).
Any hints or full solution is OK. It is also mentioned in the problem sheet that greedy rules that give minimum + 1 lines is fine.
Since you can use one line more than the minimum, you may start with an arbitrary line. Continue line by line clockwise until all circles are intersected. Each new line should have the greatest possible angle to the last as long as no circle lies between them. The 2 tangent lines you found is useful to find how far you can go in each step, but it will be time consuming to check every circle for each step. See if you can figure out how to speed it up.
This problem looks like “covering segments by points”. You can google for that or look here https://medium.com/competitive/covering-segments-by-points-fc2c56c4b038 for instance. In your case instead of segments you have angles for each of your circles. And lines instead of points.
The only difference is that the segments don’t lie on a line but on a circle. That’s why you’re allowed one extra line in your response to be able to pick a starting point arbitrarily.

Minimum area geometric cover for a set of line segments

The problem I am trying to solve is:
Given a set of M points on a plane where circles can be centered and a set of N line segments which need to be covered by the circles, find the minimum area circle cover for the line segments. That is, find the radii of the circles and the centers (chosen from the M points) such that all the N line segments are covered and the total area of the circles is minimized.
Note that a line segment is covered if no part of it is OUTSIDE a circle.
Any pointers to papers or code or approximation algorithms would be great.
Edit: Just realized that the original approach (moved to the end) probably doesn't cover the case where a line segment is best covered by multiple circles very well. So I think it's better to iterate points instead of line segments, cutting the line segments down at the circle boundaries:
Find the "worst" point, i.e. the point requiring the largest additional circle area for its best circle center option with the corresponding line segment at least partially in the circle. Construct / extend the corresponding circle.
Remove fully covered line segments from the set and cut partially covered segments at the circle boundary.
Iterate until no more line segments remain.
The main idea is to keep doing what's necessary in any case. How are overlapping circles counted? Do the areas add up, or are they merged? When going back to step one in later iterations, some kind of cost heuristics will probably be able to improve the result...
The original suggestion was:
Find the "worst" line segment, i.e. the line segment requiring the largest circle for any of the circle center options and construct the corresponding circle.
Remove covered line segments from the set.
Iterate until no more line segments remain.
I just released some code to implement the suggested algorithm here:
https://github.com/usnistgov/esc-antenna-cover

How to select outer line segments

I am having 2D line segments. My goal is to make different closed polygons. But, in here, I want to select most outer line segments when there are few parallel line segments stay closed to each other. with different line combinations, I can make different closed polygons.I was thinking and struggling to know how to get most outer lines as I need the polygon which make by outer most lines. (Polyogns are at the end constructed by intersecting adjoying line segments.)
I was thinking to get a large bounding box containing all segments and get the centroid and then find the perpendicular distances to each line. In this process, I found nearby line segments which oriented close to each other (i.e. near parallel lines). So, from those nearby parallel lines I want outer most one. (that is red one).
But If I used the centroid and compare the distnaces, then longest distance (among nearby parallel lines) does not give correct outer most line when more concave and convex turns exist as some cases outer most (red) one does not give by the longest distance. What I have is; end point coordinates of each line segments. (that is vector data)
So, I am looking for some good way to get most outer line segments from nearby parallel lines.
For you to understand I have attached a sample data which i have. The most outer line segments are shown in red color. finally this red lines give me the boundary of my polygon. So, I want to get red lines out of corresponding nearby parallel black lines.
NOTE: My line segments are oriented into different direction. And not only to X & Y axes. Also, nearby lines donot make always 90 or 180 angles with adjacent lines.
please suggest me a method. thanks in advance
for example, if A,B and C,D are nearby parallel line segments. then outer most line should be B and C. But, If i compare distances from centroid (O), then I can get C as outer most, but B can not get as distance from O to B is smaller than O to A. My method fails in this type of spots. So, look alternatives..
A general way to find lines is using the Hough Transform.
http://en.wikipedia.org/wiki/Hough_transform
However, the sample data you give has lines parallel to the axes. I don't know if that is the nature of all of your data, but if it is then the Hough Transform basically breaks down to simply summing up the intensities by rows for lines parallel to the x-axis and summing by columns for lines parallel to the y-axis.
You will end up with two 1D arrays, one with row sums and one with column sums. Since the lines are black and the foreground is white, local minimums in these arrays will represent line locations along each axis. Since you only need the outer lines, you do not have to sum every column/row - just start at the edges of the image and compute the sums until you hit a local min. Once you have the line's placement on the axis, you can traverse that cut of the axis in the image to find the endpoints of the line.

Simple math algorithm: Center point of a line

I have an algorithm as follows for finding the center of a line (midpoint).
public DoublePoint getMidPoint() {
return new DoublePoint((origin.x + endPoint.x) / 2, (origin.y + endPoint.y) / 2);
}
It seems to work for any values. But I seem to remember a much more complex algorithm, involving two circles whose radius equals the length of the line and whose center points are the ends of the line. A line drawn from the intersection of those circles would intersect the line segment you are testing, giving the line's midpoint. I know for sure that algorithm works 100% of the time. Not sure about my simpler algorithm which seems too simple.
What you are remembering is a geometric method of constructing the perpendicular bisector of a line segment using only a compass and straightedge. Consider, for instance:
This was fine for the ancient Greeks, but there are other methods (such as the one you have coded) which work better for computers.
Your simple algoritm is full correct. Method with circles is a finding the midpoint with pair of compasses.
The algorithm you vaguely remember is to use a straightedge and a compass to get the midpoint. Draw take two equal radius circles centered on the two ends of the line segment in such way that they intersect -- the length of the line segment will do. Use the straightedge to connect the points where the circles intersect. Where this line intersects the original line segment is the midpoint. Fancy animation at http://www.mathopenref.com/constbisectline.html
The algorithm and code you have is the simplest and best way to do this.
Your algorithm is a simplification of translating the line to the origin, finding the vector represented by that line, halving it, then translating it back to the original line. The simplification is valid, and the algorithm is correct.

Determining a mean camber line

Fellow programmers,
I know this is a little outside your juridistiction, but I was wondering perhaps if you have time, if you could help me with one "procedure". Not in view of math but what would be the best way to take.
This is an airfoil / profile. Usually, profiles are defined with two sets of data. One is the position of mean camber line, given in the form of x,y where x is usually given in percentages of chord length. Second set of data is thickness at percentages of chord length. Thickness is always drawn perpendicular to the camber line(!), and that gives the profile points.
Now, I have a reverse problem - I have points of a profile, and I need to determine the position of the camber line. Method of interpolation through points can vary, but it doesn't matter, since I can always interpolate as many points as I need, so it comes to linear in the end.
Remember, since the thinkness is drawn perpendicular to the camber line, the position of camber line is not mean between the points of upper and lower line of profile (called the back and face of profile).
Edit (how this is done on paper): Uhh, painfully and in large scale (I'm talking long A0 paper here, that is 1189x5945mm on a large drawing desk. You start by drawing a first camber line (CL) iteration through the midpoints (mean points) between the points of face and back at same x ordinates. After that you draw a lot of perpendicular lines, perpendicular to that CL, and find their midpoints between face and back (those points on face and back will no longer have same x values). Connect those, and that is your second iteration CL. After that you just repeat the second step of the procedure by drawing perpendicular lines onto that 2nd CL ... (it usually converges after 3 or 4 iterations).
2nd Edit: Replaced the picture with one which better shows how the thinkness is "drawn" onto the camber line (CL). Another way of presenting it, would be like picture no.2. If you drew a lot of circles, whoce center points are at the camber line, and whose radiuses were the amounts of thickness, then tangents to those circles would be the lines (would make up the curve) of the profile.
The camber line is not the mean line (mean between the points of face and back); it can coincide with it (therefore usually the confusion). That difference is easily seen in more cambered profiles (more bent ones).
3rd edit - to illustrate the difference dramatically (sorry it took me this long to draw it) between the mean line and camber line, here is the process of how it is usually done "on paper". This is a rather deformed profile, for the reason, that the difference between the two can be more easily shown (although profiles like this exist also).
In this picture the mean line is shown - it is a line formed by the mean values of face and back on the same x coordinates.
In this picture onto the mean line, perpendicular lines were drawn (green ones). Midpoints of those perpendicular lines make up for the 1st iteration of the camber line (red intermittent line). See how those circles fit better inside the airfoil compared to the first picture.
In the picture below the 2nd iteration of the camber line is shown, along with the mean line from the first picture as to illustrate the difference between the two. Those circles are fitting even better now inside (except that first one which flew out, but don't mind him).
From what I can gather from your diagram, the camber line is defined by it being the line whose tangent bisects the angle between the two tangents of the upper and lower edges.
In other words, your camber line is always the mean point between the two edges, but along a line of shortest distance between the top and bottom edges.
So, given the y-coordinates y=top(x) and y=bot(x), why don't you:
<pseudocode>
for each x:
find x2 where top(x)-bot(x2) is minimized
camber( mean(x,x2) ) = mean( top(x),bot(x2) )
</pseudocode>
and then interpolate etc.?
edit
Sorry! On second thought I think that should be
find x2 where ( (top(x)-bot(x2))^2 + (x-x2)^2 ) is minimised
obviously you should be minimising the length of that perpendicular line.
Is that right?
I'm new to stack overflow but this is a problem I have worked on quite a bit and thought I would post an alternate approach to the problem.
This approach uses the concept of a Voronoi diagram:
http://en.wikipedia.org/wiki/Voronoi_diagram
Essentially, a map is created which divides the space into regions containing one of the input points (x,y of your airfoil). The important part here is that any point within the region is closest to the input point in that region. The nodes created by this space division are equidistant to at least three of the input points.
Here is the interesting part: three equidistant points from a center point can be used to create a circle. As you mentioned, inscribed circle center points are used to draw the mean camber line because the inscribed circle measures the thickness.
We are close now. The nature of the voronoi diagram in this application means that any voronoi node inside of our airfoil region is the center point of one of these "thickness circles." (This runs into some issue very close to the LE and TE depending on your data. I usually apply some filtering here).
Basic Structure:
Create Voronoi Diagram
Extract Voronoi Nodes
Determine Nodes Which Lie Within Airfoil
Construct Mean Camber Line From Interior Nodes
Most of my work is in Matlab which has built in voronoi and inpolygon functions. As such, I'm not a huge help in developing those functions but they should be well documented elsewhere.
Trailing Edge/Leading Edge Issues
As I am sure you have experienced or know, it is difficult to measure thickness well when close to the LE/TE. This approach will contruct a fork in the nodes when the thickness circle is less than the edge radius. A check of the data for this fork will find the points which are false for the camber line. To construct the camber line all the way to the edge of the foil you could extrapolate your camber line (2nd or 3rd order should be fine) and find the intersection.
I think the best way for drawing the camber line of an airofoil is to load the profile in CATIA. After that in CATIA we can draw circles that are tangent to the both side of profile (suction side and pressure side. Then we can connect center of these circles and consequently we find the camber line accurately.
Is the mean camber line the set of points equidistant from the upper line and the lower line? If that's the definition, it's different from Sanjay's, or at least not obviously-to-me the same.
The most direct way to compute that: cast many rays perpendicular to the upper line, and many rays perpendicular to the lower line, and see where the rays from above intersect the rays from below. The intersections with the nearest-to-equal distances approximate the mean camber line (as defined here); interpolate them, with the differences in distance affecting the weights.
But I'll bet the iterative method you pasted from comments is easier to code, and I guess would converge to the same curve.

Resources