CGAL: Refining triangulation with collinear faces - c++

I have a 2D triangulation created with Constrained_triangulation_plus_2. I am adding many constraints coming from vector data for a geographic region. The problem is later when I create a Surface_mesh out of this triangulation, I come up with collinear faces (checking the triangulation faces didn't show collinear faces).
I tried to fix this problem by refining the triangulation using a Delaunay_mesher_2:
mesher.set_criteria(Criteria(0.125,edge_max_length));
mesher.refine_mesh();
This will give me the following runtime exception:
CGAL error: assertion violation!
Expression : n == zone.fh
File : ../CGAL-4.8/include/CGAL/Mesh_2/Refine_edges.h
Line : 447
Explanation:
Refer to the bug-reporting instructions at http://www.cgal.org/bug_report.html
libc++abi.dylib: terminating with uncaught exception of type CGAL::Assertion_exception: CGAL ERROR: assertion violation!
Expr: n == zone.fh
File: ../CGAL-4.8/include/CGAL/Mesh_2/Refine_edges.h
Line: 447
I couldn't really understand what is happening in Refine_edges.h, though I guess that's something to do with collinear faces. I even tried mesher.step_by_step_refine_mesh() function for some number of iterations, but that didn't fix those very small triangles.
Then I tried to remove small triangles from the triangulation, but some of them at least had a constrained edge, so that was not possible too, and I couldn't find a way to modify if an edge is constrained, or even if I do, that would break the closed region of a constraint on my triangulation.
I also tried to simplify triangulation before refining, using a call like PS::simplify(cdtp, Cost(), Stop(1e-5)), but that didn't seem to fix the error.
So, my question is how can I modify the triangulation so the refine_mesh() won't run into a problem? I'm currently using the Exact_predicates_inexact_constructions_kernel. I tried using an exact kernel too, in that case I didn't get that runtime error, but the refine function took forever.

Related

How to mesh a 2D point cloud in C++

I have a set of 2D points of a known density I want to mesh by taking the holes in account. Basically, given the following input:
I want something link this:
I tried PCL ConcaveHull, but it doens't handle the holes and splitted mesh very well.
I looked at CGAL Alpha shapes, which seems to go in the right direction (creating a polygon from a point cloud), but I don't know how to get triangles after that.
I though of passing the resulting polygons to a constrained triangulation algorithm and mark domains, but I didn't find how to get a list of polygons.
The resulting triangulated polygon is about a two step process at the least. First you need to triangulate your 2D points (using something like a Delaunay2D algorithm). There you can set the maximum length for the triangles and get the the desired shape. Then you can decimate the point cloud and re-triangulate. Another option is to use the convex hull to get the outside polygon, then extract the inside polygon through a TriangulationCDT algorithm, the apply some PolygonBooleanOperations, obtain the desired polygon, and finaly re-triangulate.
I suggest you look into the Geometric Tools library and specifically the Geometric Samples. I think everything you need is in there, and is much less library and path heavy than CGAL (the algorithms are not free for this type of work unless is a school project) or the PCL (I really like the library for segmentation, but their triangulation breaks often and is slow).
If this solves your problem, please mark it as your answer. Thank you!

Triangulation based on contour [duplicate]

I need to create a triangle mesh from a set of points. The set has very few points so it doesn't need to be fast or optimised (I will deal with 100 points maximum). The mesh needs to be a constrained "delaunay triangulation". In the image below I showed (on the left) the set of points I start from (blue and red dots). I also know the connections between these points (the outline in black). The mesh needs to look like the example on the right (including the edges in grey that form outside and inner triangles).
I can't use libraries.
I looked at many different algorithms. They are many and it's easy to be confused. I would like to know if there is a naive and thus hopefully simpler algorithm I can use in order to produce the mesh on the right? Brute force approach is fine (ps: I can do a Delaunay triangulation).
Thanks for all the answers.
I went through the process of developing a solution to this problem so thought I would share my own experience, hoping people facing the problem will find the insight useful.
So from my own experience implementing an algorithm I came to the conclusion:
There is not really quick way to this problem. It is not reasonable to think it can be achieved in just 50 lines of code. In fact the routine that I wrote (C++) is about 400 to 500 lines (hard to tell with comments). So reasonably compact yet challenging and it took me a 2 to 3 days to get the logic right (it can be tricky).
I found the algorithm propose by Sloan in "A FAST ALGORITHM FOR GENERATING CONSTRAINED DELAUNAY TRIANGULATIONS" to be perfectly well suited for the problem at hand. The reality when it comes to Delaunay triangulation which was a new subject for me, is that there seems to be a lot of different algorithms approach and this research is pretty old. So for a new comer it's really hard to know where to start.
2.1. It's hard to know which algorithm is recent, simple in its comprehension and fast and simple to implement.
2.2 Generally once you have understood the principle it's mostly a matter of coding the logic in the most efficient way (and it seems that this what most of the algorithms/papers are fighting above).
2.3 I found the paper from Sloan to be understandable, very well explained. If you follow the logic and the instructions, then anyone can really implement a constrained Delaunay triangulation.
So in conclusion:
I recommend the Sloan paper because it includes an explanation on how to create a Delaunay triangulation followed by a constrained triangulation if necessary.
To answer my own question there is not really brute force to this problem. Implementing this technique just requires to implement the full logic and most implementation must require more or less the same amount of work
With the nuance, that I wasn't looking after much optimisations because my point sets are really small. So I am sure many algorithms are better than the one described by Sloan; they probably propose optimized data structures and algorithms optimized to minimize steps such point insertion in triangulation etc.
So anyway Sloan worked. A small image to illustrate the answer and make it more attractive;-)
EDIT
This is production code so helas I can't share that... I could lead me to be fired. The process is very simple though. You look for the intersection between a segment (your constraint) and all edges in the model. Then for each intersected edge, you swap the diagonal between the 2 triangles that this edges belongs to. If the new diagonal intersects the segment still, then add the new diagonal back onto the stack of intersected edges for this segment. If the new diagonal doesn't intersect the segment then add it to the stack of newly created edges. Keep processing the stack of intersected edges until it's empty.
Then once this is finished you need to process the list of new added edges. For each one of them, check that the Delaunay triangulation criterion is respected. If not swap the diagonal of the triangle this edge belongs to. Simple ...
This is just the paper ...
Point Set
26.9375 10.6875
32.75 9.96875
31.375 4.875
27.6562 2.0625
23.9375 -0.75
18.1562 -0.75
10.875 -0.75
6.60938 3.73438
2.34375 8.21875
2.34375 16.3125
2.34375 24.6875
6.65627 29.3125
10.9688 33.9375
17.8438 33.9375
24.5 33.9375
28.7188 29.4062
32.9375 24.875
32.9375 16.6562
32.9375 16.1562
32.9062 15.1562
8.15625 15.1562
8.46875 9.6875
11.25 6.78125
14.0312 3.875
18.1875 3.875
21.2812 3.875
23.4687 5.5
25.6562 7.125
8.46875 19.7812
27 19.7812
26.625 23.9688
24.875 26.0625
22.1875 29.3125
17.9062 29.3125
14.0312 29.3125
11.3906 26.7188
8.75 24.125
These are x/y/z coordinates (z=0)
Segments:
0 1
1 3
3 5
5 7
7 9
9 11
11 13
13 15
15 17
17 19
19 20
20 22
22 24
24 26
26 0
28 29
29 31
31 33
33 35
35 28
Indices start at 0 (0 -> first vertex in vertex list)
I tried it with alpha shapes with good results for a few shapes https://concavehull.codeplex.com/ but it's nowhere near the original constrained delaunay triangulation.
Here is my alpha-shape algorithm:https://alphashape.codeplex.com.
A simple approach seems to be to implement a ear clipping algorithm. Without optimisation as in hash grids or quad trees. For ear clipping you just check every three consecutive vertices a,b, and c. If b is convex and no other vertex of the polygon lies inside the triangle abc then you can clip this triangle reducing the boundary of the polygon by one vertex, b.
Additionally you have to store the neighbourhood relations. Thus, reference from each triangle its, at most three, neighbours.
When the triangulation is finished you convert it to the constrained Delaunay triangulation (CDT). This can be done by edge flipping. Therefore you have to check for every triangle the circumcircle. If no vertex of a neighbouring triangle lies inside the triangle is conform to the CDT otherwise flip the edge of the triangle where the violation occurs.
Edit due to #Betterdev in the comments blow: Possible holes in the input polygon can be added to the initial boundary by adding a bridge. As a preprocessing one can connect a vertex of a hole to a vertex of the boundary by a "double" edge. This is always possible and makes each hole part of the main polygon boundary; and works well with ear clipping. Storing the neighbour through these bridges is vital to the flipping however.
I previously worked on a vector graphics package, so I can't tell you how many hours I've stared at that exact "e" graphic. I eventually settled on the earcut library for triangulation of point data. It's extremely fast and much simpler compared to libraries such as libtess-2.

