Puzzle : Given an even number of points in general positions on the plane (that is, no three points co-linear), can you partition the points into pairs and connect the two points of each pair with a single straight line such that the straight lines do not overlap?
My Solution : One simple approach (that seems just too simple).
Start with the point with left-most x-coordinate and then draw a line to the next least left-most x-coordinate. Then find the next least pair of points and connect and so on!
Is this correct?
Just tried it! That's one of the solutions!
Related
I have a point and a (curved) line. Now I want to find the distance to the line where the direction from the point to the point on the line stands orthogonal on the line.
Intuitively I think that the shortest connection between the closest point on the line and the point is always orthogonal, but I'm not 100% sure that my geometry intuition is correct. Can you confirm that for finding the orthogonal connection between a point and a point on a line it is enough to check the closed point on the line?
What you wrote can be true, subject to conditions.
Your curve must be either closed, or start/end infinitely far away (like the shape of y=1/x or y=x^2). Otherwise, the closest distance can be to an end point of the curve.
The curve must be smooth. For instance, a triangle is not smooth, the normal is not defined at the 3 vertices and the closest distance can be a distance to the vertex. Another example, cubic Bézier splines may contain a singularity where the normal is not defined, see the top right picture:
Again, closest distance might be a distance to that singularity point.
Also, don’t forget it can be multiple points on the curve with orthogonal connection. You gonna have to find all of them, and use the minimum distance found. Moreover, in some cases “all of them” can be “infinitely many”, if the curve contains a piece of a circular arc.
I have a thousands of line segments that I'd like to cluster by colinearity. One way to do this is to make an associative container with keys that are infinite lines. With such a container I could use a collection of line segments as values and add a line segment by determining the infinite line of which it is a segment and inserting into the corresponding bin.
Given such a set up, what is the best way to characterize the infinite lines for supporting the ability to query the data structure for line keys that are near a given line?
For example I was thinking of using an R-tree of points (Elsewhere in this project I am already using Boost.Geometry R-trees) where each point is the x-intercept and y-intercept of an infinite line. However, this only works for non-vertical and non-horizontal lines. I could handle vertical and horizontal lines as special cases but then I would not be able to easily query for lines that are "near" a vertical or horizontal line the way that I will be able to query for lines that are near a non-axis aligned line by doing a 2D range query of the intercept points in the R-tree.
I'm wondering if there is some elegant way of handling this problem. How can I represent infinite 2D lines as points such that horizontal and vertical lines are no different than any other kind of line and such that lines that are near each other map to points that are near each other?
I have two solutions.
The first is a simple one with some limitations:
For each infinite line, you could compute the point on the line where the perpendicular drawn from the origin meets the line. You could store the coordinates of this point as a "signature" of that line. This solution will work for all lines except those that pass through the origin. That is because when the line passes through the origin, the "signature" point will always be the origin no matter the slope of the line.
The second solution extends the first one to solve that problem:
In addition to the coordinates of the point described above, you can also store the angle the normal of the line makes with the x-axis. So you'd be representing each line with an ordered triplet (x, y, theta). You can store these triplets in an rtree for 3d points and query that tree.
Two lines that pass through the origin could have a theta value of pi/4 radians and 5*pi/4 respectively. They'd be coincident, but the way they are stored in the rtree doesn't reflect that. So just for the lines that pass through the origin, you could enforce a convention, say - theta must be between 0 and pi. Such a convention would fix the problem. This convention should only be enforced for lines that pass through the origin.
Update:
Coming up with a solution that is better optimized for your use-case will require a clear definition of how you measure the "proximity" between two infinite lines.
Assume you are given the equation of a line (in 2d), and the equations of lines that form a convex polygon (the polygon could be unbounded). How do I determine if the line intersects the polygon?
Furthermore, are there computational geometry libraries where such tasks are pre-defined? I ask because I'm interested not just in the 2D version but n-dimensional geometry.
For the 2D case, I think the problem simplifies a bit.
The line partitions the space into two regions.
If the polygon is present in only one of those regions, then the line does not intersect it.
If the polygon is present in both regions, then the line does intersect it.
So:
Take any perpendicular to the line, making the intersection with the
line the origin.
Project each vertex of the polytope onto the perpendicular.
If those projections occur with both signs, then the polygon
intersects the line.
[Update following elexhobby's comment.]
Forgot to include the handling of the unbounded case.
I meant to add that one could create a "virtual vertex" to represent the open area. What we really need is the "direction" of the open area. We can take this as the mean of the vectors for the bounding edges of the open area.
We then treat the dot product of that direction with the normal and add that to the set of vertex projections.
In geometry, typically see wikipedia a polygon is bounded.
What you are describing is usually called a polytope or a polyhedron see wikipedia
There are a few geometry libraries available, two that come to mind are boost (polygon) and CGAL. Generally, there is a distinct split between computational methods that deal with 2d,3d, and N-d - for obvious reasons.
For your problem, I would use a somewhat Binary Space Partitioning Tree approach. I would take the first line of your "poly" and trim the query line against it, creating a ray. The ray would start at the intersection of the two lines, and proceed in direction of the interior of the half-space generated by the first line of the "poly". Now I would repeat the procedure with the ray and the second line of the "poly". (this could generate a segment instead of ray) If at some point the ray (or now segment) origin lies on the outer side of a poly line currently considered and does not intersect it, then the answer is no - the line does not intersect your "poly". Otherwise it intersects. Take special care with various parallel edge cases. Fairly straight forward and works for multi-dimensional cases.
I am not fully sure, but I guess you can address this by use of duality. First normalize your line equations as a.x+b.y=1, and consider the set of points (a,b).
These must form a convex polygon, and my guess is that the new line may not correspond to a point inside the polygon. This is readily checked by verifying that the new point is on the same side of all the edges. (If you don't know the order of the lines, first construct the convex hull.)
Let's start from finite polygons.
To intersect polygon a line must intersect one of its edges. Intersection between line and an edge is possible only if two points lie on different sides from the line.
That can be easily checked with sign(cross_product(Ep-Lp,Ld)) for two points of the edge. Ep - edge point, Lp - some point on the line, Ld - direction vector of the line, cross_product(A,B)=Ax*By-Ay*Bx.
To deal with infinite polygons we may introduce "infinite points". If we have a half infinite edge with point E1 and direction Ed, its "second point" is something like E1+infinity*Ed, where infinity is "big enough number".
For "infinite points" the check will be slightly different:
cross_product(Ep-Lp,Ld)=
=cross_product(E1+infinity*Ed-Lp,Ld)=
=cross_product(E1-Lp+infinity*Ed,Ld)=
=cross_product(E1-Lp,Ld)+cross_product(infinity*Ed,Ld)=
=cross_product(E1-Lp,Ld)+infinity*cross_product(Ed,Ld)
If cross_product(Ed,Ld) is zero (the line is parallel to the edge), the sign will be determined by the first component. Otherwise the second component will dominate and determine the sign.
I have a maze described by walls as line segments (no given order). Given a point, I need to determine whether its inside the maze or no. Everything is in the Cartezian plane(no discretization).
My idea is to transform the problem as follows:
Given some line segments in the plane, find all polygons with vertices in the endpoints of the given segments and with sides lying on the segments (you can see in the image below that you can't assume the sides will form a subset of segments).
And then just check: if a point is only inside one polygon, then its inside of the maze, otherwise no.
The solution I have in mind would be: hash endpoints and line intersections, and then look for loops.
Any other suggestions?
Thanks!
(ignore the colors in the image)
It is enough to find boundary (outer) polygon. That can be done by finding one point on the boundary and than traversing from that point by segments in one direction. If there are more possibilities to go than choose 'outer' one. Algorithm can be described:
find boundary point
find first direction to go and go to that point
while current point is different than fist one
find next direction to go
go to next point
First point can be find as point with highest Y coordinate, if there are more like that than one with lowest X among them. We can call it upper-left point.
First direction to go: first point is connected to other points and that points have <= Y coordinate, what means that connection segments are below first point. Choose right-most of them.
Next direction to go: current point is reached by some (incoming) segment, next segment to go is furthest away in positive direction from incoming one, what is same as first segment in clock-wise direction from incoming segment.
I would like to deconstruct the following polygon shown in blue removing all of the points from the polygon that cause concavity.
Currently, what I have been attempting to do is:
Take each point out of the polygon
Test the point to see if it falls within the polygon created by the rest of the set
If true remove the point
If false keep the point
This works in most cases, but in the previous case the points at (2,3) and (2,4) will not both be removed. In both cases either one of the points will be removed, but the other will not depending on the order which the array is passed in.
What I am wondering is this:
Is there some way to test to see if the polygon I am dealing with happens to have one of these cases (IE: 3 points of failure in a row?)
or
Is there simply a more effective way of creating convex polygons?
Thank you.
I think perhaps you're looking for the convex hull?
The first algorithm that springs to mind is QuickHull. Initially, take the leftmost and the rightmost points, l and r. They must be on the hull.
Construct a first guess at the hull that's two outward faces, one from l to r and one from r to l. So you have a polygon with zero volume.
Divide all remaining points into those in front of lr and those in front of rl.
From then on, while any face has any points in front of it:
find the furthest point from the face
delete this edge and replace it with two edges, one from the original start point to the furthest point and one from the furthest point to the original end point
of all the points that were in front of the old face, put those in front of the first of the new faces you've added into its in front set, put those in front of the second into its in front set and don't retain any reference to those now inside
At the end you'll have the convex hull.
Why not simply compute the convex hull of the points?
This is a well studied problem with a number of algorithms in books and online. A method of "sweeping angles" is particularly common, eg.
http://courses.csail.mit.edu/6.854/06/scribe/s25-rasmu-sweepline.pdf
What you are looking for is known as "convex hull" finding. Look here at wikipedia for algorithms for this problem. The "gift wrapping" algorithm is easy to implement. When yout found the hull, just remove all points that are not part of the hull.
Be aware that the Convex Hull is already implemented in some languages/environments.
Example in Mathematica:
<< ComputationalGeometry`;
data2D = {{4.4, 14}, {6.7, 15.25}, {6.9,12.8}, {2.1, 11.1}, {9.5, 14.9},
{13.2, 11.9}, {10.3, 12.3}, {6.8, 9.5}, {3.3, 7.7}, {0.6, 5.1},
{5.3, 2.4}, {8.45, 4.7}, {11.5,9.6}, {13.8, 7.3}, {12.9, 3.1},
{11, 1.1}};
PlanarGraphPlot[data2D, ConvexHull[data2D]]
Output: