Connect points by triangulation to create filled surface by triangles Input points have to be unique Inspiration for make unique points is Emboss::dilate_to_unique_points.
105{
106 assert(!points.empty());
107 assert(!constrained_half_edges.empty());
108
109 assert(std::is_sorted(constrained_half_edges.begin(),
110 constrained_half_edges.end()));
111
112 assert(std::adjacent_find(constrained_half_edges.begin(), constrained_half_edges.end()) == constrained_half_edges.end());
113
115
118
119 using K = CGAL::Exact_predicates_inexact_constructions_kernel;
120 using Vb = CGAL::Triangulation_vertex_base_with_info_2<uint32_t, K>;
121 using Fb = CGAL::Constrained_triangulation_face_base_2<K>;
122 using Tds = CGAL::Triangulation_data_structure_2<Vb, Fb>;
123 using CDT = CGAL::Constrained_Delaunay_triangulation_2<K, Tds, CGAL::Exact_predicates_tag>;
124
125
126 CDT cdt;
127 {
128 std::vector<CDT::Vertex_handle> vertices_handle(points.size());
129 using Point_with_ord = std::pair<CDT::Point, size_t>;
130 using SearchTrait = CGAL::Spatial_sort_traits_adapter_2
131 <
K, CGAL::First_of_pair_property_map<Point_with_ord> >;
132
133 std::vector<Point_with_ord> cdt_points;
134 cdt_points.reserve(points.size());
135 size_t ord = 0;
136 for (const auto &p : points)
137 cdt_points.emplace_back(std::make_pair(CDT::Point{p.x(), p.y()}, ord++));
138
139 SearchTrait st;
140 CGAL::spatial_sort(cdt_points.begin(), cdt_points.end(), st);
142 for (const auto& p : cdt_points) {
143 auto handle = cdt.insert(p.first,
f);
144 handle->info() = p.second;
145 vertices_handle[p.second] = handle;
147 }
148
149
150 for (
const HalfEdge &edge : constrained_half_edges)
151 cdt.insert_constraint(vertices_handle[edge.first], vertices_handle[edge.second]);
152 }
153
154 auto faces = cdt.finite_face_handles();
155
156
157 size_t num_faces = 0;
158 for (CDT::Face_handle fh : faces) {
159 for (int i = 0; i < 3; ++i) {
160 if (!fh->is_constrained(i)) continue;
161 auto key = std::make_pair(fh->vertex((i + 2) % 3)->info(), fh->vertex((i + 1) % 3)->info());
162 auto it = std::lower_bound(constrained_half_edges.begin(), constrained_half_edges.end(), key);
163 if (it == constrained_half_edges.end() || *it != key) continue;
164
165 for (int j = 0; j < 3; ++ j)
166 fh->set_constraint(j, false);
167 --num_faces;
168 break;
169 }
170 ++num_faces;
171 }
172
173 auto inside = [](CDT::Face_handle &fh) {
174 return fh->neighbor(0) != fh &&
175 (fh->is_constrained(0) ||
176 fh->is_constrained(1) ||
177 fh->is_constrained(2));
178 };
179
180#ifdef VISUALIZE_TRIANGULATION
181 std::vector<Vec3i32> indices2;
182 indices2.reserve(num_faces);
183 for (CDT::Face_handle fh : faces)
184 if (
inside(fh)) indices2.emplace_back(fh->vertex(0)->info(), fh->vertex(1)->info(), fh->vertex(2)->info());
185 visualize(points, indices2, "C:/data/temp/triangulation_without_floodfill.obj");
186#endif
187
188
189 std::vector<CDT::Face_handle> queue;
190 queue.reserve(num_faces);
191 for (CDT::Face_handle seed : faces){
192 if (!
inside(seed))
continue;
193
194 queue.emplace_back(seed);
195 while (! queue.empty()) {
196 CDT::Face_handle fh = queue.back();
197 queue.pop_back();
198 for (int i = 0; i < 3; ++i) {
199 if (fh->is_constrained(i)) continue;
200
201 fh->set_constraint(i, true);
202 CDT::Face_handle nh = fh->neighbor(i);
203 bool was_inside =
inside(nh);
204
205 nh->set_constraint(nh->index(fh), true);
206 if (! was_inside)
207 queue.push_back(nh);
208 }
209 }
210 }
211
212 std::vector<Vec3i32> indices;
213 indices.reserve(num_faces);
214 for (CDT::Face_handle fh : faces)
216 indices.emplace_back(fh->vertex(0)->info(), fh->vertex(1)->info(), fh->vertex(2)->info());
217
218#ifdef VISUALIZE_TRIANGULATION
219 visualize(points, indices, "C:/data/temp/triangulation.obj");
220#endif
221
222 return indices;
223}
std::pair< uint32_t, uint32_t > HalfEdge
Definition Triangulation.hpp:20
bool inside(const Polygons &polygons, const Point &p)
Definition TreeNode.cpp:160
CGAL::Simple_cartesian< double > K
Definition VoronoiUtilsCgal.cpp:49
static double f(double x, double z_sin, double z_cos, bool vertical, bool flip)
Definition FillGyroid.cpp:124
bool has_bidirectional_constrained(const Triangulation::HalfEdges &constrained)
Definition Triangulation.cpp:55
bool has_self_intersection(const Points &points, const Triangulation::HalfEdges &constrained_half_edges)
Definition Triangulation.cpp:74
bool is_unique(const Points &points)
Definition Triangulation.cpp:67