RINGMesh  Version 5.0.0
A programming library for geological model meshes
test-connected-components.cpp
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2012-2017, Association Scientifique pour la Geologie et ses
3  * Applications (ASGA). All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions are met:
7  * * Redistributions of source code must retain the above copyright
8  * notice, this list of conditions and the following disclaimer.
9  * * Redistributions in binary form must reproduce the above copyright
10  * notice, this list of conditions and the following disclaimer in the
11  * documentation and/or other materials provided with the distribution.
12  * * Neither the name of ASGA nor the
13  * names of its contributors may be used to endorse or promote products
14  * derived from this software without specific prior written permission.
15  *
16  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
17  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
18  * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
19  * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL ASGA BE LIABLE FOR ANY DIRECT,
20  * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
25  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26  *
27  * http://www.ring-team.org
28  *
29  * RING Project
30  * Ecole Nationale Superieure de Geologie - GeoRessources
31  * 2 Rue du Doyen Marcel Roubault - TSA 70605
32  * 54518 VANDOEUVRE-LES-NANCY
33  * FRANCE
34  */
35 
36 #include <ringmesh/ringmesh_tests_config.h>
37 
38 #include <vector>
39 
40 #include <ringmesh/mesh/mesh.h>
42 
47 using namespace RINGMesh;
48 
49 namespace
50 {
51  void point_set_mesh_connected_component_test()
52  {
53  auto point_set = PointSetMesh3D::create_mesh();
54  auto point_set_builder =
55  PointSetMeshBuilder3D::create_builder( *point_set );
56 
57  index_t nb_connected_components{ NO_ID };
58  std::vector< index_t > connected_components;
59  std::tie( nb_connected_components, connected_components ) =
60  point_set->connected_components();
61  if( nb_connected_components != 0 || connected_components.size() != 0 )
62  {
63  throw RINGMeshException( "RINGMesh Test",
64  "Point set should have 0 connected component." );
65  }
66  const index_t max_itr{ 5 };
67  for( auto i : range( 1, max_itr + 1 ) )
68  {
69  point_set_builder->create_vertex( { static_cast< double >( i ),
70  static_cast< double >( i ), static_cast< double >( i ) } );
71  nb_connected_components = NO_ID;
72  connected_components.clear();
73  std::tie( nb_connected_components, connected_components ) =
74  point_set->connected_components();
75  if( nb_connected_components != i
76  || connected_components.size() != i )
77  {
78  throw RINGMeshException( "RINGMesh Test",
79  "Point set should have ", i, " connected components." );
80  }
81 
82  std::vector< index_t > solution( i );
83  std::iota( solution.begin(), solution.end(), 0 );
84  if( connected_components != solution )
85  {
86  throw RINGMeshException( "RINGMesh Test",
87  "Point set connected components are not correct." );
88  }
89  }
90  }
91 
92  void line_mesh_connected_component_test()
93  {
94  auto line_mesh = LineMesh3D::create_mesh();
95  auto line_mesh_builder =
96  LineMeshBuilder3D::create_builder( *line_mesh );
97 
98  index_t nb_connected_components{ NO_ID };
99  std::vector< index_t > connected_components;
100  std::tie( nb_connected_components, connected_components ) =
101  line_mesh->connected_components();
102  if( nb_connected_components != 0 || connected_components.size() != 0 )
103  {
104  throw RINGMeshException( "RINGMesh Test",
105  "Line mesh should have 0 connected component." );
106  }
107 
108  nb_connected_components = NO_ID;
109  auto v0 = line_mesh_builder->create_vertex( { 0., 0., 0. } );
110  auto v1 = line_mesh_builder->create_vertex( { 0., 0., 1. } );
111  line_mesh_builder->create_edge( v0, v1 );
112  std::tie( nb_connected_components, connected_components ) =
113  line_mesh->connected_components();
114  std::vector< index_t > solution( 1, 0 );
115  if( nb_connected_components != 1 || connected_components != solution )
116  {
117  throw RINGMeshException( "RINGMesh Test",
118  "Line mesh should have 1 connected component with index 0." );
119  }
120 
121  nb_connected_components = NO_ID;
122  auto v2 = line_mesh_builder->create_vertex( { 0., 0., 2. } );
123  line_mesh_builder->create_edge( v1, v2 );
124  std::tie( nb_connected_components, connected_components ) =
125  line_mesh->connected_components();
126  solution.push_back( 0 );
127  if( nb_connected_components != 1 || connected_components != solution )
128  {
129  throw RINGMeshException( "RINGMesh Test",
130  "Line mesh should have 1 connected component with index 0." );
131  }
132 
133  nb_connected_components = NO_ID;
134  auto v3 = line_mesh_builder->create_vertex( { 0., 0., 3. } );
135  auto v4 = line_mesh_builder->create_vertex( { 0., 0., 4. } );
136  line_mesh_builder->create_edge( v3, v4 );
137  std::tie( nb_connected_components, connected_components ) =
138  line_mesh->connected_components();
139  solution.push_back( 1 );
140  if( nb_connected_components != 2 || connected_components != solution )
141  {
142  throw RINGMeshException( "RINGMesh Test",
143  "Line mesh should have 2 connected components: 0 0 1." );
144  }
145 
146  nb_connected_components = NO_ID;
147  auto v5 = line_mesh_builder->create_vertex( { 1., 0., 0. } );
148  line_mesh_builder->create_edge( v5, v0 );
149  std::tie( nb_connected_components, connected_components ) =
150  line_mesh->connected_components();
151  solution.push_back( 0 );
152  if( nb_connected_components != 2 || connected_components != solution )
153  {
154  throw RINGMeshException( "RINGMesh Test",
155  "Line mesh should have 2 connected components: 0 0 1 0." );
156  }
157 
158  nb_connected_components = NO_ID;
159  auto v6 = line_mesh_builder->create_vertex( { 0., 0., 5. } );
160  auto v7 = line_mesh_builder->create_vertex( { 0., 0., 6. } );
161  line_mesh_builder->create_edge( v6, v7 );
162  line_mesh_builder->create_edge( v4, v6 );
163  std::tie( nb_connected_components, connected_components ) =
164  line_mesh->connected_components();
165  solution.push_back( 1 );
166  solution.push_back( 1 );
167  if( nb_connected_components != 2 || connected_components != solution )
168  {
169  throw RINGMeshException( "RINGMesh Test",
170  "Line mesh should have 2 connected components: 0 0 1 0 1 1." );
171  }
172 
173  nb_connected_components = NO_ID;
174  line_mesh_builder->create_edge( v2, v3 );
175  std::tie( nb_connected_components, connected_components ) =
176  line_mesh->connected_components();
177  solution[2] = 0;
178  solution[4] = 0;
179  solution[5] = 0;
180  solution.push_back( 0 );
181  if( nb_connected_components != 1 || connected_components != solution )
182  {
183  throw RINGMeshException( "RINGMesh Test",
184  "Line mesh should have 1 connected component: 0 0 0 0 0 0 0." );
185  }
186 
187  nb_connected_components = NO_ID;
188  auto v8 = line_mesh_builder->create_vertex( { 0., 0., 7. } );
189  auto v9 = line_mesh_builder->create_vertex( { 0., 0., 8. } );
190  line_mesh_builder->create_edge( v8, v9 );
191  auto v10 = line_mesh_builder->create_vertex( { 0., 0., 9. } );
192  auto v11 = line_mesh_builder->create_vertex( { 0., 0., 10. } );
193  line_mesh_builder->create_edge( v10, v11 );
194  line_mesh_builder->create_edge( v7, v8 );
195  std::tie( nb_connected_components, connected_components ) =
196  line_mesh->connected_components();
197  solution.push_back( 0 );
198  solution.push_back( 1 );
199  solution.push_back( 0 );
200  if( nb_connected_components != 2 || connected_components != solution )
201  {
202  throw RINGMeshException( "RINGMesh Test", "Line mesh should have 2 "
203  "connected components: 0 "
204  "0 0 0 0 0 0 0 1 0." );
205  }
206  }
207 
208  void update_polygon_adjacencies_after_adding_a_new_polygon(
209  SurfaceMeshBuilder3D& surface_mesh_builder, index_t new_polygon_id )
210  {
211  surface_mesh_builder.set_polygon_adjacent(
212  { new_polygon_id, 0 }, NO_ID );
213  surface_mesh_builder.set_polygon_adjacent(
214  { new_polygon_id, 1 }, NO_ID );
215  surface_mesh_builder.set_polygon_adjacent(
216  { new_polygon_id, 2 }, NO_ID );
217  surface_mesh_builder.connect_polygons();
218  surface_mesh_builder.repair(
219  GEO::MESH_REPAIR_TOPOLOGY, global_epsilon );
220  }
221 
222  void surface_mesh_connected_component_test()
223  {
224  auto surface_mesh = SurfaceMesh3D::create_mesh();
225  auto surface_mesh_builder =
226  SurfaceMeshBuilder3D::create_builder( *surface_mesh );
227 
228  index_t nb_connected_components{ NO_ID };
229  std::vector< index_t > connected_components;
230  std::tie( nb_connected_components, connected_components ) =
231  surface_mesh->connected_components();
232  if( nb_connected_components != 0 || connected_components.size() != 0 )
233  {
234  throw RINGMeshException( "RINGMesh Test",
235  "Surface mesh should have 0 connected component." );
236  }
237 
238  nb_connected_components = NO_ID;
239  std::vector< index_t > polygon_vertices = {
240  surface_mesh_builder->create_vertex( { 0., 0., 0. } ),
241  surface_mesh_builder->create_vertex( { 1., 0., 0. } ),
242  surface_mesh_builder->create_vertex( { 0., 1., 0. } )
243  };
244  auto polygon_id =
245  surface_mesh_builder->create_polygon( polygon_vertices );
246  update_polygon_adjacencies_after_adding_a_new_polygon(
247  *surface_mesh_builder, polygon_id );
248  std::tie( nb_connected_components, connected_components ) =
249  surface_mesh->connected_components();
250  std::vector< index_t > solution( 1, 0 );
251  if( nb_connected_components != 1 || connected_components != solution )
252  {
253  throw RINGMeshException(
254  "RINGMesh Test", "Surface mesh should have 1 connected "
255  "component with an index at 0." );
256  }
257 
258  nb_connected_components = NO_ID;
259  polygon_vertices[0] =
260  surface_mesh_builder->create_vertex( { 1., 1., 1. } );
261  polygon_id = surface_mesh_builder->create_polygon( polygon_vertices );
262  update_polygon_adjacencies_after_adding_a_new_polygon(
263  *surface_mesh_builder, polygon_id );
264  polygon_vertices[0] =
265  surface_mesh_builder->create_vertex( { 5., 5., 0. } );
266  polygon_vertices[1] =
267  surface_mesh_builder->create_vertex( { 5., 6., 0. } );
268  polygon_vertices[2] =
269  surface_mesh_builder->create_vertex( { 6., 5., 0. } );
270  polygon_id = surface_mesh_builder->create_polygon( polygon_vertices );
271  update_polygon_adjacencies_after_adding_a_new_polygon(
272  *surface_mesh_builder, polygon_id );
273  std::tie( nb_connected_components, connected_components ) =
274  surface_mesh->connected_components();
275  solution.push_back( 0 );
276  solution.push_back( 1 );
277  if( nb_connected_components != 2 || connected_components != solution )
278  {
279  throw RINGMeshException(
280  "RINGMesh Test", "Surface mesh should have 2 connected "
281  "component with an index at 0 0 1." );
282  }
283  }
284 
285  void volume_mesh_connected_component_test()
286  {
287  auto volume_mesh = VolumeMesh3D::create_mesh();
288  auto volume_mesh_builder =
289  VolumeMeshBuilder3D::create_builder( *volume_mesh );
290 
291  index_t nb_connected_components{ NO_ID };
292  std::vector< index_t > connected_components;
293  std::tie( nb_connected_components, connected_components ) =
294  volume_mesh->connected_components();
295  if( nb_connected_components != 0 || connected_components.size() != 0 )
296  {
297  throw RINGMeshException( "RINGMesh Test",
298  "Volume mesh should have 0 connected component." );
299  }
300  }
301 
302  void run_tests()
303  {
304  point_set_mesh_connected_component_test();
305  line_mesh_connected_component_test();
306  surface_mesh_connected_component_test();
307  volume_mesh_connected_component_test();
308  }
309 }
310 
311 int main()
312 {
313  using namespace RINGMesh;
314 
315  try
316  {
318 
319  Logger::out( "TEST", "Test connected components" );
320  run_tests();
321  }
322  catch( const RINGMeshException& e )
323  {
324  Logger::err( e.category(), e.what() );
325  return 1;
326  }
327  catch( const std::exception& e )
328  {
329  Logger::err( "Exception", e.what() );
330  return 1;
331  }
332  Logger::out( "TEST", "SUCCESS" );
333  return 0;
334 }
void run_tests(GeoModel3D &geomodel)
static std::unique_ptr< VolumeMeshBuilder< DIMENSION > > create_builder(VolumeMesh< DIMENSION > &mesh)
static void err(const std::string &feature, const Args &... args)
Definition: logger.h:68
static void out(const std::string &feature, const Args &... args)
Definition: logger.h:61
const std::string & category() const
Definition: common.h:165
Classes to build GeoModel from various inputs.
Definition: algorithm.h:48
static std::unique_ptr< VolumeMesh< DIMENSION > > create_mesh(const MeshType type="")
Definition: mesh.cpp:582
void RINGMESH_API default_configure()
Definition: common.cpp:99