CGAL 2.5D mesh with minimum element area

I'm trying to build a 2.5D mesh from a LIDAR dataset A consisting of ~50,000,000 points (x,y,z) to describe the terrain in an urban area. The final aim is to use this mesh for numerical simulation of flooding and I'm having trouble with too small elements. I took the following steps:
use Point_Processing_3 to create a reduced set B of points (x,y,z) retaining about 1% of the original data ( CGAL::wlop_simplify_and_regularize_point_set)
create a constrained Delaunay triangulation cdt using simplified building footprints as constraints (CGAL::Constrained_Delaunay_triangulation_2)
insert the points from B into cdt if they are located at least 1m from any existing vertex in the triangulation
refine the mesh using Delaunay_mesher_2
#include <CGAL/Delaunay_mesher_2.h>
#include <CGAL/Delaunay_mesh_size_criteria_2.h>
Meshing_engine engine(cdt);
engine.refine_mesh();
So far so good. The resulting mesh looks very nice. However, I end up with quite a lot of very small triangles which will make any hydraulic simulation very difficult. I have no idea how to get rid of these.
The criteria used in combination with refine_mesh() seem to always aim at penalizing large elements, while this is the opposite case. In many areas large triangles will be perfectly fine, but triangles with a size of 0.5sqm should never occur.
Another option would be to manually remove vertices from the triangulation using cdt.remove(vertex_handle). But, given a too small face, how to pick the vertex to remove?
Can anyone help pointing in a direction? I attached an image where one of the problematic areas is marked red.
2.5D mesh with problem areas marked red. Empty areas are buildings.

