1
+ // Copyright (c) 2015,2016 GeometryFactory
2
+ // All rights reserved.
3
+ //
4
+ // This file is part of CGAL (www.cgal.org).
5
+ //
6
+ // $URL: https://github.com/CGAL/cgal/blob/releases/CGAL-5.0-I-190/Mesh_3/include/CGAL/Mesh_3/initialize_triangulation_from_labeled_image.h $
7
+ // $Id: initialize_triangulation_from_labeled_image.h 254d60f 2019-10-19T15:23:19+02:00 Sébastien Loriot
8
+ // SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-Commercial
9
+ //
10
+ //
11
+ // Author(s) : Laurent Rineau
12
+ #ifndef CGAL_MESH_3_INITIALIZE_TRIANGULATION_FROM_LABELED_IMAGE_H
13
+ #define CGAL_MESH_3_INITIALIZE_TRIANGULATION_FROM_LABELED_IMAGE_H
14
+ #include < CGAL/license/Mesh_3.h>
15
+ #include < CGAL/Mesh_3/search_for_connected_components_in_labeled_image.h>
16
+ #include < CGAL/Mesh_3/squared_distance_Point_3_Triangle_3.h>
17
+ #include < CGAL/make_mesh_3.h>
18
+ #include < CGAL/enum.h>
19
+ #include < CGAL/iterator.h>
20
+ #include < CGAL/point_generators_3.h>
21
+ #include < CGAL/Image_3.h>
22
+ #include < iostream>
23
+ #include < queue>
24
+ template <typename Point >
25
+ struct Get_point
26
+ {
27
+ const double vx, vy, vz;
28
+ Get_point (const CGAL::Image_3* image)
29
+ : vx(image->vx ())
30
+ , vy(image->vy ())
31
+ , vz(image->vz ())
32
+ {}
33
+ Point operator ()(const std::size_t i,
34
+ const std::size_t j,
35
+ const std::size_t k) const
36
+ {
37
+ return Point (double (i) * vx, double (j) * vy, double (k) * vz);
38
+ }
39
+ };
40
+ template <class C3T3 , class MeshDomain , class MeshCriteria >
41
+ void init_tr_from_labeled_image_call_init_features (C3T3&,
42
+ const MeshDomain&,
43
+ const MeshCriteria&,
44
+ CGAL::Tag_false)
45
+ {
46
+ }
47
+ template <class C3T3 , class MeshDomain , class MeshCriteria >
48
+ void init_tr_from_labeled_image_call_init_features (C3T3& c3t3,
49
+ const MeshDomain& domain,
50
+ const MeshCriteria& criteria,
51
+ CGAL::Tag_true)
52
+ {
53
+ CGAL::Mesh_3::internal::init_c3t3_with_features (c3t3,
54
+ domain,
55
+ criteria);
56
+ std::cout << c3t3.triangulation ().number_of_vertices ()
57
+ << " initial points on 1D-features" << std::endl;
58
+ }
59
+ template <class C3T3 , class MeshDomain , class MeshCriteria ,
60
+ typename Image_word_type>
61
+ void initialize_triangulation_from_labeled_image (C3T3& c3t3,
62
+ const MeshDomain& domain,
63
+ const CGAL::Image_3& image,
64
+ const MeshCriteria& criteria,
65
+ Image_word_type,
66
+ bool protect_features = false
67
+ )
68
+ {
69
+ typedef typename C3T3::Triangulation Tr;
70
+ typedef typename Tr::Geom_traits Gt;
71
+ typedef typename Gt::FT FT;
72
+ typedef typename Tr::Weighted_point Weighted_point;
73
+ typedef typename Tr::Bare_point Bare_point;
74
+ typedef typename Tr::Segment Segment_3;
75
+ typedef typename Tr::Vertex_handle Vertex_handle;
76
+ typedef typename Tr::Cell_handle Cell_handle;
77
+ typedef typename Gt::Vector_3 Vector_3;
78
+ typedef MeshDomain Mesh_domain;
79
+ Tr& tr = c3t3.triangulation ();
80
+ typename Gt::Compare_weighted_squared_radius_3 cwsr =
81
+ tr.geom_traits ().compare_weighted_squared_radius_3_object ();
82
+ typename Gt::Construct_point_3 cp =
83
+ tr.geom_traits ().construct_point_3_object ();
84
+ typename Gt::Construct_weighted_point_3 cwp =
85
+ tr.geom_traits ().construct_weighted_point_3_object ();
86
+ if (protect_features) {
87
+ init_tr_from_labeled_image_call_init_features
88
+ (c3t3, domain, criteria,
89
+ CGAL::Mesh_3::internal::Has_features<Mesh_domain>());
90
+ }
91
+ const double max_v = (std::max)((std::max)(image.vx (),
92
+ image.vy ()),
93
+ image.vz ());
94
+ typedef std::vector<std::pair<Bare_point, std::size_t > > Seeds;
95
+ Seeds seeds;
96
+ Get_point<Bare_point> get_point (&image);
97
+ std::cout << " Searching for connected components..." << std::endl;
98
+ CGAL::Identity<Image_word_type> no_transformation;
99
+ search_for_connected_components_in_labeled_image (image,
100
+ std::back_inserter (seeds),
101
+ CGAL::Emptyset_iterator (),
102
+ no_transformation,
103
+ get_point,
104
+ Image_word_type ());
105
+ std::cout << " " << seeds.size () << " components were found." << std::endl;
106
+ std::cout << " Construct initial points..." << std::endl;
107
+ for (typename Seeds::const_iterator it = seeds.begin (), end = seeds.end ();
108
+ it != end; ++it)
109
+ {
110
+ const double radius = double (it->second + 1 )* max_v;
111
+ CGAL::Random_points_on_sphere_3<Bare_point> points_on_sphere_3 (radius);
112
+ typename Mesh_domain::Construct_intersection construct_intersection =
113
+ domain.construct_intersection_object ();
114
+ std::vector<Vector_3> directions;
115
+ if (it->second < 2 ) {
116
+ // shoot in six directions
117
+ directions.push_back (Vector_3 (-radius, 0 , 0 ));
118
+ directions.push_back (Vector_3 (+radius, 0 , 0 ));
119
+ directions.push_back (Vector_3 (0 , -radius, 0 ));
120
+ directions.push_back (Vector_3 (0 , +radius, 0 ));
121
+ directions.push_back (Vector_3 (0 , 0 , -radius));
122
+ directions.push_back (Vector_3 (0 , 0 , +radius));
123
+ }
124
+ else {
125
+ for (int i = 0 ; i < 20 ; ++i)
126
+ {
127
+ // shoot 20 random directions
128
+ directions.push_back (*points_on_sphere_3++ - CGAL::ORIGIN);
129
+ }
130
+ }
131
+ for (const Vector_3& v : directions)
132
+ {
133
+ const Bare_point test = it->first + v;
134
+ const typename Mesh_domain::Intersection intersect =
135
+ construct_intersection (Segment_3 (it->first , test));
136
+ if (std::get<2 >(intersect) != 0 )
137
+ {
138
+ const Bare_point& bpi = std::get<0 >(intersect);
139
+ Weighted_point pi = cwp (bpi);
140
+ // This would cause trouble to optimizers
141
+ // check pi will not be hidden
142
+ typename Tr::Locate_type lt;
143
+ int li, lj;
144
+ Cell_handle pi_cell = tr.locate (pi , lt, li, lj);
145
+ if (lt != Tr::OUTSIDE_AFFINE_HULL) {
146
+ switch (tr.dimension ())
147
+ { // skip dimension 0
148
+ case 1 :
149
+ if (tr.side_of_power_segment (pi_cell, pi , true ) != CGAL::ON_BOUNDED_SIDE)
150
+ continue ;
151
+ break ;
152
+ case 2 :
153
+ if (tr.side_of_power_circle (pi_cell, 3 , pi , true ) != CGAL::ON_BOUNDED_SIDE)
154
+ continue ;
155
+ break ;
156
+ case 3 :
157
+ if (tr.side_of_power_sphere (pi_cell, pi , true ) != CGAL::ON_BOUNDED_SIDE)
158
+ continue ;
159
+ }
160
+ }
161
+ // check pi is not inside a protecting ball
162
+ std::vector<Vertex_handle> conflict_vertices;
163
+ if (tr.dimension () == 3 )
164
+ {
165
+ tr.vertices_on_conflict_zone_boundary (pi , pi_cell
166
+ , std::back_inserter (conflict_vertices));
167
+ }
168
+ else
169
+ {
170
+ for (typename Tr::Finite_vertices_iterator vit = tr.finite_vertices_begin ();
171
+ vit != tr.finite_vertices_end (); ++vit)
172
+ {
173
+ const Weighted_point& wp = tr.point (vit);
174
+ if (cwsr (wp, FT (0 )) == CGAL::SMALLER) // 0 < wp's weight
175
+ conflict_vertices.push_back (vit);
176
+ }
177
+ }
178
+ bool pi_inside_protecting_sphere = false ;
179
+ for (Vertex_handle cv : conflict_vertices)
180
+ {
181
+ if (tr.is_infinite (cv))
182
+ continue ;
183
+ const Weighted_point& cv_wp = tr.point (cv);
184
+ if (cwsr (cv_wp, FT (0 )) == CGAL::EQUAL) // 0 == wp's weight
185
+ continue ;
186
+ // if the (squared) distance between bpi and cv is smaller or equal than cv's weight
187
+ if (cwsr (cv_wp, -tr.min_squared_distance (bpi, cp (cv_wp))) != CGAL::LARGER)
188
+ {
189
+ pi_inside_protecting_sphere = true ;
190
+ break ;
191
+ }
192
+ }
193
+ if (pi_inside_protecting_sphere)
194
+ continue ;
195
+ const typename Mesh_domain::Index index = std::get<1 >(intersect);
196
+ Vertex_handle v = tr.insert (pi );
197
+ // `v` could be null if `pi` is hidden by other vertices of `tr`.
198
+ CGAL_assertion (v != Vertex_handle ());
199
+ c3t3.set_dimension (v, 2 ); // by construction, points are on surface
200
+ c3t3.set_index (v, index );
201
+ }
202
+ // else
203
+ // {
204
+ // std::cerr <<
205
+ // boost::format("Error. Segment (%1%, %2%) does not intersect the surface!\n")
206
+ // % it->first % test;
207
+ // }
208
+ }
209
+ }
210
+ std::cout << " " << tr.number_of_vertices () << " initial points." << std::endl;
211
+ if (c3t3.triangulation ().dimension () != 3 )
212
+ {
213
+ std::cout << " not enough points: triangulation.dimension() == "
214
+ << c3t3.triangulation ().dimension () << std::endl;
215
+ CGAL::Mesh_3::internal::init_c3t3 (c3t3, domain, criteria, 20 );
216
+ std::cout << " -> " << tr.number_of_vertices () << " initial points." << std::endl;
217
+ }
218
+ }
219
+ #endif // CGAL_MESH_3_INITIALIZE_TRIANGULATION_FROM_LABELED_IMAGE_H
0 commit comments