Determine whether there is a line on which all points sit - algorithm

I'm trying to create an algorithm which determines whether there is a horizontal or vertical line on a plane so that for each point on the place, it is either on the vertical line, the horizontal line, or both lines. This algorithm need only be sequential, and return true or false.
I have an idea of what needs to be done, i.e. I need to check each point for its location, but I'm not sure how to check whether its on a line. Any ideas?
Thanks in advance!!

Sort all your points by x co-ordinate and by y-coordinate. If every point is either on a horizontal line or on a vertical line then at least one of these lines must cover at least half the points, and there cannot be more than two horizontal lines like this, or more than two vertical lines like this, because you can't have more than two horizontal lines each with half the points on them.
So by sorting by x-coordinate and looking for lots of points on the same x-coordinate you have at most two candidates for vertical lines, and by sorting by y-coordinate at most two candidates for horizontal lines. For each of these (at most four) candidate lines look at all the points that don't fit on that lines and look at their y-coordinates (or x-coordinates) to see if they all fit on a lines of the other type. If they do, you are done. If not, try the at most three other possibilities.

You go through each point in sequence and compare their coordinates, knowing that they must share the same x component (abscissa), y component (ordinate), or both. Your goal is to determine these values, and then check that all the points have at least one of them.
the first point may have one or both correct, so you keep both components as potential correct values,
the second point should have at least one in common with the first, so you mark the common component as the correct one for either the horizontal (for x) or the vertical line (for y).
you loop on the next points until all of them share that same component you just found as common between the first two points, if you find one point which isn't on that line, then it must belong to the other, so you've discovered the second correct component,
Now you check all the remaining points l, if one of them doesn't have either component, the result is false.

Related

Splitting set of lines into intersecting segments

I have a set of lines which may intersect at certain points. Each line is constructed of at least 2 points. What I want to do is to split each line when it intersects an other line and store all lines to a list. In this result list there may not be any line intersecting an other.
An intersection may only occur on a line's points what makes the intersection detection trivial (just compare each point with each other). What I consider to be very challenging is to find a performant algorithm to solve this problem.
Thanks for your help!
EDIT: Lines are represented as points, e.g. A = (0,0),(10,1),(20,2),(30,3),(35,4) and B = (12,-4), (10,1), (8, 5)
Plane sweep algorithm.
Look up a reference anywhere.
Essentially, we sweep along the x axis by, for each line segment, storing startx and endx as "events". Sort the events. Then you keep a second sorted list of "active" segments, add lines to the active list when you hit startx and removing it when you hit endx. The active list is sorted by y. So you only need a few actual intersection tests, where lines overlap in both x and y.

Get grids info (number and edges) given splitting line segments on a rectanglar page?

