k-way triangle set intersection and triangulation - c++

If we have K sets of potentially overlapping triangles, what is a computationally efficient way of computing a new, non-overlapping set of triangles?
For example, consider this problem:
Here we have 3 triangle sets A, B, C, with some mutual overlap, and wish to obtain the non-overlapping sets A', B', C', AB, AC, BC, ABC, where for example the triangles in AC would contain the surfaces where there is exclusive overlap among A and C; and A' would contain the surfaces of A which do not overlap any other set.

I (also) propose a two step approach.
1. Find the intersection points of all triangle sides.
As pointed out in the comments, this is a well-researched problem, typically approached with line sweep methods. Here is a very nice overview, look especially at the Bentley-Ottmann algorithm.
2. Triangulate with Constrained Delaunay.
I think Polygon Triangulation as suggested by #Claudiu cannot solve your problem as it cannot guarantee that all original edges are included. Therefore, I suggest you look at Constrained Delaunay triangulations. These allow you to specify edges that must be included in your triangulation, even if they would not be included in an unconstrained Delaunay or polygon triangulation. Furthermore, there are implementations that allow you to specify a non-convex border of your triangulation outside of which no triangles are generated. This also seems to be a requirement in your case.
Implementing Constrained Delaunay is non-trivial. There is however, a somewhat dated but very nice C implementation of available from a CMU researcher (including a command line tool). See here for the theory of this specific algorithm. This algorithm also supports specification of a border. Note that the linked algorithm can do more than just Constrained Delaunay (namely quality mesh generation), but it can be configured not to add new points, which amounts to Constrained Delaunay.
Edit See comments for another implementation.

If you want something a bit more straight forward, faster to implement, and significantly less code... I'd recommend just doing some simple polygon clipping like the old software rendering algorithms used to do (especially since you're only dealing with triangles as your input). As briefly mentioned by a couple of other people, it involves splitting each triangle at the point where every other segment intersects it.
Triangles are easy, because splitting a triangle at a given plane always results in just 1 or 2 new ones (2 or 3 total). If your data set is rather large, you could introduce a quad-tree or other form of spacial organization in order to find the intersecting triangles faster as the new ones get added.
Granted, this would generate more polygons than the suggested Constrained Delaunay algorithm. But many of those algorithms don't do well with overlapping shapes and would require you to know your silhouette segments, so you'd be doing much of the same work anyhow.
And if fewer resulting triangles is a requirement, you can always do a merging pass at the end (adding neighbor information during the clipping to speed that portion up).
Anyway, good luck!

Your example is a special case of what computational geometers call "an arrangement." The CGAL Library has extensive and efficent arrangement handling routines. If you check this part of the documentation, you'll see that you can declare an empty arrangement, then insert triangles to divide the 2d plane into disjoint faces. As others have said, you'll then need to triangulate the faces that aren't already triangles. Happily CGAL also provides the routines to do this. This example of constrained Delaunay triangulation is a good place to start.
CGAL attempts to use the most efficient algorithms available that are practical to implement. In this case it looks like you can achieve O((n + k) log n) for an arrangment with n edges (3 times the number of triangles in your case) with k intersection. The algorithm uses a general technique called "sweep line". A vertical line is swept left-to-right with "events" computed and processed along the way. Events are edge endpoints and intersections. As each event is processed, a cell of the arrangement is updated.
Delaunay algorithms are typically O(n log n) for n vertices. There are several common algorithms, easily looked up or found in the CGAL references.
Even if you can't use CGAL in your work (e.g. for licensing reasons), the documentation is full of sources on the underlying algorithms: arrangements and constrained Delaunay algorithms.
Beware however that both arrangments and triangulations are notoriously hard to implement correctly due to floating point error. Robust versions often depend on rational arithmetic (available in CGAL).

To expand a bit on the comment from Ted Hopp, this should be possible by first computing a planar subdivision in which each bounded face of the output is associated with one of the sets A', B', C', AB, AC, BC, ABC, or "none". The second phase is then to triangulate the (possibly non-convex) faces in each set.
Step 1 could be performed in O((N + K) log N) time using a variation of the Bentley-Ottmann sweep line algorithm in which the current set is maintained as part of the algorithm's state. This can be determined from the line segments that have already been crossed and their direction.
Once that's done, the disjoint polygons for each set can then be broken into monotone pieces in O(N log N) time which in turn can be triangulated in O(N) time.
If you haven't already, pick up a copy of "Computational Geometry: Algorithms and Applications" by de Berg et al.

