How to split a general closed polygon by a line segment - c++

I need a good (robust) algorithm for splitting a polygon into two sets(left/right) by a line segment. My polygon representation is simply a list of integer coordinates(ordered clock wise, never self intersecting) and the line segment is represented by a start and end point. The line always starts and ends outside the polygon, i.e. intersects the polygon an even number of times.
Here is an example:
The output of the algorithm should be the two sets(travelling clock wise):
Left: HABCH, FGDEF
Right: HCDGH, BAB, FEF
I can identify the points A-H by iterating the polygon and checking if a polygon segment crosses the line, taking care to respect border cases. I can also determine which side each multi-line belongs to. I cannot though, for the life of me, decide how to string these segment together.
Before you suggest a general purpose clipping library: I am using boost polygon which is very good at clipping polygons against each other, but I haven't found any library which let's you clip a polygon against a line segment and it is not possible in general to turn the line segment into a polygon which I could clip with.
EDIT: I had missed FEF and the fact that a polygon can have parts on both sides of the line segment.

Ok, here is a rather simple recipe of how to arrive at the answer:
Start with the set of intersection points ordered by traveling the contour clockwise:
ABCDEFGH
Sort them according to distance from the start of line:
HCFEDGBA
We also need to remember for each point if it is a left-to-right or right-to-left intersection.
Start with any point. Let's say G. Follow the contour clockwise and add GH
to the current polygon.
Now we need to travel along the line. The
direction depends on which side of the line we are. We are on the
right side, so we need to pick the value to the right of H in the
sorted set: C. Add HC to the current polygon.
Follow the contour clockwise and add CD to the current polygon.
We are on the right side, so we need to pick the value to the right of D in the sorted set: G. Add DG to the current polygon.
We have now reached the
starting point, so let's save the polygon(GHCDG) and remove used
points from the list.
Start over with another point.