I am facing a problem of finding the grids info (number and edges) given splitting line segments on a rectangle page. Given the following image as an example, all splitting line segments are shown with both end points as red circles, the number here will be 7 as annotated in the image.
Assumptions:
The line segments form a valid split of the rectangle page.
All final grids are quadrilaterals.
No crossing line segments (i.e. regard there is an extra end point right on the cross).
No line segment lies within another.
Current solution:
Random pick a point (not labelled before) within the page.
Traverse all points within current area until touching the borders or splitting lines and also label them. Current area is a valid grid.
Loop step 1-2 until all points are labelled.
Note: here I also assume that the whole page can be discrete to uniform points (just like pixels in an image).
Problem & question:
Problem of the above solution is that I have to traverse all points within the page in order to get all the grids. Is there any simpler solution to this?
I finally found a simple approach to do this by divide-and-conquer.
Theory based-on: Add a line segment will split current area into two grids.
Based on above, the number should be quite straight forward, i.e. number_line_segments+1.
To determine the edges of every grid, we further need to know which area is split when a new line segment is added.
Then, the problem is transformed to: how to determine a valid adding sequence (not unique) of all the line segments. Here, "valid" means when adding a new line segment, it will split current area into two grids.
To determine a valid adding sequence of all the line segments, all I need to do is to determine the order for any two, which can be determined as follows:
order_for_two_line_segments(LineSeg LineSeg_A, LineSeg LineSeg_B)
{
if (one of LineSeg_A's end points is on LineSeg_B)
LineSeg_B should come before LineSeg_A;
else if (one of LineSeg_B's end points is on LineSeg_A)
LineSeg_A should come before LineSeg_B;
else // neither end points of them are on the other one
they can be in any order;
}
For example, in the following image (all lines are labelled as L1-L6), L1 should come before L2 because one of L2's end point is on L1, without which L2 cannot form a valid split. And any order can be possible between L2 and L6 as neither end points of them are on the other one, which makes any one of them (without the other) can still form a valid split.
And a valid adding sequence can be L3 > L1 > L2 > L5 > L4 > L6.
Edit: The above approach should also work for general cases where the grids can be any shape.

Is Point inside a polygon?

Given a list of points that represent the polygon in 2D, how can I determine if the point is inside the polygon.
Please note that the polygon can be either concave or convex. You can also make any assumptions about the order of the points.
The best approach to doing this is to draw a line in any direction from your point, and count the number of times that you cross the boundary of the object. If you hit the boundary an even number of times, you are outside the object, if an odd, you are inside. It is usually easiest to go along one of the axis to make this determination.
Essentially, you just have to find a way to determine if you cross a point. Use the slope of a line equation(m=(y1-y2)/(x1-x2), y=m*x(x-x1)+y1, and see if you cross within the boundaries that the point is valid. Given this equation for the line between the points, determine where your line crosses this line, and figure out if it is within the range of the line.
Incidentally, the same method works for any arbitrary dimension, just determining if you hit the face becomes more difficult.
To show a couple of examples, I've drawn a simple illustration, showing both what happens inside and outside, even with a weird shape.
Incidentally, if you hit a corner, it counts for the number of times you make a transition from inside to outside.
Select a point outside of the polygon. Draw a line between your´s and the point outside. If the line intersects the polygon an odd number of times, its inside, otherwise its outside. Zero intersections are also outside. However, this only workes for non overlapping polygons
It's a known problem with many solutions, just google it.
And read this :
http://en.wikipedia.org/wiki/Point_in_polygon
Take an arbitrary line from your point, to any point definitely outside your polygon (i.e. outside of the bounds). Check how many times that line intersects with one of the edges of your polygon. If the value is odd, the point is inside.
When checking, be careful of lines that go through a vertex, where your test may indicate two edge crossings.

Elegant "Left-of" test for Polyline

Given:
(X,Y) coordinate, which is the position of a vehicle.
Array of (X,Y)'s, which are vertices in a polyline. Note that the polyline consists of straight segments only, no arcs.
What I want:
To calculate whether the vehicle is to the left or to the right of the polyline (or on top, ofcourse).
My approach:
Iterate over all line-segments, and compute the distance to each segment. Then for the closest segment you do a simple left-of test (as explained here for instance).
Possible issues:
When three points form an angle smaller than 90 degrees (such as shown in the image blow), a more complicated scenario arises. When the vehicle is in the red segment as shown below, the closest segment can be either one of the two. However, the left-of test will yield right if the first segment is chosen as the closest segment, and left otherwise. We can easily see (at least, I hope), that the correct result should be that the vehicle is left of the polyline.
My question:
How can I elegantly, but mostly efficiently take care of this specific situation?
My fix so far:
Compute for both segments a point on that segment, starting from the vertex point.
Compute the distance from the vehicle to both of the points, using Euclidian distance
Keep the segment for which the computed point is the closest.
I am not very happy with this fix, because I feel like I am missing a far more elegant solution, my fix feels rather "hacky". Efficiency is key though, because it is used on a realtime embedded system.
Existing codebase is in C++, so if you want to write in a specific language, C++ has my preference.
Thanks!
[edit]
I changed my fix, from a perpendicular point to a parallel point, as I think it is easier to follow the line segment than compute the outward normal.
This topic has been inactive for so long that I believe it's dead. I have a solution though.
However, the left-of test will yield right if the first segment is
chosen as the closest segment, and left otherwise.
You've used slightly ambiguous language. I'm gonna use segments to speak of the line segments in the polyline and quadrants to speak of the areas delimited by them. So in your case, you'd have a red quadrant which seems to be on the right of one segment and on the left of the other.
If the left-of test yields different answers for different segments, you should redo the test on the segments themselves. In your case, you'd have:
The quadrant is on the RIGHT of the first segment
The quadrant is on the LEFT of the second segment
Both segments disagree on where the quadrant lies, so you do two further disambiguation tests:
The second segment is on the RIGHT of the first segment
The first segment is on the RIGHT of the second segment
This allows us to conclude that the second segment is in between the first segment and the quadrant—since each of those two lies on a different side of the second segment. Therefore, the second segment is "closer" to the quadrant than the first and it's answer to the left-right test should be used as the correct one.
(I'm almost sure you can do with only one of the two disambiguation tests, I've put both in for clarity)
For the sake of completeness: I believe this solution also accounts for your demands of efficiency and elegance, since it uses the same method you've been using from the start (the left-of test), so it meets all the conditions specified: it's elegant, it's efficient and it takes care of the problem.
Let infinity = M where M is big enough. You can consider that everything is in the square [-M,M]x[-M,M], split the square with your polyline and you have now two polygons. Then checking if the car is in a given polygon can be done very simply with angles.
I consider that your first point and your last point have M in there coordinates. You may need to add some of these points to have a polygon: (-M,-M), (M,-M), (M,M) and (-M,M).
Once you have a polygon for the left of the polyline, sum the angles OĈP where O is a fixed point, C is the car and P is a point of the polygon. If the sum is 0 then the car is outside of the polygon, else it is inside.
Just a quick idea: would it be possible to connect the last and first vertex of your polyline, so that it would become a polygon? You could then do a simple inside/outside check do determine whether the vehicle is left/right of the line (this ofcourse depends on the direction of the polygon).
However, this method does assume that the polygon is still not self-intersecting after connecting the last and first vertex.
This is a standard sort of problem from computational geometry. Since you're looking to test whether a point (x0, y0) is left-of a given surface (your polyline), you need to identify which segment to test against by its height. One easy way to do this would be to build a tree of the lower point of each segment, and search in that for the test point's predecessor. Once you have that segment, you can do your left-of test directly: if it's left of both endpoints, or between them on the appropriate side, then you return true.
I am assuming here that you guarantee that the vertical extent of your polyline is greater than where you might find your query point, and that the line doesn't overlap itself vertically. The latter assumption might be quite poor.
Expansion in response to OP's comment:
Note that the angle example in the question contradicts the first assumption - the polyline does not reach the height of the search point.
One way to conceptualize my method is by sorting your segments vertically, and then iterating through them comparing your point's y-coordinate against the segments until your point is above the lower endpoint and below the higher endpoint. Then, use the endpoints of the segment to figure out the x-intercept at the given y. If the point has a lower x-cooordinate, it's to the left, and if it has a greater x-coordinate, it's to the right.
There are two ways to improve on this explanation in a real implementation, one of which I mentioned about:
Use a balanced search tree to find the right segment instead of iterating through a sorted list, to bring the time from O(n) to O(log n)
Reconceptualize the search as finding the intersection of the polyline and the horizontal line y = y0 through the search point. Then just compare the x value of the intersection against the search point.

Algorithm for finding empty areas

does anybody know of a good algorithm for this task:
a multi polygon contains the reserved areas
find an empty position for the given polygon which is closest to its original position but does not intersect the reserved areas
I have implemented some very basic algorithm which does the job but far from optimally.
Thank You!
Edit:
my solution basically does the following:
move given polygon in all possible directions dx and dy
check wether the new intersection is less than the previous intersection
if so, use new position and make sure that you don't move your polygon back and forth at the same position
repeat these steps a maximum of N times
Example: it is intended for placing text which should not overlap with each other.
One method that immediately pops into my mind is to shoot a ray (i.e. measure a line segment) from the original position to every vertex of the polygon. Do a comparison on those distances, and then based on those comparisons, narrow it down to the minimally far away line segment of the polygon. Compute the perpendicular intersection of that line with the origin, and you'll get the minimally far away point. If the vertex comparisons don't lead you down the right path, just shoot off lines in random directions, and just stop when you're happy with the result. It doesn't sound like you require optimality.
Let's look at the original problem: making sure that one piece of text doesn't overlap another. Presumably this is for labelling a map. The way I do it is this: draw the text invisibly, checking for overlap (by using a specialised graphics context that instead of drawing a pixel, checks whether a pixel is already there) then try another position along the line on which the text is to be placed - usually a street. I try the middle of the line first, then successive positions further and further left and right of the middle. If that fails I try again with a condensed (narrower) font.

Resources