I can think of two approaches.
A more general approach is treating your input as just a set of lines and splitting the problem in two:
Polygon Detection. Take the set of lines your initial triangles make and get a set of non-overlapping polygons. This paper offers an O((N + M)^4) approach, were N is the number of line segments and M the number of intersections, which does seem a bit slow unfortunately...
Polygon Triangulation. Take each polygon from step 1 and triangulate it. This takes O(n log* n) which is practically O(n).
Another approach is to do do a custom algorithm. Solve the problem for intersecting two triangles, apply it to the first two input triangles, then for each new triangle, apply the algorithm to all the current triangles with the new one. It seems even for two triangles this isn't that straightforward, though, as there are several cases (might not be exhaustive):
No points of the triangle are in any other trianle.
No intersection
Jewish star
Two perpendicular spikes
One point of one triangle is contained in the other
Each triangle contains one point of the other
Two points of one triangle are in the other
Three points of one are in the other - one is fully contained
etc... no, it doesn't seem like that is the right approach. Leaving it here anyway for posterity.

Related

CGAL partitioning of polygon-with-holes

I'm looking at the Partition_2 section of the manual and examples to see if CGAL can handle convex partitioning of a polygon with holes. All of the examples appear to use Polygons without any holes. Does anyone know if this is supported by any of the CGAL partitioning algorithms?
https://github.com/CGAL/cgal/blob/master/Partition_2/include/CGAL/partition_2.h
https://doc.cgal.org/latest/Partition_2/index.html
Thanks,
Josh.
From the documentation:
All the partitioning functions present the same interface to the user.
That is, the user provides a pair of input iterators, first and
beyond, an output iterator result, and a traits class traits. The
points in the range [first, beyond) are assumed to define a simple
polygon whose vertices are in counterclockwise order.
Simple means no holes and no self intersection.
Handling polygons with holes is not hard to achieve since CGAL also provides boolean operations on polygons. Just create the partition and subtract the holes. This may not be an ideal solution if your use case is performance critical (directly partitioning a polygon with holes can be faster).
Right, the "2D Polygon Partitioning" package supports only polygons without holes (as far as I know). You can always triangulate a polygon with holes using the edges (on the outer and inner CCBs) as constraints. Another option is to use vertical decomposition. It is directly provided by the "2D Minkowski Sums" package; see Polygon_vertical_decomposition_2. It is based on the decompose(arr, oi) free function that accepts as input a 2D arrangement; see CGAL::decompose(). The output is a collection of pseudo trapezoids (a pseudo trapezoid can be a triangle in degenerate cases), so it's a bit "better" than pure triangles and extremely efficient, especially if you have the underlying arrangement at hand.

how can I get if a QPolygon is simple? [duplicate]

For a polygon defined as a sequence of (x,y) points, how can I detect whether it is complex or not? A complex polygon has intersections with itself, as shown:
Is there a better solution than checking every pair which would have a time complexity of O(N2)?
There are sweep methods which can determine this much faster than a brute force approach. In addition, they can be used to break a non-simple polygon into multiple simple polygons.
For details, see this article, in particular, this code to test for a simple polygon.
See Bentley Ottmann Algorithm for a sweep based O((N + I)log N) method for this.
Where N is the number of line segments and I is number of intersection points.
In fact, this can be done in linear time use Chazelle's triangulation algorithm. It either triangulates the polygon or find out the polygon is not simple.

Algorithm to assemble a simplified jigsaw puzzle where all edges are identified

Are there any kind of algorithms out there that can assist and accelerate in the construction of a jigsaw puzzle where the edges are already identified and each edge is guaranteed to fit exactly one other edge (or no edges if that piece is a corner or border piece)?
I've got a data set here that is roughly represented by the following structure:
struct tile {
int a, b, c, d;
};
tile[SOME_LARGE_NUMBER] = ...;
Each side (a, b, c, and d) is uniquely indexed within the puzzle so that only one other tile will match an edge (if that edge has a match, since corner and border tiles might not).
Unfortunately there are no guarantees past that. The order of the tiles within the array is random, the only guarantee is that they're indexed from 0 to SOME_LARGE_NUMBER. Likewise, the side UIDs are randomized as well. They all fall within a contiguous range (where the max of that range depends on the number of tiles and the dimensions of the completed puzzle), but that's about it.
I'm trying to assemble the puzzle in the most efficient way possible, so that I can ultimately address the completed puzzle using rows and columns through a two dimensional array. How should I go about doing this?
The tile[] data defines an undirected graph where each node links with 2, 3 or 4 other nodes. Choose a node with just 2 links and set that as your origin. The two links from this node define your X and Y axes. If you follow, say, the X axis link, you will arrive at a node with 3 links — one pointing back to the origin, and two others corresponding to the positive X and Y directions. You can easily identify the link in the X direction, because it will take you to another node with 3 links (not 4).
In this way you can easily find all the pieces along one side until you reach the far corner, which only has two links. Of all the pieces found so far, the only untested links are pointing in the Y direction. This makes it easy to place the next row of pieces. Simply continue until all the pieces have been placed.
This might be not what you are looking for, but because you asked for "most efficient way possible", here is a relatively recent scientific solution.
Puzzles are a complex combinatorial problem (NP-complete) and require some help from Academia to solve them efficiently. State of the art algorithms was recently beaten by genetic algorithms.
Depending on your puzzle sizes (and desire to study scientific stuff ;)) you might be interested in this paper: A Genetic Algorithm-Based Solver for Very Large Jigsaw Puzzles . GAs would work around in surprising ways some of the problems you encounter in classic algorithms.
Note that genetic algorithms are embarrassingly parallel, so there is a straightforward way to do calculations on parallel machines, such as multi-core CPUs, GPUs (CUDA/OpenCL) and even distributed/cloud frameworks. Which makes them hundreds to thousands times faster. GPU-accelerated GAs unlock puzzle sizes unavailable for conventional algorithms.

