Branch data Line data Source code
1 : : /**
2 : : * MOAB, a Mesh-Oriented datABase, is a software component for creating,
3 : : * storing and accessing finite element mesh data.
4 : : *
5 : : * Copyright 2004 Sandia Corporation. Under the terms of Contract
6 : : * DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government
7 : : * retains certain rights in this software.
8 : : *
9 : : * This library is free software; you can redistribute it and/or
10 : : * modify it under the terms of the GNU Lesser General Public
11 : : * License as published by the Free Software Foundation; either
12 : : * version 2.1 of the License, or (at your option) any later version.
13 : : *
14 : : */
15 : :
16 : : #include "moab/GeomTopoTool.hpp"
17 : : #include "moab/GeomQueryTool.hpp"
18 : : #include "moab/OrientedBoxTreeTool.hpp"
19 : : #include "moab/Range.hpp"
20 : : #include "MBTagConventions.hpp"
21 : : #include "moab/Interface.hpp"
22 : : #include "moab/CN.hpp"
23 : : #include "moab/Skinner.hpp"
24 : : #include "Internals.hpp"
25 : : #include <iostream>
26 : :
27 : : namespace moab
28 : : {
29 : :
30 : : // Tag name used for saving sense of faces in volumes.
31 : : // We assume that the surface occurs in at most two volumes.
32 : : // Code will error out if more than two volumes per surface.
33 : : // The tag data is a pair of tag handles, representing the
34 : : // forward and reverse volumes, respectively. If a surface
35 : : // is non-manifold in a single volume, the same volume will
36 : : // be listed for both the forward and reverse slots.
37 : : const char GEOM_SENSE_2_TAG_NAME[] = "GEOM_SENSE_2";
38 : :
39 : : const char GEOM_SENSE_N_ENTS_TAG_NAME[] = "GEOM_SENSE_N_ENTS";
40 : : const char GEOM_SENSE_N_SENSES_TAG_NAME[] = "GEOM_SENSE_N_SENSES";
41 : : const char OBB_ROOT_TAG_NAME[] = "OBB_ROOT";
42 : : const char OBB_GSET_TAG_NAME[] = "OBB_GSET";
43 : :
44 : : const char IMPLICIT_COMPLEMENT_NAME[] = "impl_complement";
45 : :
46 : 202 : GeomTopoTool::GeomTopoTool( Interface* impl, bool find_geoments, EntityHandle modelRootSet, bool p_rootSets_vector,
47 : : bool restore_rootSets )
48 : : : mdbImpl( impl ), sense2Tag( 0 ), senseNEntsTag( 0 ), senseNSensesTag( 0 ), geomTag( 0 ), gidTag( 0 ),
49 : : obbRootTag( 0 ), obbGsetTag( 0 ), modelSet( modelRootSet ), updated( false ), setOffset( 0 ),
50 [ + - ][ + + ]: 1212 : m_rootSets_vector( p_rootSets_vector ), oneVolRootSet( 0 )
[ + - ][ + -
# # # # #
# ]
51 : : {
52 : :
53 [ + - ][ + - ]: 202 : obbTree = new OrientedBoxTreeTool( impl, NULL, true );
54 : :
55 : : ErrorCode rval =
56 [ + - ][ - + ]: 202 : mdbImpl->tag_get_handle( GEOM_DIMENSION_TAG_NAME, 1, MB_TYPE_INTEGER, geomTag, MB_TAG_CREAT | MB_TAG_SPARSE );MB_CHK_SET_ERR_CONT( rval, "Error: Failed to create geometry dimension tag" );
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ]
57 : :
58 : : // global id tag is not really needed, but mbsize complains if we do not set it for
59 : : // geometry entities
60 [ + - ]: 202 : gidTag = mdbImpl->globalId_tag();
61 : :
62 : : rval =
63 [ + - ][ - + ]: 202 : mdbImpl->tag_get_handle( NAME_TAG_NAME, NAME_TAG_SIZE, MB_TYPE_OPAQUE, nameTag, MB_TAG_CREAT | MB_TAG_SPARSE );MB_CHK_SET_ERR_CONT( rval, "Error: Failed to create name tag" );
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ]
64 : :
65 [ + - ][ - + ]: 202 : rval = mdbImpl->tag_get_handle( OBB_ROOT_TAG_NAME, 1, MB_TYPE_HANDLE, obbRootTag, MB_TAG_CREAT | MB_TAG_SPARSE );MB_CHK_SET_ERR_CONT( rval, "Error: Failed to create obb root tag" );
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ]
66 : :
67 [ + - ][ - + ]: 202 : rval = mdbImpl->tag_get_handle( OBB_GSET_TAG_NAME, 1, MB_TYPE_HANDLE, obbGsetTag, MB_TAG_CREAT | MB_TAG_SPARSE );MB_CHK_SET_ERR_CONT( rval, "Error: Failed to create obb gset tag" );
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ]
68 : :
69 : : // set this value to zero for comparisons
70 : 202 : impl_compl_handle = 0;
71 : :
72 : 202 : maxGlobalId[0] = maxGlobalId[1] = maxGlobalId[2] = maxGlobalId[3] = maxGlobalId[4] = 0;
73 [ + + ]: 202 : if( find_geoments )
74 : : {
75 [ + - ]: 20 : find_geomsets();
76 [ + + ]: 20 : if( restore_rootSets )
77 : : {
78 [ + - ]: 18 : rval = restore_obb_index();
79 [ + + ]: 18 : if( MB_SUCCESS != rval )
80 : : {
81 [ + - ][ - + ]: 13 : rval = delete_all_obb_trees();MB_CHK_SET_ERR_CONT( rval, "Error: Failed to delete existing obb trees" );
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ]
82 [ + - ][ - + ]: 20 : rval = construct_obb_trees();MB_CHK_SET_ERR_CONT( rval, "Error: Failed to rebuild obb trees" );
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ]
83 : : }
84 : : }
85 : : }
86 [ # # ]: 202 : }
87 : :
88 : 1407 : GeomTopoTool::~GeomTopoTool()
89 : : {
90 [ + - ]: 201 : delete obbTree;
91 [ + - ][ + + ]: 1206 : }
92 : :
93 : 5787 : int GeomTopoTool::dimension( EntityHandle this_set )
94 : : {
95 : : ErrorCode result;
96 [ - + ]: 5787 : if( 0 == geomTag )
97 : : {
98 [ # # ][ # # ]: 0 : result = mdbImpl->tag_get_handle( GEOM_DIMENSION_TAG_NAME, 1, MB_TYPE_INTEGER, geomTag );MB_CHK_SET_ERR( result, "Failed to get the geometry dimension tag" );
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ]
99 : : }
100 : :
101 : : // check if the geo set belongs to this model
102 [ + + ]: 5787 : if( modelSet )
103 : : {
104 [ + - ][ - + ]: 158 : if( !mdbImpl->contains_entities( modelSet, &this_set, 1 ) )
105 : : {
106 : : // this g set does not belong to the current model
107 : 0 : return -1;
108 : : }
109 : : }
110 : : // get the data for those tags
111 : : int dim;
112 [ + - ]: 5787 : result = mdbImpl->tag_get_data( geomTag, &this_set, 1, &dim );
113 [ - + ]: 5787 : if( MB_SUCCESS != result ) return -1;
114 : 5787 : return dim;
115 : : }
116 : :
117 : 0 : int GeomTopoTool::global_id( EntityHandle this_set )
118 : : {
119 : : ErrorCode result;
120 [ # # ][ # # ]: 0 : if( 0 == gidTag ) { gidTag = mdbImpl->globalId_tag(); }
121 : :
122 : : // check if the geo set belongs to this model
123 [ # # ]: 0 : if( modelSet )
124 : : {
125 [ # # ][ # # ]: 0 : if( !mdbImpl->contains_entities( modelSet, &this_set, 1 ) )
126 : : {
127 : : // this g set does not belong to the current model
128 : 0 : return -1;
129 : : }
130 : : }
131 : :
132 : : // get the data for those tags
133 : : int id;
134 [ # # ]: 0 : result = mdbImpl->tag_get_data( gidTag, &this_set, 1, &id );
135 [ # # ]: 0 : if( MB_SUCCESS != result ) return -1;
136 : 0 : return id;
137 : : }
138 : :
139 : 23 : EntityHandle GeomTopoTool::entity_by_id( int dimension1, int id )
140 : : {
141 [ - + ][ # # ]: 23 : if( 0 > dimension1 && 3 < dimension1 ) { MB_CHK_SET_ERR_CONT( MB_FAILURE, "Incorrect dimension provided" ); };
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ]
142 : 23 : const Tag tags[] = { gidTag, geomTag };
143 : 23 : const void* const vals[] = { &id, &dimension1 };
144 : : ErrorCode rval;
145 : :
146 [ + - ]: 23 : Range results;
147 [ + - ]: 23 : rval = mdbImpl->get_entities_by_type_and_tag( 0, MBENTITYSET, tags, vals, 2, results );
148 : :
149 [ - + ]: 23 : if( MB_SUCCESS != rval ) return 0;
150 : :
151 [ + - ]: 23 : return results.front();
152 : : }
153 : :
154 : 0 : ErrorCode GeomTopoTool::other_entity( EntityHandle bounded, EntityHandle not_this, EntityHandle across,
155 : : EntityHandle& other )
156 : : {
157 : 0 : other = 0;
158 : :
159 : : // get all children of bounded
160 [ # # ][ # # ]: 0 : Range bdy, tmpr;
161 [ # # ][ # # ]: 0 : ErrorCode rval = mdbImpl->get_child_meshsets( bounded, bdy );MB_CHK_SET_ERR( rval, "Failed to get the bounded entity's child meshsets" );
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ]
162 : :
163 : : // get all the parents of across
164 [ # # ]: 0 : rval = mdbImpl->get_parent_meshsets( across, tmpr );
165 : :
166 : : // possible candidates is the intersection
167 [ # # ][ # # ]: 0 : bdy = intersect( bdy, tmpr );
168 : :
169 : : // if only two, choose the other
170 [ # # ][ # # ]: 0 : if( 1 == bdy.size() && *bdy.begin() == not_this ) { return MB_SUCCESS; }
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
171 [ # # ][ # # ]: 0 : else if( 2 == bdy.size() )
172 : : {
173 [ # # ][ # # ]: 0 : if( *bdy.begin() == not_this ) other = *bdy.rbegin();
[ # # ][ # # ]
[ # # ]
174 [ # # ][ # # ]: 0 : if( *bdy.rbegin() == not_this )
[ # # ]
175 [ # # ][ # # ]: 0 : other = *bdy.begin();
176 : : else
177 : 0 : return MB_FAILURE;
178 : : }
179 : : else
180 : : {
181 : 0 : return MB_FAILURE;
182 : : }
183 : :
184 : 0 : return MB_SUCCESS;
185 : : }
186 : :
187 : 18 : ErrorCode GeomTopoTool::restore_obb_index()
188 : : {
189 : :
190 [ + - ][ + - ]: 18 : if( m_rootSets_vector ) resize_rootSets();
191 : :
192 : : ErrorCode rval;
193 : : EntityHandle root;
194 : :
195 [ + + ]: 28 : for( int dim = 2; dim <= 3; dim++ )
196 [ + - ][ + - ]: 50 : for( Range::iterator rit = geomRanges[dim].begin(); rit != geomRanges[dim].end(); ++rit )
[ + - ][ + - ]
[ + + ]
197 : : {
198 [ + - ][ + - ]: 40 : rval = mdbImpl->tag_get_data( obbRootTag, &( *rit ), 1, &root );
199 : :
200 [ + + ]: 40 : if( MB_SUCCESS == rval )
201 [ + - ][ + - ]: 27 : set_root_set( *rit, root );
202 : : else
203 : : {
204 : 13 : return MB_TAG_NOT_FOUND;
205 : : }
206 : : }
207 : :
208 : 18 : return MB_SUCCESS;
209 : : }
210 : :
211 : 58 : ErrorCode GeomTopoTool::find_geomsets( Range* ranges )
212 : : {
213 : : ErrorCode rval;
214 : : // get all sets with this tag
215 [ + - ]: 58 : Range geom_sets;
216 : :
217 [ - + ]: 58 : if( 0 == geomTag )
218 : : {
219 [ # # ][ # # ]: 0 : rval = mdbImpl->tag_get_handle( GEOM_DIMENSION_TAG_NAME, 1, MB_TYPE_INTEGER, geomTag );MB_CHK_SET_ERR( rval, "Failed to get geom dimension tag handle" );
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ]
220 : : }
221 : :
222 [ + - ][ - + ]: 58 : rval = mdbImpl->get_entities_by_type_and_tag( modelSet, MBENTITYSET, &geomTag, NULL, 1, geom_sets );MB_CHK_SET_ERR( rval, "Failed to get the geometry entities" );
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ]
223 : :
224 [ + - ][ - + ]: 58 : rval = separate_by_dimension( geom_sets );MB_CHK_SET_ERR( rval, "Failed to separate geometry sets by dimension" );
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ]
225 : :
226 [ + + ]: 58 : if( ranges )
227 : : {
228 [ + + ]: 120 : for( int i = 0; i < 5; i++ )
229 : : {
230 [ + - ]: 100 : ranges[i] = geomRanges[i];
231 : : }
232 : : }
233 : :
234 : 58 : return MB_SUCCESS;
235 : : }
236 : :
237 : 969 : ErrorCode GeomTopoTool::get_gsets_by_dimension( int dim, Range& gset )
238 : : {
239 : : ErrorCode rval;
240 : :
241 : 969 : const int val = dim;
242 : 969 : const void* const dim_val[] = { &val };
243 [ + - ][ - + ]: 969 : rval = mdbImpl->get_entities_by_type_and_tag( modelSet, MBENTITYSET, &geomTag, dim_val, 1, gset );MB_CHK_SET_ERR( rval, "Failed to get entity set by type and tag" );
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ]
244 : :
245 : 969 : return MB_SUCCESS;
246 : : }
247 : :
248 : 75 : ErrorCode GeomTopoTool::resize_rootSets()
249 : : {
250 : :
251 : : ErrorCode rval;
252 : :
253 : : // store original offset for later
254 : 75 : EntityHandle orig_offset = setOffset;
255 : :
256 : : // get all surfaces and volumes
257 [ + - ][ + - ]: 150 : Range surfs, vols;
258 [ + - ][ - + ]: 75 : rval = get_gsets_by_dimension( 2, surfs );MB_CHK_SET_ERR( rval, "Could not get surface sets" );
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ]
259 [ + - ][ - + ]: 75 : rval = get_gsets_by_dimension( 3, vols );MB_CHK_SET_ERR( rval, "Could not get volume sets" );
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ]
260 : :
261 : : // check the vector size
262 [ + - ]: 150 : Range surfs_and_vols;
263 [ + - ]: 75 : surfs_and_vols = vols;
264 [ + - ]: 75 : surfs_and_vols.merge( surfs );
265 : :
266 : : // update the setOffset
267 [ + - ]: 75 : setOffset = surfs_and_vols.front();
268 : :
269 [ + - ]: 75 : EntityHandle exp_size = surfs_and_vols.back() - setOffset + 1;
270 : :
271 : : // if new EnitytHandle(s) are lower than the original offset
272 [ - + ]: 75 : if( setOffset < orig_offset )
273 : : {
274 : : // insert empty values at the beginning of the vector
275 [ # # ]: 0 : rootSets.insert( rootSets.begin(), orig_offset - setOffset, 0 );
276 : : }
277 : :
278 [ + - ]: 75 : if( exp_size != rootSets.size() )
279 : : {
280 : : // resize rootSets vector if necessary (new space will be added at the back)
281 [ + - ]: 75 : rootSets.resize( exp_size );
282 : : }
283 : :
284 : 75 : return MB_SUCCESS;
285 : : }
286 : :
287 : 537 : ErrorCode GeomTopoTool::is_owned_set( EntityHandle eh )
288 : : {
289 : : // make sure entity set is part of the model
290 [ + - ]: 537 : Range model_ents;
291 [ + - ][ - + ]: 537 : ErrorCode rval = mdbImpl->get_entities_by_handle( modelSet, model_ents );MB_CHK_SET_ERR( rval, "Failed to get entities" );
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ]
292 [ + - ][ + - ]: 537 : if( model_ents.find( eh ) == model_ents.end() ) { MB_SET_ERR( MB_FAILURE, "Entity handle not in model set" ); }
[ + - ][ - + ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ]
293 : 537 : return MB_SUCCESS;
294 : : }
295 : :
296 : 4 : ErrorCode GeomTopoTool::delete_obb_tree( EntityHandle gset, bool vol_only )
297 : : {
298 : :
299 : : ErrorCode rval;
300 : :
301 : : // Make sure this set is part of the model
302 [ + - ][ - + ]: 4 : rval = is_owned_set( gset );MB_CHK_SET_ERR( rval, "Entity set is not part of this model" );
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ]
303 : :
304 : : // Find the dimension of the entity
305 : : int dim;
306 [ + - ][ - + ]: 4 : rval = mdbImpl->tag_get_data( geomTag, &gset, 1, &dim );MB_CHK_SET_ERR( rval, "Failed to get dimension" );
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ]
307 : :
308 : : // Attempt to find a root for this set
309 : : EntityHandle root;
310 [ + - ][ - + ]: 4 : rval = get_root( gset, root );MB_CHK_SET_ERR( rval, "Failed to find an obb tree root for the entity set" );
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ]
311 : :
312 : : // Create range of tree nodes to delete
313 [ + - ]: 4 : Range nodes_to_delete;
314 [ + - ]: 4 : nodes_to_delete.insert( root );
315 : :
316 : : // If passed ent is a vol and 'vol_only' is true, delete vol root and all nodes between vol and
317 : : // surf root
318 [ + + ][ + + ]: 4 : if( dim == 3 && vol_only )
319 : : {
320 : : // Range of child nodes to check before adding to delete list
321 [ + - ]: 1 : Range child_tree_nodes;
322 [ + - ][ - + ]: 1 : rval = mdbImpl->get_child_meshsets( root, child_tree_nodes );MB_CHK_SET_ERR( rval, "Problem getting child tree nodes" );
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ]
323 : :
324 : : // Traverse the tree, checking each child node until
325 : : // a surface root node is reached
326 [ + - ][ + + ]: 11 : while( child_tree_nodes.size() != 0 )
[ + - ]
327 : : {
328 [ + - ][ + - ]: 10 : EntityHandle child = *child_tree_nodes.begin();
329 : : EntityHandle surf;
330 [ + - ]: 10 : rval = mdbImpl->tag_get_data( obbGsetTag, &child, 1, &surf );
331 : : // If the node has a gset tag, it is a surf root. Stop here.
332 : : // If not, it is a tree node that needs to 1) have its children checked and
333 : : // 2) be added to delete range
334 [ + + ]: 10 : if( MB_TAG_NOT_FOUND == rval )
335 : : {
336 [ + - ]: 4 : Range new_child_tree_nodes;
337 [ + - ][ - + ]: 4 : rval = mdbImpl->get_child_meshsets( child, new_child_tree_nodes );MB_CHK_SET_ERR( rval, "Problem getting child nodes" );
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ]
338 [ + - ][ + - ]: 4 : child_tree_nodes.insert_list( new_child_tree_nodes.begin(), new_child_tree_nodes.end() );
[ + - ]
339 [ + - ][ + - ]: 4 : nodes_to_delete.insert( child );
340 : : }
341 : : // We're done checking this node, so can erase from child list
342 [ + - ]: 10 : child_tree_nodes.erase( child );
343 : 1 : }
344 : : }
345 : : // If passed ent is a surf or a vol and 'vol_only' is false, recursively gather all child nodes
346 : : // and add them to delete list
347 : : else
348 : : {
349 [ + - ]: 3 : Range all_tree_nodes;
350 [ + - ][ - + ]: 3 : rval = mdbImpl->get_child_meshsets( root, all_tree_nodes, 0 );MB_CHK_SET_ERR( rval, "Failed to get child tree node sets" );
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ]
351 [ + - ][ + - ]: 3 : nodes_to_delete.insert_list( all_tree_nodes.begin(), all_tree_nodes.end() );
[ + - ][ + - ]
352 : : }
353 : :
354 : : // Remove the root nodes from the GTT data structures
355 [ + - ][ + - ]: 32 : for( Range::iterator it = nodes_to_delete.begin(); it != nodes_to_delete.end(); ++it )
[ + - ][ + - ]
[ + + ]
356 : : {
357 : : // Check to see if node is a root
358 : : EntityHandle vol_or_surf;
359 [ + - ][ + - ]: 28 : rval = mdbImpl->tag_get_data( obbGsetTag, &( *it ), 1, &vol_or_surf );
360 [ + + ]: 28 : if( MB_SUCCESS == rval )
361 : : {
362 : : // Remove from set of all roots
363 [ + - ][ - + ]: 16 : rval = remove_root( vol_or_surf );MB_CHK_SET_ERR( rval, "Failed to remove node from GTT data structure" );
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ]
364 : : }
365 : : }
366 : :
367 : : // Delete the tree nodes from the database
368 [ + - ][ - + ]: 4 : rval = mdbImpl->delete_entities( nodes_to_delete );MB_CHK_SET_ERR( rval, "Failed to delete node set" );
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ]
369 : :
370 : 4 : return MB_SUCCESS;
371 : : }
372 : :
373 : 13 : ErrorCode GeomTopoTool::delete_all_obb_trees()
374 : : {
375 : :
376 : : ErrorCode rval;
377 : :
378 [ + - ][ + - ]: 21 : for( Range::iterator rit = geomRanges[3].begin(); rit != geomRanges[3].end(); ++rit )
[ + - ][ + - ]
[ + + ]
379 : : {
380 : : EntityHandle root;
381 [ + - ][ + - ]: 8 : rval = mdbImpl->tag_get_data( obbRootTag, &( *rit ), 1, &root );
382 [ - + ]: 8 : if( MB_SUCCESS == rval )
383 : : {
384 [ # # ][ # # ]: 0 : rval = delete_obb_tree( *rit, false );MB_CHK_SET_ERR( rval, "Failed to delete obb tree" );
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
385 : : }
386 : : }
387 : :
388 : 13 : return MB_SUCCESS;
389 : : }
390 : :
391 : 533 : ErrorCode GeomTopoTool::construct_obb_tree( EntityHandle eh )
392 : : {
393 : : ErrorCode rval;
394 : : int dim;
395 : :
396 [ + - ][ - + ]: 533 : rval = is_owned_set( eh );MB_CHK_SET_ERR( rval, "Entity set is not part of this model" );
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ]
397 : :
398 : : // get the type
399 [ + - ]: 533 : EntityType type = mdbImpl->type_from_handle( eh );
400 : :
401 : : // find the dimension of the entity
402 [ + - ][ - + ]: 533 : rval = mdbImpl->tag_get_data( geomTag, &eh, 1, &dim );MB_CHK_SET_ERR( rval, "Failed to get dimension" );
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ]
403 : :
404 : : // ensure that the rootSets vector is of the correct size
405 [ + + ][ + - ]: 533 : if( m_rootSets_vector && ( eh < setOffset || eh >= setOffset + rootSets.size() ) )
[ + + ][ + + ]
406 : : {
407 [ + - ][ - + ]: 57 : rval = resize_rootSets();MB_CHK_SET_ERR( rval, "Error setting offset and sizing rootSets vector." );
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ]
408 : : }
409 : :
410 : : EntityHandle root;
411 : : // if it's a surface
412 [ + + ][ + - ]: 533 : if( dim == 2 && type == MBENTITYSET )
413 : : {
414 [ + - ]: 365 : rval = get_root( eh, root );
415 [ + + ]: 365 : if( MB_SUCCESS == rval )
416 : : {
417 [ + - ][ + - ]: 70 : std::cerr << "Surface obb tree already exists" << std::endl;
418 : 70 : return MB_SUCCESS;
419 : : }
420 [ - + ]: 295 : else if( MB_INDEX_OUT_OF_RANGE != rval )
421 : : {
422 [ # # ][ # # ]: 0 : MB_CHK_SET_ERR( rval, "Failed to get surface obb tree root" );
[ # # ][ # # ]
[ # # ][ # # ]
423 : : }
424 : :
425 [ + - ]: 295 : Range tris;
426 [ + - ][ - + ]: 295 : rval = mdbImpl->get_entities_by_dimension( eh, 2, tris );MB_CHK_SET_ERR( rval, "Failed to get entities by dimension" );
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ]
427 : :
428 [ + - ][ - + ]: 295 : if( tris.empty() ) { std::cerr << "WARNING: Surface has no facets" << std::endl; }
[ # # ][ # # ]
429 : :
430 [ + - ][ - + ]: 295 : rval = obbTree->build( tris, root );MB_CHK_SET_ERR( rval, "Failed to build obb Tree for surface" );
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ]
431 : :
432 [ + - ][ - + ]: 295 : rval = mdbImpl->add_entities( root, &eh, 1 );MB_CHK_SET_ERR( rval, "Failed to add entities to root set" );
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ]
433 : :
434 : : // add this root to the GeomTopoTool tree root indexing
435 [ + - ]: 295 : set_root_set( eh, root );
436 : :
437 : : // if just building tree for surface, return here
438 : 365 : return MB_SUCCESS;
439 : : }
440 : : // if it's a volume
441 [ + - ][ + - ]: 168 : else if( dim == 3 && type == MBENTITYSET )
442 : : {
443 : : // get its surfaces
444 [ + - ][ + - ]: 336 : Range tmp_surfs, surf_trees;
445 [ + - ][ - + ]: 168 : rval = mdbImpl->get_child_meshsets( eh, tmp_surfs );MB_CHK_SET_ERR( rval, "Failed to get surface meshsets" );
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ]
446 : :
447 : : // get OBB trees or create for each surface
448 [ + - ][ + - ]: 634 : for( Range::iterator j = tmp_surfs.begin(); j != tmp_surfs.end(); ++j )
[ + - ][ + - ]
[ + + ]
449 : : {
450 [ + - ][ + - ]: 466 : rval = get_root( *j, root );
451 : : // if root doesn't exist, create obb tree
452 [ + + ]: 466 : if( MB_INDEX_OUT_OF_RANGE == rval )
453 : : {
454 [ + - ][ + - ]: 12 : rval = construct_obb_tree( *j );MB_CHK_SET_ERR( rval, "Failed to get create surface obb tree" );
[ - + ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
455 [ + - ][ + - ]: 12 : rval = get_root( *j, root );MB_CHK_SET_ERR( rval, "Failed to get surface obb tree root" );
[ - + ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
456 : : }
457 : : else
458 : : {
459 [ - + ][ # # ]: 454 : MB_CHK_SET_ERR( rval, "Failed to get surface obb tree root" );
[ # # ][ # # ]
[ # # ][ # # ]
460 : : }
461 : :
462 [ + - ]: 466 : surf_trees.insert( root );
463 : : }
464 : :
465 : : // build OBB tree for volume
466 [ + - ][ - + ]: 168 : rval = obbTree->join_trees( surf_trees, root );MB_CHK_SET_ERR( rval, "Failed to join the obb trees" );
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ]
467 : :
468 : : // add this root to the GeomTopoTool tree root indexing
469 [ + - ]: 168 : set_root_set( eh, root );
470 : :
471 : 336 : return MB_SUCCESS;
472 : : }
473 : : else
474 : : {
475 [ # # ][ # # ]: 533 : MB_SET_ERR( MB_FAILURE, "Improper dimension or type for constructing obb tree" );
[ # # ][ # # ]
[ # # ]
476 : : }
477 : : }
478 : :
479 : 490 : ErrorCode GeomTopoTool::set_root_set( EntityHandle vol_or_surf, EntityHandle root )
480 : : {
481 : :
482 : : // Tag the vol or surf with its obb root (obbRootTag)
483 : : ErrorCode rval;
484 [ - + ][ # # ]: 490 : rval = mdbImpl->tag_set_data( obbRootTag, &vol_or_surf, 1, &root );MB_CHK_SET_ERR( rval, "Failed to set the obb root tag" );
[ # # ][ # # ]
[ # # ][ # # ]
485 : :
486 : : // Tag obb root with corresponding gset (obbGsetTag)
487 [ + + ][ + - ]: 490 : rval = mdbImpl->tag_set_data( obbGsetTag, &root, 1, &vol_or_surf );MB_CHK_SET_ERR( rval, "Failed to set the obb gset tag" );
[ + - ][ + - ]
[ - + ][ + - ]
488 : :
489 : : // Add to the set of all roots
490 [ + + ]: 488 : if( m_rootSets_vector )
491 : 482 : rootSets[vol_or_surf - setOffset] = root;
492 : : else
493 : 6 : mapRootSets[vol_or_surf] = root;
494 : :
495 : 490 : return MB_SUCCESS;
496 : : }
497 : :
498 : 16 : ErrorCode GeomTopoTool::remove_root( EntityHandle vol_or_surf )
499 : : {
500 : :
501 : : // Find the root of the vol or surf
502 : : ErrorCode rval;
503 : : EntityHandle root;
504 [ + - ][ - + ]: 16 : rval = mdbImpl->tag_get_data( obbRootTag, &( vol_or_surf ), 1, &root );MB_CHK_SET_ERR( rval, "Failed to get obb root tag" );
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ]
505 : :
506 : : // If the ent is a vol, remove its root from obbtreetool
507 : : int dim;
508 [ + - ][ - + ]: 16 : rval = mdbImpl->tag_get_data( geomTag, &vol_or_surf, 1, &dim );MB_CHK_SET_ERR( rval, "Failed to get dimension" );
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ]
509 [ + + ]: 16 : if( dim == 3 )
510 : : {
511 [ + - ][ - + ]: 3 : rval = obbTree->remove_root( root );MB_CHK_SET_ERR( rval, "Failed to remove root from obbTreeTool" );
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ]
512 : : }
513 : :
514 : : // Delete the obbGsetTag data from the root
515 [ + - ][ - + ]: 16 : rval = mdbImpl->tag_delete_data( obbGsetTag, &root, 1 );MB_CHK_SET_ERR( rval, "Failed to delete obb root tag" );
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ]
516 : :
517 : : // Delete the obbRootTag data from the vol or surf
518 [ + - ][ - + ]: 16 : rval = mdbImpl->tag_delete_data( obbRootTag, &vol_or_surf, 1 );MB_CHK_SET_ERR( rval, "Failed to delete obb root tag" );
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ]
519 : :
520 : : // Remove the root from set of all roots
521 [ + - ]: 16 : if( m_rootSets_vector )
522 : : {
523 : 16 : unsigned int index = vol_or_surf - setOffset;
524 [ + - ][ + - ]: 16 : if( index < rootSets.size() ) { rootSets[index] = 0; }
525 : : else
526 : : {
527 : 16 : return MB_INDEX_OUT_OF_RANGE;
528 : : }
529 : : }
530 : : else
531 : : {
532 [ # # ]: 0 : mapRootSets[vol_or_surf] = 0;
533 : : }
534 : :
535 : 16 : return MB_SUCCESS;
536 : : }
537 : :
538 : 74 : ErrorCode GeomTopoTool::construct_obb_trees( bool make_one_vol )
539 : : {
540 : : ErrorCode rval;
541 : : EntityHandle root;
542 : :
543 : : // get all surfaces and volumes
544 [ + - ][ + - ]: 148 : Range surfs, vols, vol_trees;
[ + - ]
545 [ + - ][ - + ]: 74 : rval = get_gsets_by_dimension( 2, surfs );MB_CHK_SET_ERR( rval, "Could not get surface sets" );
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ]
546 [ + - ][ - + ]: 74 : rval = get_gsets_by_dimension( 3, vols );MB_CHK_SET_ERR( rval, "Could not get volume sets" );
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ]
547 : :
548 : : // for surface
549 [ + - ]: 148 : Range one_vol_trees;
550 [ + - ][ + - ]: 415 : for( Range::iterator i = surfs.begin(); i != surfs.end(); ++i )
[ + - ][ + - ]
[ + + ]
551 : : {
552 [ + - ][ + - ]: 341 : rval = construct_obb_tree( *i );MB_CHK_SET_ERR( rval, "Failed to construct obb tree for surface" );
[ - + ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
553 : : // get the root set of this volume
554 [ + - ][ + - ]: 341 : rval = get_root( *i, root );MB_CHK_SET_ERR( rval, "Failed to get obb tree root for surface" );
[ - + ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
555 : : // add to the Range of volume root sets
556 [ + - ]: 341 : one_vol_trees.insert( root );
557 : : }
558 : :
559 : : // for volumes
560 [ + - ][ + - ]: 240 : for( Range::iterator i = vols.begin(); i != vols.end(); ++i )
[ + - ][ + - ]
[ + + ]
561 : : {
562 : : // create tree for this volume
563 [ + - ][ + - ]: 166 : rval = construct_obb_tree( *i );MB_CHK_SET_ERR( rval, "Failed to construct obb tree for volume" );
[ - + ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
564 : : }
565 : :
566 : : // build OBB tree for volume
567 [ + + ]: 74 : if( make_one_vol )
568 : : {
569 [ + - ][ - + ]: 1 : rval = obbTree->join_trees( one_vol_trees, root );MB_CHK_SET_ERR( rval, "Failed to join surface trees into one volume" );
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ]
570 : 1 : oneVolRootSet = root;
571 : : }
572 : :
573 : 148 : return rval;
574 : : }
575 : :
576 : : //! Restore parent/child links between GEOM_TOPO mesh sets
577 : 0 : ErrorCode GeomTopoTool::restore_topology_from_adjacency()
578 : : {
579 : :
580 : : // look for geometric topology sets and restore parent/child links between them
581 : : // algorithm:
582 : : // - for each entity of dimension d=D-1..0:
583 : : // . get d-dimensional entity in entity
584 : : // . get all (d+1)-dim adjs to that entity
585 : : // . for each geom entity if dim d+1, if it contains any of the ents,
586 : : // add it to list of parents
587 : : // . make parent/child links with parents
588 : :
589 : : // the geomRanges are already known, separated by dimension
590 : :
591 [ # # ]: 0 : std::vector< EntityHandle > parents;
592 [ # # ]: 0 : Range tmp_parents;
593 : : ErrorCode result;
594 : :
595 : : // loop over dimensions
596 [ # # ]: 0 : for( int dim = 2; dim >= 0; dim-- )
597 : : {
598 : : // mark entities of next higher dimension with their owners; regenerate tag
599 : : // each dimension so prev dim's tag data goes away
600 : : Tag owner_tag;
601 : 0 : EntityHandle dum_val = 0;
602 : : result = mdbImpl->tag_get_handle( "__owner_tag", 1, MB_TYPE_HANDLE, owner_tag, MB_TAG_DENSE | MB_TAG_CREAT,
603 [ # # ]: 0 : &dum_val );
604 [ # # ]: 0 : if( MB_SUCCESS != result ) continue;
605 [ # # ]: 0 : Range dp1ents;
606 [ # # ][ # # ]: 0 : std::vector< EntityHandle > owners;
607 [ # # ][ # # ]: 0 : for( Range::iterator rit = geomRanges[dim + 1].begin(); rit != geomRanges[dim + 1].end(); ++rit )
[ # # ][ # # ]
[ # # ]
608 : : {
609 [ # # ]: 0 : dp1ents.clear();
610 [ # # ][ # # ]: 0 : result = mdbImpl->get_entities_by_dimension( *rit, dim + 1, dp1ents );
611 [ # # ]: 0 : if( MB_SUCCESS != result ) continue;
612 [ # # ][ # # ]: 0 : owners.resize( dp1ents.size() );
613 [ # # ][ # # ]: 0 : std::fill( owners.begin(), owners.end(), *rit );
614 [ # # ][ # # ]: 0 : result = mdbImpl->tag_set_data( owner_tag, dp1ents, &owners[0] );
615 [ # # ]: 0 : if( MB_SUCCESS != result ) continue;
616 : : }
617 : :
618 [ # # ][ # # ]: 0 : for( Range::iterator d_it = geomRanges[dim].begin(); d_it != geomRanges[dim].end(); ++d_it )
[ # # ][ # # ]
[ # # ]
619 : : {
620 [ # # ]: 0 : Range dents;
621 [ # # ][ # # ]: 0 : result = mdbImpl->get_entities_by_dimension( *d_it, dim, dents );
622 [ # # ]: 0 : if( MB_SUCCESS != result ) continue;
623 [ # # ][ # # ]: 0 : if( dents.empty() ) continue;
624 : :
625 : : // get (d+1)-dimensional adjs
626 [ # # ]: 0 : dp1ents.clear();
627 [ # # ][ # # ]: 0 : result = mdbImpl->get_adjacencies( &( *dents.begin() ), 1, dim + 1, false, dp1ents );
[ # # ]
628 [ # # ][ # # ]: 0 : if( MB_SUCCESS != result || dp1ents.empty() ) continue;
[ # # ][ # # ]
629 : :
630 : : // get owner tags
631 [ # # ][ # # ]: 0 : parents.resize( dp1ents.size() );
632 [ # # ][ # # ]: 0 : result = mdbImpl->tag_get_data( owner_tag, dp1ents, &parents[0] );
633 [ # # ][ # # ]: 0 : if( MB_TAG_NOT_FOUND == result ) { MB_CHK_SET_ERR( result, "Could not find owner tag" ); }
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ]
634 [ # # ]: 0 : if( MB_SUCCESS != result ) continue;
635 : :
636 : : // compress to a range to remove duplicates
637 [ # # ]: 0 : tmp_parents.clear();
638 [ # # ][ # # ]: 0 : std::copy( parents.begin(), parents.end(), range_inserter( tmp_parents ) );
639 [ # # ][ # # ]: 0 : for( Range::iterator pit = tmp_parents.begin(); pit != tmp_parents.end(); ++pit )
[ # # ][ # # ]
[ # # ]
640 : : {
641 [ # # ][ # # ]: 0 : result = mdbImpl->add_parent_child( *pit, *d_it );MB_CHK_SET_ERR( result, "Failed to create parent child relationship" );
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ]
642 : : }
643 : :
644 : : // store surface senses within regions, and edge senses within surfaces
645 [ # # ]: 0 : if( dim == 0 ) continue;
646 : 0 : const EntityHandle *conn3 = NULL, *conn2 = NULL;
647 : 0 : int len3 = 0, len2 = 0, err = 0, num = 0, sense = 0, offset = 0;
648 [ # # ]: 0 : for( size_t i = 0; i < parents.size(); ++i )
[ # # # ]
649 : : {
650 [ # # ][ # # ]: 0 : result = mdbImpl->get_connectivity( dp1ents[i], conn3, len3, true );MB_CHK_SET_ERR( result, "Failed to get the connectivity of the element" );
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
651 [ # # ][ # # ]: 0 : result = mdbImpl->get_connectivity( dents.front(), conn2, len2, true );MB_CHK_SET_ERR( result, "Failed to get the connectivity of the first element" );
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
652 [ # # ][ # # ]: 0 : if( len2 > 4 ) { MB_SET_ERR( MB_FAILURE, "Connectivity of incorrect length" ); }
[ # # ][ # # ]
[ # # ][ # # ]
653 [ # # ][ # # ]: 0 : err = CN::SideNumber( TYPE_FROM_HANDLE( dp1ents[i] ), conn3, conn2, len2, dim, num, sense, offset );
[ # # ]
654 [ # # ]: 0 : if( err ) return MB_FAILURE;
655 : :
656 [ # # ][ # # ]: 0 : result = set_sense( *d_it, parents[i], sense );
[ # # ]
657 [ # # ]: 0 : if( MB_MULTIPLE_ENTITIES_FOUND == result )
658 : : {
659 [ # # ]: 0 : if( 2 == dim )
660 [ # # ][ # # ]: 0 : std::cerr << "Warning: Multiple volumes use surface with same sense." << std::endl
661 [ # # ][ # # ]: 0 : << " Some geometric sense data lost." << std::endl;
662 : : }
663 [ # # ]: 0 : else if( MB_SUCCESS != result )
664 : : {
665 : 0 : return result;
666 : : }
667 : : }
668 : 0 : }
669 : :
670 : : // now delete owner tag on this dimension, automatically removes tag data
671 [ # # ][ # # ]: 0 : result = mdbImpl->tag_delete( owner_tag );MB_CHK_SET_ERR( result, "Failed to delete the owner tag" );
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
672 : :
673 : 0 : } // dim
674 : :
675 : 0 : return result;
676 : : }
677 : :
678 : 58 : ErrorCode GeomTopoTool::separate_by_dimension( const Range& geom_sets )
679 : : {
680 : : ErrorCode result;
681 : :
682 [ + - ][ - + ]: 58 : result = check_geom_tag();MB_CHK_SET_ERR( result, "Could not verify geometry dimension tag" );
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ]
683 : :
684 : : // get the data for those tags
685 [ + - ][ + - ]: 58 : std::vector< int > tag_vals( geom_sets.size() );
686 [ + - ][ + - ]: 58 : result = mdbImpl->tag_get_data( geomTag, geom_sets, &tag_vals[0] );MB_CHK_SET_ERR( result, "Failed to get the geometry dimension tag" );
[ - + ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
687 : :
688 [ + - ]: 58 : Range::const_iterator git;
689 : 58 : std::vector< int >::iterator iit;
690 : :
691 [ + + ]: 348 : for( int i = 0; i < 5; i++ )
692 [ + - ]: 290 : this->geomRanges[i].clear();
693 : :
694 [ + - ][ + - ]: 1186 : for( git = geom_sets.begin(), iit = tag_vals.begin(); git != geom_sets.end(); ++git, ++iit )
[ + - ][ + - ]
[ + - ][ + + ]
695 : : {
696 [ + - ][ + - ]: 1128 : if( 0 <= *iit && 4 >= *iit )
[ + - ][ + - ]
[ + - ]
697 [ + - ][ + - ]: 1128 : geomRanges[*iit].insert( *git );
[ + - ]
698 : : else
699 : : {
700 : : // assert(false);
701 : : // do nothing for now
702 : : }
703 : : }
704 : :
705 : : // establish the max global ids so far, per dimension
706 [ - + ][ # # ]: 58 : if( 0 == gidTag ) { gidTag = mdbImpl->globalId_tag(); }
707 : :
708 [ + + ]: 348 : for( int i = 0; i <= 4; i++ )
709 : : {
710 : 290 : maxGlobalId[i] = 0;
711 [ + - ][ + - ]: 1418 : for( Range::iterator it = geomRanges[i].begin(); it != geomRanges[i].end(); ++it )
[ + - ][ + - ]
[ + + ]
712 : : {
713 [ + - ]: 1128 : EntityHandle set = *it;
714 : : int gid;
715 : :
716 [ + - ]: 1128 : result = mdbImpl->tag_get_data( gidTag, &set, 1, &gid );
717 [ + - ]: 1128 : if( MB_SUCCESS == result )
718 : : {
719 [ + + ]: 1128 : if( gid > maxGlobalId[i] ) maxGlobalId[i] = gid;
720 : : }
721 : : }
722 : : }
723 : :
724 : 58 : return MB_SUCCESS;
725 : : }
726 : :
727 : 0 : ErrorCode GeomTopoTool::construct_vertex_ranges( const Range& geom_sets, const Tag verts_tag )
728 : : {
729 : : // construct the vertex range for each entity and put on that tag
730 [ # # ]: 0 : Range *temp_verts, temp_elems;
731 : 0 : ErrorCode result = MB_SUCCESS;
732 [ # # ][ # # ]: 0 : for( Range::const_iterator it = geom_sets.begin(); it != geom_sets.end(); ++it )
[ # # ][ # # ]
[ # # ]
733 : : {
734 [ # # ]: 0 : temp_elems.clear();
735 : :
736 : : // get all the elements in the set, recursively
737 [ # # ][ # # ]: 0 : result = mdbImpl->get_entities_by_handle( *it, temp_elems, true );MB_CHK_SET_ERR( result, "Failed to get the geometry set entities" );
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
738 : :
739 : : // make the new range
740 [ # # ][ # # ]: 0 : temp_verts = new( std::nothrow ) Range();
741 [ # # ][ # # ]: 0 : if( NULL == temp_verts ) { MB_SET_ERR( MB_FAILURE, "Could not construct Range object" ); }
[ # # ][ # # ]
[ # # ][ # # ]
742 : :
743 : : // get all the verts of those elements; use get_adjacencies 'cuz it handles ranges better
744 [ # # ]: 0 : result = mdbImpl->get_adjacencies( temp_elems, 0, false, *temp_verts, Interface::UNION );
745 [ # # ][ # # ]: 0 : if( MB_SUCCESS != result ) { delete temp_verts; }
746 [ # # ][ # # ]: 0 : MB_CHK_SET_ERR( result, "Failed to get the element's adjacent vertices" );
[ # # ][ # # ]
[ # # ][ # # ]
747 : :
748 : : // store this range as a tag on the entity
749 [ # # ][ # # ]: 0 : result = mdbImpl->tag_set_data( verts_tag, &( *it ), 1, &temp_verts );
750 [ # # ][ # # ]: 0 : if( MB_SUCCESS != result ) { delete temp_verts; }
751 [ # # ][ # # ]: 0 : MB_CHK_SET_ERR( result, "Failed to get the adjacent vertex data" );
[ # # ][ # # ]
[ # # ][ # # ]
752 : :
753 [ # # ]: 0 : delete temp_verts;
754 : 0 : temp_verts = NULL;
755 : : }
756 : :
757 : 0 : return result;
758 : : }
759 : :
760 : : //! Store sense of entity relative to wrt_entity.
761 : : //!\return MB_MULTIPLE_ENTITIES_FOUND if surface already has a forward volume.
762 : : //! MB_SUCCESS if successful
763 : : //! otherwise whatever internal error code occurred.
764 : 320 : ErrorCode GeomTopoTool::set_sense( EntityHandle entity, EntityHandle wrt_entity, int sense )
765 : : {
766 : : // entity is lower dim (edge or face), wrt_entity is face or volume
767 : 320 : int edim = dimension( entity );
768 : 320 : int wrtdim = dimension( wrt_entity );
769 [ + - ][ - + ]: 320 : if( -1 == edim || -1 == wrtdim ) MB_SET_ERR( MB_FAILURE, "Non-geometric entity provided" );
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ]
770 [ - + ][ # # ]: 320 : if( wrtdim - edim != 1 ) MB_SET_ERR( MB_FAILURE, "Entity dimension mismatch" );
[ # # ][ # # ]
[ # # ][ # # ]
771 [ + - ][ - + ]: 320 : if( sense < -1 || sense > 1 ) MB_SET_ERR( MB_FAILURE, "Invalid sense data provided" );
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ]
772 : :
773 : : ErrorCode rval;
774 : :
775 [ + + ]: 320 : if( 1 == edim )
776 : : {
777 : : // this case is about setting the sense of an edge in a face
778 : : // it could be -1, 0 (rare, non manifold), or 1
779 [ + - ][ - + ]: 104 : rval = check_edge_sense_tags( true );MB_CHK_SET_ERR( rval, "Failed to check the curve to surface sense tag handles" );
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ]
780 [ + - ]: 104 : std::vector< EntityHandle > higher_ents;
781 [ + - ][ + - ]: 208 : std::vector< int > senses;
782 [ + - ]: 104 : rval = get_senses( entity, higher_ents, senses ); // the tags should be defined here
783 : : // if there are no higher_ents, we are fine, we will just set them
784 : : // if wrt_entity is not among higher_ents, we will add it to the list
785 : : // it is possible the entity (edge set) has no prior faces adjancent; in that case, the
786 : : // tag would not be set, and rval could be MB_TAG_NOT_FOUND; it is not a fatal error
787 [ + + ][ - + ]: 104 : if( MB_SUCCESS != rval && MB_TAG_NOT_FOUND != rval )
788 [ # # ][ # # ]: 0 : MB_CHK_SET_ERR( rval, "cannot determine sense tags for edge" );
[ # # ][ # # ]
[ # # ][ # # ]
789 : 104 : bool append = true;
790 [ + + ]: 104 : if( !higher_ents.empty() )
791 : : {
792 [ + - ]: 44 : std::vector< EntityHandle >::iterator it = std::find( higher_ents.begin(), higher_ents.end(), wrt_entity );
793 [ + - ][ - + ]: 44 : if( it != higher_ents.end() )
794 : : {
795 : : // we should not reset the sense, if the sense is the same
796 : : // if the sense is different, put BOTH
797 [ # # ]: 0 : unsigned int idx = it - higher_ents.begin();
798 [ # # ]: 0 : int oldSense = senses[idx];
799 [ # # ]: 0 : if( oldSense == sense ) return MB_SUCCESS; // sense already set fine, do not reset
800 [ # # ][ # # ]: 0 : if( 0 != oldSense && oldSense + sense != 0 ) return MB_MULTIPLE_ENTITIES_FOUND;
801 [ # # ]: 0 : senses[idx] = SENSE_BOTH; // allow double senses
802 : : // do not need to add a new sense, but still need to reset the tag
803 : : // because of a new value
804 : 44 : append = false;
805 : : }
806 : : }
807 [ + - ]: 104 : if( append )
808 : : {
809 : : // what happens if a var tag data was already set before, and now it is
810 : : // reset with a different size??
811 [ + - ]: 104 : higher_ents.push_back( wrt_entity );
812 [ + - ]: 104 : senses.push_back( sense );
813 : : }
814 : : // finally, set the senses :
815 : 104 : int dum_size = higher_ents.size();
816 [ + - ]: 104 : void* dum_ptr = &higher_ents[0];
817 [ + - ][ - + ]: 104 : rval = mdbImpl->tag_set_by_ptr( senseNEntsTag, &entity, 1, &dum_ptr, &dum_size );MB_CHK_SET_ERR( rval, "Failed to set the sense data" );
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ]
818 : :
819 [ + - ]: 104 : dum_ptr = &senses[0];
820 : 104 : dum_size = higher_ents.size();
821 [ + - ][ - + ]: 208 : rval = mdbImpl->tag_set_by_ptr( senseNSensesTag, &entity, 1, &dum_ptr, &dum_size );MB_CHK_SET_ERR( rval, "Failed to set the sense data by pointer" );
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ + - ]
822 : : }
823 : : else
824 : : {
825 : : // this case is about a face in the volume
826 : : // there could be only 2 volumes
827 : :
828 [ + - ][ - + ]: 216 : rval = check_face_sense_tag( true );MB_CHK_SET_ERR( rval, "Failed to verify the face sense tag" );
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ]
829 : :
830 : 216 : EntityHandle sense_data[2] = { 0, 0 };
831 [ + - ]: 216 : rval = mdbImpl->tag_get_data( sense2Tag, &entity, 1, sense_data );
832 [ + - ][ - + ]: 216 : if( MB_TAG_NOT_FOUND != rval && MB_SUCCESS != rval ) MB_CHK_SET_ERR( rval, "Failed to get the sense2Tag data" );
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
833 : :
834 [ - + ]: 216 : if( 0 == sense )
835 : : {
836 [ # # ][ # # ]: 0 : if( 0 != sense_data[0] && wrt_entity != sense_data[0] ) return MB_MULTIPLE_ENTITIES_FOUND;
837 [ # # ][ # # ]: 0 : if( 0 != sense_data[1] && wrt_entity != sense_data[1] ) return MB_MULTIPLE_ENTITIES_FOUND;
838 : 0 : sense_data[0] = sense_data[1] = wrt_entity;
839 : : }
840 [ + + ]: 216 : else if( -1 == sense )
841 : : {
842 [ - + ][ # # ]: 88 : if( 0 != sense_data[1] && wrt_entity != sense_data[1] ) return MB_MULTIPLE_ENTITIES_FOUND;
843 [ - + ]: 88 : if( sense_data[1] == wrt_entity ) return MB_SUCCESS; // already set as we want
844 : 88 : sense_data[1] = wrt_entity;
845 : : }
846 [ + - ]: 128 : else if( 1 == sense )
847 : : {
848 [ - + ][ # # ]: 128 : if( 0 != sense_data[0] && wrt_entity != sense_data[0] ) return MB_MULTIPLE_ENTITIES_FOUND;
849 [ - + ]: 128 : if( sense_data[0] == wrt_entity ) return MB_SUCCESS; // already set as we want
850 : 128 : sense_data[0] = wrt_entity;
851 : : }
852 [ + - ]: 216 : return mdbImpl->tag_set_data( sense2Tag, &entity, 1, sense_data );
853 : : }
854 : 320 : return MB_SUCCESS;
855 : : }
856 : :
857 : : //! Get the sense of entity with respect to wrt_entity
858 : : //! Returns MB_ENTITY_NOT_FOUND if no relationship found
859 : 2002 : ErrorCode GeomTopoTool::get_sense( EntityHandle entity, EntityHandle wrt_entity, int& sense )
860 : : {
861 : : // entity is lower dim (edge or face), wrt_entity is face or volume
862 : 2002 : int edim = dimension( entity );
863 : 2002 : int wrtdim = dimension( wrt_entity );
864 [ + - ][ - + ]: 2002 : if( -1 == edim || -1 == wrtdim ) MB_SET_ERR( MB_FAILURE, "Non-geometric entity provided" );
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ]
865 [ - + ][ # # ]: 2002 : if( wrtdim - edim != 1 ) MB_SET_ERR( MB_FAILURE, "Entity dimension mismatch" );
[ # # ][ # # ]
[ # # ][ # # ]
866 : :
867 : : ErrorCode rval;
868 : :
869 [ + + ]: 2002 : if( 1 == edim )
870 : : {
871 : : // edge in face
872 [ + - ][ - + ]: 17 : rval = check_edge_sense_tags( false );MB_CHK_SET_ERR( rval, "Failed to check the curve to surface sense tag handles" );
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ]
873 : :
874 [ + - ]: 17 : std::vector< EntityHandle > faces;
875 [ + - ][ + - ]: 34 : std::vector< int > senses;
876 [ + - ]: 17 : rval = get_senses( entity, faces, senses ); // the tags should be defined here
877 [ - + ][ # # ]: 17 : MB_CHK_SET_ERR( rval, "Failed to get the curve to surface sense data" );
[ # # ][ # # ]
[ # # ][ # # ]
878 : :
879 [ + - ]: 17 : std::vector< EntityHandle >::iterator it = std::find( faces.begin(), faces.end(), wrt_entity );
880 [ + - ][ - + ]: 17 : if( it == faces.end() ) return MB_ENTITY_NOT_FOUND;
881 [ + - ]: 17 : unsigned int index = it - faces.begin();
882 [ + - ][ + - ]: 34 : sense = senses[index];
883 : : }
884 : : else
885 : : {
886 : : // face in volume
887 [ + - ][ - + ]: 1985 : rval = check_face_sense_tag( false );MB_CHK_SET_ERR( rval, "Failed to check the surface to volume sense tag handle" );
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ]
888 : 1985 : EntityHandle sense_data[2] = { 0, 0 };
889 [ + - ]: 1985 : rval = mdbImpl->tag_get_data( sense2Tag, &entity, 1, sense_data );
890 [ + - ][ - + ]: 1985 : if( MB_TAG_NOT_FOUND != rval && MB_SUCCESS != rval )
891 [ # # ][ # # ]: 0 : MB_CHK_SET_ERR( rval, "Failed to get the surface to volume sense data" );
[ # # ][ # # ]
[ # # ][ # # ]
892 [ + + ][ - + ]: 1985 : if( ( wrt_entity == sense_data[0] ) && ( wrt_entity == sense_data[1] ) )
893 : 0 : sense = 0;
894 [ + + ]: 1985 : else if( wrt_entity == sense_data[0] )
895 : 1972 : sense = 1;
896 [ + - ]: 13 : else if( wrt_entity == sense_data[1] )
897 : 13 : sense = -1;
898 : : else
899 : 1985 : return MB_ENTITY_NOT_FOUND;
900 : : }
901 : 2002 : return MB_SUCCESS;
902 : : }
903 : :
904 : 832 : ErrorCode GeomTopoTool::get_surface_senses( EntityHandle surface_ent, EntityHandle& forward_vol,
905 : : EntityHandle& reverse_vol )
906 : : {
907 : : ErrorCode rval;
908 : : // this method should only be called to retrieve surface to volume
909 : : // sense relationships
910 [ + - ]: 832 : int ent_dim = dimension( surface_ent );
911 : : // verify the incoming entity dimensions for this call
912 [ - + ][ # # ]: 832 : if( ent_dim != 2 ) { MB_SET_ERR( MB_FAILURE, "Entity dimension is incorrect for surface meshset" ); }
[ # # ][ # # ]
[ # # ][ # # ]
913 : :
914 : : // get the sense information for this surface
915 : 832 : EntityHandle parent_vols[2] = { 0, 0 };
916 [ + - ][ - + ]: 832 : rval = mdbImpl->tag_get_data( sense2Tag, &surface_ent, 1, parent_vols );MB_CHK_SET_ERR( rval, "Failed to get surface sense data" );
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ]
917 : :
918 : : // set the outgoing values
919 : 832 : forward_vol = parent_vols[0];
920 : 832 : reverse_vol = parent_vols[1];
921 : :
922 : 832 : return MB_SUCCESS;
923 : : }
924 : :
925 : 114 : ErrorCode GeomTopoTool::set_surface_senses( EntityHandle surface_ent, EntityHandle forward_vol,
926 : : EntityHandle reverse_vol )
927 : : {
928 : : ErrorCode rval;
929 : : // this mthod should only be called to retrieve surface to volume
930 : : // sense relationships
931 [ + - ]: 114 : int ent_dim = dimension( surface_ent );
932 : : // verify the incoming entity dimensions for this call
933 [ - + ][ # # ]: 114 : if( ent_dim != 2 ) { MB_SET_ERR( MB_FAILURE, "Entity dimension is incorrect for surface meshset" ); }
[ # # ][ # # ]
[ # # ][ # # ]
934 : :
935 : : // set the sense information for this surface
936 : 114 : EntityHandle parent_vols[2] = { forward_vol, reverse_vol };
937 [ + - ][ - + ]: 114 : rval = mdbImpl->tag_set_data( sense2Tag, &surface_ent, 1, parent_vols );MB_CHK_SET_ERR( rval, "Failed to set surface sense data" );
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ]
938 : :
939 : 114 : return MB_SUCCESS;
940 : : }
941 : :
942 : : // get sense of surface(s) wrt volume
943 : 128 : ErrorCode GeomTopoTool::get_surface_senses( EntityHandle volume, int num_surfaces, const EntityHandle* surfaces,
944 : : int* senses_out )
945 : : {
946 : :
947 : : /* The sense tags do not reference the implicit complement handle.
948 : : All surfaces that interact with the implicit complement should have
949 : : a null handle in the direction of the implicit complement. */
950 : : // if (volume == impl_compl_handle)
951 : : // volume = (EntityHandle) 0;
952 : :
953 [ + + ]: 1196 : for( int surf_num = 0; surf_num < num_surfaces; surf_num++ )
954 : : {
955 : 1068 : get_sense( surfaces[surf_num], volume, senses_out[surf_num] );
956 : : }
957 : :
958 : 128 : return MB_SUCCESS;
959 : : }
960 : :
961 : 192 : ErrorCode GeomTopoTool::get_senses( EntityHandle entity, std::vector< EntityHandle >& wrt_entities,
962 : : std::vector< int >& senses )
963 : : {
964 : : // the question here is: the wrt_entities is supplied or not?
965 : : // I assume not, we will obtain it !!
966 : 192 : int edim = dimension( entity );
967 : :
968 [ - + ][ # # ]: 192 : if( -1 == edim ) MB_SET_ERR( MB_FAILURE, "Non-geometric entity provided" );
[ # # ][ # # ]
[ # # ][ # # ]
969 : :
970 : : ErrorCode rval;
971 : 192 : wrt_entities.clear();
972 : 192 : senses.clear();
973 : :
974 [ + + ]: 192 : if( 1 == edim ) // edge
975 : : {
976 [ + - ][ - + ]: 181 : rval = check_edge_sense_tags( false );MB_CHK_SET_ERR( rval, "Failed to check the curve to surface sense tag handles" );
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ]
977 : : const void* dum_ptr;
978 : : int num_ents;
979 [ + - ][ + + ]: 181 : rval = mdbImpl->tag_get_by_ptr( senseNEntsTag, &entity, 1, &dum_ptr, &num_ents );MB_CHK_ERR( rval );
[ - + ][ + - ]
980 : :
981 : 121 : const EntityHandle* ents_data = static_cast< const EntityHandle* >( dum_ptr );
982 [ + - ][ + - ]: 121 : std::copy( ents_data, ents_data + num_ents, std::back_inserter( wrt_entities ) );
983 : :
984 [ + - ][ - + ]: 121 : rval = mdbImpl->tag_get_by_ptr( senseNSensesTag, &entity, 1, &dum_ptr, &num_ents );MB_CHK_ERR( rval );
[ # # ][ # # ]
985 : :
986 : 121 : const int* senses_data = static_cast< const int* >( dum_ptr );
987 [ + - ][ + - ]: 181 : std::copy( senses_data, senses_data + num_ents, std::back_inserter( senses ) );
988 : : }
989 : : else // face in volume, edim == 2
990 : : {
991 [ + - ][ - + ]: 11 : rval = check_face_sense_tag( false );MB_CHK_SET_ERR( rval, "Failed to check the surface to volume sense tag handle" );
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ]
992 : 11 : EntityHandle sense_data[2] = { 0, 0 };
993 [ + - ][ - + ]: 11 : rval = mdbImpl->tag_get_data( sense2Tag, &entity, 1, sense_data );MB_CHK_SET_ERR( rval, "Failed to get the surface to volume sense data" );
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ]
994 [ + + ][ - + ]: 11 : if( sense_data[0] != 0 && sense_data[1] == sense_data[0] )
995 : : {
996 [ # # ]: 0 : wrt_entities.push_back( sense_data[0] );
997 [ # # ]: 0 : senses.push_back( 0 ); // both
998 : : }
999 : : else
1000 : : {
1001 [ + + ]: 11 : if( sense_data[0] != 0 )
1002 : : {
1003 [ + - ]: 5 : wrt_entities.push_back( sense_data[0] );
1004 [ + - ]: 5 : senses.push_back( 1 );
1005 : : }
1006 [ + + ]: 11 : if( sense_data[1] != 0 )
1007 : : {
1008 [ + - ]: 1 : wrt_entities.push_back( sense_data[1] );
1009 [ + - ]: 11 : senses.push_back( -1 );
1010 : : }
1011 : : }
1012 : : }
1013 : : // filter the results with the sets that are in the model at this time
1014 : : // this was introduced because extracting some sets (e.g. neumann set, with mbconvert)
1015 : : // from a model would leave some sense tags not defined correctly
1016 : : // also, the geom ent set really needs to be part of the current model set
1017 : 132 : unsigned int currentSize = 0;
1018 : :
1019 [ + + ]: 303 : for( unsigned int index = 0; index < wrt_entities.size(); index++ )
1020 : : {
1021 [ + - ]: 171 : EntityHandle wrt_ent = wrt_entities[index];
1022 [ + - ]: 171 : if( wrt_ent )
1023 : : {
1024 [ + - ][ + - ]: 171 : if( mdbImpl->contains_entities( modelSet, &wrt_ent, 1 ) )
1025 : : {
1026 [ + - ][ + - ]: 171 : wrt_entities[currentSize] = wrt_entities[index];
1027 [ + - ][ + - ]: 171 : senses[currentSize] = senses[index];
1028 : 171 : currentSize++;
1029 : : }
1030 : : }
1031 : : }
1032 : 132 : wrt_entities.resize( currentSize );
1033 : 132 : senses.resize( currentSize );
1034 : : //
1035 : 192 : return MB_SUCCESS;
1036 : : }
1037 : :
1038 : 48 : ErrorCode GeomTopoTool::set_senses( EntityHandle entity, std::vector< EntityHandle >& wrt_entities,
1039 : : std::vector< int >& senses )
1040 : : {
1041 : : // not efficient, and maybe wrong
1042 [ + + ]: 106 : for( unsigned int i = 0; i < wrt_entities.size(); i++ )
1043 : : {
1044 [ - + ][ # # ]: 58 : ErrorCode rval = set_sense( entity, wrt_entities[i], senses[i] );MB_CHK_SET_ERR( rval, "Failed to set the sense" );
[ # # ][ # # ]
[ # # ][ # # ]
1045 : : }
1046 : :
1047 : 48 : return MB_SUCCESS;
1048 : : }
1049 : :
1050 : 4 : ErrorCode GeomTopoTool::next_vol( EntityHandle surface, EntityHandle old_volume, EntityHandle& new_volume )
1051 : : {
1052 [ + - ]: 4 : std::vector< EntityHandle > parents;
1053 [ + - ]: 4 : ErrorCode rval = mdbImpl->get_parent_meshsets( surface, parents );
1054 : :
1055 [ + - ]: 4 : if( MB_SUCCESS == rval )
1056 : : {
1057 [ - + ]: 4 : if( parents.size() != 2 )
1058 : 0 : rval = MB_FAILURE;
1059 [ + - ][ + + ]: 4 : else if( parents.front() == old_volume )
1060 [ + - ]: 2 : new_volume = parents.back();
1061 [ + - ][ + - ]: 2 : else if( parents.back() == old_volume )
1062 [ + - ]: 2 : new_volume = parents.front();
1063 : : else
1064 : 4 : rval = MB_FAILURE;
1065 : : }
1066 : :
1067 [ - + ]: 4 : if( rval != MB_SUCCESS )
1068 : : {
1069 [ # # ][ # # ]: 0 : std::cerr << "mesh error in next_vol for surf " << surface
1070 [ # # ]: 0 : << std::endl; // todo: use geomtopotool to get id by entity handle
1071 : : }
1072 : :
1073 : 4 : return rval;
1074 : : }
1075 : :
1076 : 86 : ErrorCode GeomTopoTool::check_geom_tag( bool create )
1077 : : {
1078 : : ErrorCode rval;
1079 [ + + ]: 86 : unsigned flags = create ? MB_TAG_DENSE | MB_TAG_CREAT : MB_TAG_DENSE;
1080 [ - + ]: 86 : if( !geomTag )
1081 : : {
1082 : : // get any kind of tag that already exists
1083 [ # # ][ # # ]: 0 : rval = mdbImpl->tag_get_handle( GEOM_DIMENSION_TAG_NAME, 1, MB_TYPE_INTEGER, geomTag, flags );MB_CHK_SET_ERR( rval, "Could not get/create the geometry dimension tag" );
[ # # ][ # # ]
[ # # ][ # # ]
1084 : : }
1085 : 86 : return MB_SUCCESS;
1086 : : }
1087 : :
1088 : 10 : ErrorCode GeomTopoTool::check_gid_tag( bool create )
1089 : : {
1090 : : ErrorCode rval;
1091 [ + - ]: 10 : unsigned flags = create ? MB_TAG_DENSE | MB_TAG_CREAT : MB_TAG_DENSE;
1092 [ - + ]: 10 : if( !gidTag )
1093 : : {
1094 : : // get any kind of tag that already exists
1095 [ # # ][ # # ]: 0 : rval = mdbImpl->tag_get_handle( GLOBAL_ID_TAG_NAME, 1, MB_TYPE_INTEGER, gidTag, flags );MB_CHK_SET_ERR( rval, "Could not get/create the global id tag" );
[ # # ][ # # ]
[ # # ][ # # ]
1096 : : }
1097 : 10 : return MB_SUCCESS;
1098 : : }
1099 : :
1100 : : // move the sense tag existence creation in private methods
1101 : : // verify sense face tag
1102 : 2265 : ErrorCode GeomTopoTool::check_face_sense_tag( bool create )
1103 : : {
1104 : : ErrorCode rval;
1105 [ + + ]: 2265 : unsigned flags = create ? MB_TAG_SPARSE | MB_TAG_CREAT | MB_TAG_ANY : MB_TAG_SPARSE | MB_TAG_ANY;
1106 [ + + ]: 2265 : if( !sense2Tag )
1107 : : {
1108 : 172 : EntityHandle def_val[2] = { 0, 0 };
1109 [ + - ][ - + ]: 172 : rval = mdbImpl->tag_get_handle( GEOM_SENSE_2_TAG_NAME, 2, MB_TYPE_HANDLE, sense2Tag, flags, def_val );MB_CHK_SET_ERR( rval, "Could not get/create the sense2Tag" );
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ]
1110 : : }
1111 : 2265 : return MB_SUCCESS;
1112 : : }
1113 : :
1114 : : // verify sense edge tags
1115 : 306 : ErrorCode GeomTopoTool::check_edge_sense_tags( bool create )
1116 : : {
1117 : : ErrorCode rval;
1118 : 306 : unsigned flags = MB_TAG_VARLEN | MB_TAG_SPARSE;
1119 [ + + ]: 306 : if( create ) flags |= MB_TAG_CREAT;
1120 [ + + ]: 306 : if( !senseNEntsTag )
1121 : : {
1122 [ - + ][ # # ]: 17 : rval = mdbImpl->tag_get_handle( GEOM_SENSE_N_ENTS_TAG_NAME, 0, MB_TYPE_HANDLE, senseNEntsTag, flags );MB_CHK_SET_ERR( rval, "Failed to get the curve to surface entity tag handle" );
[ # # ][ # # ]
[ # # ][ # # ]
1123 [ - + ][ # # ]: 17 : rval = mdbImpl->tag_get_handle( GEOM_SENSE_N_SENSES_TAG_NAME, 0, MB_TYPE_INTEGER, senseNSensesTag, flags );MB_CHK_SET_ERR( rval, "Failed to get the curve to surface sense tag handle" );
[ # # ][ # # ]
[ # # ][ # # ]
1124 : : }
1125 : 306 : return MB_SUCCESS;
1126 : : }
1127 : :
1128 : 93 : ErrorCode GeomTopoTool::add_geo_set( EntityHandle set, int dim, int gid )
1129 : : {
1130 [ + - ][ - + ]: 93 : if( dim < 0 || dim > 4 ) MB_SET_ERR( MB_FAILURE, "Invalid geometric dimension provided" );
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ]
1131 : :
1132 : : // see if it is not already set
1133 [ + - ][ + - ]: 93 : if( geomRanges[dim].find( set ) != geomRanges[dim].end() )
[ - + ]
1134 : : {
1135 : 0 : return MB_SUCCESS; // nothing to do, we already have it as a geo set of proper dimension
1136 : : }
1137 : 93 : updated = false; // this should trigger at least an obb recomputation
1138 : : // get the geom topology tag
1139 : : ErrorCode result;
1140 [ - + ]: 93 : if( 0 == geomTag )
1141 : : {
1142 [ # # ][ # # ]: 0 : result = mdbImpl->tag_get_handle( GEOM_DIMENSION_TAG_NAME, 1, MB_TYPE_INTEGER, geomTag );MB_CHK_SET_ERR( result, "Failed to get the geometry dimension tag handle" );
[ # # ][ # # ]
[ # # ][ # # ]
1143 : : }
1144 : :
1145 [ - + ]: 93 : if( 0 == gidTag ) { gidTag = mdbImpl->globalId_tag(); }
1146 : :
1147 : : // make sure the added set has the geom tag properly set
1148 [ - + ][ # # ]: 93 : result = mdbImpl->tag_set_data( geomTag, &set, 1, &dim );MB_CHK_SET_ERR( result, "Failed set the geometry dimension tag value" );
[ # # ][ # # ]
[ # # ][ # # ]
1149 : :
1150 : 93 : geomRanges[dim].insert( set );
1151 : : // not only that, but also add it to the root model set
1152 [ - + ]: 93 : if( modelSet )
1153 : : {
1154 [ # # ][ # # ]: 0 : result = mdbImpl->add_entities( modelSet, &set, 1 );MB_CHK_SET_ERR( result, "Failed to add new geometry set to the tool's modelSet" );
[ # # ][ # # ]
[ # # ][ # # ]
1155 : : }
1156 : :
1157 : : // set the global ID value
1158 : : // if passed 0, just increase the max id for the dimension
1159 [ + - ]: 93 : if( 0 == gid ) { gid = ++maxGlobalId[dim]; }
1160 : :
1161 [ - + ][ # # ]: 93 : result = mdbImpl->tag_set_data( gidTag, &set, 1, &gid );MB_CHK_SET_ERR( result, "Failed to get the global id tag value for the geom entity" );
[ # # ][ # # ]
[ # # ][ # # ]
1162 : :
1163 : 93 : return MB_SUCCESS;
1164 : : }
1165 : :
1166 : : // will assume no geo sets are defined for this surface
1167 : : // will output a mesh_set that contains everything (all sets of interest), for proper output
1168 : 1 : ErrorCode GeomTopoTool::geometrize_surface_set( EntityHandle surface, EntityHandle& output )
1169 : : {
1170 : : // usual scenario is to read a surface smf file, and "geometrize" it, and output it as a
1171 : : // h5m file with proper sets, tags defined for mesh-based geometry
1172 : :
1173 : : // get all triangles/quads from the surface, then build loops
1174 : : // we may even have to
1175 : : // proper care has to be given to the orientation, material to the left!!!
1176 : : // at some point we may have to reorient triangles, not only edges, for proper definition
1177 : 1 : bool debugFlag = false;
1178 : :
1179 [ + - ][ + - ]: 2 : Range surface_ents, edge_ents, loop_range;
[ + - ]
1180 : :
1181 : : // most of these should be triangles and quads
1182 [ + - ][ - + ]: 1 : ErrorCode rval = mdbImpl->get_entities_by_dimension( surface, 2, surface_ents );MB_CHK_SET_ERR( rval, "Failed to get the surface entities" );
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ]
1183 : :
1184 : 1 : EntityHandle face = surface;
1185 [ + - ]: 1 : if( !surface ) // in the case it is root set, create another set
1186 : : {
1187 [ + - ][ - + ]: 1 : rval = mdbImpl->create_meshset( MESHSET_SET, face );MB_CHK_SET_ERR( rval, "Failed to create a the new surface meshset" );
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ]
1188 : : }
1189 : : // set the geo tag
1190 [ + - ][ - + ]: 1 : rval = add_geo_set( face, 2 );MB_CHK_SET_ERR( rval, "Failed to add the geometry set to the tool" );
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ]
1191 : :
1192 : : // this will be our output set, will contain all our new geo sets
1193 [ + - ][ - + ]: 1 : rval = mdbImpl->create_meshset( MESHSET_SET, output );MB_CHK_SET_ERR( rval, "Failed to create the output meshset" );
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ]
1194 : :
1195 : : // add first geo set (face) to the output set
1196 [ + - ][ - + ]: 1 : rval = mdbImpl->add_entities( output, &face, 1 );MB_CHK_SET_ERR( rval, "Failed to add the new meshset to the output meshset" );
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ]
1197 : :
1198 : : // how many edges do we need to create?
1199 : : // depends on how many loops we have
1200 : : // also, we should avoid non-manifold topology
1201 [ + - ]: 1 : if( !surface )
1202 : : { // in this case, surface is root, so we have to add entities
1203 [ + - ][ - + ]: 1 : rval = mdbImpl->add_entities( face, surface_ents );MB_CHK_SET_ERR( rval, "Failed to add surface entities to the surface meshset" );
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ]
1204 : : }
1205 : :
1206 [ + - ]: 2 : Skinner tool( mdbImpl );
1207 [ + - ][ - + ]: 1 : rval = tool.find_skin( 0, surface_ents, 1, edge_ents );MB_CHK_SET_ERR( rval, "Failed to skin the surface entities" );
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ]
1208 [ - + ]: 1 : if( debugFlag )
1209 : : {
1210 [ # # ][ # # ]: 0 : std::cout << "skinning edges: " << edge_ents.size() << "\n";
[ # # ][ # # ]
1211 [ # # ][ # # ]: 0 : for( Range::iterator it = edge_ents.begin(); it != edge_ents.end(); ++it )
[ # # ][ # # ]
[ # # ]
1212 : : {
1213 [ # # ]: 0 : EntityHandle ed = *it;
1214 [ # # ][ # # ]: 0 : std::cout << "edge: " << mdbImpl->id_from_handle( ed ) << " type:" << mdbImpl->type_from_handle( ed )
[ # # ][ # # ]
[ # # ][ # # ]
1215 [ # # ]: 0 : << "\n";
1216 [ # # ][ # # ]: 0 : std::cout << mdbImpl->list_entity( ed );
1217 : : }
1218 : : }
1219 : :
1220 [ + - ]: 2 : std::vector< EntityHandle > edges_loop;
1221 : :
1222 [ + - ]: 2 : Range pool_of_edges = edge_ents;
1223 [ + - ]: 2 : Range used_edges; // these edges are already used for some loops
1224 : : // get a new one
1225 : :
1226 [ + - ][ + + ]: 2 : while( !pool_of_edges.empty() )
1227 : : {
1228 : : // get the first edge, and start a loop with it
1229 [ + - ]: 1 : EntityHandle current_edge = pool_of_edges[0];
1230 [ - + ]: 1 : if( debugFlag )
1231 : : {
1232 [ # # ][ # # ]: 0 : std::cout << "Start current edge: " << mdbImpl->id_from_handle( current_edge ) << "\n ";
[ # # ][ # # ]
1233 [ # # ][ # # ]: 0 : std::cout << mdbImpl->list_entity( current_edge );
1234 : : }
1235 : : // get its triangle / quad and see its orientation
1236 [ + - ]: 1 : std::vector< EntityHandle > tris;
1237 [ + - ][ - + ]: 1 : rval = mdbImpl->get_adjacencies( ¤t_edge, 1, 2, false, tris );MB_CHK_SET_ERR( rval, "Failed to get the adjacent triangles to the current edge" );
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ]
1238 [ - + ][ # # ]: 1 : if( tris.size() != 1 ) MB_SET_ERR( MB_FAILURE, "Edge not on boundary" );
[ # # ][ # # ]
[ # # ][ # # ]
1239 : :
1240 : : int side_n, sense, offset;
1241 [ + - ][ + - ]: 1 : rval = mdbImpl->side_number( tris[0], current_edge, side_n, sense, offset );MB_CHK_SET_ERR( rval, "Failed to get the current edge's side number" );
[ - + ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
1242 : :
1243 : : const EntityHandle* conn2;
1244 : : int nnodes2;
1245 [ + - ][ - + ]: 1 : rval = mdbImpl->get_connectivity( current_edge, conn2, nnodes2 );MB_CHK_SET_ERR( rval, "Failed to get the current edge's connectivity" );
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ]
1246 : :
1247 [ - + ][ # # ]: 1 : if( nnodes2 != 2 ) MB_SET_ERR( MB_FAILURE, "Incorrect number of nodes found." );
[ # # ][ # # ]
[ # # ][ # # ]
1248 : :
1249 : 1 : EntityHandle start_node = conn2[0];
1250 : 1 : EntityHandle next_node = conn2[1];
1251 : :
1252 [ - + ]: 1 : if( sense == -1 )
1253 : : {
1254 : : // revert the edge, and start well
1255 : 0 : EntityHandle nn2[2] = { conn2[1], conn2[0] };
1256 [ # # ][ # # ]: 0 : rval = mdbImpl->set_connectivity( current_edge, nn2, 2 );MB_CHK_SET_ERR( rval, "Failed to set the connectivity of the current edge" );
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ]
1257 : :
1258 : 0 : start_node = nn2[0]; // or conn2[0] !!! beware: conn2 is modified
1259 : 0 : next_node = nn2[1]; // or conn2[1] !!!
1260 : : // reset connectivity of edge
1261 [ # # ][ # # ]: 0 : if( debugFlag ) std::cout << " current edge needs reversed\n";
1262 : : }
1263 : : // start a new loop of edges
1264 : 1 : edges_loop.clear(); // every edge loop starts fresh
1265 [ + - ]: 1 : edges_loop.push_back( current_edge );
1266 [ + - ]: 1 : used_edges.insert( current_edge );
1267 [ + - ]: 1 : pool_of_edges.erase( current_edge );
1268 : :
1269 [ - + ]: 1 : if( debugFlag )
1270 : : {
1271 [ # # ][ # # ]: 0 : std::cout << " start node: " << start_node << "\n";
[ # # ]
1272 [ # # ][ # # ]: 0 : std::cout << mdbImpl->list_entity( start_node );
1273 [ # # ][ # # ]: 0 : std::cout << " next node: " << next_node << "\n";
[ # # ]
1274 [ # # ][ # # ]: 0 : std::cout << mdbImpl->list_entity( next_node );
1275 : : }
1276 [ + + ]: 200 : while( next_node != start_node )
1277 : : {
1278 : : // find the next edge in the skin
1279 [ + - ]: 199 : std::vector< EntityHandle > candidate_edges;
1280 [ + - ][ - + ]: 199 : rval = mdbImpl->get_adjacencies( &next_node, 1, 1, false, candidate_edges );MB_CHK_SET_ERR( rval, "Failed to get the adjacent edges to the next node" );
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ]
1281 : : // filter the edges that are used, or the edges not in the skin
1282 [ + - ][ + - ]: 398 : std::vector< EntityHandle > good_edges;
1283 [ + + ]: 597 : for( int k = 0; k < (int)candidate_edges.size(); k++ )
1284 : : {
1285 [ + - ]: 398 : EntityHandle edg = candidate_edges[k];
1286 [ + - ][ + - ]: 398 : if( used_edges.find( edg ) != used_edges.end() ) continue;
[ + - ][ + + ]
1287 [ + - ][ + - ]: 199 : if( pool_of_edges.find( edg ) != pool_of_edges.end() ) good_edges.push_back( edg );
[ + - ][ + - ]
[ + - ]
1288 : : }
1289 [ - + ]: 199 : if( good_edges.size() != 1 )
1290 : : {
1291 [ # # ][ # # ]: 0 : std::cout << " good_edges.size()=" << good_edges.size() << " STOP\n";
[ # # ]
1292 [ # # ][ # # ]: 0 : MB_SET_ERR( MB_FAILURE, "Number of good edges is not one. Could not complete the loop" );
[ # # ][ # # ]
[ # # ]
1293 : : }
1294 : : // see if the orientation is good; if not, revert it
1295 : :
1296 [ + - ]: 199 : current_edge = good_edges[0];
1297 [ + - ][ - + ]: 199 : rval = mdbImpl->get_connectivity( current_edge, conn2, nnodes2 );MB_CHK_SET_ERR( rval, "Failed to get the connectivity of the current edge" );
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ]
1298 [ - + ][ # # ]: 199 : if( nnodes2 != 2 ) MB_SET_ERR( MB_FAILURE, "Incorrect number of nodes found" );
[ # # ][ # # ]
[ # # ][ # # ]
1299 : :
1300 [ - + ]: 199 : if( conn2[0] != next_node )
1301 : : {
1302 [ # # ]: 0 : if( conn2[1] != next_node )
1303 : : {
1304 : : // the edge is not connected then to current edge
1305 : : // bail out
1306 [ # # ][ # # ]: 0 : std::cout << "edge " << mdbImpl->id_from_handle( current_edge ) << " not connected to node "
[ # # ][ # # ]
1307 [ # # ][ # # ]: 0 : << next_node << "\n";
1308 [ # # ][ # # ]: 0 : MB_SET_ERR( MB_FAILURE, "Current edge is not connected to node" );
[ # # ][ # # ]
[ # # ]
1309 : : ;
1310 : : }
1311 [ # # ]: 0 : if( debugFlag )
1312 : : {
1313 [ # # ][ # # ]: 0 : std::cout << " revert edge " << mdbImpl->id_from_handle( current_edge ) << "\n";
[ # # ][ # # ]
1314 [ # # ][ # # ]: 0 : std::cout << mdbImpl->list_entity( current_edge );
1315 : : }
1316 : : // orientation should be reversed
1317 : 0 : EntityHandle nn2[2] = { conn2[1], conn2[0] };
1318 [ # # ][ # # ]: 0 : rval = mdbImpl->set_connectivity( current_edge, nn2, 2 );MB_CHK_SET_ERR( rval, "Failed to set the connectivity of the current edge" );
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ]
1319 : :
1320 : : {
1321 [ # # ][ # # ]: 0 : std::cout << "after revert edge " << mdbImpl->id_from_handle( current_edge ) << "\n";
[ # # ][ # # ]
1322 [ # # ][ # # ]: 0 : std::cout << mdbImpl->list_entity( current_edge );
1323 [ # # ][ # # ]: 0 : std::cout << " conn2: " << conn2[0] << " " << conn2[1] << "\n";
[ # # ][ # # ]
[ # # ]
1324 : : }
1325 : : }
1326 : : // before reversion, conn2 was something { n1, next_node}
1327 : : // after reversion, conn2 became {next_node, n1}, so the
1328 : : // new next node will be still conn2[1]; big surprise, as
1329 : : // I didn't expect the conn2 to change.
1330 : : // it seems that const EntityHandle * conn2 means conn2 cannot be
1331 : : // changed, but what is pointed to by it will change when we reset connectivity for edge
1332 : 199 : next_node = conn2[1];
1333 : :
1334 [ - + ]: 199 : if( debugFlag )
1335 : : {
1336 [ # # ][ # # ]: 0 : std::cout << " current edge: " << mdbImpl->id_from_handle( current_edge ) << "\n ";
[ # # ][ # # ]
1337 [ # # ][ # # ]: 0 : std::cout << mdbImpl->list_entity( current_edge );
1338 [ # # ][ # # ]: 0 : std::cout << "next node: " << next_node << "\n ";
[ # # ]
1339 [ # # ][ # # ]: 0 : std::cout << mdbImpl->list_entity( next_node );
1340 : : }
1341 [ + - ]: 199 : edges_loop.push_back( current_edge );
1342 [ + - ]: 199 : used_edges.insert( current_edge );
1343 [ + - ][ + - ]: 199 : pool_of_edges.erase( current_edge );
1344 : 199 : }
1345 : : // at this point, we have a loop formed;
1346 : : // create a geo edge, a vertex set, and add it to our sets
1347 : :
1348 : : EntityHandle edge;
1349 [ + - ][ - + ]: 1 : rval = mdbImpl->create_meshset( MESHSET_ORDERED, edge );MB_CHK_SET_ERR( rval, "Failed to create the edge meshset" );
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ]
1350 : :
1351 [ + - ][ - + ]: 1 : rval = add_geo_set( edge, 1 );MB_CHK_SET_ERR( rval, "Failed to add the edge meshset to the tool's model set" );
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ]
1352 : : // add the mesh edges:
1353 : : // add loops edges to the edge set
1354 [ + - ][ + - ]: 1 : rval = mdbImpl->add_entities( edge, &edges_loop[0], edges_loop.size() ); //
1355 [ - + ][ # # ]: 1 : MB_CHK_SET_ERR( rval, "Failed to add entities to the edge meshset" );
[ # # ][ # # ]
[ # # ][ # # ]
1356 : : // create a vertex set
1357 : : EntityHandle vertex;
1358 [ + - ][ - + ]: 1 : rval = mdbImpl->create_meshset( MESHSET_SET, vertex );MB_CHK_SET_ERR( rval, "Failed to create the vertex meshset" );
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ]
1359 [ + - ][ - + ]: 1 : rval = add_geo_set( vertex, 0 );MB_CHK_SET_ERR( rval, "Failed to add the vertex meshset to the tool's model set" );
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ]
1360 : : // add one node to the vertex set
1361 : :
1362 [ + - ]: 1 : rval = mdbImpl->add_entities( vertex, &start_node, 1 ); //
1363 [ - + ][ # # ]: 1 : MB_CHK_SET_ERR( rval, "Failed to add entities to the vertex meshset" );
[ # # ][ # # ]
[ # # ][ # # ]
1364 : :
1365 [ + - ][ - + ]: 1 : rval = mdbImpl->add_parent_child( face, edge );MB_CHK_SET_ERR( rval, "Failed to create the edge to face parent child relationship" );
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ]
1366 : :
1367 [ + - ][ - + ]: 1 : rval = mdbImpl->add_parent_child( edge, vertex );MB_CHK_SET_ERR( rval, "Failed to create the vertex to edge parent child relationship" );
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ]
1368 : :
1369 : : // the sense of the edge in face is for sure positive (forward)
1370 [ + - ]: 1 : rval = set_sense( edge, face, 1 ); //
1371 [ - + ][ # # ]: 1 : MB_CHK_SET_ERR( rval, "Failed to set the edge to face sense" );
[ # # ][ # # ]
[ # # ][ # # ]
1372 : : // also add our sets to the output set, to be sure to be exported
1373 : :
1374 [ + - ][ - + ]: 1 : rval = mdbImpl->add_entities( output, &edge, 1 );MB_CHK_SET_ERR( rval, "Failed to add the edge meshset to the output set" );
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ]
1375 [ + - ][ - + ]: 1 : rval = mdbImpl->add_entities( output, &vertex, 1 );MB_CHK_SET_ERR( rval, "Failed to add the vertex meshset to the output set" );
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ]
1376 : :
1377 [ - + ]: 1 : if( debugFlag )
1378 [ # # ][ # # ]: 1 : { std::cout << "add edge with start node " << start_node << " with " << edges_loop.size() << " edges\n"; }
[ # # ][ # # ]
[ # # ][ + - ]
1379 : 1 : }
1380 : :
1381 : 2 : return MB_SUCCESS;
1382 : : }
1383 : :
1384 : : /*
1385 : : * This would create a deep copy of the geom topo model, into a new geom topo tool
1386 : : * sets will be duplicated, but entities not
1387 : : * modelSet will be a new one
1388 : : * if the original set was null (root), a new model set will be created for
1389 : : * original model, and its entities will be the original g sets
1390 : : * Scenario: split a face along a ground line, then write only one surface
1391 : : * the common line has 2 faces in var len tag for sense edge; if we write only one
1392 : : * surface to a new database, the var len tag of the edge will be extracted with 2 values, but
1393 : : * only one value will make sense, the other will be zero.
1394 : : *
1395 : : * There is no workaround; we need to create a duplicate model that has only that surface
1396 : : * and its children (and grand-children). Then the var len sense edge-face tags will have
1397 : : * the right size.
1398 : : *
1399 : : */
1400 : 4 : ErrorCode GeomTopoTool::duplicate_model( GeomTopoTool*& duplicate, std::vector< EntityHandle >* pvGEnts )
1401 : : {
1402 : : // will
1403 : : EntityHandle rootModelSet;
1404 [ + - ][ - + ]: 4 : ErrorCode rval = mdbImpl->create_meshset( MESHSET_SET, rootModelSet );MB_CHK_SET_ERR( rval, "Failed to create the rootModelSet" );
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ]
1405 : :
1406 [ - + ]: 4 : if( 0 == geomTag )
1407 : : {
1408 [ # # ][ # # ]: 0 : rval = mdbImpl->tag_get_handle( GEOM_DIMENSION_TAG_NAME, 1, MB_TYPE_INTEGER, geomTag );MB_CHK_SET_ERR( rval, "Failed to get the geometry dimension tag handle" );
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ]
1409 : : }
1410 [ - + ][ # # ]: 4 : if( 0 == gidTag ) { gidTag = mdbImpl->globalId_tag(); }
1411 : : // extract from the geomSet the dimension, children, and grand-children
1412 [ + - ]: 4 : Range depSets; // dependents of the geomSet, including the geomSet
1413 : : // add in this range all the dependents of this, to filter the ones that need to be deep copied
1414 : :
1415 [ + + ]: 4 : if( pvGEnts != NULL )
1416 : : {
1417 : 2 : unsigned int numGents = pvGEnts->size();
1418 [ + + ]: 4 : for( unsigned int k = 0; k < numGents; k++ )
1419 : : {
1420 [ + - ]: 2 : EntityHandle geomSet = ( *pvGEnts )[k];
1421 : : // will keep accumulating to the depSets range
1422 [ + - ]: 2 : rval = mdbImpl->get_child_meshsets( geomSet, depSets, 0 ); // 0 for numHops means that all
1423 : : // dependents are returned, not only the direct children.
1424 [ - + ][ # # ]: 2 : MB_CHK_SET_ERR( rval, "Failed to get the geometry set's child meshsets" );
[ # # ][ # # ]
[ # # ][ # # ]
1425 : :
1426 [ + - ]: 2 : depSets.insert( geomSet );
1427 : : }
1428 : : }
1429 : :
1430 : : // add to the root model set copies of the gsets, with correct sets
1431 : : // keep a map between sets to help in copying parent/child relations
1432 [ + - ]: 8 : std::map< EntityHandle, EntityHandle > relate;
1433 : : // each set will get the same entities as the original
1434 [ + + ]: 24 : for( int dim = 0; dim < 5; dim++ )
1435 : : {
1436 : 20 : int gid = 0;
1437 [ + + ]: 20 : unsigned int set_options = ( ( 1 != dim ) ? MESHSET_SET : MESHSET_ORDERED );
1438 [ + - ][ + - ]: 95 : for( Range::iterator it = geomRanges[dim].begin(); it != geomRanges[dim].end(); ++it )
[ + - ][ + - ]
[ + + ]
1439 : : {
1440 [ + - ]: 75 : EntityHandle set = *it;
1441 [ + + ][ + - ]: 75 : if( pvGEnts != NULL && depSets.find( set ) == depSets.end() )
[ + - ][ + - ]
[ + + ][ + + ]
[ + + ][ + +
# # # # ]
1442 : 9 : continue; // this means that this set is not of interest, skip it
1443 : : EntityHandle newSet;
1444 [ + - ][ - + ]: 66 : rval = mdbImpl->create_meshset( set_options, newSet );MB_CHK_SET_ERR( rval, "Failed to create new meshset" );
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ]
1445 : :
1446 [ + - ]: 66 : relate[set] = newSet;
1447 [ + - ][ - + ]: 66 : rval = mdbImpl->add_entities( rootModelSet, &newSet, 1 );MB_CHK_SET_ERR( rval, "Failed to add the new meshset to the tool's modelSet" );
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ]
1448 : :
1449 : : // make it a geo set, and give also global id in order
1450 [ + - ][ - + ]: 66 : rval = mdbImpl->tag_set_data( geomTag, &newSet, 1, &dim );MB_CHK_SET_ERR( rval, "Failed to set the new meshset's geometry dimension data" );
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ]
1451 : :
1452 : 66 : gid++; // increment global id, everything starts with 1 in the new model!
1453 [ + - ][ - + ]: 66 : rval = mdbImpl->tag_set_data( gidTag, &newSet, 1, &gid );MB_CHK_SET_ERR( rval, "Failed to get the new meshset's global id data" );
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ]
1454 : :
1455 [ + + ]: 66 : if( dim == 1 )
1456 : : {
1457 : : // the entities are ordered, we need to retrieve them ordered, and set them ordered
1458 [ + - ]: 30 : std::vector< EntityHandle > mesh_edges;
1459 [ + - ][ - + ]: 30 : rval = mdbImpl->get_entities_by_handle( set, mesh_edges );MB_CHK_SET_ERR( rval, "Failed to get the meshset entities by handle" );
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ]
1460 : :
1461 [ + - ][ + - ]: 30 : rval = mdbImpl->add_entities( newSet, &( mesh_edges[0] ), (int)mesh_edges.size() );MB_CHK_SET_ERR( rval, "Failed to add the new entities to the new meshset" );
[ - + ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ + - ]
1462 : : }
1463 : : else
1464 : : {
1465 [ + - ]: 36 : Range ents;
1466 [ + - ][ - + ]: 36 : rval = mdbImpl->get_entities_by_handle( set, ents );MB_CHK_SET_ERR( rval, "Failed to add the entities to the existing meshset" );
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ]
1467 : :
1468 [ + - ][ - + ]: 36 : rval = mdbImpl->add_entities( newSet, ents );MB_CHK_SET_ERR( rval, "Failed to add the entities to the new meshset" );
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ + - ]
1469 : : }
1470 : : // set parent/child relations if dim>=1
1471 [ + + ]: 66 : if( dim >= 1 )
1472 : : {
1473 [ + - ]: 42 : Range children;
1474 : : // the children of geo sets are only g sets
1475 [ + - ]: 42 : rval = mdbImpl->get_child_meshsets( set, children ); // num_hops = 1 by default
1476 [ - + ][ # # ]: 42 : MB_CHK_SET_ERR( rval, "Failed to get the child meshsets of the existing set" );
[ # # ][ # # ]
[ # # ][ # # ]
1477 : :
1478 [ + - ][ + - ]: 152 : for( Range::iterator it2 = children.begin(); it2 != children.end(); ++it2 )
[ + - ][ + - ]
[ + + ][ + - ]
1479 : : {
1480 [ + - ][ + - ]: 110 : EntityHandle newChildSet = relate[*it2];
1481 [ + - ][ - + ]: 110 : rval = mdbImpl->add_parent_child( newSet, newChildSet );MB_CHK_SET_ERR( rval, "Failed to create parent child relationship to the new meshset" );
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ]
1482 : 66 : }
1483 : : }
1484 : : }
1485 : : }
1486 : :
1487 [ + - ][ + - ]: 4 : duplicate = new GeomTopoTool( mdbImpl, true, rootModelSet ); // will retrieve the
1488 : : // sets and put them in ranges
1489 : :
1490 : : // this is the lazy way to it:
1491 : : // newgtt->restore_topology_from_adjacency(); // will reset the sense entities, and with this,
1492 : : // the model represented by this new gtt will be complete set senses by peeking at the old model
1493 : : // make sure we have the sense tags defined
1494 [ + - ][ - + ]: 4 : rval = check_face_sense_tag( true );MB_CHK_SET_ERR( rval, "Failed to check the face to volume sense tag handle" );
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ]
1495 : :
1496 [ + - ][ - + ]: 4 : rval = check_edge_sense_tags( true );MB_CHK_SET_ERR( rval, "Failed to check the curve to surface sense tag handles" );
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ]
1497 : :
1498 [ + + ]: 12 : for( int dd = 1; dd <= 2; dd++ ) // do it for surfaces and edges
1499 : : {
1500 [ + - ][ + - ]: 55 : for( Range::iterator it = geomRanges[dd].begin(); it != geomRanges[dd].end(); ++it )
[ + - ][ + - ]
[ + + ]
1501 : : {
1502 [ + - ]: 47 : EntityHandle surf = *it;
1503 [ + + ][ + - ]: 47 : if( pvGEnts != NULL && depSets.find( surf ) == depSets.end() )
[ + - ][ + - ]
[ + + ][ + + ]
[ + + ][ + +
# # # # ]
1504 : 6 : continue; // this means that this set is not of interest, skip it
1505 [ + - ]: 41 : EntityHandle newSurf = relate[surf];
1506 : : // we can actually look at the tag data, to be more efficient
1507 : : // or use the
1508 [ + - ]: 41 : std::vector< EntityHandle > solids;
1509 [ + - ][ + - ]: 82 : std::vector< int > senses;
1510 [ + - ][ - + ]: 41 : rval = this->get_senses( surf, solids, senses );MB_CHK_SET_ERR( rval, "Failed to get the sense data for the surface with respect to its volumes" );
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ]
1511 : :
1512 [ + - ][ + - ]: 82 : std::vector< EntityHandle > newSolids;
1513 [ + - ][ + - ]: 82 : std::vector< int > newSenses;
1514 [ + + ]: 103 : for( unsigned int i = 0; i < solids.size(); i++ )
1515 : : {
1516 [ + + ][ + - ]: 62 : if( pvGEnts != NULL && depSets.find( solids[i] ) == depSets.end() )
[ + - ][ + - ]
[ + - ][ + + ]
[ + + ][ + + ]
[ + + # #
# # ]
1517 : 12 : continue; // this means that this set is not of interest, skip it
1518 [ + - ][ + - ]: 50 : EntityHandle newSolid = relate[solids[i]];
1519 : : // see which "solids" are in the new model
1520 [ + - ]: 50 : newSolids.push_back( newSolid );
1521 [ + - ][ + - ]: 50 : newSenses.push_back( senses[i] );
1522 : : }
1523 [ + - ][ - + ]: 41 : rval = duplicate->set_senses( newSurf, newSolids, newSenses );MB_CHK_SET_ERR( rval, "Failed to set the sense data for the surface with respect to the new volumes" );
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ + - ]
1524 : 41 : }
1525 : : }
1526 : : // if the original root model set for this model is 0 (root set), then create
1527 : : // a new set and put all the old sets in the new model set
1528 : : // in this way, the existing gtt remains valid (otherwise, the modelSet would contain all the
1529 : : // gsets, the old ones and the new ones; the root set contains everything)
1530 [ + - ]: 4 : if( modelSet == 0 )
1531 : : {
1532 [ + - ][ - + ]: 4 : rval = mdbImpl->create_meshset( MESHSET_SET, modelSet );MB_CHK_SET_ERR( rval, "Failed to create the modelSet meshset" );
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ]
1533 : :
1534 : : // add to this new set all previous sets (which are still in ranges)
1535 [ + + ]: 24 : for( int dim = 0; dim < 5; dim++ )
1536 : : {
1537 [ + - ][ - + ]: 20 : rval = mdbImpl->add_entities( modelSet, geomRanges[dim] );MB_CHK_SET_ERR( rval, "Failed to add the geometric meshsets to the tool's modelSet" );
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ]
1538 : : }
1539 : : }
1540 : 8 : return MB_SUCCESS;
1541 : : }
1542 : :
1543 : 1834 : ErrorCode GeomTopoTool::get_implicit_complement( EntityHandle& implicit_complement )
1544 : : {
1545 [ + - ]: 1834 : if( impl_compl_handle )
1546 : : {
1547 : 1834 : implicit_complement = impl_compl_handle;
1548 : 1834 : return MB_SUCCESS;
1549 : : }
1550 : : else
1551 : : {
1552 : 0 : return MB_ENTITY_NOT_FOUND;
1553 : : }
1554 : : }
1555 : :
1556 : 17 : ErrorCode GeomTopoTool::setup_implicit_complement()
1557 : : {
1558 : :
1559 : : // if the implicit complement is already setup,
1560 : : // we're done
1561 [ - + ]: 17 : if( impl_compl_handle != 0 )
1562 : : {
1563 [ # # ][ # # ]: 0 : std::cout << "IPC already exists!" << std::endl;
1564 : 0 : return MB_SUCCESS;
1565 : : }
1566 : :
1567 : : // if not, then query for a set with it's name
1568 [ + - ]: 17 : Range entities;
1569 : 17 : const void* const tagdata[] = { IMPLICIT_COMPLEMENT_NAME };
1570 [ + - ]: 17 : ErrorCode rval = mdbImpl->get_entities_by_type_and_tag( modelSet, MBENTITYSET, &nameTag, tagdata, 1, entities );
1571 : : // query error
1572 [ - + ][ # # ]: 17 : MB_CHK_SET_ERR( rval, "Unable to query for implicit complement" );
[ # # ][ # # ]
[ # # ][ # # ]
1573 : :
1574 : : // if we found exactly one, set it as the implicit complement
1575 [ + - ][ + + ]: 17 : if( entities.size() == 1 )
1576 : : {
1577 [ + - ]: 2 : impl_compl_handle = entities.front();
1578 : 2 : return MB_SUCCESS;
1579 : : }
1580 : :
1581 : : // found too many
1582 [ + - ][ - + ]: 15 : if( entities.size() > 1 ) MB_CHK_SET_ERR( MB_MULTIPLE_ENTITIES_FOUND, "Too many implicit complement sets" );
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ]
1583 : :
1584 : : // found none
1585 [ + - ][ + - ]: 15 : if( entities.empty() )
1586 : : {
1587 : : // create implicit complement if requested
1588 [ + - ][ - + ]: 15 : rval = generate_implicit_complement( impl_compl_handle );MB_CHK_SET_ERR( rval, "Could not create implicit complement" );
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ]
1589 : :
1590 [ + - ][ - + ]: 15 : rval = mdbImpl->tag_set_data( nameTag, &impl_compl_handle, 1, &IMPLICIT_COMPLEMENT_NAME );MB_CHK_SET_ERR( rval, "Could not set the name tag for the implicit complement" );
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ]
1591 : :
1592 [ + - ][ - + ]: 15 : rval = add_geo_set( impl_compl_handle, 3 );MB_CHK_SET_ERR( rval, "Failed to add implicit complement to model" );
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ]
1593 : :
1594 : : // assign category tag - this is presumably for consistency so that the
1595 : : // implicit complement has all the appearance of being the same as any
1596 : : // other volume
1597 : : Tag category_tag;
1598 : : rval = mdbImpl->tag_get_handle( CATEGORY_TAG_NAME, CATEGORY_TAG_SIZE, MB_TYPE_OPAQUE, category_tag,
1599 [ + - ][ - + ]: 15 : MB_TAG_SPARSE | MB_TAG_CREAT );MB_CHK_SET_ERR( rval, "Could not get the category tag" );
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ]
1600 : :
1601 : : static const char volume_category[CATEGORY_TAG_SIZE] = "Volume\0";
1602 [ + - ][ - + ]: 15 : rval = mdbImpl->tag_set_data( category_tag, &impl_compl_handle, 1, volume_category );MB_CHK_SET_ERR( rval, "Could not set the category tag for the implicit complement" );
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ]
1603 : :
1604 : 15 : return MB_SUCCESS;
1605 : : }
1606 : :
1607 : 17 : return MB_FAILURE;
1608 : : }
1609 : :
1610 : 15 : ErrorCode GeomTopoTool::generate_implicit_complement( EntityHandle& implicit_complement_set )
1611 : : {
1612 : :
1613 : : ErrorCode rval;
1614 [ + - ][ - + ]: 15 : rval = mdbImpl->create_meshset( MESHSET_SET, implicit_complement_set );MB_CHK_SET_ERR( rval, "Failed to create mesh set for implicit complement" );
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ]
1615 : :
1616 : : // make sure the sense2Tag is set
1617 [ - + ][ # # ]: 15 : if( !sense2Tag ) { check_face_sense_tag( true ); }
1618 : :
1619 : : // get all geometric surface sets
1620 [ + - ]: 15 : Range surfs;
1621 [ + - ][ - + ]: 15 : rval = get_gsets_by_dimension( 2, surfs );MB_CHK_SET_ERR( rval, "Could not get surface sets" );
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ]
1622 : :
1623 : : // search through all surfaces
1624 [ + - ]: 30 : std::vector< EntityHandle > parent_vols;
1625 [ + - ][ + - ]: 129 : for( Range::iterator surf_i = surfs.begin(); surf_i != surfs.end(); ++surf_i )
[ + - ][ + - ]
[ + + ]
1626 : : {
1627 : :
1628 : 114 : parent_vols.clear();
1629 : : // get parents of each surface
1630 [ + - ][ + - ]: 114 : rval = mdbImpl->get_parent_meshsets( *surf_i, parent_vols );MB_CHK_SET_ERR( rval, "Failed to get volume meshsets" );
[ - + ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
1631 : :
1632 : : // if only one parent, get the OBB root for this surface
1633 [ + - ]: 114 : if( parent_vols.size() == 1 )
1634 : : {
1635 : :
1636 : : // add this surf to the topology of the implicit complement volume
1637 [ + - ][ + - ]: 114 : rval = mdbImpl->add_parent_child( implicit_complement_set, *surf_i );MB_CHK_SET_ERR( rval, "Could not add surface to implicit complement set" );
[ - + ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
1638 : :
1639 : : // get the surface sense wrt original volume
1640 : 114 : EntityHandle sense_data[2] = { 0, 0 };
1641 [ + - ][ + - ]: 114 : rval = get_surface_senses( *surf_i, sense_data[0], sense_data[1] );MB_CHK_SET_ERR( rval, "Could not get surface sense data" );
[ - + ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
1642 : :
1643 : : // set the surface sense wrt implicit complement volume
1644 [ - + ][ # # ]: 114 : if( 0 == sense_data[0] && 0 == sense_data[1] )
1645 [ # # ][ # # ]: 0 : MB_SET_ERR( MB_FAILURE, "No sense data for current surface" );
[ # # ][ # # ]
[ # # ]
1646 [ - + ]: 114 : if( 0 == sense_data[0] )
1647 : 0 : sense_data[0] = implicit_complement_set;
1648 [ + - ]: 114 : else if( 0 == sense_data[1] )
1649 : 114 : sense_data[1] = implicit_complement_set;
1650 : : else
1651 [ # # ][ # # ]: 0 : MB_SET_ERR( MB_FAILURE, "Could not insert implicit complement into surface sense data" );
[ # # ][ # # ]
[ # # ]
1652 : :
1653 : : // set the new sense data for this surface
1654 [ + - ][ + - ]: 114 : rval = set_surface_senses( *surf_i, sense_data[0], sense_data[1] );MB_CHK_SET_ERR( rval, "Failed to set sense tag data" );
[ - + ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
1655 : : }
1656 : : } // end surface loop
1657 : :
1658 : 30 : return MB_SUCCESS;
1659 : : }
1660 : :
1661 : : #define RETFALSE( a, b ) \
1662 : : { \
1663 : : std::cout << a << "\n"; \
1664 : : mdbImpl->list_entity( b ); \
1665 : : return false; \
1666 : : }
1667 : 2 : bool GeomTopoTool::check_model()
1668 : : {
1669 : : // vertex sets should have one node
1670 [ + - ]: 2 : Range::iterator rit;
1671 : : ErrorCode rval;
1672 [ + - ][ + - ]: 12 : for( rit = geomRanges[0].begin(); rit != geomRanges[0].end(); ++rit )
[ + - ][ + - ]
[ + + ]
1673 : : {
1674 [ + - ]: 10 : EntityHandle vSet = *rit;
1675 [ + - ]: 10 : Range nodes;
1676 [ + - ]: 10 : rval = mdbImpl->get_entities_by_handle( vSet, nodes );
1677 [ - + ][ # # ]: 10 : if( MB_SUCCESS != rval ) RETFALSE( " failed to get nodes from vertex set ", vSet );
[ # # ][ # # ]
1678 [ + - ][ - + ]: 10 : if( nodes.size() != 1 ) RETFALSE( " number of nodes is different from 1 ", vSet )
[ # # ][ # # ]
[ # # ]
1679 [ + - ][ + - ]: 10 : EntityType type = mdbImpl->type_from_handle( nodes[0] );
1680 [ - + ][ # # ]: 10 : if( type != MBVERTEX ) RETFALSE( " entity in vertex set is not a node ", nodes[0] )
[ # # ][ # # ]
[ # # ]
1681 : : // get all parents, and see if they belong to geomRanges[1]
1682 [ + - ][ + - ]: 20 : Range edges;
1683 [ + - ]: 10 : rval = mdbImpl->get_parent_meshsets( vSet, edges );
1684 [ - + ][ # # ]: 10 : if( MB_SUCCESS != rval ) RETFALSE( " can't get parent edges for a node set ", vSet )
[ # # ][ # # ]
1685 [ + - ][ + - ]: 20 : Range notEdges = subtract( edges, geomRanges[1] );
1686 [ + - ][ - + ]: 10 : if( !notEdges.empty() ) RETFALSE( " some parents of a node set are not geo edges ", notEdges[0] )
[ # # ][ # # ]
[ # # ][ # # ]
[ + - ]
1687 : 10 : }
1688 : :
1689 : : // edges to be formed by continuous chain of mesh edges, oriented correctly
1690 [ + - ][ + - ]: 14 : for( rit = geomRanges[1].begin(); rit != geomRanges[1].end(); ++rit )
[ + - ][ + - ]
[ + + ]
1691 : : {
1692 [ + - ]: 12 : EntityHandle edge = *rit;
1693 [ + - ]: 12 : std::vector< EntityHandle > mesh_edges;
1694 [ + - ]: 12 : rval = mdbImpl->get_entities_by_type( edge, MBEDGE, mesh_edges );
1695 [ - + ][ # # ]: 12 : if( MB_SUCCESS != rval ) RETFALSE( " can't get mesh edges from edge set", edge )
[ # # ][ # # ]
1696 : 12 : int num_edges = (int)mesh_edges.size();
1697 [ - + ][ # # ]: 12 : if( num_edges == 0 ) RETFALSE( " no mesh edges in edge set ", edge )
[ # # ][ # # ]
1698 : : EntityHandle firstNode;
1699 : : EntityHandle currentNode; // will also hold the last node in chain of edges
1700 : : const EntityHandle* conn2;
1701 : : int nnodes2;
1702 : : // get all parents, and see if they belong to geomRanges[1]
1703 [ + + ]: 338 : for( int i = 0; i < num_edges; i++ )
1704 : : {
1705 [ + - ][ + - ]: 326 : rval = mdbImpl->get_connectivity( mesh_edges[i], conn2, nnodes2 );
1706 [ + - ][ - + ]: 326 : if( MB_SUCCESS != rval || nnodes2 != 2 ) RETFALSE( " mesh edge connectivity is wrong ", mesh_edges[i] )
[ # # ][ # # ]
[ # # ][ # # ]
1707 [ + + ]: 326 : if( i == 0 )
1708 : : {
1709 : 12 : firstNode = conn2[0];
1710 : 12 : currentNode = conn2[1];
1711 : : }
1712 : :
1713 : : else // if ( (i>0) )
1714 : : {
1715 : : // check the current node is conn[0]
1716 [ - + ]: 314 : if( conn2[0] != currentNode )
1717 : : {
1718 [ # # ][ # # ]: 0 : std::cout << "i=" << i << " conn2:" << conn2[0] << " " << conn2[1] << " currentNode:" << currentNode
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
1719 [ # # ]: 0 : << "\n";
1720 [ # # ][ # # ]: 0 : mdbImpl->list_entity( mesh_edges[i] );
1721 [ # # ][ # # ]: 0 : RETFALSE( " edges are not contiguous in edge set ", edge )
[ # # ]
1722 : : }
1723 : 314 : currentNode = conn2[1];
1724 : : }
1725 : : }
1726 : : // check the children of the edge set; do they have the first and last node?
1727 [ + - ][ + - ]: 24 : Range vertSets;
1728 [ + - ]: 12 : rval = mdbImpl->get_child_meshsets( edge, vertSets );
1729 [ - + ][ # # ]: 12 : if( MB_SUCCESS != rval ) RETFALSE( " can't get vertex children ", edge )
[ # # ][ # # ]
1730 [ + - ][ + - ]: 24 : Range notVertices = subtract( vertSets, geomRanges[0] );
1731 [ + - ][ - + ]: 12 : if( !notVertices.empty() ) RETFALSE( " children sets that are not vertices ", notVertices[0] )
[ # # ][ # # ]
[ # # ][ # # ]
1732 [ + - ][ + - ]: 36 : for( Range::iterator it = vertSets.begin(); it != vertSets.end(); ++it )
[ + - ][ + - ]
[ + + ]
1733 : : {
1734 [ + - ][ + - ]: 36 : if( !mdbImpl->contains_entities( *it, &firstNode, 1 ) &&
[ + + ][ - + ]
[ - + ]
1735 [ + - ][ + - ]: 12 : !mdbImpl->contains_entities( *it, ¤tNode, 1 ) )
1736 [ # # ][ # # ]: 0 : RETFALSE( " a vertex set is not containing the first and last nodes ", *it )
[ # # ][ # # ]
1737 : : }
1738 : : // check now the faces / parents
1739 [ + - ][ + - ]: 24 : Range faceSets;
1740 [ + - ]: 12 : rval = mdbImpl->get_parent_meshsets( edge, faceSets );
1741 [ - + ][ # # ]: 12 : if( MB_SUCCESS != rval ) RETFALSE( " can't get edge parents ", edge )
[ # # ][ # # ]
1742 [ + - ][ + - ]: 24 : Range notFaces = subtract( faceSets, geomRanges[2] );
1743 [ + - ][ - + ]: 12 : if( !notFaces.empty() ) RETFALSE( " parent sets that are not faces ", notFaces[0] )
[ # # ][ # # ]
[ # # ][ # # ]
1744 : :
1745 : : // for a geo edge, check the sense tags with respect to the adjacent faces
1746 : : // in general, it is sufficient to check one mesh edge (the first one)
1747 : : // edge/face senses
1748 [ + - ]: 12 : EntityHandle firstMeshEdge = mesh_edges[0];
1749 : : // get all entities/elements adjacent to it
1750 [ + - ][ + - ]: 24 : Range adjElem;
1751 [ + - ]: 12 : rval = mdbImpl->get_adjacencies( &firstMeshEdge, 1, 2, false, adjElem );
1752 [ - + ][ # # ]: 12 : if( MB_SUCCESS != rval ) RETFALSE( " can't get adjacent elements to the edge ", firstMeshEdge )
[ # # ][ # # ]
1753 [ + - ][ + - ]: 27 : for( Range::iterator it2 = adjElem.begin(); it2 != adjElem.end(); ++it2 )
[ + - ][ + - ]
[ + + ][ + - ]
1754 : : {
1755 [ + - ]: 15 : EntityHandle elem = *it2;
1756 : : // find the geo face it belongs to
1757 : 15 : EntityHandle gFace = 0;
1758 [ + - ][ + - ]: 18 : for( Range::iterator fit = faceSets.begin(); fit != faceSets.end(); ++fit )
[ + - ][ + - ]
[ + - ]
1759 : : {
1760 [ + - ]: 18 : EntityHandle possibleFace = *fit;
1761 [ + - ][ + + ]: 18 : if( mdbImpl->contains_entities( possibleFace, &elem, 1 ) )
1762 : : {
1763 : 15 : gFace = possibleFace;
1764 : 15 : break;
1765 : : }
1766 : : }
1767 [ - + ]: 15 : if( 0 == gFace )
1768 [ # # ][ # # ]: 0 : RETFALSE( " can't find adjacent surface that contains the adjacent element to the edge ",
[ # # ]
1769 : : firstMeshEdge )
1770 : :
1771 : : // now, check the sense of mesh_edge in element, and the sense of gedge in gface
1772 : : // side_number
1773 : : int side_n, sense, offset;
1774 [ + - ]: 15 : rval = mdbImpl->side_number( elem, firstMeshEdge, side_n, sense, offset );
1775 [ - + ][ # # ]: 15 : if( MB_SUCCESS != rval ) RETFALSE( " can't get sense and side number of an element ", elem )
[ # # ][ # # ]
1776 : : // now get the sense
1777 : : int topoSense;
1778 [ + - ]: 15 : rval = this->get_sense( edge, gFace, topoSense );
1779 [ - + ][ # # ]: 15 : if( topoSense != sense ) RETFALSE( " geometric topo sense and element sense do not agree ", edge )
[ # # ][ # # ]
1780 : : }
1781 : 12 : }
1782 : : // surfaces to be true meshes
1783 : : // for surfaces, check that the skinner will find the correct boundary
1784 : :
1785 : : // use the skinner for boundary check
1786 [ + - ]: 2 : Skinner tool( mdbImpl );
1787 : :
1788 [ + - ][ + - ]: 6 : for( rit = geomRanges[2].begin(); rit != geomRanges[2].end(); ++rit )
[ + - ][ + - ]
[ + + ]
1789 : : {
1790 [ + - ]: 4 : EntityHandle faceSet = *rit;
1791 : : // get all boundary edges (adjacent edges)
1792 : :
1793 [ + - ]: 4 : Range edges;
1794 [ + - ]: 4 : rval = mdbImpl->get_child_meshsets( faceSet, edges );
1795 [ - + ][ # # ]: 4 : if( MB_SUCCESS != rval ) RETFALSE( " can't get children edges for a face set ", faceSet )
[ # # ][ # # ]
1796 [ + - ][ + - ]: 8 : Range notEdges = subtract( edges, geomRanges[1] );
1797 [ + - ][ - + ]: 4 : if( !notEdges.empty() ) RETFALSE( " some children of a face set are not geo edges ", notEdges[0] )
[ # # ][ # # ]
[ # # ][ # # ]
1798 : :
1799 [ + - ][ + - ]: 8 : Range boundary_mesh_edges;
1800 [ + - ][ + - ]: 19 : for( Range::iterator it = edges.begin(); it != edges.end(); ++it )
[ + - ][ + - ]
[ + + ]
1801 : : {
1802 [ + - ][ + - ]: 15 : rval = mdbImpl->get_entities_by_type( *it, MBEDGE, boundary_mesh_edges );
1803 [ - + ][ # # ]: 15 : if( MB_SUCCESS != rval ) RETFALSE( " can't get edge elements from the edge set ", *it )
[ # # ][ # # ]
[ # # ]
1804 : : }
1805 : : // skin the elements of the surface
1806 : : // most of these should be triangles and quads
1807 [ + - ][ + - ]: 8 : Range surface_ents, edge_ents;
[ + - ][ + - ]
1808 [ + - ]: 4 : rval = mdbImpl->get_entities_by_dimension( faceSet, 2, surface_ents );
1809 [ - + ][ # # ]: 4 : if( MB_SUCCESS != rval ) RETFALSE( " can't get surface elements from the face set ", faceSet )
[ # # ][ # # ]
1810 : :
1811 [ + - ]: 4 : rval = tool.find_skin( 0, surface_ents, 1, edge_ents );
1812 [ - + ][ # # ]: 4 : if( MB_SUCCESS != rval ) RETFALSE( "can't skin a surface ", surface_ents[0] )
[ # # ][ # # ]
[ # # ]
1813 : :
1814 : : // those 2 ranges for boundary edges now must be equal
1815 [ + - ][ - + ]: 4 : if( boundary_mesh_edges != edge_ents ) RETFALSE( "boundary ranges are different", boundary_mesh_edges[0] )
[ # # ][ # # ]
[ # # ][ # # ]
[ + - ]
1816 : 4 : }
1817 : :
1818 : : // solids to be filled correctly, maybe a skin procedure too.
1819 : : // (maybe the solids are empty)
1820 : :
1821 : 2 : return true;
1822 : : }
1823 : :
1824 : 0 : bool GeomTopoTool::have_obb_tree()
1825 : : {
1826 [ # # ][ # # ]: 0 : return rootSets.size() != 0 || mapRootSets.size() != 0;
1827 : : }
1828 : :
1829 : : // This function gets coordinates of the minimum and maxmiumum points
1830 : : // from an OBB/AABB, ie. such that these points represent
1831 : : // the maximum and minium extents of an AABB
1832 : 3707 : ErrorCode GeomTopoTool::get_bounding_coords( EntityHandle volume, double minPt[3], double maxPt[3] )
1833 : : {
1834 : : double center[3], axis1[3], axis2[3], axis3[3];
1835 : :
1836 : : // get center point and vectors to OBB faces
1837 [ + - ][ - + ]: 3707 : ErrorCode rval = get_obb( volume, center, axis1, axis2, axis3 );MB_CHK_SET_ERR( rval, "Failed to get the oriented bounding box of the volume" );
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ]
1838 : :
1839 : : // compute min and max vertices
1840 [ + + ]: 14828 : for( int i = 0; i < 3; i++ )
1841 : : {
1842 : 11121 : double sum = fabs( axis1[i] ) + fabs( axis2[i] ) + fabs( axis3[i] );
1843 : 11121 : minPt[i] = center[i] - sum;
1844 : 11121 : maxPt[i] = center[i] + sum;
1845 : : }
1846 : 3707 : return MB_SUCCESS;
1847 : : }
1848 : :
1849 : 3707 : ErrorCode GeomTopoTool::get_obb( EntityHandle volume, double center[3], double axis1[3], double axis2[3],
1850 : : double axis3[3] )
1851 : : {
1852 : : // find EntityHandle node_set for use in box
1853 : : EntityHandle root;
1854 [ + - ][ - + ]: 3707 : ErrorCode rval = get_root( volume, root );MB_CHK_SET_ERR( rval, "Failed to get volume's obb tree root" );
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ]
1855 : :
1856 : : // call box to get center and vectors to faces
1857 [ + - ]: 3707 : return obbTree->box( root, center, axis1, axis2, axis3 );
1858 : : }
1859 : :
1860 : 626 : Range GeomTopoTool::get_ct_children_by_dimension( EntityHandle parent, int desired_dimension )
1861 : : {
1862 [ + - ][ + - ]: 626 : Range all_children, desired_children;
1863 [ + - ]: 626 : Range::iterator it;
1864 : : int actual_dimension;
1865 : :
1866 [ + - ]: 626 : desired_children.clear();
1867 [ + - ]: 626 : all_children.clear();
1868 [ + - ]: 626 : mdbImpl->get_child_meshsets( parent, all_children );
1869 : :
1870 [ + - ][ + - ]: 1378 : for( it = all_children.begin(); it != all_children.end(); ++it )
[ + - ][ + - ]
[ + + ]
1871 : : {
1872 [ + - ][ + - ]: 752 : mdbImpl->tag_get_data( geomTag, &( *it ), 1, &actual_dimension );
1873 [ + + ][ + - ]: 752 : if( actual_dimension == desired_dimension ) desired_children.insert( *it );
[ + - ]
1874 : : }
1875 : :
1876 : 626 : return desired_children;
1877 : : }
1878 : :
1879 : : // runs GeomQueryTool point_in_vol and to test if vol A is inside vol B
1880 : : // returns true or false
1881 : 190 : bool GeomTopoTool::A_is_in_B( EntityHandle volume_A, EntityHandle volume_B, GeomQueryTool* GQT )
1882 : : {
1883 : : ErrorCode rval;
1884 : :
1885 [ + - ][ + - ]: 380 : Range child_surfaces, triangles, vertices;
[ + - ]
1886 : : double coord[3]; // coord[0] = x, etc.
1887 : : int result; // point in vol result; 0=F, 1=T
1888 : :
1889 : : // find coordinates of any point on surface of A
1890 : : // get surface corresponding to volume, then get the triangles
1891 [ + - ][ + - ]: 190 : child_surfaces = get_ct_children_by_dimension( volume_A, 2 );
1892 [ + - ][ + - ]: 190 : rval = mdbImpl->get_entities_by_type( *child_surfaces.begin(), MBTRI, triangles );MB_CHK_ERR( rval );
[ + - ][ - + ]
[ # # ][ # # ]
1893 : :
1894 : : // now get 1st triangle vertices
1895 [ + - ][ + - ]: 190 : rval = mdbImpl->get_connectivity( &( *triangles.begin() ), 1, vertices );MB_CHK_ERR( rval );
[ + - ][ - + ]
[ # # ][ # # ]
1896 : :
1897 : : // now get coordinates of first vertex
1898 [ + - ][ + - ]: 190 : rval = mdbImpl->get_coords( &( *vertices.begin() ), 1, &( coord[0] ) );MB_CHK_ERR( rval );
[ + - ][ - + ]
[ # # ][ # # ]
1899 : :
1900 : : // if point on A is inside vol B, return T; o.w. return F
1901 [ + - ][ - + ]: 190 : rval = GQT->point_in_volume( volume_B, coord, result );MB_CHK_SET_ERR( rval, "Failed to complete point in volume query." );
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ]
1902 : :
1903 : 380 : return ( result != 0 );
1904 : : }
1905 : :
1906 : 118 : ErrorCode GeomTopoTool::insert_in_tree( EntityHandle ct_root, EntityHandle volume, GeomQueryTool* GQT )
1907 : : {
1908 : : ErrorCode rval;
1909 : :
1910 : 118 : bool inserted = false;
1911 : 118 : EntityHandle current_volume = volume; // volume to be inserted
1912 : 118 : EntityHandle tree_volume = ct_root; // volume already existing in the tree
1913 : 118 : EntityHandle parent = ct_root;
1914 [ + - ]: 118 : Range child_volumes;
1915 : :
1916 : : // while not inserted in tree
1917 [ + + ]: 372 : while( !inserted )
1918 : : {
1919 : : // if current volume is insde of tree volume-- always true if tree volume
1920 : : // is the root of the tree
1921 [ + + ][ + - ]: 254 : if( tree_volume == ct_root || ( tree_volume != ct_root && A_is_in_B( current_volume, tree_volume, GQT ) ) )
[ + - ][ + + ]
[ + + ]
1922 : : {
1923 : :
1924 : 200 : parent = tree_volume;
1925 : :
1926 : : // if tree_volume has children then we must test them,
1927 : : // (tree_volume will change)
1928 [ + - ][ + - ]: 200 : child_volumes = get_ct_children_by_dimension( tree_volume, 3 );
1929 [ + - ][ + + ]: 200 : if( child_volumes.size() > 0 ) tree_volume = child_volumes.pop_front();
[ + - ]
1930 : : // otherwise current_volume is the only child of the tree volume
1931 : : else
1932 : : {
1933 [ + - ][ - + ]: 64 : rval = mdbImpl->add_parent_child( parent, current_volume );MB_CHK_SET_ERR( rval, "Failed to add parent-child relationship." );
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ]
1934 : :
1935 : 200 : inserted = true;
1936 : : }
1937 : : // if current volume is not in the tree volume, the converse may be true
1938 : : }
1939 : : else
1940 : : {
1941 : : // if the tree volume is inside the current volume
1942 [ + - ][ + - ]: 54 : if( A_is_in_B( tree_volume, current_volume, GQT ) )
1943 : : {
1944 : : // reverse their parentage
1945 [ + - ][ - + ]: 54 : rval = mdbImpl->remove_parent_child( parent, tree_volume );MB_CHK_SET_ERR( rval, "Failed to remove parent-child relationship." );
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ]
1946 [ + - ][ - + ]: 54 : rval = mdbImpl->add_parent_child( current_volume, tree_volume );MB_CHK_SET_ERR( rval, "Failed to add parent-child relationship." );
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ]
1947 : : }
1948 : :
1949 [ + - ][ + - ]: 54 : if( child_volumes.size() == 0 )
1950 : : {
1951 [ + - ][ - + ]: 54 : rval = mdbImpl->add_parent_child( parent, current_volume );MB_CHK_SET_ERR( rval, "Failed to add parent-child relationship." );
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ]
1952 : 54 : inserted = true;
1953 : : }
1954 : : else
1955 [ # # ]: 0 : tree_volume = child_volumes.pop_front();
1956 : : }
1957 : : }
1958 : 118 : return MB_SUCCESS;
1959 : : }
1960 : :
1961 : 32 : ErrorCode GeomTopoTool::restore_topology_from_geometric_inclusion( const Range& flat_volumes )
1962 : : {
1963 : :
1964 : : ErrorCode rval;
1965 : : // local var will go out of scope if errors appear, no need to free it also
1966 [ + - ]: 32 : GeomQueryTool GQT( this );
1967 [ + - ]: 64 : std::map< EntityHandle, EntityHandle > volume_surface; // map of volume
1968 : : // to its surface
1969 : :
1970 : : EntityHandle ct_root;
1971 : : // create root meshset-- this will be top of tree
1972 [ + - ]: 64 : std::string meshset_name = "build_hierarchy_root";
1973 [ + - ][ - + ]: 32 : rval = mdbImpl->create_meshset( MESHSET_SET, ct_root );MB_CHK_ERR( rval );
[ # # ][ # # ]
1974 [ + - ][ - + ]: 32 : rval = mdbImpl->tag_set_data( nameTag, &ct_root, 1, meshset_name.c_str() );MB_CHK_ERR( rval );
[ # # ][ # # ]
1975 : :
1976 [ + - ][ + - ]: 150 : for( Range::iterator vol = flat_volumes.begin(); vol != flat_volumes.end(); vol++ )
[ + - ][ + - ]
[ + + ]
1977 : : {
1978 : : // get the surface corresponding to each volume
1979 : : // at this point, each volume meshset only has one 'child' surface
1980 : : // which exactly corresponds to that volume
1981 [ + - ][ + - ]: 118 : Range child_surfaces = get_ct_children_by_dimension( *vol, 2 );
1982 [ + - ][ + - ]: 118 : volume_surface[*vol] = *child_surfaces.begin();
[ + - ][ + - ]
1983 : :
1984 [ + - ][ + - ]: 118 : rval = insert_in_tree( ct_root, *vol, &GQT );MB_CHK_SET_ERR( rval, "Failed to insert volume into tree." );
[ - + ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ + - ]
1985 : 118 : }
1986 : :
1987 : : // for each original volume, get its child volumes
1988 [ + - ][ + - ]: 150 : for( Range::iterator parent_it = flat_volumes.begin(); parent_it != flat_volumes.end(); parent_it++ )
[ + - ][ + - ]
[ + + ]
1989 : : {
1990 [ + - ][ + - ]: 118 : Range volume_children = get_ct_children_by_dimension( *parent_it, 3 );
1991 : :
1992 [ + - ][ + + ]: 118 : if( volume_children.size() != 0 )
1993 : : {
1994 : : // loop over all of original volume's child volumes
1995 [ + - ][ + - ]: 204 : for( Range::iterator child_it = volume_children.begin(); child_it != volume_children.end(); ++child_it )
[ + - ][ + - ]
[ + + ][ + - ]
1996 : : {
1997 : : // set the sense of the surface mapped to the child volume to REVERSE
1998 : : // wrt the parent volume
1999 [ + - ][ + - ]: 86 : rval = set_sense( volume_surface[*child_it], *parent_it, SENSE_REVERSE );MB_CHK_SET_ERR( rval, "Failed to set sense." );
[ + - ][ + - ]
[ - + ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
2000 : :
2001 : : // add the child volume's surface as a child of the original volume
2002 : : // and delete the child volume as a child of original volume
2003 [ + - ][ + - ]: 86 : rval = mdbImpl->add_parent_child( *parent_it, volume_surface[*child_it] );MB_CHK_SET_ERR( rval, "Failed to add parent-child relationship." );
[ + - ][ + - ]
[ - + ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
2004 [ + - ][ + - ]: 86 : rval = mdbImpl->remove_parent_child( *parent_it, *child_it );MB_CHK_SET_ERR( rval, "Failed to remove parent-child relationship." );
[ + - ][ - + ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ]
2005 : : }
2006 : : }
2007 : 118 : }
2008 : :
2009 : 64 : return MB_SUCCESS;
2010 : : }
2011 : :
2012 [ + - ][ + - ]: 228 : } // namespace moab
|