For each intersection of the polygon border with the line segment:
Add a new point to the polygon.
Remember the new points in a new-point set.
Add the original polygon to the polygon set.
For each pair of points in the new-point set:
For each polygon in the current polygon set:
If the line segment between the points is completely inside the polygon.
Replace the polygon in the polygon set with two polygons
generated by dividing the original polygon along the line
segment between the points.
For each polygon in the polygon set:
Add it to the Left result set or the Right result set.
(Note this may not be possible.
Consider your example of the segment starting between C and F:
You will end up with a polygon (GABCFG) that touches both
sides of the dividing segment. Is that a Left or a Right?

I've solved something similar once and I gave up trying to be clever.
Run round all the vertices making them into connected line segments,
starting a new segment with a new point every time you intersect the
cutting line.
Find all segments which share an end point and join them back up into one longer one.
Connect all the open ends.

Related

Project a line segment onto a mesh

What are the graphic/mathematical algorithms I have to look for in order to achieve the red line in the following image?
Explaining it better: I need to plot two points on the mesh and then generate a straight line segment from one point to the next. This line segment would be formed by new vertices created on every single edge in its way.
I'm currently working with CGAL and Libigl, but none of them seem to have the solution. I have tried CGAL::Surface_mesh_shortest_path but it adds too much overhead (code runs very slowly) and the line would not be guaranteed to be straight depending on the mesh deformation.
Ignoring whatever you mean as "straight", here is one simple algorithm I can think of that would produce images to the one similar shown in the question. There is no guarantee of what is produced being the shortest path. I'm just spitballing here with no knowledge on the topic, there are probably better ways.
Pick 4 variables:
The starting point
The ending point
The line's normal
A marching constant
Let's calculate a few constants from the variables:
Direction = ending point - starting point
Increment vector = normalize(Direction) * marching constant.
Begin from the starting point and march towards your ending point by some constant, checking above and below your current position for where you are on the mesh. You use the line's normal to understand the "up" and "down" directions in order to perform intersection tests.
On each intersection test, if you do not intersect for both the up and down directions, then the normal you chose will not work for the given two points and mesh, and you'll have to try a different normal. If you do end up intersecting from one of the directions, you will need to add 2 points to your final line: a point on the calculated direction line closest to the start that lies on the triangle, and a point on the calculated direction line farthest from the start that lies on the triangle. If there's both an intersection on the up and down directions, choose the up direction to work with.

Polygon Detection from a Set of Lines?

I have a set of connected, intersecting line segments. I want to detect all polygons that result from the intersection of these line segments, as follows:
I found a paper that presents an algorithm for solving this problem, but I'm not really a computer science person so I wasn't able to understand it. Here's a link to the paper. At this moment, my plan is to 1) find all intersections, and 2) somehow use these intersections to identify the polygons. I'm able to solve (1) through brute force, but (2) is a bit trickier. I'd prefer a solution in R or C++, but any language will do.
Assuming you have your line segments always as a closed polygonal chain and you have them in some sort of edge list. And, as you said, you have the intersection points already computed (brute force means O(n^2) time, in this case that is optimal as the line segments can intersect n^2 times).
You can insert your intersection points from (1) into this list splitting the intersecting line segments, mark them as intersection points and reference to all intersecting line segments in this point. Furthermore, on every line segment two polygons are incident, thus add respective reference fields to every edge. Then just take the leftmost vertex in you input and walk along the edge list. Add to every edge that is traversed a reference to its left incident polygon (in this case) polygon number one. If you reach an intersection point, put it on some sort of stack for later recovery. Now analyse that point and continue walking on the leftmost path (between the line segment on which you reached the intersection point and all outgoing segments). At some point you reach your starting point and you have the first simple polygon closed.
Now take the first intersection point from the stack. There must be an even number of line segments that start/end there. Find a line segment that has at most one incident polygon referenced (yet) and use it as as starting segment for polygon number two. You can walk along its chain in the same manner as before. (If you reference a line segment`s right incident polygon, take the rightmost turn on an intersection point.) When your stack ist empty your are done.
Edit: After I looked one more time for a solution I found this implementation from Dan Sunday. I assume that is more useful as it is also already implemented.
Alfredo Ferreira developed c++ code for detecting polygons from a set of overlapping lines. You can find the code at his page here: http://3dorus.ist.utl.pt/tools/PolygonDetector.html
Hope this Helps
I just published my implementation which is extremely fast after trying the algo from the paper.
The basic idea is to remove the detected cycles and redo the search (remove the “ears” of the detected cycle).
I am also unsing just the line segments that have connected points to the graph. The overlapping are removed in two steps: by using the area formula, which is pretty much exact and then approximate the intersection points difference in a specific range.
https://github.com/realuptime/PolyDetector

Finding a point inside a Boost::Geometry::Polygon

I have a Polygon object and I'm looking for an efficient way to find any point strictly inside it (not on its boundary). What is the best way to do so?
I had the following ideas, which I don't really like:
Triangulating the polygon and reporting a point on one of the triangulation edges (too expensive).
Checking the polygon's winding direction and reporting a point located in an epsilon-distance from one of the polygon's edges (doesn't work in edge-cases).
Given a polygon, you can find the first two points where the polygon crosses a line parallel to x axis and lies between the yMin & yMax of your polygon (0 & 1 in the image below).
Any point between these points will be inside your polygon. The basic idea comes from scan converting a polygon —i.e. these are the points you would fill. The part of the line after the second point has a winding of 0 or 2, depending on your polygon.
The first two crossings (or last) has to be taken, as the crossing points are sorted along the x-axis.
Some corner cases:
If you omit all points of the polygon which just touches the line, in some cases this can fail (image below).
If there are overlapping lines in your polygon, you have to resolve those.
To avoid the first issue, make sure to take the first point as a definite crossing and the next one can be either a crossing or a point where polygon just touches the line.
This can be easily implemented without using any special functions in most languages. Since I am not familiar with Boost methods, I am posting a sketch of the basic idea in javascript.
The drawing is done using paper.js —although, the code for the algorithm outlined here itself is self contained.
You can translate this to C++ as long as you can enumerate through all points in a Boost::polygon
Here is the demo.

How to distinguish between an inbound and an outbound edge of a polygon?

The basics of Weiler-Atherton Polygon Clipping algorithm are:
Start from the first edge which is going inside the clipping area.
When an edge of a candidate/subject polygon enters the clipping area, save the intersection point.
When an edge of a candidate/subject polygon exits the clipping area, save the intersection point and follow the clipping polygon.
How to distinguish between an inbound and an outbound edge of a polygon?
It seems like finding inbound edges invole another huge algorithm and thereby affects the efficiency of the algorithm.
Another question is, how can I find the first inbound intersection?
This answer seems to be shedding some light on the problem. But, sadly it doesn't work.
For example, if I reverse the direction of vectors, the angle is not negated.
https://www.wolframalpha.com/input/?i=angle+between+vector+%7B0%2C180%7D+%7B180%2C0%7D
https://www.wolframalpha.com/input/?i=angle+between+vector+%7B0%2C180%7D+%7B-180%2C0%7D
First, a reminder that the Weiler–Atherton algorithm uses polygons defined by vertices in a specific order, clockwise. In short, you test for edges going in or out by traversing the polygon clockwise. The first edge going in (and therefore the first inbound intersection) is simply the first edge you traverse which started outside the clipping area (see below).
Also, the algorithm is typically run in two phases. First find all intersections, these are added to a list of vertices for your polygons, inserted at the correct position. During this phase you would typically mark whether each vertex is within the other polygon. For the second phase, traverse the vertices to determine clipping polygons.
Lets try some examples. Take a triangle defined by vertices A,B,C, and a rectangle w,x,y,z. The triangle will be the clipping area, rectangle is the subject.
The list of points we have generated for the subject is therefore w,x,R,Q,y,z. The triangle list is now A,B,Q,C,R.
Starting at w, R is the first intersection, it is inbound because the previous point (x) is outside. The traversal of the area will be R,Q,C, and back to R(done).
The intersections are unlabeled here, but they will still be R and Q. The list of points we have generated for the subject is therefore w,x,R,y,Q,z. The triangle list is now A,B,C,Q,R.
The clipping traversal is R,y,Q, and R(done)
Let P and Q be two polygons. One can pick any vertex v of P in order to determine the position of v with respect to Q (i.e inside or outside it) via the ray casting algorithm (or any other algorithm that suits all the requirements of the problem).
You only need to determine the position of one such vertex v of P with respect to Q in this manner because the position of the other vertices of P can be inferred by iterating over the ordered set of vertices and intersection points of P.
Lets say v is outside Q. Then, by iterating over the ordered set of vertices and intersection points of P, the first intersection point one finds is laying on an entering edge. If v is inside Q, the first intersection point one finds is laying on an exiting edge. Keep in mind that one edge can be both entering and exiting, depending on the number of intersection points laying on it.
The idea behind the ray casting algorithm is simple, but one should pick vertex v of P if |V(P)|>=|V(Q)| and v of Q otherwise (in order to lower the impact the ray casting algorithm has on the overall performance, though not significantly).
You do not necessarily need to start at the first inbound intersection, this is fine when you are looking at the polygons drawn on a piece of paper and can drop your pen wherever you want, but as you noted would require more effort to find when coding it.
You just need to make sure you get all the intersections calculated for your two polygons first walking around the source polygons line segments checking for intersections with the clipping polygons line segments. At this point it does not matter whether it is inside or outside.
Once you have all the intersections and your two polygons points in order (I think I had two lists that could link to each other), walk around your source polygon point by point. If your first source polygon point is inside the clip polygon that is the first point of your solution polygon, if not the first point of your solution polygon is the first intersection with the clip polygon.
Once you have your first solution point each point from there is the next solution point. As you hit intersections you switch to the other polygon and carry on until you return back to your first solution point.
It has been a while since I have coded this, but if I remember correctly points that can catch you out are when polygons are entirely inside each other (in which case the contained one is your solution) and make sure you are prepared for more than one solution polygon if you have some odd polygon shapes.

Line segment in a triangle

How can we check if a line segment falls partially or fully inside a triangle?
Cheers.
Get the function for the line from the end points of the line segment. Check where this line crosses any of the sides of the triangle.
If any part of the line segment is inside the triangle, the line will either pass in through one side and out through another, or it will pass exactly along one side of the triangle and pass through two of it's corners.
If the line passes through the triangle, you compare the points where the line crosses the triangle sides (or corners) with the end points of the segment, to see if the segment is part of the line that crosses the triangle.
For checking if a line is fully inside a triangle, you need to check whether both end points of the line segment are located inside of the triangle.
Checking if a point is inside of a triangle can be done using techniques described here.
Checking if a segment intersects the triangle partially is a bit more complex, since checking its end points may not be enough. There are two possible cases of partial intersection:
One end point is inside of the triangle, and the other isn't
Both end points are outside of the triangle, but the segment crosses at least one of the triangle sides.
Checking 1. can be done by this technique. Checking 2. can be done by algorithms that check whether two segments intersect. One example of how it can be done is here.
If one of the points of the segment is inside of the triangle => partially, if both are => fully
Point O is inside of the triangle if and only if the sum of angles AOB, BOC, COA equals 360 deg.
Cheers,
Gleb
Better algorithm follows:
Why not do this:
If both end points of the line segment lie inside or on triangle, then line segment must lie on or inside triangle.
To check if a point lie inside triangle:
Stand at the point, look at each vertex of the triangle
If you look at each vertex in clockwise / anticlockwise direction then you are inside or outside