More accurate houghline OpenCV

I have been working with houghlines in OpenCV and I cant seem to get a more accurate line reading, sometimes there are two duplicate lines on top of each other. I have looked at tutorial on the opencv website but it gives a similar result.
To remove those duplicate lines, there are two things that may help you:
Double edges may appear that may lead to duplicate lines. A sequence of blurring/dilating the input image would solve these issues.
Close lines that have almost same slope can be removed by using lower angle resolutions for the theta argument of Hough Line method. For example using π/180 would result in finding lines that differ only by one degree in their slope. You may use 5*π/180 to find lines in 5 degree resolution.
As an example, the following lines are detected by using the raw image and a 1-degree resolution:
After a bit of blurring and using a 3-degree resolution you can get a result like the following:
By changing the threshold, you can get more or less lines.
About fitting curves you pointed in the comments section, yes you can fit curves, but not with hough lines method. You need to find a parametric definition of that shape and try to run the voting procedure in hough transform yourself. The only other shape that opencv helps you to find is circle.

Detecting curves in OpenCV

I am just starting to use OpenCV to detect specific curves in an image. First, I want to verify if there is a curve, and next, I would like to identify the type of curve according to vertical or horizontal convex or concave curve. Is there an available function in OpenCV? If not, can you give me some ideas about how can I possibly write such a function? Thanks! By the way, I'm using C++.
Template matching is not a robust way to solve this problem (its like looking at an object from a small pinhole) and edge detectors don't necessarily return you the true edges in the image; false edges such as those due to shadows are returned too. Further, you have to deal with the problem of incomplete edges and other problems that scales up with the complexity of the scene in your image.
The problem you posed, in general, is a very challenging one and, except for toy examples, there are no good solutions.
A rough attempt could be to first try to detect plausible edges using an edge detector (e.g. the canny edge detector suggested). Next, use RANSAC to try to fit a subset of the points in the detected edges to your curve model.
For e.g. let's say you are trying to detect a curve of the following form f(x) = ax^2 + bx + c. RANSAC will basically try to find from among the points in the detected edges, a subset of them that would best fit this curve model. To detect different curves, change f(x) accordingly and run RANSAC for each of them. You can then try to determine if the curve represented by f(x) really exists in your image using some heuristic applied to from the points that were assigned to it by RANSAC (e.g. if too few points were fitted to the model it is likely that the curve is not there. But how to determine a good threshold for the number of points?). You model will get more complex when you have to account for allowable transformation such as rotation etc.
The problem with this approach is you are basically trying fit what you think should be in the image to the points and sometimes, even if what you are looking for is not there, it will return you the "best possible" fit. For e.g. you have a whole bunch of points detected from a concentric circle. If you try to detect straight lines from these points, RANSAC will return you the best fit line! In fact, it could give you many different lines from different runs depending on which points it selected during its random initialization stage.
For more details on how to use RANSAC on this sort of problem, have a look at RANSAC for Dummies by Marco Zuliani. He also has a nice MATLAB toolbox to accompany this tech report, which you can probably port to the language of your choice.
Unless you know what you background looks like, or if you are in control of it e.g. by forcing a clean background, this is a very difficult problem to solve.