Given 2 points with known speed direction and location, compute a path composed of (circle) arcs

So, I have two points, say A and B, each one has a known (x, y) coordinate and a speed vector in the same coordinate system. I want to write a function to generate a set of arcs (radius and angle) that lead A to status B.
The angle difference is known, since I can get it by subtracting speed unit vector. Say I move a certain distance with (radius=r, angle=theta) then I got into the exact same situation. Does it have a unique solution? I only need one solution, or even an approximation.
Of course I can solve it by giving a certain circle and a line(radius=infine), but that's not what I want to do. I think there's a library that has a function for this, since it's quite a common approach.
A biarc is a smooth curve consisting of two circular arcs. Given two points with tangents, it is almost always possible to construct a biarc passing through them (with correct tangents).
This is a very basic routine in geometric modelling, and it is indispensable for smoothly approximating an arbirtrary curve (bezier, NURBS, etc) with arcs. Approximation with arcs and lines is heavily used in CAM, because modellers use NURBS without a problem, but machine controllers usually understand only lines and arcs. So I strongly suggest reading on this topic.
In particular, here is a great article on biarcs on biarcs, I seriously advice reading it. It even contains some working code, and an interactive demo.

what kind of algorithm for generating height-map from contour line?

I'm looking for interpolating some contour lines to generating a 3D view. The contours are not stored in a picture, coordinates of each point of the contour are simply stored in a std::vector.
for convex contours :
, it seems (I didn't check by myself) that the height can be easily calculates (linear interpolation) by using the distance between the two closest points of the two closest contours.
my contours are not necessarily convex :
, so it's more tricky... actualy I don't have any idea what kind of algorithm I can use.
UPDATE : 26 Nov. 2013
I finished to write a Discrete Laplace example :
you can get the code here
What you have is basically the classical Dirichlet problem:
Given the values of a function on the boundary of a region of space, assign values to the function in the interior of the region so that it satisfies a specific equation (such as Laplace's equation, which essentially requires the function to have no arbitrary "bumps") everywhere in the interior.
There are many ways to calculate approximate solutions to the Dirichlet problem. A simple approach, which should be well suited to your problem, is to start by discretizing the system; that is, you take a finite grid of height values, assign fixed values to those points that lie on a contour line, and then solve a discretized version of Laplace's equation for the remaining points.
Now, what Laplace's equation actually specifies, in plain terms, is that every point should have a value equal to the average of its neighbors. In the mathematical formulation of the equation, we require this to hold true in the limit as the radius of the neighborhood tends towards zero, but since we're actually working on a finite lattice, we just need to pick a suitable fixed neighborhood. A few reasonable choices of neighborhoods include:
the four orthogonally adjacent points surrounding the center point (a.k.a. the von Neumann neighborhood),
the eight orthogonally and diagonally adjacent grid points (a.k.a. the Moore neigborhood), or
the eight orthogonally and diagonally adjacent grid points, weighted so that the orthogonally adjacent points are counted twice (essentially the sum or average of the above two choices).
(Out of the choices above, the last one generally produces the nicest results, since it most closely approximates a Gaussian kernel, but the first two are often almost as good, and may be faster to calculate.)
Once you've picked a neighborhood and defined the fixed boundary points, it's time to compute the solution. For this, you basically have two choices:
Define a system of linear equations, one per each (unconstrained) grid point, stating that the value at each point is the average of its neighbors, and solve it. This is generally the most efficient approach, if you have access to a good sparse linear system solver, but writing one from scratch may be challenging.
Use an iterative method, where you first assign an arbitrary initial guess to each unconstrained grid point (e.g. using linear interpolation, as you suggest) and then loop over the grid, replacing the value at each point with the average of its neighbors. Then keep repeating this until the values stop changing (much).
You can generate the Constrained Delaunay Triangulation of the vertices and line segments describing the contours, then use the height defined at each vertex as a Z coordinate.
The resulting triangulation can then be rendered like any other triangle soup.
Despite the name, you can use TetGen to generate the triangulations, though it takes a bit of work to set up.