If I have a segment between 2 vertices of a polygon, is there a way to extend this segment until it reaches the polygon boundary, using CGAL? (this can happen if at least one of the vertices is a reflex vertex).
You could get the supporting line of the segment via mySegment.supporting_line() and check where this line intersects with the polygon boundary. You can then create a new Segment that is based on the found intersection points.
Let p1 and p2 be the Vertices of your Segment. If I get you right, you'd want to sort the intersection points by their coordinates and create a Segment that goes from the 1st intersection Point smaller than p1 and p2 to the 1st intersection point greater than p1 and p2. (Note that several special cases are to be handled here.)
To get the intersection points, you can iterate over the segments of your polygon and intersect each one with the mentioned supporting line via CGAL::intersection.
A more sophisticated approach would be to create an Arrangement containing your polygon, attaching an Observer to it and then adding the mentioned supporting line to the Arrangement. You'd then get the information you need from the automatic calls to obs.before_split_face() and obs.before_split_face().
Related
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.
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.
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.
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.
I have two concave polygons on input represented as two vectors of points. I want to do some polygon operation on it - union, intersection and difference. I found intersection points between these polygons and insert them into the right place in each polygon. Then I give an information about its position (Inner - it is inside the other polygon, Outer - it is outside the other polygon, Intersection - point, where two edges of polygons intersects) to each vertex. Now I know which points create the union of these polygons (Outer and Intersection) etc., but I need to know how to sort them to the right order. In case of the intersection operation I need to divide these sorted points into the right number of sets, because the result of intersection could be more than one polygon.
I am using C++, but I don't need necessarily the code, I only want to need how to sort these final polygon points. And I don't want to use any library for these operations because I already have my own functions and want to use them.
I looked at this question How to intersect two polygons? and also some others but none of them is solving final sorting of points.
I also read this article http://www.gvu.gatech.edu/~jarek/graphics/papers/04PolygonBooleansMargalit.pdf , but I probably don't get it.
Any help would be appreciated.
If you follow all my recommendations from my comments:
Distinguish between intersection and touching points
Keep a link between the two equivalents of the intersection points in the two polygons
The solution for the union will be:
Consider only outer, touching and intersection points
Make sure the points in the two polygons are ordered in different direction (one of the sets is in clockwise direction, the other one in counter-clockwise)
Start from random point in any of the two polygons.
For every vertex in any of the two polygons keep if you have visited it
Every time you encounter an intersection point keep on traversing from the next to follow point in the other polygon after the equivalent of the intersection point.
If you come back to the point you started from this closes one of the components of the join of the two polygons. If not all vertices were traversed repeat the whole of it from any unvisited vertex.
In the end calculate the area of all the polygons you have found. The largest in area will be the real union. The rest will be holes in the union.
The solution for the join will be:
Consider only inner and intersection points
Make sure the points in the two polygons are ordered in the same direction
Start from random point in any of the two polygons.
For every vertex in any of the two polygons keep if you have visited it
Every time you encounter an intersection point keep on traversing from the next to follow point in the other polygon after the equivalent of the intersection point.
If you come back to the point you started from this closes one of the components of the join of the two polygons. If not all vertices were traversed repeat the whole of it from any unvisited vertex.
EDIT: As I already mentioned, I have the god feeling my approach with the polygon orientation needs to be revised. However, when searching through the web I found a description of algorithm that might do the work for you: The Vatti clipping algorithm
EDIT2 One more article describing such clipping algorithm.