1 // Copyright (c) 2009, 2014 INRIA Sophia-Antipolis (France).
2 // Copyright (c) 2017 GeometryFactory (France).
3 // All rights reserved.
4 //
5 // This file is part of CGAL (www.cgal.org).
6 //
7 // $URL: https://github.com/CGAL/cgal/blob/v5.3/Periodic_3_mesh_3/include/CGAL/make_periodic_3_mesh_3.h $
8 // $Id: make_periodic_3_mesh_3.h 0779373 2020-03-26T13:31:46+01:00 Sébastien Loriot
9 // SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-Commercial
10 //
11 // Author(s)     : Stéphane Tayeb,
12 //                 Mikhail Bogdanov,
13 //                 Mael Rouxel-Labbé
14 //
15 //******************************************************************************
16 // File Description : make_periodic_3_mesh_3 function definition.
17 //******************************************************************************
18 
19 #ifndef CGAL_PERIODIC_3_MESH_3_MAKE_PERIODIC_3_MESH_3_H
20 #define CGAL_PERIODIC_3_MESH_3_MAKE_PERIODIC_3_MESH_3_H
21 
22 #include <CGAL/license/Periodic_3_mesh_3.h>
23 
24 #include <CGAL/Periodic_3_mesh_3/config.h>
25 #include <CGAL/Periodic_3_mesh_3/Protect_edges_sizing_field.h>
26 #include <CGAL/refine_periodic_3_mesh_3.h>
27 
28 #include <CGAL/assertions.h>
29 #include <CGAL/boost/parameter.h>
30 #include <CGAL/make_mesh_3.h>
31 #include <CGAL/Mesh_3/C3T3_helpers.h>
32 
33 #include <boost/parameter/preprocessor.hpp>
34 
35 namespace CGAL {
36 namespace Periodic_3_mesh_3 {
37 namespace internal {
38 
39 template<typename C3T3>
mark_dummy_points(C3T3 & c3t3)40 void mark_dummy_points(C3T3& c3t3)
41 {
42   CGAL_precondition(c3t3.triangulation().is_1_cover());
43 
44   typedef typename C3T3::Triangulation::Vertex_iterator       Vertex_iterator;
45 
46   for(Vertex_iterator vit = c3t3.triangulation().vertices_begin();
47                       vit != c3t3.triangulation().vertices_end(); ++vit)
48   {
49     c3t3.set_index(vit, 0);
50   }
51 }
52 
53 template <typename C3T3, typename MeshDomain, typename MeshCriteria>
54 void init_c3t3_with_features(C3T3& c3t3,
55                              const MeshDomain& domain,
56                              const MeshCriteria& criteria,
57                              bool nonlinear = false)
58 {
59   typedef typename MeshCriteria::Edge_criteria                                Edge_criteria;
60   typedef Mesh_3::internal::Edge_criteria_sizing_field_wrapper<Edge_criteria> Sizing_field;
61 
62   CGAL::Periodic_3_mesh_3::Protect_edges_sizing_field<C3T3, MeshDomain, Sizing_field>
63     protect_edges(c3t3, domain, Sizing_field(criteria.edge_criteria_object()));
64   protect_edges.set_nonlinear_growth_of_balls(nonlinear);
65 
66   protect_edges(true);
67 }
68 
69 // C3t3_initializer: initialize c3t3
70 template <typename C3T3,
71           typename MeshDomain,
72           typename MeshCriteria,
73           bool MeshDomainHasHasFeatures,
74           typename HasFeatures = int>
75 struct C3t3_initializer_base
76   : public CGAL::Mesh_3::internal::C3t3_initializer<
77       C3T3, MeshDomain, MeshCriteria, MeshDomainHasHasFeatures, HasFeatures>
78 {
79   typedef CGAL::Mesh_3::internal::C3t3_initializer<
80             C3T3, MeshDomain, MeshCriteria,
81             MeshDomainHasHasFeatures, HasFeatures>              Base;
82 
operatorC3t3_initializer_base83   void operator()(C3T3& c3t3,
84                   const MeshDomain& domain,
85                   const MeshCriteria& criteria,
86                   bool with_features,
87                   const parameters::internal::Mesh_3_options& mesh_options)
88   {
89     c3t3.triangulation().set_domain(domain.bounding_box());
90     c3t3.triangulation().insert_dummy_points();
91     mark_dummy_points(c3t3);
92 
93     // Call the basic initialization from c3t3, which handles features and
94     // adds a bunch of points on the surface
95     Base::operator()(c3t3, domain, criteria, with_features, mesh_options);
96   }
97 };
98 
99 template <typename C3T3,
100           typename MeshDomain,
101           typename MeshCriteria,
102           bool MeshDomainHasHasFeatures,
103           typename HasFeatures = int>
104 struct C3t3_initializer
105   : public C3t3_initializer_base<C3T3, MeshDomain, MeshCriteria, MeshDomainHasHasFeatures, HasFeatures>
106 {
107   typedef C3t3_initializer_base<C3T3, MeshDomain, MeshCriteria,
108                                 MeshDomainHasHasFeatures, HasFeatures> Base;
109 
operatorC3t3_initializer110   void operator()(C3T3& c3t3, const MeshDomain& domain, const MeshCriteria& criteria,
111                   bool with_features,
112                   const parameters::internal::Mesh_3_options& mesh_options)
113   {
114     return Base::operator()(c3t3, domain, criteria, with_features, mesh_options);
115   }
116 };
117 
118 // Specialization when the mesh domain has 'Has_features'
119 template <typename C3T3,
120           typename MeshDomain,
121           typename MeshCriteria,
122           typename HasFeatures>
123 struct C3t3_initializer<C3T3, MeshDomain, MeshCriteria, true, HasFeatures>
124 {
125   void operator()(C3T3& c3t3, const MeshDomain& domain, const MeshCriteria& criteria,
126                   bool with_features,
127                   const parameters::internal::Mesh_3_options& mesh_options)
128   {
129     C3t3_initializer<C3T3, MeshDomain, MeshCriteria, true, typename MeshDomain::Has_features>()
130         (c3t3, domain, criteria, with_features, mesh_options);
131   }
132 };
133 
134 // Specialization when the mesh domain has 'Has_features' and it's set to CGAL::Tag_true
135 template < typename C3T3,
136            typename MeshDomain,
137            typename MeshCriteria>
138 struct C3t3_initializer<C3T3, MeshDomain, MeshCriteria, true, CGAL::Tag_true>
139   : public C3t3_initializer_base<C3T3, MeshDomain, MeshCriteria, true, CGAL::Tag_true>
140 {
141   typedef C3t3_initializer_base<C3T3, MeshDomain, MeshCriteria, true, CGAL::Tag_true> Base;
142 
143   virtual ~C3t3_initializer() { }
144 
145   // this override will be used when initialize_features() is called, in make_mesh_3.h
146   virtual void
147   initialize_features(C3T3& c3t3,
148                       const MeshDomain& domain,
149                       const MeshCriteria& criteria,
150                       const parameters::internal::Mesh_3_options& mesh_options)
151   {
152     return Periodic_3_mesh_3::internal::init_c3t3_with_features
153       (c3t3, domain, criteria, mesh_options.nonlinear_growth_of_balls);
154   }
155 
156   void operator()(C3T3& c3t3, const MeshDomain& domain, const MeshCriteria& criteria,
157                   bool with_features,
158                   const parameters::internal::Mesh_3_options& mesh_options)
159   {
160     return Base::operator()(c3t3, domain, criteria, with_features, mesh_options);
161   }
162 };
163 
164 } // namespace internal
165 } // namespace Periodic_3_mesh_3
166 
167 // -----------------------------------
168 // make_periodic_3_mesh_3 stuff
169 // -----------------------------------
170 
171 // Manual redirections
172 // boost::parameter can't handle make_periodic_3_mesh_3 return_type alone...
173 template <typename C3T3, typename MD, typename MC, typename ... T>
174 C3T3 make_periodic_3_mesh_3(const MD& md, const MC& mc, const T& ...t)
175 {
176   C3T3 c3t3;
177   make_periodic_3_mesh_3_bp(c3t3,md,mc,t...);
178   return c3t3;
179 }
180 
181 #if defined(BOOST_MSVC)
182 #  pragma warning(push)
183 #  pragma warning(disable:4003) // not enough actual parameters for macro
184 #endif
185 
186 // see <CGAL/config.h>
187 CGAL_PRAGMA_DIAG_PUSH
188 // see <CGAL/boost/parameter.h>
189 CGAL_IGNORE_BOOST_PARAMETER_NAME_WARNINGS
190 
191 BOOST_PARAMETER_FUNCTION(
192   (void),
193   make_periodic_3_mesh_3_bp,
194   parameters::tag,
195   (required (in_out(c3t3),*) (domain,*) (criteria,*) ) // nondeduced
196   (deduced
197    (optional
198     (features_param, (parameters::internal::Features_options), parameters::features(domain))
199     (exude_param, (parameters::internal::Exude_options), parameters::exude())
200     (perturb_param, (parameters::internal::Perturb_options), parameters::perturb())
201     (odt_param, (parameters::internal::Odt_options), parameters::no_odt())
202     (lloyd_param, (parameters::internal::Lloyd_options), parameters::no_lloyd())
203     (mesh_options_param, (parameters::internal::Mesh_3_options),
204                          parameters::internal::Mesh_3_options())
205     (manifold_options_param, (parameters::internal::Manifold_options),
206                              parameters::internal::Manifold_options())
207     )
208    )
209   )
210 {
211   make_periodic_3_mesh_3_impl(c3t3, domain, criteria,
212                               exude_param, perturb_param, odt_param, lloyd_param,
213                               features_param.features(), mesh_options_param,
214                               manifold_options_param);
215 }
216 CGAL_PRAGMA_DIAG_POP
217 
218 #if defined(BOOST_MSVC)
219 #  pragma warning(pop)
220 #endif
221 
222 /**
223  * @brief This function meshes the domain defined by mesh_traits
224  * (respecting criteria), and outputs the mesh to c3t3
225  *
226  * @param domain the domain to be discretized
227  * @param criteria the criteria
228  * @param exude if it is set to \c true, an exudation step will be done at
229  *   the end of the Delaunay refinement process
230  *
231  * @return The mesh as a C3T3 object
232  */
233 template<class C3T3, class MeshDomain, class MeshCriteria>
234 void make_periodic_3_mesh_3_impl(C3T3& c3t3,
235                                  const MeshDomain& domain,
236                                  const MeshCriteria& criteria,
237                                  const parameters::internal::Exude_options& exude,
238                                  const parameters::internal::Perturb_options& perturb,
239                                  const parameters::internal::Odt_options& odt,
240                                  const parameters::internal::Lloyd_options& lloyd,
241                                  const bool with_features,
242                                  const parameters::internal::Mesh_3_options&
243                                    mesh_options = parameters::internal::Mesh_3_options(),
244                                  const parameters::internal::Manifold_options&
245                                    manifold_options = parameters::internal::Manifold_options())
246 {
247   // Initialize c3t3
248   Periodic_3_mesh_3::internal::C3t3_initializer<
249     C3T3, MeshDomain, MeshCriteria,
250     Mesh_3::internal::has_Has_features<MeshDomain>::value>()(c3t3,
251                                                              domain,
252                                                              criteria,
253                                                              with_features,
254                                                              mesh_options);
255 
256   // Build mesher and launch refinement process
257   refine_periodic_3_mesh_3(c3t3, domain, criteria,
258                            exude, perturb, odt, lloyd,
259                            parameters::no_reset_c3t3(), // do not reset c3t3 as we just created it
260                            mesh_options, manifold_options);
261 }
262 
263 } // end namespace CGAL
264 
265 #endif // CGAL_PERIODIC_3_MESH_3_MAKE_PERIODIC_3_MESH_3_H
266