How to construct a voronoi diagram inside a polygon? - c++

I need an algorithm that fills a 2D non-convex polygon that may have holes with points randomly, and then constructs a voronoi diagram on them. The diagram should be bounded with the polygon and the algorithm should run in O(n log n).
My idea was to fill the poly by testing random points inside the polys bounding box and taking only the points inside the poly, and than building voronoi on them, and than clipping the edges of the diagram that exit the polygon.
The problem is, testing random points and clipping the edges is O(n^2).
Can this be done in boost, or is there another small library, or anything else really?

I guess with "holes" you man self-intersections of a single, closed polygon.
Do a Delaunay triangulation of your polygon first:
Calculate section points between segments; add these points, split the segments and rearrange the input so that "inside" is always on the same side of the edge when traversing the polygon's points.
Trangulate all points in your polygon.
Delete the triangles that lie outside your polygon. These will be the concavities and holes created by self-intersections. You can identify them by walking along your polygon and deleting all triangles that lie outside an edge. You need the connectivity of the edges, but that's a byproduct of the triangulation.
You now have the starting point for further triangulation with the Bowyer-Watson algorithm, which triangulates by successively adding points to a parent triangle. So, to add a random point, we can pick a point and update the triangulation in one go:
Pick a random triangle, where the probability for each triangle to be picked is proportional to its area.
Chose a random location inside that riangle by picking barycentric coordinates s in [0, 1], t in[0, 1]and withs + t < 1`. Your new point is then:
{P} = s * ({N2} - {N1}) + t * ({N3} - {N1})
Add your point and retriangulate the parent triangle and other triangles whose circumcircle contains the new point.
The set of triangles to pick has now changed.
You now have a Delaunay triangulation, but you want a Voronoi diagram, which you can easily obtain by connecting the centres of all circumcircles of adjacent triangles. Again, the Delaunay triangulation provides you with the information on the circumcircles and on which triangles are adjacent.
You can use the Bowyer-Watson algorithm on your initial triangulation when you create a large dummy triangle that encloses all your points.
I'm not aware of any triangulation libraries for C++, but this question might get you started.

Related

Generate the faces of a 3D object given its points and edges

I have a 3D wire-frame consisting of 3D points and edges. How do I go about identifying sets of vertices forming a face of the 3D object?
I am using QT and want to render a 3D object given its point set and edge set. The best I have been able to do is given three points forming a triangular face, I am able to render it in 3D. But how to do the same given more points and edges? Or, alternatively, how to break down the set in sets of 3 points forming a triangular face?
Just take your first edge and its vertices (V1 and V2).
Find all edges that use V2 - their second vertices are your potential V3's.
For each potential V3 check if you have edge V1-V3 - if so, then you've found a triangle V1-V2-V3. For most meshes you should have one or two such triangles. When you're adding a new triangle always check if wasn't found already.
Do the same for edges that use V1.
Take next edge and repeat.
Depending on your exact data, edge directions, etc. it may need slight modifications but you should get the point.

Create Topographic 2D Curves from Polygonal Mesh

I'm trying to convert a polygonal 3D mesh into a series of topographic curves that represent the part of the mesh at a specific height for every interval. So far, I've come up with the idea to intersect a horizontal plane with the mesh and get the intersection curve(s). So for this mesh:
I'd intersect a plane repeatedly at a set interval of precision:
and etc.
While this is straightforward to do visually and in a CAD application, I'm completely lost doing this programmatically. How could I achieve calculating this in a programming environment/ what algorithms can I look into to achieve this?
I'm programming in an STL C++ environment (with Boost), loading .obj meshes with this simple loader, and need simple cartesian 2D points to define the output curve.
An option is to process all the faces in turn and for every face determine the horizontal planes that traverses them. For a given plane and face, check all four vertexes in turn and find the changes of sign (of Zvertex - Zplane). There will be exactly two such changes, defining an edge that belongs to a level curve. (Exceptionally you can find four changes of sign, which occurs when the facet isn't planar - join the points in pairs.)
Every time you find an intersection point, you tag it with the (unique) index of the plane and the (unique) index of the edge that was intersected; you also tag it with the index of the other edge that was intersected in that face.
By sorting on the plane index, you can group the intersections per plane.
For a given plane, using a hash table, you can follow the chain of intersections, from edge to edge.
This gives you the desired set of curves.

CGAL: Difference between normal and weighted 3D triangulation

For a set of 3D points, all of them specified by their cartesian coordinates, what is the main difference in CGAL between its 3D Delaunay triangulation and its weighted (as depicted here) or regular 3D triangulation?
As you know, given a set of points, there exist many triangulations defined over this set of points.
The Delaunay triangulation is the one such that for each tetrahedron, the circumscribed sphere
does not contain any other points but the vertices of the tetrahedron. It is unique if no more than 4 points are co-spherical.
A regular triangulation uses the weight associated each point to define a similar emptiness criteria as described on this page using the power of a weighted point. In particular, in a regular triangulation, a point might be hidden (does not appear in the triangulation with an associated vertex), if it is not on the convex hull and if its weight is too small compared to its neighbors.

Determine if a 2d polygon can be drawn with a single triangle fan

At first, I thought this problem would be equivalent to determining if a polygon is convex, however it seems that a non-convex polygon could still be drawn by one triangle fan. Consider this shape, a non-convex polygon. One could easily imagine some region of centerpoints that would allow this polygon to be drawn with a triangle fan (although there would be other centerpoints that would not). Given a fixed centerpoint, I want to be able to determine if the set of 2d points defining the polygon allow for it to be drawn with a single triangle fan.
It seems like the key is making sure nothing "gets in the way" of a line drawn from the centerpoint to any of the vertices, that means other edge lines of vertices. However, it is important to make this as computationally inexpensive as possible, and I'm not sure if there's a nice math shortcut to doing this.
Ultimately, I'm going to have the vertices of polygons moving, and I'll need to determine the "boundary" a vertex is allowed to move, given the rest are fixed (and perhaps later even allowing the simultaneous reactive movement of the direct 2 neighbors as well), to keep the polygon capable of being drawn in a single triangle fan. But that's the future, hopefully the test over the full polygon can be broken into a subset of calculations to test the bounds of a single vertex's movement with the assumption of an already convex polygon.
The property you're looking for is "star-shaped". Star-shaped polygons are are defined by having a point from which the entire polygon is visible.
To test that a polygon is star-shaped, you can construct the region from which the whole polygon will be visible. That region would be a convex set, so you can intersect it with a halfplane in O(log(n)).
That means you can intersect the halfplanes formed by the edges and check that the resulting visibility region is nonempty in O(n log n).
A polygon can be drawn as a triangle fan if the angle from the anchor to each vertex moves in the same direction. The easiest way to test this is to check the dot products of the cross products of the successive vertices.
It will look something like this:
vector lastCross = cross_product( vector(vertex[0] - center), vector(vertex[numVerts - 1] - center) );
canBeFan = true;
for (n = 1; canBeFan && n < numVerts; ++n) {
vector testCross = cross_product( vector(vertex[n] - center), vector(vertex[n - 1] - center) );
if (0.0 >= dot_product(testCross, lastCross) ) {
canBeFan = false;
}
}
It looks like all potential centerpoints will need to be on the interior side of every edge of your polygon. So, treat all your edges as half-spaces, and determine if their intersection is empty or not.
As #jpalecek says, the term for this is star-shaped. If your polygon is star-shaped, there will be a convex polygon (interior to the original) whose points can view all edges of the original -- and, conversely, if no such sub-polygon exists, the original is not star-shaped, and you cannot draw it with a triangle fan.
Determining this sub-polygon is basically a dual application of the convex hull problem; it can be computed in O(n log n).

Creating OOBB from points

How can I create minimal OOBB for given points? Creating AABB or sphere is very easy, but I have problems creating minimal OOBB.
[edit]
First answer didn't get me good results. I don't have huge cloud of points. I have little amount of points. I am doing collision geometry generation. For example, cube has 36 points (6 sides, 2 triangles each, 3 points for each triangle). And algorithm from first post gave bad results for cube. Example points for cube: http://nopaste.dk/download/3382 (should return identity axis)
The PCA/covariance/eigenvector method essentially finds the axes of an ellipsoid that approximates the vertices of your object. It should work for random objects, but will give bad results for symmetric objects like the cube. That's because the approximating ellipsoid for a cube is a sphere, and a sphere does not have well defined axes. So you're not getting the standard axes that you expect.
Perhaps if you know in advance that an object is, for example, a cube you can use a specialized method, and use PCA for everything else.
On the other hand, if you want to compute the true OBB there are existing implementations you can use e.g. http://www.geometrictools.com/LibMathematics/Containment/Containment.html
(archived at https://web.archive.org/web/20110817024344/geometrictools.com/LibMathematics/Containment/Containment.html and https://github.com/timprepscius/GeometricTools/blob/master/WildMagic5/LibMathematics/Containment/Wm5ContMinBox3.cpp). I believe this implements the algorithm alluded to in the comments to your question.
Quoting from that page:
The ContMinBox3 files implement an
algorithm for computing the
minimum-volume box containing the
points. This method computes the
convex hull of the points, a convex
polyhedron. The minimum-volume box
either has a face coincident with a
face of the convex polyhedron or has
axis directions given by three
mutually perpendicular edges of the
convex polyhedron. Each face of the
convex polyhedron is processed by
projecting the polyhedron to the plane
of the face, computing the
minimum-area rectangle containing the
projections, and computing the
minimum-length interval containing the
projections onto the perpendicular of
the face. The minimum-area rectangle
and minimum-length interval combine to
form a candidate box. Then all triples
of edges of the convex polyhedron are
processed. If any triple has mutually
perpendicular edges, the smallest box
with axes in the directions of the
edges is computed. Of all these boxes,
the one with the smallest volume is
the minimum-volume box containing the
original point set.
If, as you say, your objects do not have a large number of vertices, the running time should be acceptable.
In a discussion at http://www.gamedev.net/topic/320675-how-to-create-oriented-bounding-box/ the author of the above library casts some more light on the topic:
Gottschalk's approach to OBB construction is to compute a covariance matrix for the point set. The eigenvectors of this matrix are the OBB axes. The average of the points is the OBB center. The OBB is not guaranteed to have the minimum volume of all containing boxes. An OBB tree is built by recursively splitting the triangle mesh whose vertices are the point set. A couple of heuristics are mentioned for the splitting.
The minimum volume box (MVB) containing a point set is the minimum volume box containing the convex hull of the points. The hull is a convex polyhedron. Based on a result of Joe O'Rourke, the MVB is supported by a face of the polyhedron or by three perpendicular edges of the polyhedron. "Supported by a face" means that the MVB has a face coincident with a polyhedron face. "Supported by three perpendicular edges" means that three perpendicular edges of the MVB are coincident with edges of the polyhedron.
As jyk indicates, the implementations of any of these algorithms is not trivial. However, never let that discourage you from trying :) An AABB can be a good fit, but it can also be a very bad fit. Consider a "thin" cylinder with end points at (0,0,0) and (1,1,1) [imagine the cylinder is the line segment connecting the points]. The AABB is 0 <= x <= 1, 0 <= y <= 1, and 0 <= z <= 1, with a volume of 1. The MVB has center (1,1,1)/2, an axis (1,1,1)/sqrt(3), and an extent for this axis of sqrt(3)/2. It also has two additional axes perpendicular to the first axis, but the extents are 0. The volume of this box is 0. If you give the line segment a little thickness, the MVB becomes slightly larger, but still has a volume much smaller than that of the AABB.
Which type of box you choose should depend on your own application's data.
Implementations of all of this are at my www.geometrictools.com website. I use the median-split heuristic for the bounding-volume trees. The MVB construction requires a convex hull finder in 2D, a convex hull finder in 3D, and a method for computing the minimum area box containing a set of planar points--I use the rotating caliper method for this.
First you have to compute the centroid of the points, in pseudcode
mu = sum(0..N, x[i]) / N
then you have to compute the covariance matrix
C = sum(0..N, mult(x[i]-mu, transpose(x[i]-mu)));
Note that the mult performs an (3x1) matrix multiplication by (1x3) matrix multiplication, and the result is a 3x3 matrix.
The eigenvectors of the C matrix define the three axis of the OBB.
There is a new library ApproxMVBB in C++ online which computes an approximation for the minimum volume bounding box. Its released under MPL 2.0 Licences, and written by me.
If you have time look at: http://gabyx.github.io/ApproxMVBB/
The library is C++11 compatible and only needs Eigen http://eigen.tuxfamily.org.
Tests show that an approximation for 140Million points in 3D can be computed in reasonable time (arround 5-7 seconds) depending on your settings for the approximation.