Skip to content

Commit 3fa6e77

Browse files
authored
Mesh_2: Make lloyd_optimize_mesh_2() deterministic (#8768)
## Summary of Changes Replace a `std::set<Vertex_handle>` by a `std::set<std::pair<std::size_t,Vertex_handle>>` to make traversing the set deterministic. At the same time, do not `erase()` a key, but an `iterator`. ## Release Management * Affected package(s): Mesh_2 * Issue(s) solved (if any): fix #8719 * License and copyright ownership: unchanged
2 parents f3ff704 + 7da3375 commit 3fa6e77

File tree

2 files changed

+208
-6
lines changed

2 files changed

+208
-6
lines changed

Mesh_2/include/CGAL/Mesh_2/Mesh_global_optimizer_2.h

+15-6
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,14 @@ class Mesh_global_optimizer_2
6161
typedef typename Gt::Vector_2 Vector_2;
6262

6363
typedef typename std::vector<Face_handle> Face_vector;
64-
typedef typename std::set<Vertex_handle> Vertex_set;
64+
typedef std::pair<std::size_t,Vertex_handle> IndexVertexPair;
65+
struct IVP_less {
66+
bool operator()(const IndexVertexPair& ivp1, const IndexVertexPair& ivp2) const
67+
{
68+
return ivp1.first < ivp2.first;
69+
}
70+
};
71+
typedef typename std::set<IndexVertexPair,IVP_less> Vertex_set;
6572
typedef typename std::list<FT> FT_list;
6673
typedef typename std::pair<Vertex_handle,Point_2> Move;
6774

@@ -114,13 +121,14 @@ class Mesh_global_optimizer_2
114121

115122
// Fill set containing moving vertices
116123
Vertex_set moving_vertices;
124+
std::size_t ind = 0;
117125
for(typename Tr::Finite_vertices_iterator
118126
vit = cdt_.finite_vertices_begin();
119127
vit != cdt_.finite_vertices_end();
120128
++vit )
121129
{
122130
if(!cdt_.are_there_incident_constraints(vit))
123-
moving_vertices.insert(vit);
131+
moving_vertices.insert(std::make_pair(ind++, vit));
124132
}
125133

126134
double initial_vertices_nb = static_cast<double>(moving_vertices.size());
@@ -236,11 +244,12 @@ class Mesh_global_optimizer_2
236244
std::fill(big_moves_.begin(), big_moves_.end(), FT(0));
237245

238246
// Get move for each moving vertex
239-
for ( typename Vertex_set::const_iterator vit = moving_vertices.begin() ;
240-
vit != moving_vertices.end() ; )
247+
for ( typename Vertex_set::iterator vit = moving_vertices.begin() ;
248+
vit != moving_vertices.end() ;)
241249
{
242-
Vertex_handle oldv = *vit;
250+
Vertex_handle oldv = vit->second;
243251
Vector_2 move = compute_move(oldv);
252+
typename Vertex_set::iterator old_vit = vit;
244253
++vit;
245254

246255
if ( CGAL::NULL_VECTOR != move )
@@ -249,7 +258,7 @@ class Mesh_global_optimizer_2
249258
moves.push_back(std::make_pair(oldv, new_position));
250259
}
251260
else if(sq_freeze_ratio_ > 0.) //freezing ON
252-
moving_vertices.erase(oldv);
261+
moving_vertices.erase(old_vit);
253262

254263
// Stop if time_limit_ is reached
255264
if ( is_time_limit_reached() )

Mesh_2/test/Mesh_2/issue8719.cpp

+193
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,193 @@
1+
#include <cmath>
2+
#include <iostream>
3+
#include <sstream>
4+
#include <vector>
5+
#include <string>
6+
7+
#include <CGAL/Exact_predicates_inexact_constructions_kernel.h>
8+
#include <CGAL/Constrained_Delaunay_triangulation_2.h>
9+
#include <CGAL/Delaunay_mesher_2.h>
10+
#include <CGAL/Delaunay_mesh_face_base_2.h>
11+
#include <CGAL/Delaunay_mesh_vertex_base_2.h>
12+
#include <CGAL/Delaunay_mesh_size_criteria_2.h>
13+
#include <CGAL/lloyd_optimize_mesh_2.h>
14+
15+
16+
typedef CGAL::Exact_predicates_inexact_constructions_kernel K;
17+
typedef CGAL::Delaunay_mesh_vertex_base_2<K> Vb;
18+
typedef CGAL::Delaunay_mesh_face_base_2<K> Fb;
19+
typedef CGAL::Triangulation_data_structure_2<Vb, Fb> Tds;
20+
typedef CGAL::Constrained_Delaunay_triangulation_2<K, Tds> CDT;
21+
typedef CGAL::Delaunay_mesh_size_criteria_2<CDT> Criteria;
22+
typedef CGAL::Delaunay_mesher_2<CDT, Criteria> Mesher;
23+
typedef CDT::Vertex_handle Vertex_handle;
24+
typedef CDT::Point Point;
25+
26+
27+
using namespace std;
28+
29+
std::string result;
30+
31+
void CGAL_Remesh(double* vert_xyz_array, size_t vert_count, double criteria_a, double criteria_b, int iteration_number, double*& newVertices, int*& vCount, int*& newFaces, int*& fCount, int fileNum)
32+
{
33+
CDT cdt;
34+
35+
36+
37+
vector<Vertex_handle> cdt_Vh_Boundary;
38+
39+
for (size_t i = 0; i < vert_count; ++i)
40+
{
41+
Vertex_handle vh = cdt.insert(Point(vert_xyz_array[3 * i + 0], vert_xyz_array[3 * i + 1]));
42+
cdt_Vh_Boundary.push_back(vh);
43+
}
44+
45+
// insert Constrain
46+
for (size_t i = 0; i < cdt_Vh_Boundary.size() - 1; ++i)
47+
{
48+
cdt.insert_constraint(cdt_Vh_Boundary[i], cdt_Vh_Boundary[i + 1]);
49+
}
50+
cdt.insert_constraint(cdt_Vh_Boundary[cdt_Vh_Boundary.size() - 1], cdt_Vh_Boundary[0]);
51+
52+
// refine and optimize mesh
53+
54+
Mesher mesher(cdt);
55+
mesher.set_criteria(Criteria(criteria_a, criteria_b));
56+
mesher.refine_mesh();
57+
CGAL::lloyd_optimize_mesh_2(cdt, CGAL::parameters::max_iteration_number = iteration_number);
58+
59+
60+
// make index pair
61+
vector <CDT::Vertex_handle> visitedVertices; // collect visited vertices
62+
63+
map <CDT::Vertex_handle, int> indexList; // create a map to note the index
64+
65+
int i = 0;
66+
for (CDT::Vertex_iterator v_it = cdt.vertices_begin(); v_it != cdt.vertices_end(); ++v_it)
67+
{
68+
69+
CDT::Vertex_handle vh = v_it;
70+
indexList[vh] = i;
71+
visitedVertices.push_back(vh);
72+
i++;
73+
}
74+
75+
// Convert data into double array
76+
int vNum = cdt.number_of_vertices();
77+
78+
newVertices = new double[vNum * 3];
79+
80+
i = 0;
81+
for (CDT::Vertex_iterator vi = cdt.vertices_begin(); vi != cdt.vertices_end(); ++vi)
82+
{
83+
newVertices[i] = vi->point()[0];
84+
i += 1;
85+
newVertices[i] = vi->point()[1];
86+
i += 1;
87+
newVertices[i] = 0;
88+
i += 1;
89+
}
90+
91+
92+
int vertexCount = vNum;
93+
vCount = &vertexCount;
94+
95+
int num_face_in_domain = 0;
96+
97+
for (CDT::Face_iterator f_it = cdt.faces_begin(); f_it != cdt.faces_end(); ++f_it)
98+
{
99+
CDT::Face_handle face = f_it;
100+
if (face->is_in_domain())
101+
{
102+
num_face_in_domain++;
103+
}
104+
}
105+
106+
107+
newFaces = new int[num_face_in_domain * 3];
108+
109+
110+
i = 0;
111+
for (CDT::Face_iterator f_it = cdt.faces_begin(); f_it != cdt.faces_end(); ++f_it)
112+
{
113+
CDT::Face_handle face = f_it;
114+
115+
if (face->is_in_domain())
116+
{
117+
newFaces[i] = int(indexList.find(face->vertex(0))->second);
118+
i += 1;
119+
newFaces[i] = int(indexList.find(face->vertex(1))->second);
120+
i += 1;
121+
newFaces[i] = int(indexList.find(face->vertex(2))->second);
122+
i += 1;
123+
}
124+
}
125+
int faceCount = num_face_in_domain;
126+
fCount = &faceCount;
127+
128+
129+
// print
130+
std::stringstream outputFile;
131+
132+
if (fCount && newFaces) {
133+
outputFile << "\nRemeshed faces (" << *fCount << "):\n";
134+
for (int i = 0; i < (*fCount) * 3; i += 3) {
135+
outputFile << newFaces[i] << " " << newFaces[i + 1] << " " << newFaces[i + 2] << "\n";
136+
}
137+
}
138+
139+
if(fileNum == 1)
140+
{
141+
result = outputFile.str();
142+
}
143+
else
144+
{
145+
assert(result == outputFile.str());
146+
}
147+
148+
}
149+
150+
int main()
151+
{
152+
//
153+
double vert_xyz_array[] = {
154+
3375.4981, 1935.35224056, 0.0,
155+
3350.77259333, 2066.38188194, 0.0,
156+
3210.83712383, 2054.53004190, 0.0,
157+
3068.88, 2060.98161842, 0.0,
158+
3034.24939361, 2066.55369658, 0.0,
159+
3025.6776, 2008.40156297, 0.0,
160+
3013.23241519, 1927.9864, 0.0,
161+
3033.36312437, 1924.87291062, 0.0,
162+
3078.68871988, 1917.86131994, 0.0,
163+
3124.01437021, 1910.85008365, 0.0,
164+
3167.66255113, 1908.86629111, 0.0,
165+
3169.83178711, 1908.76770020, 0.0,
166+
3215.64920401, 1906.68531674, 0.0,
167+
3260.96808047, 1913.74020504, 0.0,
168+
3306.03738982, 1922.24487242, 0.0,
169+
3351.10669914, 1930.74953992, 0.0
170+
};
171+
172+
173+
size_t vert_count = 16;
174+
double criteria_a = 0.125;
175+
double criteria_b = 36.691771392;
176+
int iteration_number = 20;
177+
178+
double* newVertices = nullptr;
179+
int* vCount = nullptr;
180+
int* newFaces = nullptr;
181+
int* fCount = nullptr;
182+
183+
for (int i = 1; i <= 2; ++i)
184+
{
185+
CGAL_Remesh(vert_xyz_array, vert_count, criteria_a, criteria_b, iteration_number, newVertices, vCount, newFaces, fCount, i);
186+
}
187+
188+
189+
std::cout << "\nDone";
190+
191+
192+
return 0;
193+
}

0 commit comments

Comments
 (0)