1
15
16 #include "moab/DualTool.hpp"
17 #include "moab/Range.hpp"
18
19 #include "moab/Core.hpp"
20 #include "Internals.hpp"
21 #include "MBTagConventions.hpp"
22 #include "moab/Skinner.hpp"
23 #include "moab/Core.hpp"
24 #include "moab/MeshTopoUtil.hpp"
25 #include "AEntityFactory.hpp"
26 #include "moab/CN.hpp"
27 #include <string>
28 #include <algorithm>
29 #include <iostream>
30 #include <sstream>
31 #include <cassert>
32
33 #define RR \
34 if( MB_SUCCESS != result ) return result
35 #define SWAP( a, b ) \
36 { \
37 EntityHandle tmp_ent = a; \
38 ( a ) = b; \
39 ( b ) = tmp_ent; \
40 }
41
42 namespace moab
43 {
44
45 bool debug = false;
46 bool debug_ap = false;
47
48
49 const char* DualTool::DUAL_SURFACE_TAG_NAME = "DUAL_SURFACE";
50
51
52 const char* DualTool::DUAL_CURVE_TAG_NAME = "DUAL_CURVE";
53
54
55 const char* DualTool::IS_DUAL_CELL_TAG_NAME = "__IS_DUAL_CELL";
56
57
58 const char* DualTool::DUAL_ENTITY_TAG_NAME = "__DUAL_ENTITY";
59
60
61 const char* DualTool::EXTRA_DUAL_ENTITY_TAG_NAME = "__EXTRA_DUAL_ENTITY";
62
63
64 const char* DualTool::DUAL_GRAPHICS_POINT_TAG_NAME = "__DUAL_GRAPHICS_POINT";
65
66
67
68 DualTool::DualTool( Interface* impl ) : mbImpl( impl )
69 {
70 EntityHandle dum_handle = 0;
71 ErrorCode result;
72
73 result = mbImpl->tag_get_handle( DUAL_SURFACE_TAG_NAME, 1, MB_TYPE_HANDLE, dualSurfaceTag,
74 MB_TAG_SPARSE | MB_TAG_CREAT, &dum_handle );
75 assert( MB_SUCCESS == result );
76
77 result = mbImpl->tag_get_handle( DUAL_CURVE_TAG_NAME, 1, MB_TYPE_HANDLE, dualCurveTag, MB_TAG_SPARSE | MB_TAG_CREAT,
78 &dum_handle );
79 assert( MB_SUCCESS == result );
80
81 unsigned int dummy = 0;
82 result = mbImpl->tag_get_handle( IS_DUAL_CELL_TAG_NAME, 1, MB_TYPE_INTEGER, isDualCellTag,
83 MB_TAG_SPARSE | MB_TAG_CREAT, &dummy );
84 assert( MB_SUCCESS == result );
85
86 result = mbImpl->tag_get_handle( DUAL_ENTITY_TAG_NAME, 1, MB_TYPE_HANDLE, dualEntityTag,
87 MB_TAG_DENSE | MB_TAG_CREAT, &dum_handle );
88 assert( MB_SUCCESS == result );
89
90 result = mbImpl->tag_get_handle( EXTRA_DUAL_ENTITY_TAG_NAME, 1, MB_TYPE_HANDLE, extraDualEntityTag,
91 MB_TAG_SPARSE | MB_TAG_CREAT, &dum_handle );
92 assert( MB_SUCCESS == result );
93
94 static const char dum_name[CATEGORY_TAG_SIZE] = { 0 };
95 result = mbImpl->tag_get_handle( CATEGORY_TAG_NAME, CATEGORY_TAG_SIZE, MB_TYPE_OPAQUE, categoryTag,
96 MB_TAG_SPARSE | MB_TAG_CREAT, dum_name );
97 assert( MB_SUCCESS == result );
98
99 DualTool::GraphicsPoint dum_pt( 0.0, 0.0, 0.0, -1 );
100 result = mbImpl->tag_get_handle( DUAL_GRAPHICS_POINT_TAG_NAME, sizeof( DualTool::GraphicsPoint ), MB_TYPE_DOUBLE,
101 dualGraphicsPointTag, MB_TAG_DENSE | MB_TAG_CREAT | MB_TAG_BYTES, &dum_pt );
102 assert( MB_SUCCESS == result );
103
104 globalIdTag = mbImpl->globalId_tag();
105
106 if( MB_SUCCESS == result )
107 {
108 }
109
110 maxHexId = -1;
111 }
112
113 DualTool::~DualTool() {}
114
115
116 ErrorCode DualTool::construct_dual( EntityHandle* entities, const int num_entities )
117 {
118
119
120
121
122 Range regions, faces, edges, vertices;
123 ErrorCode result;
124
125 if( NULL == entities || 0 == num_entities )
126 {
127
128
129
130 result = mbImpl->get_entities_by_dimension( 0, 0, vertices );
131 if( MB_SUCCESS != result ) return result;
132
133 result = MeshTopoUtil( mbImpl ).construct_aentities( vertices );
134 if( MB_SUCCESS != result ) return result;
135
136
137
138
139 result = mbImpl->get_entities_by_dimension( 0, 1, edges );
140 if( MB_SUCCESS != result ) return result;
141 result = mbImpl->get_entities_by_dimension( 0, 2, faces );
142 if( MB_SUCCESS != result ) return result;
143 result = mbImpl->get_entities_by_dimension( 0, 3, regions );
144 if( MB_SUCCESS != result ) return result;
145
146
147 std::vector< int > gid_vec( regions.size() );
148 result = mbImpl->tag_get_data( globalId_tag(), regions, &gid_vec[0] );
149 if( MB_SUCCESS != result ) return result;
150 maxHexId = -1;
151 Range::iterator rit;
152 unsigned int i;
153 for( rit = regions.begin(), i = 0; rit != regions.end(); ++rit, i++ )
154 {
155 if( gid_vec[i] > maxHexId && mbImpl->type_from_handle( *rit ) == MBHEX ) maxHexId = gid_vec[i];
156 }
157 }
158 else
159 {
160
161 result = mbImpl->get_adjacencies( entities, num_entities, 0, true, vertices, Interface::UNION );
162 if( MB_SUCCESS != result ) return result;
163 result = mbImpl->get_adjacencies( entities, num_entities, 1, true, edges, Interface::UNION );
164 if( MB_SUCCESS != result ) return result;
165 result = mbImpl->get_adjacencies( entities, num_entities, 2, true, faces, Interface::UNION );
166 if( MB_SUCCESS != result ) return result;
167 result = mbImpl->get_adjacencies( entities, num_entities, 3, true, regions, Interface::UNION );
168 if( MB_SUCCESS != result ) return result;
169 }
170
171 Range dual_verts;
172 result = construct_dual_vertices( regions, dual_verts );
173 if( MB_SUCCESS != result || dual_verts.size() != regions.size() ) return result;
174 if( debug ) std::cout << "Constructed " << dual_verts.size() << " dual vertices." << std::endl;
175
176
177 Range dual_edges;
178 result = construct_dual_edges( faces, dual_edges );
179 if( MB_SUCCESS != result || dual_edges.size() != faces.size() ) return result;
180 if( debug ) std::cout << "Constructed " << dual_edges.size() << " dual edges." << std::endl;
181
182
183 Range dual_faces;
184 result = construct_dual_faces( edges, dual_faces );
185 if( MB_SUCCESS != result || dual_faces.size() != edges.size() ) return result;
186 if( debug ) std::cout << "Constructed " << dual_faces.size() << " dual faces." << std::endl;
187
188
189 Range dual_cells;
190 result = construct_dual_cells( vertices, dual_cells );
191 if( MB_SUCCESS != result || dual_cells.size() != vertices.size() ) return result;
192 if( debug ) std::cout << "Constructed " << dual_cells.size() << " dual cells." << std::endl;
193
194 return MB_SUCCESS;
195 }
196
197 ErrorCode DualTool::construct_dual_vertices( const Range& all_regions, Range& dual_ents )
198 {
199 if( all_regions.empty() ) return MB_SUCCESS;
200
201
202 assert( 3 == CN::Dimension( TYPE_FROM_HANDLE( *all_regions.begin() ) ) &&
203 3 == CN::Dimension( TYPE_FROM_HANDLE( *all_regions.rbegin() ) ) );
204
205 Range::const_iterator rit;
206 EntityHandle dual_ent;
207 ErrorCode tmp_result = MB_SUCCESS;
208 ErrorCode result = MB_SUCCESS;
209
210 for( rit = all_regions.begin(); rit != all_regions.end(); ++rit )
211 {
212 if( tmp_result != MB_SUCCESS ) result = tmp_result;
213
214 tmp_result = mbImpl->tag_get_data( dualEntity_tag(), &( *rit ), 1, &dual_ent );
215 if( MB_SUCCESS == tmp_result && 0 != dual_ent )
216 {
217 dual_ents.insert( dual_ent );
218 continue;
219 }
220 else if( MB_SUCCESS != tmp_result )
221 continue;
222
223 tmp_result = construct_dual_vertex( *rit, dual_ent, false, true );
224 if( MB_SUCCESS != tmp_result ) continue;
225
226
227 dual_ents.insert( dual_ent );
228 }
229
230 return result;
231 }
232
233 ErrorCode DualTool::construct_dual_vertex( EntityHandle entity,
234 EntityHandle& dual_ent,
235 const bool extra,
236 const bool add_graphics_pt )
237 {
238
239 unsigned int is_dual = 0x1;
240 double avg_pos[3];
241 ErrorCode result = MeshTopoUtil( mbImpl ).get_average_position( entity, avg_pos );
242 if( MB_SUCCESS != result ) return result;
243
244
245 result = mbImpl->create_vertex( avg_pos, dual_ent );
246 if( MB_SUCCESS != result ) return result;
247
248
249 result = mbImpl->tag_set_data( isDualCell_tag(), &dual_ent, 1, &is_dual );
250 if( MB_SUCCESS != result ) return result;
251
252
253 if( extra )
254 result = mbImpl->tag_set_data( extraDualEntity_tag(), &( entity ), 1, &dual_ent );
255 else
256 result = mbImpl->tag_set_data( dualEntity_tag(), &( entity ), 1, &dual_ent );
257 if( MB_SUCCESS != result ) return result;
258
259 result = mbImpl->tag_set_data( dualEntity_tag(), &dual_ent, 1, &( entity ) );
260 if( MB_SUCCESS != result ) return result;
261
262 if( add_graphics_pt )
263
264 result = add_graphics_point( dual_ent, avg_pos );
265
266 return result;
267 }
268
269 ErrorCode DualTool::add_graphics_point( EntityHandle entity, double* avg_pos )
270 {
271
272 double my_pos[3];
273 ErrorCode result;
274
275 if( NULL == avg_pos )
276 {
277 result = MeshTopoUtil( mbImpl ).get_average_position( entity, my_pos );
278 if( MB_SUCCESS != result ) return result;
279 }
280 else
281 for( int i = 0; i < 3; i++ )
282 my_pos[i] = avg_pos[i];
283
284 DualTool::GraphicsPoint dum_pt( my_pos, -1 );
285 result = mbImpl->tag_set_data( dualGraphicsPoint_tag(), &entity, 1, &dum_pt );
286 return result;
287 }
288
289 ErrorCode DualTool::construct_dual_edges( const Range& all_faces, Range& dual_ents )
290 {
291 if( all_faces.empty() ) return MB_SUCCESS;
292
293
294 assert( 2 == CN::Dimension( TYPE_FROM_HANDLE( *all_faces.begin() ) ) &&
295 2 == CN::Dimension( TYPE_FROM_HANDLE( *all_faces.rbegin() ) ) );
296
297 Range::const_iterator rit;
298 EntityHandle dual_ent;
299 unsigned int is_dual = 0x1;
300 ErrorCode tmp_result = MB_SUCCESS;
301 ErrorCode result = MB_SUCCESS;
302
303 for( rit = all_faces.begin(); rit != all_faces.end(); ++rit )
304 {
305 if( tmp_result != MB_SUCCESS ) result = tmp_result;
306
307 tmp_result = mbImpl->tag_get_data( dualEntity_tag(), &( *rit ), 1, &dual_ent );
308 if( MB_SUCCESS == tmp_result && 0 != dual_ent )
309 {
310 dual_ents.insert( dual_ent );
311 continue;
312 }
313
314
315 std::vector< EntityHandle > out_ents;
316 tmp_result = mbImpl->get_adjacencies( &( *rit ), 1, 3, false, out_ents );
317 if( MB_SUCCESS != tmp_result || out_ents.empty() ) continue;
318
319
320 std::vector< EntityHandle > dual_verts( out_ents.size() );
321 tmp_result = mbImpl->tag_get_data( dualEntity_tag(), &out_ents[0], out_ents.size(), &dual_verts[0] );
322 if( MB_SUCCESS != tmp_result ) continue;
323 assert( dual_verts.size() <= 2 );
324
325 double avg_pos[3];
326 bool bdy_face = ( dual_verts.size() == 1 ? true : false );
327 if( bdy_face )
328 {
329
330 tmp_result = construct_dual_vertex( *rit, dual_ent, true, true );
331
332
333 dual_verts.push_back( dual_ent );
334 }
335
336 assert( dual_verts.size() == 2 );
337
338
339 tmp_result = mbImpl->create_element( MBEDGE, &dual_verts[0], 2, dual_ent );
340 if( MB_SUCCESS != tmp_result || 0 == dual_ent ) continue;
341
342
343 dual_ents.insert( dual_ent );
344
345
346 tmp_result = mbImpl->tag_set_data( dualEntity_tag(), &( *rit ), 1, &dual_ent );
347 if( MB_SUCCESS != tmp_result ) continue;
348
349 tmp_result = mbImpl->tag_set_data( dualEntity_tag(), &dual_ent, 1, &( *rit ) );
350 if( MB_SUCCESS != tmp_result ) continue;
351
352
353 tmp_result = mbImpl->tag_set_data( isDualCell_tag(), &dual_ent, 1, &is_dual );
354 if( MB_SUCCESS != tmp_result ) continue;
355
356
357
358 if( bdy_face )
359 tmp_result = add_graphics_point( dual_ent );
360 else
361 {
362
363 tmp_result = MeshTopoUtil( mbImpl ).get_average_position( *rit, avg_pos );
364 if( MB_SUCCESS != tmp_result ) continue;
365 tmp_result = add_graphics_point( dual_ent, avg_pos );
366 }
367 if( MB_SUCCESS != tmp_result ) continue;
368 }
369
370 return result;
371 }
372
373 ErrorCode DualTool::construct_dual_faces( const Range& all_edges, Range& dual_ents )
374 {
375 if( all_edges.empty() ) return MB_SUCCESS;
376
377
378 assert( 1 == CN::Dimension( TYPE_FROM_HANDLE( *all_edges.begin() ) ) &&
379 1 == CN::Dimension( TYPE_FROM_HANDLE( *all_edges.rbegin() ) ) );
380
381 Range::const_iterator rit;
382 EntityHandle dual_ent;
383 unsigned int is_dual = 0x1;
384 ErrorCode tmp_result = MB_SUCCESS;
385 ErrorCode result = MB_SUCCESS;
386 Range equiv_edges;
387 #define TRC \
388 if( MB_SUCCESS != tmp_result ) \
389 { \
390 result = tmp_result; \
391 continue; \
392 }
393 for( rit = all_edges.begin(); rit != all_edges.end(); ++rit )
394 {
395
396 tmp_result = mbImpl->tag_get_data( dualEntity_tag(), &( *rit ), 1, &dual_ent );
397 if( MB_SUCCESS == tmp_result && 0 != dual_ent )
398 {
399 dual_ents.insert( dual_ent );
400 continue;
401 }
402
403
404
405 std::vector< EntityHandle > rad_dverts;
406 bool bdy_edge;
407 tmp_result = get_radial_dverts( *rit, rad_dverts, bdy_edge );
408 TRC if( rad_dverts.empty() ) continue;
409
410 tmp_result = mbImpl->create_element( MBPOLYGON, &rad_dverts[0], rad_dverts.size(), dual_ent );
411 TRC
412
413
414 tmp_result = mbImpl->tag_set_data( isDualCell_tag(), &dual_ent, 1, &is_dual );
415 TRC tmp_result = mbImpl->tag_set_data( dualEntity_tag(), &( *rit ), 1, &dual_ent );
416 TRC tmp_result = mbImpl->tag_set_data( dualEntity_tag(), &dual_ent, 1, &( *rit ) );
417 TRC
418
419
420 dual_ents.insert( dual_ent );
421
422
423
424 double avg_pos[3];
425 tmp_result = MeshTopoUtil( mbImpl ).get_average_position( *rit, avg_pos );
426 TRC if( bdy_edge )
427 {
428
429
430 EntityHandle new_edge;
431 tmp_result = mbImpl->create_element( MBEDGE, &rad_dverts[rad_dverts.size() - 2], 2, new_edge );
432 TRC tmp_result = mbImpl->tag_set_data( isDualCell_tag(), &new_edge, 1, &is_dual );
433 TRC
434
435
436
437 tmp_result = mbImpl->tag_set_data( dualEntity_tag(), &new_edge, 1, &( *rit ) );
438 TRC
439
440
441 tmp_result = add_graphics_point( dual_ent );
442 TRC tmp_result = add_graphics_point( new_edge, avg_pos );
443 TRC
444 }
445
446 else
447 {
448
449 tmp_result = add_graphics_point( dual_ent, avg_pos );
450 TRC
451 }
452
453
454 Range dum_edges, dum_poly( dual_ent, dual_ent );
455 tmp_result = mbImpl->get_adjacencies( dum_poly, 1, false, dum_edges );
456 if( MB_MULTIPLE_ENTITIES_FOUND == tmp_result )
457 {
458
459 equiv_edges.merge( dum_edges );
460 }
461 }
462
463 if( !equiv_edges.empty() ) result = check_dual_equiv_edges( equiv_edges );
464
465 return result;
466 }
467
468 ErrorCode DualTool::check_dual_equiv_edges( Range& dual_edges )
469 {
470
471
472
473 ErrorCode tmp_result, result = MB_SUCCESS;
474
475 Range all_dedges( dual_edges );
476
477
478 for( Range::iterator rit = dual_edges.begin(); rit != dual_edges.end(); ++rit )
479 {
480 Range connect, dum_range( *rit, *rit );
481 tmp_result = mbImpl->get_adjacencies( dum_range, 0, false, connect );
482 if( MB_SUCCESS != tmp_result ) continue;
483 tmp_result = mbImpl->get_adjacencies( connect, 1, false, all_dedges, Interface::UNION );
484 if( MB_SUCCESS != tmp_result ) continue;
485 }
486
487
488 Range save_all_2cells;
489
490
491 while( !all_dedges.empty() )
492 {
493 EntityHandle this_edge = *all_dedges.begin();
494 all_dedges.erase( all_dedges.begin() );
495
496 const EntityHandle* connect;
497 int num_connect;
498 result = mbImpl->get_connectivity( this_edge, connect, num_connect );
499 if( MB_SUCCESS != result ) continue;
500
501 Range dum_edges, verts;
502 verts.insert( connect[0] );
503 verts.insert( connect[1] );
504 tmp_result = mbImpl->get_adjacencies( verts, 1, false, dum_edges );
505 if( MB_SUCCESS != tmp_result )
506 {
507 result = tmp_result;
508 continue;
509 }
510 if( dum_edges.size() == 1 )
511 {
512
513 continue;
514 }
515
516
517
518 EntityHandle dedge_quad;
519 tmp_result = mbImpl->tag_get_data( dualEntity_tag(), &this_edge, 1, &dedge_quad );
520 if( MB_SUCCESS != tmp_result )
521 {
522 result = tmp_result;
523 continue;
524 }
525
526 if( MBQUAD == mbImpl->type_from_handle( dedge_quad ) )
527 {
528
529
530 Range dum_quad_range( dedge_quad, dedge_quad ), adj_pedges;
531 tmp_result = mbImpl->get_adjacencies( dum_quad_range, 1, false, adj_pedges );
532 if( MB_SUCCESS != tmp_result )
533 {
534 result = tmp_result;
535 continue;
536 }
537
538 std::vector< EntityHandle > dcells;
539 dcells.resize( adj_pedges.size() );
540 tmp_result = mbImpl->tag_get_data( dualEntity_tag(), adj_pedges, &dcells[0] );
541 if( MB_SUCCESS != tmp_result )
542 {
543 result = tmp_result;
544 continue;
545 }
546
547 std::vector< EntityHandle >::iterator vit;
548 for( vit = dcells.begin(); vit != dcells.end(); ++vit )
549 {
550 save_all_2cells.insert( *vit );
551
552 assert( MBPOLYGON == mbImpl->type_from_handle( *vit ) );
553 tmp_result = mbImpl->add_adjacencies( this_edge, &( *vit ), 1, false );
554 if( MB_SUCCESS != tmp_result )
555 {
556 result = tmp_result;
557 continue;
558 }
559
560 const EntityHandle* adjs;
561 int num_adjs;
562 tmp_result = reinterpret_cast< Core* >( mbImpl )->a_entity_factory()->get_adjacencies( this_edge, adjs,
563 num_adjs );
564 if( NULL == adjs || std::find( adjs, adjs + num_adjs, *vit ) == adjs + num_adjs )
565 std::cout << "Add_adjacencies failed in construct_dual_faces." << std::endl;
566 }
567 }
568 else
569 {
570
571
572 EntityHandle bdy_dcell;
573 tmp_result = mbImpl->tag_get_data( dualEntity_tag(), &dedge_quad, 1, &bdy_dcell );
574 TRC assert( MBPOLYGON == mbImpl->type_from_handle( bdy_dcell ) );
575
576 tmp_result = mbImpl->add_adjacencies( this_edge, &bdy_dcell, 1, false );
577 if( MB_SUCCESS != tmp_result )
578 {
579 result = tmp_result;
580 continue;
581 }
582 }
583 }
584
585
586 for( Range::iterator vit = save_all_2cells.begin(); vit != save_all_2cells.end(); ++vit )
587 {
588 Range adj_edges, dum_quad_range;
589 dum_quad_range.insert( *vit );
590 assert( MBPOLYGON == mbImpl->type_from_handle( *vit ) );
591 tmp_result = mbImpl->get_adjacencies( dum_quad_range, 1, false, adj_edges );
592 if( MB_MULTIPLE_ENTITIES_FOUND == tmp_result )
593 {
594 std::cout << "Multiple entities returned for polygon " << mbImpl->id_from_handle( *vit ) << "."
595 << std::endl;
596 continue;
597 }
598 }
599
600 return result;
601 }
602
603 ErrorCode DualTool::construct_dual_cells( const Range& all_verts, Range& dual_ents )
604 {
605 if( all_verts.empty() ) return MB_SUCCESS;
606
607
608 assert( 0 == CN::Dimension( TYPE_FROM_HANDLE( *all_verts.begin() ) ) &&
609 0 == CN::Dimension( TYPE_FROM_HANDLE( *all_verts.rbegin() ) ) );
610
611 Range::const_iterator rit;
612 EntityHandle dual_ent;
613 unsigned int is_dual = 0x1;
614 ErrorCode tmp_result = MB_SUCCESS;
615 ErrorCode result = MB_SUCCESS;
616 std::vector< EntityHandle > edges, dfaces;
617
618 for( rit = all_verts.begin(); rit != all_verts.end(); ++rit )
619 {
620 if( tmp_result != MB_SUCCESS ) result = tmp_result;
621
622 tmp_result = mbImpl->tag_get_data( dualEntity_tag(), &( *rit ), 1, &dual_ent );
623 if( MB_SUCCESS == tmp_result && 0 != dual_ent )
624 {
625 dual_ents.insert( dual_ent );
626 continue;
627 }
628
629
630 edges.clear();
631 dfaces.clear();
632 tmp_result = mbImpl->get_adjacencies( &( *rit ), 1, 1, false, edges );
633 if( MB_SUCCESS != tmp_result ) continue;
634
635
636 dfaces.resize( edges.size() );
637 tmp_result = mbImpl->tag_get_data( dualEntity_tag(), &edges[0], edges.size(), &dfaces[0] );
638 if( MB_SUCCESS != tmp_result ) continue;
639
640
641 tmp_result = mbImpl->create_element( MBPOLYHEDRON, &dfaces[0], dfaces.size(), dual_ent );
642 if( MB_SUCCESS != tmp_result || 0 == dual_ent ) continue;
643
644
645 dual_ents.insert( dual_ent );
646
647
648 tmp_result = mbImpl->tag_set_data( isDualCell_tag(), &dual_ent, 1, &is_dual );
649 if( MB_SUCCESS != tmp_result ) continue;
650
651
652 tmp_result = mbImpl->tag_set_data( dualEntity_tag(), &( *rit ), 1, &dual_ent );
653 if( MB_SUCCESS != tmp_result ) continue;
654 tmp_result = mbImpl->tag_set_data( dualEntity_tag(), &dual_ent, 1, &( *rit ) );
655 if( MB_SUCCESS != tmp_result ) continue;
656 }
657
658 return result;
659 }
660
661
662
663 ErrorCode DualTool::get_radial_dverts( const EntityHandle edge,
664 std::vector< EntityHandle >& rad_dverts,
665 bool& bdy_edge )
666 {
667 rad_dverts.clear();
668
669 std::vector< EntityHandle > rad_faces, rad_ents;
670 ErrorCode result = MeshTopoUtil( mbImpl ).star_entities( edge, rad_faces, bdy_edge, 0, &rad_ents );
671 if( MB_SUCCESS != result ) return result;
672
673 if( bdy_edge )
674 {
675
676 rad_ents.push_back( *rad_faces.rbegin() );
677 rad_ents.push_back( *rad_faces.begin() );
678 }
679
680 rad_dverts.resize( rad_ents.size() );
681 for( unsigned int i = 0; i < rad_ents.size(); i++ )
682 {
683 EntityHandle dual_ent;
684 result = mbImpl->tag_get_data( dualEntity_tag(), &rad_ents[i], 1, &dual_ent );
685 if( !bdy_edge || i < rad_ents.size() - 2 )
686 rad_dverts[i] = dual_ent;
687 else
688 {
689
690 assert( mbImpl->type_from_handle( dual_ent ) == MBEDGE );
691
692
693 const EntityHandle* connect;
694 int num_connect;
695 result = mbImpl->get_connectivity( dual_ent, connect, num_connect );
696 if( MB_SUCCESS != result ) return result;
697
698
699 int last_hex = ( i == rad_ents.size() - 1 ? 0 : i - 1 );
700 EntityHandle last_face = ( connect[0] == rad_dverts[last_hex] ? connect[1] : connect[0] );
701 rad_dverts[i] = last_face;
702 }
703 }
704
705 return result;
706 }
707
708
709 ErrorCode DualTool::construct_hex_dual( Range& entities )
710 {
711 std::vector< EntityHandle > evec;
712 std::copy( entities.begin(), entities.end(), std::back_inserter( evec ) );
713 return construct_hex_dual( &evec[0], evec.size() );
714 }
715
716
717 ErrorCode DualTool::construct_hex_dual( EntityHandle* entities, const int num_entities )
718 {
719
720
721
722 ErrorCode result = construct_dual( entities, num_entities );
723 if( MB_SUCCESS != result )
724 {
725 std::cerr << "Error constructing dual entities for primal entities." << std::endl;
726 return result;
727 }
728
729
730 result = construct_dual_hyperplanes( 1, entities, num_entities );
731 if( MB_SUCCESS != result )
732 {
733 std::cerr << "Problem traversing 1d hyperplanes." << std::endl;
734 return result;
735 }
736
737 result = construct_dual_hyperplanes( 2, entities, num_entities );
738 if( MB_SUCCESS != result )
739 {
740 std::cerr << "Problem traversing 2d hyperplanes." << std::endl;
741 return result;
742 }
743
744 result = construct_hp_parent_child();
745 if( MB_SUCCESS != result )
746 {
747 std::cerr << "Problem constructing parent/child relations between hyperplanes." << std::endl;
748 return result;
749 }
750
751
752 return MB_SUCCESS;
753 }
754
755
756 ErrorCode DualTool::get_dual_entities( const int dim, EntityHandle* entities, const int num_entities, Range& dual_ents )
757 {
758 if( 0 == isDualCell_tag() ) return MB_SUCCESS;
759 if( 0 > dim || 3 < dim ) return MB_INDEX_OUT_OF_RANGE;
760
761 unsigned int dum = 0x1;
762 const void* dum_ptr = &dum;
763 static EntityType dual_type[] = { MBVERTEX, MBEDGE, MBPOLYGON, MBPOLYHEDRON };
764
765 Range dim_ents;
766
767 ErrorCode result;
768
769 if( 0 == entities || 0 == num_entities )
770 {
771
772 result = mbImpl->get_entities_by_type_and_tag( 0, dual_type[dim], &isDualCellTag, &dum_ptr, 1, dual_ents );
773 }
774 else
775 {
776
777 result = mbImpl->get_adjacencies( entities, num_entities, 3 - dim, false, dim_ents, Interface::UNION );
778 if( MB_SUCCESS != result ) return result;
779 std::vector< EntityHandle > dual_ents_vec( dim_ents.size() );
780 result = mbImpl->tag_get_data( dualEntity_tag(), dim_ents, &dual_ents_vec[0] );
781 if( MB_SUCCESS != result ) return result;
782 std::copy( dual_ents_vec.begin(), dual_ents_vec.end(), range_inserter( dual_ents ) );
783 }
784
785 return result;
786 }
787
788
789 ErrorCode DualTool::get_dual_entities( const int dim,
790 EntityHandle* entities,
791 const int num_entities,
792 std::vector< EntityHandle >& dual_ents )
793 {
794 Range tmp_range;
795 ErrorCode result = get_dual_entities( dim, entities, num_entities, tmp_range );
796 if( MB_SUCCESS != result ) return result;
797
798
799 dual_ents.reserve( dual_ents.size() + tmp_range.size() );
800 for( Range::const_iterator it = tmp_range.begin(); it != tmp_range.end(); ++it )
801 {
802 dual_ents.push_back( *it );
803 }
804 return MB_SUCCESS;
805 }
806
807 ErrorCode DualTool::get_dual_hyperplanes( const Interface* impl, const int dim, Range& dual_ents )
808 {
809 if( dim != 1 && dim != 2 ) return MB_INDEX_OUT_OF_RANGE;
810
811 Tag dual_tag;
812 ErrorCode result;
813
814 if( dim == 1 )
815 result = impl->tag_get_handle( DUAL_CURVE_TAG_NAME, 1, MB_TYPE_HANDLE, dual_tag );
816 else
817 result = impl->tag_get_handle( DUAL_SURFACE_TAG_NAME, 1, MB_TYPE_HANDLE, dual_tag );
818
819 if( MB_SUCCESS == result )
820 result = impl->get_entities_by_type_and_tag( 0, MBENTITYSET, &dual_tag, NULL, 1, dual_ents, Interface::UNION );
821
822 return result;
823 }
824
825 ErrorCode DualTool::construct_dual_hyperplanes( const int dim, EntityHandle* entities, const int num_entities )
826 {
827
828
829
830
831 int num_quads, num_hexes;
832 if(
833
834 ( dim != 1 && dim != 2 ) ||
835
836 mbImpl->get_number_entities_by_type( 0, MBQUAD, num_quads ) != MB_SUCCESS ||
837 mbImpl->get_number_entities_by_type( 0, MBHEX, num_hexes ) != MB_SUCCESS ||
838
839 ( num_quads == 0 && dim == 1 ) ||
840
841 ( num_hexes == 0 && dim == 2 ) )
842 return MB_FAILURE;
843
844 Tag hp_tag = ( 1 == dim ? dualCurve_tag() : dualSurface_tag() );
845
846
847
848 std::vector< EntityHandle > tot_untreated;
849
850
851 ErrorCode result = get_dual_entities( dim, entities, num_entities, tot_untreated );
852 if( MB_SUCCESS != result ) return result;
853
854
855 EntityHandle this_ent;
856 EntityHandle this_hp;
857
858 while( !tot_untreated.empty() )
859 {
860 if( debug && dim == 2 )
861 std::cout << "Untreated list size " << tot_untreated.size() << "." << std::endl;
862
863 this_ent = tot_untreated.back();
864 tot_untreated.pop_back();
865 result = mbImpl->tag_get_data( hp_tag, &this_ent, 1, &this_hp );
866 if( MB_SUCCESS != result && MB_TAG_NOT_FOUND != result ) return result;
867
868
869 else if( this_hp != 0 )
870 continue;
871
872 if( 1 == dim && check_1d_loop_edge( this_ent ) ) continue;
873
874
875 result = traverse_hyperplane( hp_tag, this_hp, this_ent );
876 if( MB_SUCCESS != result )
877 {
878 std::cout << "Failed to traverse hyperplane ";
879 if( this_hp )
880 std::cout << mbImpl->id_from_handle( this_hp ) << "." << std::endl;
881 else
882 std::cout << "0." << std::endl;
883 return result;
884 }
885
886
887 if( 1 == dim ) order_chord( this_hp );
888 }
889
890 return MB_SUCCESS;
891 }
892
893 ErrorCode DualTool::traverse_hyperplane( const Tag hp_tag, EntityHandle& this_hp, EntityHandle this_ent )
894 {
895 Range tmp_star, star, tmp_range, new_hyperplane_ents;
896 std::vector< EntityHandle > hp_untreated;
897 int dim = mbImpl->dimension_from_handle( this_ent );
898 MeshTopoUtil mtu( mbImpl );
899 this_hp = 0;
900 ErrorCode result;
901
902 unsigned short mark_val = 0x0;
903 Tag mark_tag;
904 result = mbImpl->tag_get_handle( "__hyperplane_mark", 1, MB_TYPE_BIT, mark_tag, MB_TAG_CREAT | MB_TAG_BIT );
905 if( MB_SUCCESS != result ) return result;
906 mark_val = 0x1;
907
908 while( 0 != this_ent )
909 {
910 EntityHandle tmp_hp = get_dual_hyperplane( this_ent );
911 if( 0 == this_hp && 0 != tmp_hp ) this_hp = tmp_hp;
912
913 if( 0 == tmp_hp ) new_hyperplane_ents.insert( this_ent );
914
915 if( debug && hp_untreated.size() % 10 == 0 )
916 std::cout << "Dual surface " << this_hp << ", hp_untreated list size = " << hp_untreated.size() << "."
917 << std::endl;
918
919
920 tmp_range.clear();
921 tmp_star.clear();
922 star.clear();
923 result = mtu.get_bridge_adjacencies( this_ent, dim - 1, dim, star );RR;
924
925
926 result = mtu.get_bridge_adjacencies( this_ent, dim + 1, dim, tmp_star );RR;
927 tmp_range = subtract( star, tmp_star );
928
929 for( Range::iterator rit = tmp_range.begin(); rit != tmp_range.end(); ++rit )
930 {
931 if( new_hyperplane_ents.find( *rit ) != new_hyperplane_ents.end() ) continue;
932
933
934
935 unsigned short tmp_mark = 0x0;
936 result = mbImpl->tag_get_data( mark_tag, &( *rit ), 1, &tmp_mark );
937 if( MB_SUCCESS == result && mark_val == tmp_mark ) continue;
938
939
940 if( 1 == dim && check_1d_loop_edge( *rit ) ) continue;
941
942
943
944 hp_untreated.push_back( *rit );
945 result = mbImpl->tag_set_data( mark_tag, &( *rit ), 1, &mark_val );
946 if( MB_SUCCESS != result ) return result;
947 }
948
949
950 if( hp_untreated.empty() )
951 this_ent = 0;
952 else
953 {
954 this_ent = hp_untreated.back();
955 hp_untreated.pop_back();
956 }
957 }
958
959 if( debug_ap )
960 {
961 std::string hp_name;
962 if( 2 == dim )
963 hp_name = "sheet";
964 else
965 hp_name = "chord";
966
967 if( 0 == this_hp )
968 std::cout << "Constructed new " << hp_name << " with ";
969 else
970 {
971 int this_id;
972 result = mbImpl->tag_get_data( globalId_tag(), &this_hp, 1, &this_id );RR;
973 std::cout << "Added to " << hp_name << " " << this_id << " ";
974 }
975 if( dim == 2 )
976 std::cout << "edges:" << std::endl;
977 else
978 std::cout << "quads:" << std::endl;
979 std::vector< EntityHandle > pents( new_hyperplane_ents.size() );
980 result = mbImpl->tag_get_data( dualEntity_tag(), new_hyperplane_ents, &pents[0] );RR;
981 for( std::vector< EntityHandle >::iterator vit = pents.begin(); vit != pents.end(); ++vit )
982 {
983 if( vit != pents.begin() ) std::cout << ", ";
984 std::cout << mbImpl->id_from_handle( *vit );
985 }
986 std::cout << std::endl;
987 }
988
989 if( 0 == this_hp )
990 {
991
992 int new_id = -1;
993 result = construct_new_hyperplane( dim, this_hp, new_id );
994 if( MB_SUCCESS != result ) return result;
995
996 if( debug_ap )
997 {
998 std::cout << "New ";
999 if( 2 == dim )
1000 std::cout << " sheet ";
1001 else
1002 std::cout << " chord ";
1003 std::cout << new_id << " constructed." << std::endl;
1004 }
1005 }
1006
1007
1008 std::vector< EntityHandle > hp_tags( new_hyperplane_ents.size() );
1009 std::fill( hp_tags.begin(), hp_tags.end(), this_hp );
1010 result = mbImpl->tag_set_data( hp_tag, new_hyperplane_ents, &hp_tags[0] );
1011 if( MB_SUCCESS != result ) return result;
1012 result = mbImpl->add_entities( this_hp, new_hyperplane_ents );
1013 if( MB_SUCCESS != result ) return result;
1014
1015
1016 result = mbImpl->tag_delete( mark_tag );
1017 if( MB_SUCCESS != result ) return result;
1018
1019 return MB_SUCCESS;
1020 }
1021
1022 ErrorCode DualTool::order_chord( EntityHandle chord_set )
1023 {
1024
1025
1026 Range verts, one_cells;
1027 ErrorCode result = mbImpl->get_entities_by_dimension( chord_set, 1, one_cells );
1028 if( MB_SUCCESS != result || one_cells.empty() ) return MB_FAILURE;
1029
1030 result = mbImpl->get_adjacencies( one_cells, 0, false, verts, Interface::UNION );
1031 if( MB_SUCCESS != result || verts.empty() ) return MB_FAILURE;
1032
1033 EntityHandle last_vert = 0;
1034 for( Range::iterator rit = verts.begin(); rit != verts.end(); ++rit )
1035 {
1036 if( TYPE_FROM_HANDLE( get_dual_entity( *rit ) ) == MBQUAD )
1037 {
1038 last_vert = *rit;
1039 break;
1040 }
1041 }
1042
1043 if( 0 == last_vert ) last_vert = *verts.begin();
1044
1045
1046 std::vector< EntityHandle > ordered_1cells;
1047 EntityHandle last_1cell = 0;
1048 Range dum1, dum2;
1049 const EntityHandle* connect;
1050 int num_connect;
1051 ErrorCode tmp_result = MB_SUCCESS;
1052 while( ordered_1cells.size() != one_cells.size() )
1053 {
1054 dum1 = one_cells;
1055 result = mbImpl->get_adjacencies( &last_vert, 1, 1, false, dum1 );
1056 if( 0 != last_1cell ) dum1.erase( last_1cell );
1057
1058 if( 0 != last_1cell && 1 != dum1.size() )
1059 {
1060 std::cerr << "unexpected size traversing chord." << std::endl;
1061 tmp_result = MB_FAILURE;
1062 }
1063
1064 last_1cell = *dum1.begin();
1065 ordered_1cells.push_back( last_1cell );
1066 result = mbImpl->get_connectivity( last_1cell, connect, num_connect );RR;
1067 if( last_vert == connect[0] )
1068 last_vert = connect[1];
1069 else
1070 last_vert = connect[0];
1071 }
1072
1073
1074 if( MB_SUCCESS == tmp_result )
1075 {
1076 result = mbImpl->remove_entities( chord_set, one_cells );RR;
1077 result = mbImpl->add_entities( chord_set, &ordered_1cells[0], ordered_1cells.size() );RR;
1078 }
1079
1080 return MB_SUCCESS;
1081 }
1082
1083 ErrorCode DualTool::construct_new_hyperplane( const int dim, EntityHandle& new_hyperplane, int& id )
1084 {
1085 ErrorCode result;
1086 if( 1 == dim )
1087 result = mbImpl->create_meshset( ( MESHSET_ORDERED | MESHSET_TRACK_OWNER ), new_hyperplane );
1088 else
1089 result = mbImpl->create_meshset( ( MESHSET_SET | MESHSET_TRACK_OWNER ), new_hyperplane );
1090 if( MB_SUCCESS != result ) return result;
1091
1092 if( -1 == id )
1093 {
1094 Range all_hyperplanes;
1095 result = get_dual_hyperplanes( mbImpl, dim, all_hyperplanes );RR;
1096 std::vector< int > gids( all_hyperplanes.size() );
1097 result = mbImpl->tag_get_data( globalIdTag, all_hyperplanes, ( gids.empty() ) ? NULL : &gids[0] );RR;
1098 for( unsigned int i = 0; i < gids.size(); i++ )
1099 if( gids[i] > id ) id = gids[i];
1100 id++;
1101 if( 0 == id ) id++;
1102 }
1103
1104 result = mbImpl->tag_set_data( globalId_tag(), &new_hyperplane, 1, &id );RR;
1105 Tag hp_tag = ( 1 == dim ? dualCurve_tag() : dualSurface_tag() );
1106 result = mbImpl->tag_set_data( hp_tag, &new_hyperplane, 1, &new_hyperplane );RR;
1107
1108
1109 static const char dual_category_names[2][CATEGORY_TAG_SIZE] = { "Chord\0", "Sheet\0" };
1110
1111 result = mbImpl->tag_set_data( categoryTag, &new_hyperplane, 1, dual_category_names[dim - 1] );
1112
1113 return result;
1114 }
1115
1116 bool DualTool::check_1d_loop_edge( EntityHandle this_ent )
1117 {
1118
1119 if( MBEDGE != mbImpl->type_from_handle( this_ent ) ) return false;
1120
1121
1122 unsigned int dum;
1123 ErrorCode result = mbImpl->tag_get_data( isDualCell_tag(), &this_ent, 1, &dum );
1124 if( MB_SUCCESS != result || dum != 0x1 ) return false;
1125
1126 const EntityHandle* verts;
1127 EntityHandle vert_tags[2];
1128 int num_verts;
1129 result = mbImpl->get_connectivity( this_ent, verts, num_verts );
1130 if( MB_SUCCESS != result ) return false;
1131
1132 result = mbImpl->tag_get_data( dualEntity_tag(), verts, 2, vert_tags );
1133 if( MB_SUCCESS != result || mbImpl->type_from_handle( vert_tags[0] ) != MBQUAD ||
1134 mbImpl->type_from_handle( vert_tags[1] ) != MBQUAD )
1135 return false;
1136
1137 else
1138 return true;
1139 }
1140
1141 ErrorCode DualTool::construct_hp_parent_child()
1142 {
1143 Range dual_surfs, dual_cells, dual_edges;
1144 ErrorCode result = this->get_dual_hyperplanes( mbImpl, 2, dual_surfs );
1145 if( MB_SUCCESS != result || dual_surfs.empty() ) return result;
1146 std::vector< EntityHandle > dual_curve_sets;
1147
1148 for( Range::iterator surf_it = dual_surfs.begin(); surf_it != dual_surfs.end(); ++surf_it )
1149 {
1150
1151 dual_cells.clear();
1152 result = mbImpl->get_entities_by_handle( *surf_it, dual_cells );
1153 if( MB_SUCCESS != result ) return result;
1154 dual_edges.clear();
1155 result = mbImpl->get_adjacencies( dual_cells, 1, false, dual_edges, Interface::UNION );
1156 if( MB_SUCCESS != result ) return result;
1157 dual_curve_sets.resize( dual_edges.size() );
1158 result = mbImpl->tag_get_data( dualCurve_tag(), dual_edges, &dual_curve_sets[0] );
1159 if( MB_SUCCESS != result ) return result;
1160
1161
1162 dual_cells.clear();
1163 for( unsigned int i = 0; i < dual_edges.size(); i++ )
1164 if( dual_curve_sets[i] != 0 ) dual_cells.insert( dual_curve_sets[i] );
1165
1166
1167 for( Range::iterator rit = dual_cells.begin(); rit != dual_cells.end(); ++rit )
1168 {
1169 result = mbImpl->add_parent_child( *surf_it, *rit );
1170 if( MB_SUCCESS != result ) return result;
1171 }
1172 }
1173
1174 return MB_SUCCESS;
1175 }
1176
1177 ErrorCode DualTool::get_graphics_points( EntityHandle dual_ent,
1178 std::vector< int >& npts,
1179 std::vector< GraphicsPoint >& points )
1180 {
1181
1182 assert( MBENTITYSET != mbImpl->type_from_handle( dual_ent ) );
1183
1184
1185 GraphicsPoint gp_array[DualTool::GP_SIZE];
1186
1187 ErrorCode result = MB_SUCCESS;
1188
1189
1190 switch( mbImpl->dimension_from_handle( dual_ent ) )
1191 {
1192 case 0:
1193
1194 result = mbImpl->tag_get_data( dualGraphicsPoint_tag(), &dual_ent, 1, gp_array );
1195 if( MB_SUCCESS == result ) points.push_back( gp_array[0] );
1196
1197 break;
1198
1199 case 1:
1200
1201 const EntityHandle* connect;
1202 int num_connect;
1203 result = mbImpl->get_connectivity( dual_ent, connect, num_connect );
1204 if( MB_SUCCESS != result ) break;
1205
1206 result = mbImpl->tag_get_data( dualGraphicsPoint_tag(), connect, 2, gp_array );
1207 if( MB_SUCCESS == result )
1208 {
1209 points.push_back( gp_array[0] );
1210 points.push_back( gp_array[0] );
1211 points.push_back( gp_array[1] );
1212 result = mbImpl->tag_get_data( dualGraphicsPoint_tag(), &dual_ent, 1, gp_array );
1213 if( MB_SUCCESS == result ) points[1] = gp_array[0];
1214 }
1215
1216 npts.push_back( 3 );
1217
1218 break;
1219
1220 case 2:
1221 result = get_cell_points( dual_ent, npts, points );
1222 break;
1223 }
1224
1225 return result;
1226 }
1227
1228 ErrorCode DualTool::get_cell_points( EntityHandle dual_ent,
1229 std::vector< int >& npts,
1230 std::vector< GraphicsPoint >& points )
1231 {
1232 assert( MBPOLYGON == mbImpl->type_from_handle( dual_ent ) );
1233
1234
1235 Range one_cells;
1236
1237 Range tc_range;
1238 tc_range.insert( dual_ent );
1239 ErrorCode result = mbImpl->get_adjacencies( tc_range, 1, false, one_cells, Interface::UNION );RR;
1240
1241 int num_edges = one_cells.size();
1242 std::vector< GraphicsPoint > dum_gps( num_edges + 1 );
1243
1244
1245 result = mbImpl->tag_get_data( dualGraphicsPoint_tag(), one_cells, &dum_gps[0] );RR;
1246 result = mbImpl->tag_get_data( dualGraphicsPoint_tag(), &dual_ent, 1, &( dum_gps[num_edges] ) );RR;
1247
1248 Range::iterator eit;
1249 const EntityHandle* connect;
1250 int num_connect;
1251 GraphicsPoint vert_gps[2];
1252 int i;
1253 for( i = 0, eit = one_cells.begin(); i < num_edges; i++, ++eit )
1254 {
1255
1256 result = mbImpl->get_connectivity( *eit, connect, num_connect );RR;
1257 result = mbImpl->tag_get_data( dualGraphicsPoint_tag(), connect, 2, vert_gps );RR;
1258
1259
1260
1261 npts.push_back( 3 );
1262 points.push_back( dum_gps[num_edges] );
1263 points.push_back( vert_gps[0] );
1264 points.push_back( dum_gps[i] );
1265
1266 npts.push_back( 3 );
1267 points.push_back( dum_gps[num_edges] );
1268 points.push_back( dum_gps[i] );
1269 points.push_back( vert_gps[1] );
1270 }
1271
1272 return result;
1273 }
1274
1275 ErrorCode DualTool::get_graphics_points( const Range& in_range,
1276 std::vector< GraphicsPoint >& points,
1277 const bool assign_ids,
1278 const int start_id )
1279 {
1280
1281
1282 ErrorCode result;
1283
1284
1285 Range::const_iterator rit;
1286
1287 Range two_cells, all_cells;
1288 for( rit = in_range.begin(); rit != in_range.end(); ++rit )
1289 {
1290
1291 two_cells.clear();
1292 EntityType this_type = mbImpl->type_from_handle( *rit );
1293 if( MBENTITYSET == this_type )
1294 {
1295 result = mbImpl->get_entities_by_handle( *rit, two_cells );RR;
1296
1297 std::copy( two_cells.begin(), two_cells.end(), range_inserter( all_cells ) );
1298 }
1299
1300 else
1301 {
1302 two_cells.insert( *rit );
1303 assert( this_type == MBVERTEX || this_type == MBEDGE || this_type == MBPOLYGON ||
1304 this_type == MBPOLYHEDRON );
1305 }
1306
1307 result = mbImpl->get_adjacencies( two_cells, 0, false, all_cells, Interface::UNION );RR;
1308 result = mbImpl->get_adjacencies( two_cells, 1, false, all_cells, Interface::UNION );RR;
1309 }
1310
1311
1312 points.resize( all_cells.size() );
1313
1314 result = mbImpl->tag_get_data( dualGraphicsPointTag, all_cells, &points[0] );RR;
1315
1316 if( assign_ids )
1317 {
1318 int i = start_id;
1319
1320 for( std::vector< GraphicsPoint >::iterator vit = points.begin(); vit != points.end(); ++vit )
1321 vit->id = i++;
1322
1323 result = mbImpl->tag_set_data( dualGraphicsPoint_tag(), all_cells, &points[0] );RR;
1324 }
1325
1326 return result;
1327 }
1328
1329 EntityHandle DualTool::next_loop_vertex( const EntityHandle last_v,
1330 const EntityHandle this_v,
1331 const EntityHandle dual_surf )
1332 {
1333
1334
1335 assert( ( 0 == last_v || mbImpl->type_from_handle( last_v ) == MBVERTEX ) &&
1336 mbImpl->type_from_handle( this_v ) == MBVERTEX && mbImpl->type_from_handle( dual_surf ) == MBENTITYSET );
1337
1338
1339 MeshTopoUtil tpu( mbImpl );
1340 Range other_verts;
1341 ErrorCode result = tpu.get_bridge_adjacencies( this_v, 1, 0, other_verts );
1342 if( MB_SUCCESS != result || other_verts.empty() ) return 0;
1343
1344
1345
1346 Range tcells, tcells2, verts;
1347 result = mbImpl->get_entities_by_type( dual_surf, MBPOLYGON, tcells );
1348 if( MB_SUCCESS != result || tcells.empty() ) return 0;
1349
1350
1351 verts.insert( this_v );
1352 result = mbImpl->get_adjacencies( verts, 2, false, tcells );
1353 if( MB_SUCCESS != result || tcells.empty() ) return 0;
1354
1355
1356
1357 verts.clear();
1358 result = mbImpl->get_adjacencies( tcells, 0, false, verts );
1359 if( MB_SUCCESS != result || verts.empty() ) return 0;
1360
1361 Range tmp_verts = subtract( other_verts, verts );
1362 other_verts.swap( tmp_verts );
1363 if( 0 != last_v ) other_verts.erase( last_v );
1364
1365
1366
1367 tmp_verts = other_verts;
1368 Range tmp_faces( *tcells.begin(), *tcells.begin() );
1369 result = mbImpl->get_adjacencies( tmp_faces, 0, false, tmp_verts );
1370 if( MB_SUCCESS == result && !tmp_verts.empty() ) return *tmp_verts.begin();
1371 tmp_faces.clear();
1372 tmp_faces.insert( *tcells.rbegin() );
1373 result = mbImpl->get_adjacencies( tmp_faces, 0, false, other_verts );
1374 if( MB_SUCCESS == result && !other_verts.empty() ) return *other_verts.begin();
1375
1376
1377 return 0;
1378 }
1379
1380 EntityHandle DualTool::get_dual_hyperplane( const EntityHandle ncell )
1381 {
1382
1383 std::vector< EntityHandle > adj_sets;
1384 ErrorCode result = mbImpl->get_adjacencies( &ncell, 1, 4, false, adj_sets );
1385 if( MB_SUCCESS != result ) return 0;
1386
1387 EntityHandle dum_set;
1388 for( std::vector< EntityHandle >::iterator vit = adj_sets.begin(); vit != adj_sets.end(); ++vit )
1389 {
1390 if( mbImpl->tag_get_data( dualCurve_tag(), &( *vit ), 1, &dum_set ) != MB_TAG_NOT_FOUND ||
1391 mbImpl->tag_get_data( dualSurface_tag(), &( *vit ), 1, &dum_set ) != MB_TAG_NOT_FOUND )
1392 return *vit;
1393 }
1394
1395 return 0;
1396 }
1397
1398
1399 ErrorCode DualTool::set_dual_surface_or_curve( EntityHandle entity,
1400 const EntityHandle dual_hyperplane,
1401 const int dual_entity_dimension )
1402 {
1403 if( 1 == dual_entity_dimension )
1404 mbImpl->tag_set_data( dualCurve_tag(), &entity, 1, &dual_hyperplane );
1405 else if( 2 == dual_entity_dimension )
1406 mbImpl->tag_set_data( dualSurface_tag(), &entity, 1, &dual_hyperplane );
1407 else
1408 return MB_INDEX_OUT_OF_RANGE;
1409
1410 return MB_SUCCESS;
1411 }
1412
1413
1414 EntityHandle DualTool::get_dual_entity( const EntityHandle this_ent ) const
1415 {
1416 EntityHandle dual_ent;
1417 ErrorCode result = mbImpl->tag_get_data( dualEntity_tag(), &this_ent, 1, &dual_ent );
1418 if( MB_SUCCESS != result || MB_TAG_NOT_FOUND == result )
1419 return 0;
1420 else
1421 return dual_ent;
1422 }
1423
1424
1425 EntityHandle DualTool::get_extra_dual_entity( const EntityHandle this_ent )
1426 {
1427 EntityHandle dual_ent;
1428 ErrorCode result = mbImpl->tag_get_data( extraDualEntity_tag(), &this_ent, 1, &dual_ent );
1429 if( MB_SUCCESS != result || MB_TAG_NOT_FOUND == result )
1430 return 0;
1431 else
1432 return dual_ent;
1433 }
1434
1435 ErrorCode DualTool::atomic_pillow( EntityHandle odedge, EntityHandle& quad1, EntityHandle& quad2 )
1436 {
1437 if( debug_ap ) ( (Core*)mbImpl )->check_adjacencies();
1438
1439 if( debug_ap )
1440 {
1441 Range sets;
1442 Tag ms_tag;
1443
1444 ErrorCode result = mbImpl->tag_get_handle( "MATERIAL_SET", 1, MB_TYPE_INTEGER, ms_tag );
1445 if( MB_SUCCESS == result )
1446 {
1447 result = mbImpl->get_entities_by_type_and_tag( 0, MBENTITYSET, &ms_tag, NULL, 1, sets );
1448 if( MB_SUCCESS == result ) result = mbImpl->delete_entities( sets );
1449 }
1450 }
1451
1452 std::cout << "-AP(";
1453 print_cell( odedge );
1454 std::cout << ")" << std::endl;
1455
1456
1457
1458
1459 quad1 = get_dual_entity( odedge );
1460 assert( 0 != quad1 );
1461
1462
1463
1464
1465 MeshTopoUtil mtu( mbImpl );
1466 Range star_cells, tmp_cells;
1467 ErrorCode result = mbImpl->get_adjacencies( &odedge, 1, 2, false, star_cells );RR;
1468 result = mbImpl->get_adjacencies( star_cells, 3, false, tmp_cells, Interface::UNION );RR;
1469 star_cells.merge( tmp_cells );
1470 star_cells.insert( odedge );
1471
1472
1473 result = delete_dual_entities( star_cells );RR;
1474
1475
1476 std::vector< EntityHandle > verts;
1477 result = mbImpl->get_connectivity( &quad1, 1, verts );RR;
1478
1479
1480 double coords[12], avg[3] = { 0.0, 0.0, 0.0 };
1481 result = mbImpl->get_coords( &verts[0], verts.size(), coords );RR;
1482 for( int i = 0; i < 4; i++ )
1483 {
1484 avg[0] += coords[3 * i];
1485 avg[1] += coords[3 * i + 1];
1486 avg[2] += coords[3 * i + 2];
1487 }
1488 for( int i = 0; i < 3; i++ )
1489 avg[i] *= 0.25;
1490
1491
1492 double new_coords[12];
1493 for( int i = 0; i < 4; i++ )
1494 {
1495 new_coords[3 * i] = avg[0] + .5 * ( coords[3 * i] - avg[0] );
1496 new_coords[3 * i + 1] = avg[1] + .5 * ( coords[3 * i + 1] - avg[1] );
1497 new_coords[3 * i + 2] = avg[2] + .5 * ( coords[3 * i + 2] - avg[2] );
1498 }
1499
1500
1501 for( int i = 0; i < 4; i++ )
1502 {
1503 verts.push_back( 0 );
1504 result = mbImpl->create_vertex( &new_coords[3 * i], verts[4 + i] );RR;
1505 }
1506
1507
1508 Range hexes;
1509 result = mbImpl->get_adjacencies( &quad1, 1, 3, false, hexes );RR;
1510 assert( hexes.size() <= 2 );
1511
1512
1513
1514 result = mbImpl->remove_adjacencies( quad1, &( *hexes.begin() ), 1 );RR;
1515 if( hexes.size() == 2 )
1516 {
1517 result = mbImpl->add_adjacencies( quad1, &( *hexes.rbegin() ), 1, false );RR;
1518 }
1519
1520
1521
1522 std::vector< EntityHandle > tmp_verts;
1523 std::copy( verts.begin(), verts.end(), std::back_inserter( tmp_verts ) );
1524
1525 result = mbImpl->create_element( MBQUAD, &tmp_verts[0], 4, quad2 );RR;
1526 result = mbImpl->add_adjacencies( quad2, &( *hexes.begin() ), 1, false );RR;
1527
1528
1529 std::reverse( verts.begin(), verts.begin() + 4 );
1530 std::reverse( verts.begin() + 4, verts.end() );
1531
1532
1533 EntityHandle new_hexes[2];
1534 result = mbImpl->create_element( MBHEX, &verts[0], 8, new_hexes[0] );RR;
1535 result = mbImpl->create_element( MBHEX, &tmp_verts[0], 8, new_hexes[1] );RR;
1536
1537
1538 int new_hex_ids[2] = { maxHexId + 1, maxHexId + 2 };
1539 maxHexId += 2;
1540 result = mbImpl->tag_set_data( globalId_tag(), new_hexes, 2, new_hex_ids );
1541 if( MB_SUCCESS != result ) return result;
1542
1543
1544 result = mbImpl->add_adjacencies( quad1, &new_hexes[0], 1, false );RR;
1545 result = mbImpl->add_adjacencies( quad2, &new_hexes[1], 1, false );RR;
1546
1547 if( debug_ap ) ( (Core*)mbImpl )->check_adjacencies();
1548
1549
1550 result = construct_hex_dual( &new_hexes[0], 2 );RR;
1551
1552
1553
1554 Range new_edge;
1555 verts[1] = verts[4];
1556 result = mbImpl->get_adjacencies( &verts[0], 2, 1, false, new_edge );
1557 if( MB_SUCCESS != result || new_edge.size() != 1 ) return result;
1558
1559 return MB_SUCCESS;
1560 }
1561
1562
1563 ErrorCode DualTool::rev_atomic_pillow( EntityHandle pillow, Range& chords )
1564 {
1565
1566
1567
1568 if( debug_ap ) ( (Core*)mbImpl )->check_adjacencies();
1569
1570 std::cout << "-AP(";
1571 print_cell( pillow );
1572 std::cout << ")" << std::endl;
1573
1574 Range dverts;
1575 ErrorCode result = get_dual_entities( pillow, NULL, NULL, &dverts, NULL, NULL );
1576 if( MB_SUCCESS != result ) return result;
1577 assert( 2 == dverts.size() );
1578
1579 EntityHandle hexes[2];
1580 result = mbImpl->tag_get_data( dualEntity_tag(), dverts, hexes );RR;
1581 assert( hexes[0] != 0 && hexes[1] != 0 );
1582
1583 std::vector< EntityHandle > dcells[4];
1584 Range pcells[4];
1585 std::copy( hexes, hexes + 2, range_inserter( pcells[3] ) );
1586 std::copy( dverts.begin(), dverts.end(), std::back_inserter( dcells[0] ) );
1587 for( int dim = 0; dim <= 2; dim++ )
1588 {
1589 result = mbImpl->get_adjacencies( hexes, 2, dim, false, pcells[dim], Interface::UNION );RR;
1590 dcells[3 - dim].resize( pcells[dim].size() );
1591 result = mbImpl->tag_get_data( dualEntity_tag(), pcells[dim], &dcells[3 - dim][0] );RR;
1592 }
1593
1594
1595 result = mbImpl->delete_entities( &pillow, 1 );
1596 if( MB_SUCCESS != result ) return result;
1597
1598 result = mbImpl->delete_entities( chords );
1599 if( MB_SUCCESS != result ) return result;
1600
1601 for( int i = 3; i >= 0; i-- )
1602 {
1603 result = delete_dual_entities( &dcells[i][0], dcells[i].size() );RR;
1604 }
1605
1606
1607
1608 Range del_faces, del_edges, del_verts, tmp_faces, tmp_verts;
1609
1610
1611 result = mbImpl->get_adjacencies( hexes, 2, 2, false, del_faces );RR;
1612 assert( 5 == del_faces.size() );
1613 std::copy( pcells[2].begin(), pcells[2].end(), range_inserter( tmp_faces ) );
1614 tmp_faces = subtract( tmp_faces, del_faces );
1615 del_faces.insert( *tmp_faces.rbegin() );
1616 result = mbImpl->get_adjacencies( tmp_faces, 0, false, tmp_verts );RR;
1617 std::copy( pcells[0].begin(), pcells[0].end(), range_inserter( del_verts ) );
1618 del_verts = subtract( del_verts, tmp_verts );
1619 assert( 4 == del_verts.size() );
1620 result = mbImpl->get_adjacencies( del_verts, 1, false, del_edges, Interface::UNION );RR;
1621 assert( 8 == del_edges.size() );
1622
1623 result = mbImpl->delete_entities( hexes, 2 );RR;
1624 result = mbImpl->delete_entities( del_faces );RR;
1625 result = mbImpl->delete_entities( del_edges );RR;
1626 result = mbImpl->delete_entities( del_verts );RR;
1627
1628 if( debug_ap ) ( (Core*)mbImpl )->check_adjacencies();
1629
1630
1631
1632 Range tmp_hexes;
1633 result = mbImpl->get_adjacencies( tmp_verts, 3, false, tmp_hexes, Interface::UNION );RR;
1634 result = construct_hex_dual( tmp_hexes );RR;
1635
1636 return MB_SUCCESS;
1637 }
1638
1639 ErrorCode DualTool::delete_dual_entities( EntityHandle* entities, int num_entities )
1640 {
1641 Range tmp_ents;
1642 std::copy( entities, entities + num_entities, range_inserter( tmp_ents ) );
1643 return delete_dual_entities( tmp_ents );
1644 }
1645
1646 ErrorCode DualTool::delete_dual_entities( Range& entities )
1647 {
1648 if( entities.empty() ) return delete_whole_dual();
1649
1650 EntityHandle null_entity = 0;
1651 ErrorCode result;
1652 Range ents_to_delete;
1653
1654 while( !entities.empty() )
1655 {
1656 EntityHandle this_entity = entities.pop_back();
1657
1658
1659 EntityHandle primal = get_dual_entity( this_entity );
1660 if( get_dual_entity( primal ) == this_entity )
1661 {
1662 result = mbImpl->tag_set_data( dualEntity_tag(), &primal, 1, &null_entity );RR;
1663 }
1664 EntityHandle extra = get_extra_dual_entity( primal );
1665 if( 0 != extra )
1666 {
1667 result = mbImpl->tag_set_data( extraDualEntity_tag(), &primal, 1, &null_entity );RR;
1668 }
1669
1670 ents_to_delete.insert( this_entity );
1671
1672
1673 if( mbImpl->type_from_handle( this_entity ) == MBPOLYGON )
1674 {
1675
1676 Range loop_edges;
1677 result = mbImpl->get_adjacencies( &this_entity, 1, 1, false, loop_edges );
1678 for( Range::iterator rit = loop_edges.begin(); rit != loop_edges.end(); ++rit )
1679 if( check_1d_loop_edge( *rit ) ) entities.insert( *rit );
1680 }
1681 else if( extra && extra != this_entity )
1682
1683
1684 ents_to_delete.insert( extra );
1685 }
1686
1687
1688 return mbImpl->delete_entities( ents_to_delete );
1689 }
1690
1691 void DualTool::print_cell( EntityHandle cell )
1692 {
1693 const EntityHandle* connect;
1694 int num_connect;
1695 ErrorCode result = mbImpl->get_connectivity( cell, connect, num_connect );
1696 if( MB_SUCCESS != result ) return;
1697 bool first = true;
1698 EntityHandle primals[20];
1699 std::vector< int > ids;
1700
1701 assert( num_connect < 20 );
1702 result = mbImpl->tag_get_data( dualEntityTag, connect, num_connect, primals );
1703 if( MB_SUCCESS != result ) return;
1704 ids.resize( num_connect );
1705 result = mbImpl->tag_get_data( globalIdTag, primals, num_connect, &ids[0] );
1706 if( MB_SUCCESS != result ) return;
1707 for( int i = 0; i < num_connect; i++ )
1708 {
1709 if( !first ) std::cout << "-";
1710 EntityType this_type = mbImpl->type_from_handle( primals[i] );
1711 if( this_type == MBHEX )
1712 std::cout << "h";
1713 else if( this_type == MBQUAD )
1714 std::cout << "f";
1715 else
1716 std::cout << "u";
1717
1718 if( ids[i] != 0 )
1719 std::cout << ids[i];
1720 else
1721 std::cout << mbImpl->id_from_handle( primals[i] );
1722
1723 first = false;
1724 }
1725 }
1726
1727 ErrorCode DualTool::face_open_collapse( EntityHandle ocl, EntityHandle ocr )
1728 {
1729 if( debug_ap ) ( (Core*)mbImpl )->check_adjacencies();
1730
1731 MeshTopoUtil mtu( mbImpl );
1732
1733 std::cout << "OC(";
1734 print_cell( ocl );
1735 std::cout << ")-(";
1736 print_cell( ocr );
1737 std::cout << ")" << std::endl;
1738
1739
1740 EntityHandle split_quads[2] = { 0 }, split_edges[3] = { 0 }, split_nodes[2] = { 0 }, other_edges[6] = { 0 },
1741 other_nodes[6] = { 0 };
1742 Range hexes;
1743 ErrorCode result = foc_get_ents( ocl, ocr, split_quads, split_edges, split_nodes, hexes, other_edges, other_nodes );RR;
1744
1745
1746 std::vector< EntityHandle > star_dp1[2], star_dp2[2];
1747 result = foc_get_stars( split_quads, split_edges, star_dp1, star_dp2 );RR;
1748
1749 if( MBQUAD != mbImpl->type_from_handle( split_quads[0] ) || MBQUAD != mbImpl->type_from_handle( split_quads[1] ) )
1750 return MB_TYPE_OUT_OF_RANGE;
1751
1752 result = foc_delete_dual( split_quads, split_edges, hexes );
1753 if( MB_SUCCESS != result ) return result;
1754
1755 EntityHandle new_quads[2], new_edges[3], new_nodes[2];
1756 result = split_pair_nonmanifold( split_quads, split_edges, split_nodes, star_dp1, star_dp2, other_edges,
1757 other_nodes, new_quads, new_edges, new_nodes );
1758 if( MB_SUCCESS != result ) return result;
1759
1760
1761 EntityHandle keepit, deleteit;
1762 #define MIN( a, b ) ( ( a ) < ( b ) ? ( a ) : ( b ) )
1763 #define MAX( a, b ) ( ( a ) > ( b ) ? ( a ) : ( b ) )
1764 #define KEEP_DELETE( a, b, c, d ) \
1765 { \
1766 ( c ) = MIN( a, b ); \
1767 ( d ) = MAX( a, b ); \
1768 }
1769
1770
1771 int num_shared_edges = ( split_edges[2] ? 3 : ( split_edges[1] ? 2 : 1 ) );
1772
1773
1774 for( int i = 0; i < 3 - num_shared_edges; i++ )
1775 {
1776 KEEP_DELETE( other_nodes[2 + 2 * i], other_nodes[3 + 2 * i], keepit, deleteit );
1777 result = mbImpl->merge_entities( keepit, deleteit, false, true );RR;
1778 }
1779
1780
1781 for( int i = 0; i < 4 - num_shared_edges; i++ )
1782 {
1783 KEEP_DELETE( other_edges[2 * i], other_edges[2 * i + 1], keepit, deleteit );
1784 result = mbImpl->merge_entities( keepit, deleteit, false, true );RR;
1785 }
1786
1787
1788 KEEP_DELETE( split_quads[0], split_quads[1], keepit, deleteit );
1789 result = mbImpl->merge_entities( keepit, deleteit, false, true );RR;
1790
1791 result = mbImpl->merge_entities( new_quads[0], new_quads[1], false, true );RR;
1792
1793 if( debug_ap ) ( (Core*)mbImpl )->check_adjacencies();
1794
1795
1796 result = construct_hex_dual( hexes );
1797 if( MB_SUCCESS != result ) return result;
1798
1799 return check_dual_adjs();
1800 }
1801
1802 ErrorCode DualTool::foc_get_ents( EntityHandle ocl,
1803 EntityHandle ocr,
1804 EntityHandle* split_quads,
1805 EntityHandle* split_edges,
1806 EntityHandle* split_nodes,
1807 Range& hexes,
1808 EntityHandle* other_edges,
1809 EntityHandle* other_nodes )
1810 {
1811
1812
1813
1814
1815
1816
1817
1818
1819
1820
1821
1822
1823
1824
1825
1826
1827
1828
1829 split_quads[0] = get_dual_entity( ocl );
1830 split_quads[1] = get_dual_entity( ocr );
1831 if( MBQUAD != mbImpl->type_from_handle( split_quads[0] ) || MBQUAD != mbImpl->type_from_handle( split_quads[1] ) )
1832 return MB_TYPE_OUT_OF_RANGE;
1833
1834 Range common_edges;
1835 ErrorCode result = mbImpl->get_adjacencies( split_quads, 2, 1, false, common_edges );
1836 if( MB_SUCCESS != result ) return result;
1837
1838 if( common_edges.empty() ) return MB_FAILURE;
1839 for( unsigned int i = 0; i < common_edges.size(); i++ )
1840 split_edges[i] = common_edges[i];
1841
1842 MeshTopoUtil mtu( mbImpl );
1843
1844 if( common_edges.size() == 3 )
1845 {
1846
1847 for( int i = 0; i < 2; i++ )
1848 {
1849 Range tmp_edges;
1850 result = mbImpl->get_adjacencies( &split_quads[i], 1, 1, false, tmp_edges );
1851 if( MB_SUCCESS != result ) return result;
1852 tmp_edges = subtract( tmp_edges, common_edges );
1853 assert( tmp_edges.size() == 1 );
1854 other_edges[i] = *tmp_edges.begin();
1855 }
1856 assert( other_edges[0] && other_edges[1] && other_edges[0] != other_edges[1] );
1857
1858
1859 result = mtu.opposite_entity( split_quads[0], other_edges[0], split_edges[1] );RR;
1860 common_edges.erase( split_edges[1] );
1861 split_edges[0] = *common_edges.begin();
1862 split_edges[2] = *common_edges.rbegin();
1863 common_edges.insert( split_edges[1] );
1864
1865
1866 split_nodes[0] = mtu.common_entity( split_edges[0], split_edges[1], 0 );
1867 split_nodes[1] = mtu.common_entity( split_edges[2], split_edges[1], 0 );
1868 other_nodes[0] = mtu.common_entity( split_edges[0], other_edges[0], 0 );
1869 other_nodes[1] = mtu.common_entity( split_edges[2], other_edges[1], 0 );
1870
1871 assert( other_nodes[0] && other_nodes[1] && split_nodes[0] && split_nodes[1] );
1872 assert( split_edges[0] && split_edges[1] && split_edges[2] && split_edges[0] != split_edges[1] &&
1873 split_edges[1] != split_edges[2] && split_edges[0] != split_edges[2] );
1874 }
1875 else if( common_edges.size() == 2 )
1876 {
1877
1878 split_nodes[0] = mtu.common_entity( split_edges[0], split_edges[1], 0 );
1879 if( 0 == split_nodes[0] ) return MB_FAILURE;
1880
1881 result = mtu.opposite_entity( split_edges[0], split_nodes[0], other_nodes[0] );RR;
1882 result = mtu.opposite_entity( split_edges[1], split_nodes[0], other_nodes[1] );RR;
1883
1884 for( int i = 0; i < 2; i++ )
1885 {
1886
1887 result = mtu.opposite_entity( split_quads[i], split_edges[1], other_edges[i] );RR;
1888
1889 result = mtu.opposite_entity( split_quads[i], split_edges[0], other_edges[2 + i] );RR;
1890
1891 result = mtu.opposite_entity( split_quads[i], split_nodes[0], other_nodes[2 + i] );RR;
1892 }
1893 }
1894 else
1895 {
1896 const EntityHandle* connect;
1897 int num_connect;
1898 result = mbImpl->get_connectivity( split_edges[0], connect, num_connect );
1899 if( MB_SUCCESS != result ) return result;
1900
1901 other_nodes[0] = connect[0];
1902 other_nodes[1] = connect[1];
1903
1904
1905 for( int i = 0; i < 2; i++ )
1906 {
1907
1908
1909 Range tmp_range1, tmp_range2;
1910 tmp_range1.insert( connect[0] );
1911 tmp_range1.insert( split_quads[i] );
1912 result = mbImpl->get_adjacencies( tmp_range1, 1, false, tmp_range2 );
1913 if( MB_SUCCESS != result ) return result;
1914 tmp_range2.erase( split_edges[0] );
1915 assert( tmp_range2.size() == 1 );
1916 other_edges[i] = *tmp_range2.begin();
1917
1918
1919 result = mtu.opposite_entity( split_quads[i], other_edges[i], other_edges[4 + i] );RR;
1920
1921 result = mtu.opposite_entity( split_quads[i], split_edges[0], other_edges[2 + i] );RR;
1922
1923
1924 other_nodes[2 + i] = mtu.common_entity( other_edges[i], other_edges[2 + i], 0 );
1925 other_nodes[4 + i] = mtu.common_entity( other_edges[4 + i], other_edges[2 + i], 0 );
1926 if( 0 == other_nodes[2 + i] || 0 == other_nodes[4 + i] ) return MB_FAILURE;
1927 }
1928 }
1929
1930 result = mbImpl->get_adjacencies( split_edges, common_edges.size(), 3, false, hexes, Interface::UNION );
1931 if( MB_SUCCESS != result ) return result;
1932
1933 assert( "split node not in other_nodes" && other_nodes[0] != split_nodes[0] && other_nodes[0] != split_nodes[1] &&
1934 other_nodes[1] != split_nodes[0] && other_nodes[1] != split_nodes[1] );
1935 assert( "each split node on an end of a split edge" && mtu.common_entity( other_nodes[0], split_edges[0], 0 ) &&
1936 ( ( ( split_edges[2] && mtu.common_entity( other_nodes[1], split_edges[2], 0 ) ) ||
1937 ( split_edges[1] && mtu.common_entity( other_nodes[1], split_edges[1], 0 ) ) ||
1938 mtu.common_entity( other_nodes[1], split_edges[0], 0 ) ) ) );
1939 assert( "opposite other edges meet at an other node" &&
1940 ( mtu.common_entity( other_edges[0], other_edges[1], 0 ) == other_nodes[0] ||
1941 ( split_edges[2] && mtu.common_entity( other_edges[0], other_edges[1], 0 ) == other_nodes[1] ) ) &&
1942 ( split_edges[2] ||
1943 ( split_edges[1] && mtu.common_entity( other_edges[2], other_edges[3], 0 ) == other_nodes[1] ) ||
1944 mtu.common_entity( other_edges[4], other_edges[5], 0 ) == other_nodes[1] ) );
1945
1946 return MB_SUCCESS;
1947 }
1948
1949 ErrorCode DualTool::split_pair_nonmanifold( EntityHandle* split_quads,
1950 EntityHandle* split_edges,
1951 EntityHandle* split_nodes,
1952 std::vector< EntityHandle >* star_dp1,
1953 std::vector< EntityHandle >* star_dp2,
1954 EntityHandle* ,
1955 EntityHandle* ,
1956 EntityHandle* new_quads,
1957 EntityHandle* new_edges,
1958 EntityHandle* new_nodes )
1959 {
1960
1961
1962
1963 MeshTopoUtil mtu( mbImpl );
1964 ErrorCode result;
1965
1966
1967 int new_side = -1;
1968 if( std::find( star_dp1[0].begin(), star_dp1[0].end(), split_quads[0] ) != star_dp1[0].end() )
1969 new_side = 1;
1970 else if( std::find( star_dp1[1].begin(), star_dp1[1].end(), split_quads[0] ) != star_dp1[1].end() )
1971 new_side = 0;
1972 assert( -1 != new_side );
1973 if( -1 == new_side ) return MB_FAILURE;
1974
1975
1976
1977 for( int i = 0; i < 2; i++ )
1978 {
1979
1980
1981
1982 EntityHandle gowith_hex = 0;
1983 for( std::vector< EntityHandle >::iterator vit = star_dp2[new_side].begin(); vit != star_dp2[new_side].end();
1984 ++vit )
1985 {
1986 if( mtu.common_entity( *vit, split_quads[i], 2 ) )
1987 {
1988 gowith_hex = *vit;
1989 break;
1990 }
1991 }
1992 assert( 0 != gowith_hex );
1993
1994
1995 result =
1996 mtu.split_entities_manifold( split_quads + i, 1, new_quads + i, NULL, ( gowith_hex ? &gowith_hex : NULL ) );RR;
1997 }
1998
1999
2000
2001
2002 Range tmp_addl_faces[2], addl_faces[2];
2003 for( int i = 0; i < 2; i++ )
2004 {
2005 std::copy( star_dp1[i].begin(), star_dp1[i].end(), range_inserter( tmp_addl_faces[i] ) );
2006 tmp_addl_faces[new_side].insert( new_quads[i] );
2007 }
2008 #ifndef NDEBUG
2009 bool cond1 = ( "split_quads on 1, new_quads on 0" &&
2010 tmp_addl_faces[0].find( split_quads[0] ) == tmp_addl_faces[0].end() &&
2011 tmp_addl_faces[0].find( split_quads[1] ) == tmp_addl_faces[0].end() &&
2012 tmp_addl_faces[1].find( split_quads[0] ) != tmp_addl_faces[1].end() &&
2013 tmp_addl_faces[1].find( split_quads[1] ) != tmp_addl_faces[1].end() &&
2014 tmp_addl_faces[0].find( new_quads[0] ) != tmp_addl_faces[0].end() &&
2015 tmp_addl_faces[0].find( new_quads[1] ) != tmp_addl_faces[0].end() &&
2016 tmp_addl_faces[1].find( new_quads[0] ) == tmp_addl_faces[1].end() &&
2017 tmp_addl_faces[1].find( new_quads[1] ) == tmp_addl_faces[1].end() ),
2018 cond2 = ( "split_quads on 0, new_quads on 1" &&
2019 tmp_addl_faces[0].find( split_quads[0] ) != tmp_addl_faces[0].end() &&
2020 tmp_addl_faces[0].find( split_quads[1] ) != tmp_addl_faces[0].end() &&
2021 tmp_addl_faces[1].find( split_quads[0] ) == tmp_addl_faces[1].end() &&
2022 tmp_addl_faces[1].find( split_quads[1] ) == tmp_addl_faces[1].end() &&
2023 tmp_addl_faces[0].find( new_quads[0] ) == tmp_addl_faces[0].end() &&
2024 tmp_addl_faces[0].find( new_quads[1] ) == tmp_addl_faces[0].end() &&
2025 tmp_addl_faces[1].find( new_quads[0] ) != tmp_addl_faces[1].end() &&
2026 tmp_addl_faces[1].find( new_quads[1] ) != tmp_addl_faces[1].end() );
2027
2028 assert( cond1 || cond2 );
2029 #endif
2030
2031
2032 for( int j = 0; j < 3; j++ )
2033 {
2034 if( !split_edges[j] ) break;
2035
2036
2037 addl_faces[0] = tmp_addl_faces[0];
2038 addl_faces[1] = tmp_addl_faces[1];
2039 for( int i = 0; i < 2; i++ )
2040 {
2041 result = mbImpl->get_adjacencies( &split_edges[j], 1, 2, false, addl_faces[i] );RR;
2042 }
2043
2044
2045 result = mtu.split_entity_nonmanifold( split_edges[j], addl_faces[1 - new_side], addl_faces[new_side],
2046 new_edges[j] );RR;
2047 }
2048
2049
2050
2051 for( int j = 0; j < 2; j++ )
2052 {
2053 if( !split_nodes[j] ) break;
2054
2055
2056
2057 Range tmp_addl_edges[2];
2058 result = foc_get_addl_ents( star_dp1, star_dp2, split_edges, split_nodes[j], tmp_addl_edges );RR;
2059
2060
2061
2062 for( int i = 0; i < 3; i++ )
2063 {
2064 if( !split_edges[i] ) break;
2065 tmp_addl_edges[new_side].insert( new_edges[i] );
2066 tmp_addl_edges[1 - new_side].insert( split_edges[i] );
2067 }
2068
2069
2070 for( int i = 0; i < 2; i++ )
2071 {
2072 std::copy( star_dp1[i].begin(), star_dp1[i].end(), range_inserter( tmp_addl_edges[i] ) );
2073 std::copy( star_dp2[i].begin(), star_dp2[i].end(), range_inserter( tmp_addl_edges[i] ) );
2074 }
2075
2076
2077 for( int i = 0; i < 2; i++ )
2078 tmp_addl_edges[new_side].insert( new_quads[i] );
2079
2080
2081 Range addl_edges[2];
2082 for( int i = 0; i < 2; i++ )
2083 {
2084 for( Range::reverse_iterator rit = tmp_addl_edges[i].rbegin(); rit != tmp_addl_edges[i].rend(); ++rit )
2085 {
2086 if( mtu.common_entity( *rit, split_nodes[j], 0 ) ) addl_edges[i].insert( *rit );
2087 }
2088 }
2089
2090
2091 result = mtu.split_entity_nonmanifold( split_nodes[j], addl_edges[1 - new_side], addl_edges[new_side],
2092 new_nodes[j] );RR;
2093 }
2094
2095 return MB_SUCCESS;
2096 }
2097
2098 ErrorCode DualTool::foc_get_addl_ents( std::vector< EntityHandle >* star_dp1,
2099 std::vector< EntityHandle >* ,
2100 EntityHandle* split_edges,
2101 EntityHandle split_node,
2102 Range* addl_ents )
2103 {
2104
2105
2106
2107
2108
2109
2110
2111
2112
2113 Range R2;
2114 MeshTopoUtil mtu( mbImpl );
2115 ErrorCode result = mbImpl->get_adjacencies( &split_node, 1, 1, false, R2 );RR;
2116 Range::iterator rit;
2117
2118 for( int i = 0; i < 2; i++ )
2119 {
2120 Range R1, R3;
2121 result = mbImpl->get_adjacencies( &star_dp1[i][0], star_dp1[i].size(), 1, false, R1, Interface::UNION );RR;
2122 R3 = intersect( R1, R2 );
2123 for( int j = 0; j < 3; j++ )
2124 if( split_edges[j] ) R3.erase( split_edges[j] );
2125 addl_ents[i].merge( R3 );
2126 }
2127
2128 return MB_SUCCESS;
2129 }
2130
2131 ErrorCode DualTool::foc_get_stars( EntityHandle* split_quads,
2132 EntityHandle* split_edges,
2133 std::vector< EntityHandle >* star_dp1,
2134 std::vector< EntityHandle >* star_dp2 )
2135 {
2136 bool on_bdy = false, on_bdy_tmp;
2137 ErrorCode result;
2138 MeshTopoUtil mtu( mbImpl );
2139
2140
2141 std::vector< EntityHandle > qstar, hstar;
2142 unsigned int qpos = 0;
2143
2144 for( int i = 0; i < 3; i++ )
2145 {
2146 if( !split_edges[i] ) break;
2147
2148
2149 unsigned int qpos_tmp = 0;
2150 std::vector< EntityHandle > qstar_tmp, hstar_tmp;
2151 result = mtu.star_entities( split_edges[i], qstar_tmp, on_bdy_tmp, 0, &hstar_tmp );RR;
2152
2153 if( on_bdy_tmp )
2154 {
2155 assert( hstar_tmp.size() == qstar_tmp.size() - 1 );
2156 hstar_tmp.push_back( 0 );
2157 on_bdy = true;
2158 }
2159
2160
2161 while( qpos_tmp < qstar_tmp.size() && qstar_tmp[qpos_tmp] != split_quads[0] )
2162 qpos_tmp++;
2163 if( qpos_tmp == qstar_tmp.size() ) return MB_FAILURE;
2164
2165 bool forward;
2166
2167 if( 0 == i ) forward = true;
2168
2169
2170 else if( hstar[qpos] == hstar_tmp[qpos_tmp] )
2171 forward = true;
2172 else if( hstar[qpos] == hstar_tmp[( qpos_tmp + qstar_tmp.size() - 1 ) % qstar_tmp.size()] &&
2173 hstar_tmp[qpos_tmp] == hstar[( qpos + qstar.size() - 1 ) % qstar.size()] )
2174 forward = false;
2175 else
2176 return MB_FAILURE;
2177
2178 if( forward )
2179 {
2180
2181
2182 star_dp2[0].push_back( hstar_tmp[qpos_tmp] );
2183 qpos_tmp = ( qpos_tmp + 1 ) % qstar_tmp.size();
2184 while( qstar_tmp[qpos_tmp] != split_quads[1] )
2185 {
2186 star_dp1[0].push_back( qstar_tmp[qpos_tmp] );
2187 star_dp2[0].push_back( hstar_tmp[qpos_tmp] );
2188 qpos_tmp = ( qpos_tmp + 1 ) % qstar_tmp.size();
2189 }
2190
2191
2192 star_dp2[1].push_back( hstar_tmp[qpos_tmp] );
2193 qpos_tmp = ( qpos_tmp + 1 ) % qstar_tmp.size();
2194 while( qstar_tmp[qpos_tmp] != split_quads[0] )
2195 {
2196 star_dp1[1].push_back( qstar_tmp[qpos_tmp] );
2197 star_dp2[1].push_back( hstar_tmp[qpos_tmp] );
2198 qpos_tmp = ( qpos_tmp + 1 ) % qstar_tmp.size();
2199 }
2200 }
2201 else
2202 {
2203
2204
2205
2206
2207 qpos_tmp = ( qpos_tmp + qstar_tmp.size() - 1 ) % qstar_tmp.size();
2208 star_dp2[0].push_back( hstar_tmp[qpos_tmp] );
2209 while( qstar_tmp[qpos_tmp] != split_quads[1] )
2210 {
2211 star_dp1[0].push_back( qstar_tmp[qpos_tmp] );
2212 qpos_tmp = ( qpos_tmp + qstar_tmp.size() - 1 ) % qstar_tmp.size();
2213 star_dp2[0].push_back( hstar_tmp[qpos_tmp] );
2214 }
2215
2216
2217 qpos_tmp = ( qpos_tmp + qstar_tmp.size() - 1 ) % qstar_tmp.size();
2218 star_dp2[1].push_back( hstar_tmp[qpos_tmp] );
2219 while( qstar_tmp[qpos_tmp] != split_quads[0] )
2220 {
2221 star_dp1[1].push_back( qstar_tmp[qpos_tmp] );
2222 qpos_tmp = ( qpos_tmp + qstar_tmp.size() - 1 ) % qstar_tmp.size();
2223 star_dp2[1].push_back( hstar_tmp[qpos_tmp] );
2224 }
2225 }
2226
2227 if( 0 == i )
2228 {
2229
2230
2231 qstar.swap( qstar_tmp );
2232 hstar.swap( hstar_tmp );
2233 on_bdy = on_bdy_tmp;
2234 qpos = qpos_tmp;
2235 }
2236 }
2237
2238
2239 if( on_bdy )
2240 {
2241 if( std::find( star_dp2[0].begin(), star_dp2[0].end(), 0 ) != star_dp2[0].end() )
2242 {
2243
2244 star_dp2[0].erase( std::remove( star_dp2[0].begin(), star_dp2[0].end(), 0 ), star_dp2[0].end() );
2245
2246 star_dp1[0].push_back( split_quads[0] );
2247 star_dp1[0].push_back( split_quads[1] );
2248 }
2249 else
2250 {
2251 star_dp2[1].erase( std::remove( star_dp2[1].begin(), star_dp2[1].end(), 0 ), star_dp2[1].end() );
2252
2253 star_dp1[1].push_back( split_quads[0] );
2254 star_dp1[1].push_back( split_quads[1] );
2255 }
2256 }
2257 else
2258 {
2259 star_dp1[1].push_back( split_quads[0] );
2260 star_dp1[1].push_back( split_quads[1] );
2261 }
2262
2263
2264 if( !( ( ( std::find( star_dp1[0].begin(), star_dp1[0].end(), split_quads[0] ) == star_dp1[0].end() &&
2265 std::find( star_dp1[0].begin(), star_dp1[0].end(), split_quads[1] ) == star_dp1[0].end() &&
2266 std::find( star_dp1[1].begin(), star_dp1[1].end(), split_quads[0] ) != star_dp1[1].end() &&
2267 std::find( star_dp1[1].begin(), star_dp1[1].end(), split_quads[1] ) != star_dp1[1].end() ) ||
2268
2269 ( std::find( star_dp1[1].begin(), star_dp1[1].end(), split_quads[0] ) == star_dp1[1].end() &&
2270 std::find( star_dp1[1].begin(), star_dp1[1].end(), split_quads[1] ) == star_dp1[1].end() &&
2271 std::find( star_dp1[0].begin(), star_dp1[0].end(), split_quads[0] ) != star_dp1[0].end() &&
2272 std::find( star_dp1[0].begin(), star_dp1[0].end(), split_quads[1] ) != star_dp1[0].end() ) ) ) )
2273 {
2274 std::cerr << "foc_get_stars: both split quads should be on the same star list half and not "
2275 << "on the other, failed" << std::endl;
2276 return MB_FAILURE;
2277 }
2278
2279 if( !( std::find( star_dp2[0].begin(), star_dp2[0].end(), 0 ) == star_dp2[0].end() &&
2280 std::find( star_dp2[1].begin(), star_dp2[1].end(), 0 ) == star_dp2[1].end() ) )
2281 {
2282 std::cerr << "foc_get_stars: no NULLs on the hstar lists, failed";
2283 return MB_FAILURE;
2284 }
2285
2286 return MB_SUCCESS;
2287 }
2288
2289 ErrorCode DualTool::foc_delete_dual( EntityHandle* split_quads, EntityHandle* split_edges, Range& hexes )
2290 {
2291
2292
2293
2294
2295 EntityHandle sheet1 = get_dual_hyperplane( get_dual_entity( split_edges[0] ) );
2296 if( split_edges[1] ) sheet1 = get_dual_hyperplane( get_dual_entity( split_edges[1] ) );
2297 EntityHandle chordl = get_dual_hyperplane( get_dual_entity( split_quads[0] ) );
2298 EntityHandle chordr = get_dual_hyperplane( get_dual_entity( split_quads[1] ) );
2299 assert( 0 != sheet1 && 0 != chordl && 0 != chordr );
2300 Range parentsl, parentsr;
2301 ErrorCode result = mbImpl->get_parent_meshsets( chordl, parentsl );
2302 if( MB_SUCCESS != result ) return result;
2303 result = mbImpl->get_parent_meshsets( chordr, parentsr );
2304 if( MB_SUCCESS != result ) return result;
2305 parentsl.erase( sheet1 );
2306 parentsr.erase( sheet1 );
2307
2308
2309
2310 Range adj_ents, dual_ents, cells1or2;
2311 for( int i = 0; i < 3; i++ )
2312 {
2313 result = mbImpl->get_adjacencies( hexes, i, false, adj_ents, Interface::UNION );
2314 if( MB_SUCCESS != result ) return result;
2315 }
2316
2317
2318 result = mbImpl->get_adjacencies( adj_ents, 3, false, hexes, Interface::UNION );
2319 if( MB_SUCCESS != result ) return result;
2320
2321 for( Range::iterator rit = adj_ents.begin(); rit != adj_ents.end(); ++rit )
2322 {
2323 EntityHandle this_ent = get_dual_entity( *rit );
2324 dual_ents.insert( this_ent );
2325 int dim = mbImpl->dimension_from_handle( this_ent );
2326 if( 1 == dim || 2 == dim ) cells1or2.insert( this_ent );
2327 }
2328
2329 Range dual_hps;
2330 for( Range::iterator rit = cells1or2.begin(); rit != cells1or2.end(); ++rit )
2331 dual_hps.insert( get_dual_hyperplane( *rit ) );
2332
2333 result = delete_dual_entities( dual_ents );
2334 if( MB_SUCCESS != result ) return result;
2335
2336
2337 EntityHandle sheet_delete = 0;
2338 if( is_blind( *parentsl.begin() ) )
2339 sheet_delete = *parentsl.begin();
2340 else if( is_blind( *parentsr.begin() ) )
2341 sheet_delete = *parentsr.begin();
2342 else
2343 {
2344
2345 Range tmp_ents;
2346 int numl, numr;
2347 result = mbImpl->get_number_entities_by_handle( *parentsl.begin(), numl );
2348 if( MB_SUCCESS != result ) return result;
2349 result = mbImpl->get_number_entities_by_handle( *parentsr.begin(), numr );
2350 if( MB_SUCCESS != result ) return result;
2351 sheet_delete = ( numl > numr ? *parentsr.begin() : *parentsl.begin() );
2352 }
2353 assert( 0 != sheet_delete );
2354
2355
2356 for( Range::iterator rit = dual_hps.begin(); rit != dual_hps.end(); ++rit )
2357 {
2358 Range tmp_ents;
2359 result = mbImpl->get_entities_by_handle( *rit, tmp_ents );
2360 if( MB_SUCCESS != result ) return result;
2361 if( tmp_ents.empty() )
2362 {
2363 result = mbImpl->delete_entities( &( *rit ), 1 );
2364 if( MB_SUCCESS != result ) return result;
2365 }
2366 else if( *rit == sheet_delete )
2367 {
2368
2369 result = mbImpl->delete_entities( &( *rit ), 1 );
2370 if( MB_SUCCESS != result ) return result;
2371 }
2372 }
2373
2374
2375
2376 Range tmp_hexes;
2377 MeshTopoUtil mtu( mbImpl );
2378 for( Range::iterator rit = hexes.begin(); rit != hexes.end(); ++rit )
2379 {
2380 result = mtu.get_bridge_adjacencies( *rit, 0, 3, tmp_hexes );
2381 if( MB_SUCCESS != result ) return result;
2382 }
2383 hexes.merge( tmp_hexes );
2384
2385 return MB_SUCCESS;
2386 }
2387
2388
2389 bool DualTool::is_blind( const EntityHandle chord_or_sheet )
2390 {
2391
2392 if( TYPE_FROM_HANDLE( chord_or_sheet ) != MBENTITYSET ) return false;
2393
2394
2395 Range verts, ents;
2396 ErrorCode result = mbImpl->get_entities_by_handle( chord_or_sheet, ents );
2397 if( MB_SUCCESS != result || ents.empty() ) return false;
2398
2399 result = mbImpl->get_adjacencies( ents, 0, false, verts, Interface::UNION );
2400 if( MB_SUCCESS != result || verts.empty() ) return false;
2401
2402 for( Range::iterator rit = verts.begin(); rit != verts.end(); ++rit )
2403 {
2404
2405 EntityHandle dual_ent = get_dual_entity( *rit );
2406 if( 0 == dual_ent ) continue;
2407 if( TYPE_FROM_HANDLE( dual_ent ) == MBQUAD ) return false;
2408 }
2409
2410
2411 return true;
2412 }
2413
2414
2415
2416 ErrorCode DualTool::get_opposite_verts( const EntityHandle middle_edge, const EntityHandle chord, EntityHandle* verts )
2417 {
2418
2419 std::vector< EntityHandle > chord_edges;
2420 const EntityHandle* connect;
2421 int num_connect;
2422
2423 ErrorCode result = mbImpl->get_entities_by_handle( chord, chord_edges );RR;
2424 std::vector< EntityHandle >::iterator vit = std::find( chord_edges.begin(), chord_edges.end(), middle_edge );
2425 result = mbImpl->get_connectivity( middle_edge, connect, num_connect );RR;
2426
2427 if(
2428
2429 vit == chord_edges.end() ||
2430
2431 chord_edges.size() == 1 ||
2432
2433 ( ( vit == chord_edges.begin() || vit == chord_edges.end() - 1 ) && !is_blind( chord ) ) )
2434 return MB_FAILURE;
2435
2436 else if( chord_edges.size() == 2 )
2437 {
2438
2439 verts[0] = connect[1];
2440 verts[1] = connect[0];
2441 return MB_SUCCESS;
2442 }
2443
2444
2445 if( vit == chord_edges.begin() )
2446 vit = chord_edges.end() - 1;
2447 else
2448 --vit;
2449 Range dum_connect, middle_connect;
2450 result = mbImpl->get_connectivity( &middle_edge, 1, middle_connect );RR;
2451 result = mbImpl->get_connectivity( &( *vit ), 1, dum_connect );RR;
2452 dum_connect = subtract( dum_connect, middle_connect );
2453 if( dum_connect.size() != 1 )
2454 {
2455 std::cerr << "Trouble traversing chord." << std::endl;
2456 return MB_FAILURE;
2457 }
2458
2459
2460 verts[0] = *dum_connect.begin();
2461
2462
2463 ++vit;
2464 if( vit == chord_edges.end() ) vit = chord_edges.begin();
2465 ++vit;
2466 dum_connect.clear();
2467 result = mbImpl->get_connectivity( &( *vit ), 1, dum_connect );RR;
2468 dum_connect = subtract( dum_connect, middle_connect );
2469 if( dum_connect.size() != 1 )
2470 {
2471 std::cerr << "Trouble traversing chord." << std::endl;
2472 return MB_FAILURE;
2473 }
2474
2475
2476 verts[1] = *dum_connect.begin();
2477
2478
2479 MeshTopoUtil mtu( mbImpl );
2480 if( 0 == mtu.common_entity( verts[0], connect[0], 1 ) )
2481 {
2482 EntityHandle dum_h = verts[0];
2483 verts[0] = verts[1];
2484 verts[1] = dum_h;
2485 }
2486
2487 if( 0 == mtu.common_entity( verts[0], connect[0], 1 ) )
2488 {
2489 std::cerr << "Trouble traversing chord." << std::endl;
2490 return MB_FAILURE;
2491 }
2492
2493 return MB_SUCCESS;
2494 }
2495
2496 ErrorCode DualTool::get_dual_entities( const EntityHandle dual_ent,
2497 Range* dcells,
2498 Range* dedges,
2499 Range* dverts,
2500 Range* dverts_loop,
2501 Range* dedges_loop )
2502 {
2503 ErrorCode result = MB_SUCCESS;
2504
2505 if( NULL != dcells )
2506 {
2507 result = mbImpl->get_entities_by_type( dual_ent, MBPOLYGON, *dcells );
2508 if( MB_SUCCESS != result ) return result;
2509 }
2510
2511 if( NULL != dedges )
2512 {
2513 if( NULL != dcells )
2514 result = mbImpl->get_adjacencies( *dcells, 1, false, *dedges, Interface::UNION );
2515 else
2516 result = mbImpl->get_entities_by_type( dual_ent, MBEDGE, *dedges );
2517
2518 if( MB_SUCCESS != result ) return result;
2519 }
2520
2521 if( NULL != dverts )
2522 {
2523 if( NULL != dcells )
2524 result = mbImpl->get_adjacencies( *dcells, 0, false, *dverts, Interface::UNION );
2525 else if( NULL != dedges )
2526 result = mbImpl->get_adjacencies( *dedges, 0, false, *dverts, Interface::UNION );
2527 else
2528 {
2529 Range all_ents;
2530 result = mbImpl->get_entities_by_handle( dual_ent, all_ents );RR;
2531 result = mbImpl->get_adjacencies( all_ents, 0, false, *dverts, Interface::UNION );
2532 }
2533
2534 if( MB_SUCCESS != result ) return result;
2535 }
2536
2537 if( NULL != dverts_loop && NULL != dverts )
2538 {
2539 static std::vector< EntityHandle > dual_ents;
2540 dual_ents.resize( dverts->size() );
2541 result = mbImpl->tag_get_data( dualEntity_tag(), *dverts, &dual_ents[0] );
2542 if( MB_SUCCESS != result ) return result;
2543 Range::iterator rit;
2544 unsigned int i;
2545 for( rit = dverts->begin(), i = 0; rit != dverts->end(); ++rit, i++ )
2546 if( 0 != dual_ents[i] && mbImpl->type_from_handle( dual_ents[i] ) == MBQUAD ) dverts_loop->insert( *rit );
2547 }
2548
2549 if( NULL != dedges_loop && NULL != dedges )
2550 {
2551 static std::vector< EntityHandle > dual_ents;
2552 dual_ents.resize( dedges->size() );
2553 result = mbImpl->tag_get_data( dualEntity_tag(), *dedges, &dual_ents[0] );
2554 if( MB_SUCCESS != result ) return result;
2555 Range::iterator rit;
2556 unsigned int i;
2557 for( rit = dedges->begin(), i = 0; rit != dedges->end(); ++rit, i++ )
2558 if( 0 != dual_ents[i] && mbImpl->type_from_handle( dual_ents[i] ) == MBEDGE ) dedges_loop->insert( *rit );
2559 }
2560
2561 return result;
2562 }
2563
2564 ErrorCode DualTool::list_entities( const EntityHandle* entities, const int num_entities ) const
2565 {
2566 Range temp_range;
2567 ErrorCode result;
2568 if( NULL == entities && 0 == num_entities )
2569 return mbImpl->list_entities( entities, num_entities );
2570
2571 else if( NULL == entities && 0 < num_entities )
2572 {
2573
2574
2575 std::cout << std::endl;
2576 for( EntityType this_type = MBVERTEX; this_type < MBMAXTYPE; this_type++ )
2577 {
2578 result = mbImpl->get_entities_by_type( 0, this_type, temp_range );
2579 if( MB_SUCCESS != result ) return result;
2580 }
2581 }
2582
2583 else
2584 {
2585 std::copy( entities, entities + num_entities, range_inserter( temp_range ) );
2586 }
2587
2588 return list_entities( temp_range );
2589 }
2590
2591 ErrorCode DualTool::list_entities( const Range& entities ) const
2592 {
2593
2594
2595 ErrorCode result = MB_SUCCESS, tmp_result;
2596 for( Range::const_iterator iter = entities.begin(); iter != entities.end(); ++iter )
2597 {
2598 EntityType this_type = TYPE_FROM_HANDLE( *iter );
2599 std::cout << CN::EntityTypeName( this_type ) << " " << ID_FROM_HANDLE( *iter ) << ":" << std::endl;
2600
2601 EntityHandle dual_ent = get_dual_entity( *iter );
2602 if( 0 != dual_ent )
2603 {
2604 std::cout << "Dual to " << CN::EntityTypeName( mbImpl->type_from_handle( dual_ent ) ) << " "
2605 << mbImpl->id_from_handle( dual_ent ) << std::endl;
2606 }
2607
2608 if( TYPE_FROM_HANDLE( *iter ) == MBENTITYSET )
2609 {
2610 EntityHandle chord = 0, sheet = 0;
2611 int id;
2612 result = mbImpl->tag_get_data( dualCurve_tag(), &( *iter ), 1, &chord );
2613 if( MB_SUCCESS != result ) return result;
2614 result = mbImpl->tag_get_data( dualSurface_tag(), &( *iter ), 1, &sheet );
2615 if( MB_SUCCESS != result ) return result;
2616 result = mbImpl->tag_get_data( globalId_tag(), &( *iter ), 1, &id );
2617 if( MB_SUCCESS != result ) return result;
2618
2619 if( 0 != chord ) std::cout << "(Dual chord " << id << ")" << std::endl;
2620 if( 0 != sheet ) std::cout << "(Dual sheet " << id << ")" << std::endl;
2621 }
2622
2623 tmp_result = mbImpl->list_entity( *iter );
2624 if( MB_SUCCESS != tmp_result ) result = tmp_result;
2625 }
2626
2627 return result;
2628 }
2629
2630 ErrorCode DualTool::face_shrink( EntityHandle odedge )
2631 {
2632
2633 if( mbImpl->type_from_handle( odedge ) != MBEDGE ) return MB_TYPE_OUT_OF_RANGE;
2634
2635 if( debug_ap ) ( (Core*)mbImpl )->check_adjacencies();
2636
2637 std::cout << "FS(";
2638 print_cell( odedge );
2639 std::cout << ")" << std::endl;
2640
2641 EntityHandle quads[4], hexes[2];
2642 std::vector< EntityHandle > connects[4], side_quads[2];
2643
2644
2645
2646 ErrorCode result = fs_get_quads( odedge, quads, hexes, connects );
2647 if( MB_SUCCESS != result ) return result;
2648
2649
2650 result = fs_check_quad_sense( hexes[0], quads[0], connects );
2651 if( MB_SUCCESS != result ) return result;
2652
2653
2654 result = fs_get_quad_loops( hexes, connects, side_quads );
2655 if( MB_SUCCESS != result ) return result;
2656
2657
2658
2659 Range adj_verts, adj_edges, dual_ents, cells1or2;
2660 MeshTopoUtil mtu( mbImpl );
2661 result = mtu.get_bridge_adjacencies( odedge, 0, 1, adj_edges );
2662 if( MB_SUCCESS != result ) return result;
2663 result = mbImpl->get_adjacencies( adj_edges, 0, false, adj_verts, Interface::UNION );
2664 if( MB_SUCCESS != result ) return result;
2665 for( int i = 1; i <= 3; i++ )
2666 {
2667 result = mbImpl->get_adjacencies( adj_verts, i, false, dual_ents, Interface::UNION );
2668 if( MB_SUCCESS != result ) return result;
2669 }
2670
2671
2672 for( Range::iterator rit = dual_ents.begin(); rit != dual_ents.end(); ++rit )
2673 {
2674 int dim = mbImpl->dimension_from_handle( *rit );
2675 if( 1 == dim || 2 == dim ) cells1or2.insert( *rit );
2676 }
2677 Range dual_hps;
2678 for( Range::iterator rit = cells1or2.begin(); rit != cells1or2.end(); ++rit )
2679 dual_hps.insert( get_dual_hyperplane( *rit ) );
2680
2681 dual_ents.insert( odedge );
2682 result = delete_dual_entities( dual_ents );
2683 if( MB_SUCCESS != result ) return result;
2684
2685
2686 for( Range::iterator rit = dual_hps.begin(); rit != dual_hps.end(); ++rit )
2687 {
2688 Range tmp_ents;
2689 result = mbImpl->get_entities_by_handle( *rit, tmp_ents );
2690 if( MB_SUCCESS != result ) return result;
2691 if( tmp_ents.empty() )
2692 {
2693 result = mbImpl->delete_entities( &( *rit ), 1 );
2694 if( MB_SUCCESS != result ) return result;
2695 }
2696 }
2697
2698
2699
2700 for( int i = 0; i < 4; i++ )
2701 {
2702 for( int j = 0; j < 2; j++ )
2703 {
2704 result = mbImpl->remove_adjacencies( side_quads[j][i], &hexes[j], 1 );
2705 }
2706 }
2707
2708
2709
2710 double q2coords[12], avg[3] = { 0.0, 0.0, 0.0 };
2711 result = mbImpl->get_coords( &connects[1][0], 4, q2coords );
2712 if( MB_SUCCESS != result ) return result;
2713 for( int i = 0; i < 4; i++ )
2714 {
2715 avg[0] += q2coords[3 * i];
2716 avg[1] += q2coords[3 * i + 1];
2717 avg[2] += q2coords[3 * i + 2];
2718 }
2719 avg[0] *= .25;
2720 avg[1] *= .25;
2721 avg[2] *= .25;
2722
2723 connects[3].resize( 4 );
2724 for( int i = 0; i < 4; i++ )
2725 {
2726 q2coords[3 * i] = avg[0] + .25 * ( q2coords[3 * i] - avg[0] );
2727 q2coords[3 * i + 1] = avg[1] + .25 * ( q2coords[3 * i + 1] - avg[1] );
2728 q2coords[3 * i + 2] = avg[2] + .25 * ( q2coords[3 * i + 2] - avg[2] );
2729 result = mbImpl->create_vertex( &q2coords[3 * i], connects[3][i] );
2730 if( MB_SUCCESS != result ) return result;
2731 }
2732
2733
2734 EntityHandle hconnect[8], new_hexes[4];
2735 int new_hex_ids[4];
2736
2737 for( int i = 0; i < 4; i++ )
2738 {
2739 int i1 = i, i2 = ( i + 1 ) % 4;
2740 hconnect[0] = connects[0][i1];
2741 hconnect[1] = connects[0][i2];
2742 hconnect[2] = connects[3][i2];
2743 hconnect[3] = connects[3][i1];
2744
2745 hconnect[4] = connects[1][i1];
2746 hconnect[5] = connects[1][i2];
2747 hconnect[6] = connects[2][i2];
2748 hconnect[7] = connects[2][i1];
2749
2750 result = mbImpl->create_element( MBHEX, hconnect, 8, new_hexes[i] );
2751 if( MB_SUCCESS != result ) return result;
2752
2753
2754
2755 for( int j = 0; j < 2; j++ )
2756 {
2757 if( mtu.equivalent_entities( side_quads[j][i] ) )
2758 {
2759 result = mbImpl->add_adjacencies( side_quads[j][i], &new_hexes[i], 1, false );
2760 if( MB_SUCCESS != result ) return result;
2761 }
2762 }
2763
2764 new_hex_ids[i] = ++maxHexId;
2765 }
2766
2767
2768 result = mbImpl->tag_set_data( globalId_tag(), new_hexes, 4, new_hex_ids );
2769 if( MB_SUCCESS != result ) return result;
2770
2771
2772
2773
2774 int tmp_ids[2];
2775 result = mbImpl->tag_get_data( globalId_tag(), hexes, 2, tmp_ids );
2776 if( MB_SUCCESS != result ) return result;
2777
2778 result = mbImpl->delete_entities( hexes, 2 );
2779 if( MB_SUCCESS != result ) return result;
2780 result = mbImpl->delete_entities( &quads[1], 1 );
2781 if( MB_SUCCESS != result ) return result;
2782 for( int i = 0; i < 4; i++ )
2783 {
2784 hconnect[i] = connects[3][i];
2785 hconnect[4 + i] = connects[2][i];
2786 }
2787 result = mbImpl->create_element( MBHEX, hconnect, 8, hexes[0] );
2788 if( MB_SUCCESS != result ) return result;
2789
2790 for( int i = 0; i < 4; i++ )
2791 {
2792 hconnect[i] = connects[0][i];
2793 hconnect[4 + i] = connects[3][i];
2794 }
2795 result = mbImpl->create_element( MBHEX, hconnect, 8, hexes[1] );
2796 if( MB_SUCCESS != result ) return result;
2797
2798
2799 if( mtu.equivalent_entities( quads[0] ) ) mbImpl->add_adjacencies( quads[0], &hexes[1], 1, false );
2800 if( mtu.equivalent_entities( quads[2] ) ) mbImpl->add_adjacencies( quads[2], &hexes[0], 1, false );
2801
2802
2803 result = mbImpl->tag_set_data( globalId_tag(), hexes, 2, tmp_ids );
2804 if( MB_SUCCESS != result ) return result;
2805
2806 if( debug_ap ) ( (Core*)mbImpl )->check_adjacencies();
2807
2808
2809 Range tmph;
2810 result = mtu.get_bridge_adjacencies( hexes[0], 0, 3, tmph );
2811 if( MB_SUCCESS != result ) return result;
2812 result = mtu.get_bridge_adjacencies( hexes[1], 0, 3, tmph );
2813 if( MB_SUCCESS != result ) return result;
2814 tmph.insert( hexes[1] );
2815 result = construct_hex_dual( tmph );
2816 if( MB_SUCCESS != result ) return result;
2817
2818 return result;
2819 }
2820
2821 ErrorCode DualTool::fs_get_quad_loops( EntityHandle* hexes,
2822 std::vector< EntityHandle >* connects,
2823 std::vector< EntityHandle >* side_quads )
2824 {
2825 for( int i = 0; i < 4; i++ )
2826 {
2827 for( int j = 0; j < 2; j++ )
2828 {
2829 Range adj_ents, dum_quads;
2830 adj_ents.insert( hexes[j] );
2831 adj_ents.insert( connects[j][i] );
2832 adj_ents.insert( connects[j][( i + 1 ) % 4] );
2833 adj_ents.insert( connects[j + 1][i] );
2834 adj_ents.insert( connects[j + 1][( i + 1 ) % 4] );
2835
2836 ErrorCode result = mbImpl->get_adjacencies( adj_ents, 2, false, dum_quads );
2837 if( MB_SUCCESS != result ) return result;
2838 assert( 1 == dum_quads.size() );
2839 side_quads[j].push_back( *dum_quads.begin() );
2840 }
2841 }
2842
2843 return MB_SUCCESS;
2844 }
2845
2846 ErrorCode DualTool::fs_check_quad_sense( EntityHandle hex0, EntityHandle quad0, std::vector< EntityHandle >* connects )
2847 {
2848
2849
2850 int dum1, dum2, sense = 0;
2851 ErrorCode result = mbImpl->side_number( hex0, quad0, dum1, sense, dum2 );
2852 if( MB_SUCCESS != result ) return result;
2853 assert( 0 != sense );
2854 if( 1 == sense )
2855 {
2856
2857 EntityHandle dum = connects[0][0];
2858 connects[0][0] = connects[0][2];
2859 connects[0][2] = dum;
2860 }
2861
2862
2863 int index0 = -1, index2 = -1, sense0 = 0, sense2 = 0;
2864 MeshTopoUtil mtu( mbImpl );
2865 for( int i = 0; i < 4; i++ )
2866 {
2867 if( 0 != mtu.common_entity( connects[0][0], connects[1][i], 1 ) )
2868 {
2869 index0 = i;
2870 if( 0 != mtu.common_entity( connects[0][1], connects[1][( i + 1 ) % 4], 1 ) )
2871 sense0 = 1;
2872 else if( 0 != mtu.common_entity( connects[0][1], connects[1][( i + 4 - 1 ) % 4], 1 ) )
2873 sense0 = -1;
2874 break;
2875 }
2876 }
2877
2878 assert( index0 != -1 && sense0 != 0 );
2879
2880 if( sense0 == -1 )
2881 {
2882 EntityHandle dumh = connects[1][0];
2883 connects[1][0] = connects[1][2];
2884 connects[1][2] = dumh;
2885 if( index0 % 2 == 0 ) index0 = ( index0 + 2 ) % 4;
2886 }
2887
2888 if( index0 != 0 )
2889 {
2890 std::vector< EntityHandle > tmpc;
2891 for( int i = 0; i < 4; i++ )
2892 tmpc.push_back( connects[1][( index0 + i ) % 4] );
2893 connects[1].swap( tmpc );
2894 }
2895
2896 for( int i = 0; i < 4; i++ )
2897 {
2898 if( 0 != mtu.common_entity( connects[1][0], connects[2][i], 1 ) )
2899 {
2900 index2 = i;
2901 if( 0 != mtu.common_entity( connects[1][1], connects[2][( i + 1 ) % 4], 1 ) )
2902 sense2 = 1;
2903 else if( 0 != mtu.common_entity( connects[1][1], connects[2][( i + 4 - 1 ) % 4], 1 ) )
2904 sense2 = -1;
2905 break;
2906 }
2907 }
2908
2909 assert( index2 != -1 && sense2 != 0 );
2910
2911 if( sense2 == -1 )
2912 {
2913 EntityHandle dumh = connects[2][0];
2914 connects[2][0] = connects[2][2];
2915 connects[2][2] = dumh;
2916 if( index2 % 2 == 0 ) index2 = ( index2 + 2 ) % 4;
2917 }
2918
2919 if( index2 != 0 )
2920 {
2921 std::vector< EntityHandle > tmpc;
2922 for( int i = 0; i < 4; i++ )
2923 tmpc.push_back( connects[2][( index2 + i ) % 4] );
2924 connects[2].swap( tmpc );
2925 }
2926
2927 return MB_SUCCESS;
2928 }
2929
2930
2931 ErrorCode DualTool::rev_face_shrink( EntityHandle odedge )
2932 {
2933 if( debug_ap ) ( (Core*)mbImpl )->check_adjacencies();
2934
2935
2936 if( mbImpl->type_from_handle( odedge ) != MBEDGE ) return MB_TYPE_OUT_OF_RANGE;
2937
2938 std::cout << "-FS(";
2939 print_cell( odedge );
2940 std::cout << ")" << std::endl;
2941
2942 EntityHandle quads[4], hexes[2];
2943 std::vector< EntityHandle > connects[4], side_quads[2];
2944
2945
2946
2947 ErrorCode result = fs_get_quads( odedge, quads, hexes, connects );
2948 if( MB_SUCCESS != result ) return result;
2949
2950
2951
2952 result = fs_check_quad_sense( hexes[0], quads[0], connects );
2953 if( MB_SUCCESS != result ) return result;
2954
2955 result = fsr_get_fourth_quad( connects, side_quads );
2956 if( MB_SUCCESS != result )
2957 {
2958 std::cout << "Can't do -FS here, two hexes must be adjacent to ring of 4 hexes." << std::endl;
2959 return result;
2960 }
2961
2962 Range adj_ents, outer_hexes, all_adjs;
2963
2964
2965 for( int i = 1; i <= 3; i++ )
2966 {
2967 result = mbImpl->get_adjacencies( &connects[1][0], 4, i, false, adj_ents, Interface::UNION );
2968 if( MB_SUCCESS != result ) return result;
2969 }
2970
2971
2972
2973 for( int i = 0; i < 3; i++ )
2974 {
2975 result = mbImpl->get_adjacencies( adj_ents, i, false, all_adjs, Interface::UNION );
2976 if( MB_SUCCESS != result ) return result;
2977 }
2978
2979
2980 Range dual_ents, dual_hps;
2981 for( Range::iterator rit = all_adjs.begin(); rit != all_adjs.end(); ++rit )
2982 {
2983 EntityHandle this_ent = get_dual_entity( *rit );
2984 dual_ents.insert( this_ent );
2985 }
2986
2987
2988 for( Range::iterator rit = dual_ents.begin(); rit != dual_ents.end(); ++rit )
2989 {
2990 int dim = mbImpl->dimension_from_handle( *rit );
2991 if( 1 == dim || 2 == dim ) dual_hps.insert( get_dual_hyperplane( *rit ) );
2992 }
2993
2994 result = delete_dual_entities( dual_ents );
2995 if( MB_SUCCESS != result ) return result;
2996
2997
2998 for( Range::iterator rit = dual_hps.begin(); rit != dual_hps.end(); ++rit )
2999 {
3000 Range tmp_ents;
3001 result = mbImpl->get_entities_by_handle( *rit, tmp_ents );
3002 if( MB_SUCCESS != result ) return result;
3003 if( tmp_ents.empty() )
3004 {
3005 result = mbImpl->delete_entities( &( *rit ), 1 );
3006 if( MB_SUCCESS != result ) return result;
3007 }
3008 }
3009
3010
3011
3012
3013 bool need_explicit = false;
3014 Range adj_quads;
3015 result = mbImpl->get_adjacencies( &connects[3][0], 4, 2, false, adj_quads );
3016 if( MB_MULTIPLE_ENTITIES_FOUND == result || !adj_quads.empty() )
3017 {
3018
3019
3020
3021 need_explicit = true;
3022 for( Range::iterator rit = adj_quads.begin(); rit != adj_quads.end(); ++rit )
3023 {
3024 Range adj_hexes;
3025 result = mbImpl->get_adjacencies( &( *rit ), 1, 3, false, adj_hexes );RR;
3026 result = mbImpl->add_adjacencies( *rit, adj_hexes, false );RR;
3027 }
3028 }
3029
3030
3031 std::vector< EntityHandle > new_connect;
3032 std::copy( connects[3].begin(), connects[3].end(), std::back_inserter( new_connect ) );
3033 std::copy( connects[2].begin(), connects[2].end(), std::back_inserter( new_connect ) );
3034 result = mbImpl->set_connectivity( hexes[0], &new_connect[0], 8 );
3035 if( MB_SUCCESS != result ) return result;
3036
3037 new_connect.clear();
3038 std::copy( connects[0].begin(), connects[0].end(), std::back_inserter( new_connect ) );
3039 std::copy( connects[3].begin(), connects[3].end(), std::back_inserter( new_connect ) );
3040 result = mbImpl->set_connectivity( hexes[1], &new_connect[0], 8 );
3041 if( MB_SUCCESS != result ) return result;
3042
3043
3044
3045 MeshTopoUtil mtu( mbImpl );
3046 for( int j = 0; j < 2; j++ )
3047 {
3048 for( int i = 0; i < 4; i++ )
3049 {
3050 if( mtu.equivalent_entities( side_quads[j][i] ) )
3051 {
3052 result = mbImpl->add_adjacencies( side_quads[j][i], &hexes[j], 1, false );
3053 if( MB_SUCCESS != result ) return result;
3054 }
3055 }
3056 }
3057
3058
3059 adj_ents.erase( hexes[0] );
3060 adj_ents.erase( hexes[1] );
3061
3062
3063 result = mbImpl->delete_entities( adj_ents );
3064 if( MB_SUCCESS != result ) return result;
3065
3066 EntityHandle new_quad;
3067 result = mbImpl->create_element( MBQUAD, &connects[3][0], 4, new_quad );RR;
3068 if( need_explicit )
3069 {
3070 result = mbImpl->add_adjacencies( new_quad, hexes, 2, false );RR;
3071 }
3072
3073 if( debug_ap ) ( (Core*)mbImpl )->check_adjacencies();
3074
3075
3076 result = construct_hex_dual( hexes, 2 );
3077 if( MB_SUCCESS != result ) return result;
3078
3079 return MB_SUCCESS;
3080 }
3081
3082 ErrorCode DualTool::fsr_get_fourth_quad( std::vector< EntityHandle >* connects,
3083 std::vector< EntityHandle >* side_quads )
3084 {
3085
3086
3087
3088
3089
3090 for( int i = 0; i < 4; i++ )
3091 {
3092 Range start_verts, tmp_verts, quads;
3093 for( int j = 0; j < 3; j++ )
3094 start_verts.insert( connects[j][i] );
3095 ErrorCode result = mbImpl->get_adjacencies( start_verts, 2, false, quads );
3096 if( MB_SUCCESS != result ) return result;
3097 assert( quads.size() == 1 );
3098 result = mbImpl->get_adjacencies( &( *quads.begin() ), 1, 0, false, tmp_verts );RR;
3099 tmp_verts = subtract( tmp_verts, start_verts );
3100 assert( 1 == tmp_verts.size() );
3101 connects[3].push_back( *tmp_verts.begin() );
3102 }
3103
3104
3105 for( int i = 0; i < 4; i++ )
3106 {
3107 Range dum_ents, hexes;
3108 dum_ents.insert( connects[1][i] );
3109 dum_ents.insert( connects[1][( i + 1 ) % 4] );
3110 dum_ents.insert( connects[3][i] );
3111 ErrorCode result = mbImpl->get_adjacencies( dum_ents, 3, false, hexes );
3112 if( MB_SUCCESS != result ) return result;
3113 assert( 1 == hexes.size() );
3114
3115 hexes.insert( connects[0][i] );
3116 hexes.insert( connects[0][( i + 1 ) % 4] );
3117 hexes.insert( connects[3][i] );
3118 hexes.insert( connects[3][( i + 1 ) % 4] );
3119 dum_ents.clear();
3120 result = mbImpl->get_adjacencies( hexes, 2, false, dum_ents );
3121 if( MB_SUCCESS != result ) return result;
3122 assert( dum_ents.size() == 1 );
3123 side_quads[0].push_back( *dum_ents.begin() );
3124
3125 hexes.erase( connects[0][i] );
3126 hexes.erase( connects[0][( i + 1 ) % 4] );
3127 hexes.insert( connects[2][i] );
3128 hexes.insert( connects[2][( i + 1 ) % 4] );
3129 dum_ents.clear();
3130 result = mbImpl->get_adjacencies( hexes, 2, false, dum_ents );
3131 if( MB_SUCCESS != result ) return result;
3132 side_quads[1].push_back( *dum_ents.begin() );
3133 }
3134
3135 return MB_SUCCESS;
3136 }
3137
3138 ErrorCode DualTool::fs_get_quads( EntityHandle odedge,
3139 EntityHandle* quads,
3140 EntityHandle* hexes,
3141 std::vector< EntityHandle >* connects )
3142 {
3143
3144 EntityHandle chord = get_dual_hyperplane( odedge );
3145 if( 0 == chord ) return MB_FAILURE;
3146
3147 std::vector< EntityHandle > edges;
3148 ErrorCode result = mbImpl->get_entities_by_handle( chord, edges );
3149 if( MB_FAILURE == result ) return result;
3150
3151 std::vector< EntityHandle >::iterator vit = std::find( edges.begin(), edges.end(), odedge );
3152
3153 if( vit == edges.end() || *edges.begin() == *vit || *edges.rbegin() == *vit ) return MB_FAILURE;
3154
3155
3156 quads[0] = get_dual_entity( *( vit - 1 ) );
3157 quads[1] = get_dual_entity( *vit );
3158 quads[2] = get_dual_entity( *( vit + 1 ) );
3159 for( int i = 0; i < 3; i++ )
3160 {
3161 result = mbImpl->get_connectivity( &quads[i], 1, connects[i], true );
3162 if( MB_SUCCESS != result ) return result;
3163 }
3164
3165 Range tmph;
3166 result = mbImpl->get_adjacencies( quads, 2, 3, false, tmph );
3167 if( MB_SUCCESS != result ) return result;
3168 assert( tmph.size() == 1 );
3169 hexes[0] = *tmph.begin();
3170
3171 tmph.clear();
3172 result = mbImpl->get_adjacencies( &quads[1], 2, 3, false, tmph );
3173 if( MB_SUCCESS != result ) return result;
3174 assert( tmph.size() == 1 );
3175 hexes[1] = *tmph.begin();
3176
3177 return MB_SUCCESS;
3178 }
3179
3180 ErrorCode DualTool::delete_whole_dual()
3181 {
3182
3183 Range dual_surfs, dual_curves;
3184 ErrorCode result = this->get_dual_hyperplanes( mbImpl, 2, dual_surfs );RR;
3185 result = mbImpl->delete_entities( dual_surfs );RR;
3186 result = this->get_dual_hyperplanes( mbImpl, 1, dual_curves );RR;
3187 result = mbImpl->delete_entities( dual_curves );RR;
3188
3189
3190 Range dual_ents;
3191 result = mbImpl->get_entities_by_type_and_tag( 0, MBVERTEX, &isDualCellTag, NULL, 1, dual_ents, Interface::UNION );RR;
3192 result = mbImpl->get_entities_by_type_and_tag( 0, MBEDGE, &isDualCellTag, NULL, 1, dual_ents, Interface::UNION );RR;
3193 result = mbImpl->get_entities_by_type_and_tag( 0, MBPOLYGON, &isDualCellTag, NULL, 1, dual_ents, Interface::UNION );RR;
3194 result =
3195 mbImpl->get_entities_by_type_and_tag( 0, MBPOLYHEDRON, &isDualCellTag, NULL, 1, dual_ents, Interface::UNION );RR;
3196
3197
3198 ErrorCode tmp_result;
3199 for( Range::reverse_iterator rit = dual_ents.rbegin(); rit != dual_ents.rend(); ++rit )
3200 {
3201 tmp_result = mbImpl->delete_entities( &( *rit ), 1 );
3202 if( MB_SUCCESS != tmp_result ) result = tmp_result;
3203 }
3204 RR;
3205
3206
3207 if( 0 != dualSurfaceTag )
3208 {
3209 tmp_result = mbImpl->tag_delete( dualSurfaceTag );
3210 if( MB_SUCCESS != tmp_result && MB_TAG_NOT_FOUND != tmp_result ) result = tmp_result;
3211 }
3212 if( 0 != dualCurveTag )
3213 {
3214 tmp_result = mbImpl->tag_delete( dualCurveTag );
3215 if( MB_SUCCESS != tmp_result && MB_TAG_NOT_FOUND != tmp_result ) result = tmp_result;
3216 }
3217 if( 0 != dualEntityTag )
3218 {
3219 tmp_result = mbImpl->tag_delete( dualEntityTag );
3220 if( MB_SUCCESS != tmp_result && MB_TAG_NOT_FOUND != tmp_result ) result = tmp_result;
3221 }
3222 if( 0 != extraDualEntityTag )
3223 {
3224 tmp_result = mbImpl->tag_delete( extraDualEntityTag );
3225 if( MB_SUCCESS != tmp_result && MB_TAG_NOT_FOUND != tmp_result ) result = tmp_result;
3226 }
3227 if( 0 != dualGraphicsPointTag )
3228 {
3229 tmp_result = mbImpl->tag_delete( dualGraphicsPointTag );
3230 if( MB_SUCCESS != tmp_result && MB_TAG_NOT_FOUND != tmp_result ) result = tmp_result;
3231 }
3232
3233 return MB_SUCCESS;
3234 }
3235
3236 ErrorCode DualTool::check_dual_adjs()
3237 {
3238
3239
3240
3241 Range pents[4];
3242 ErrorCode result = mbImpl->get_entities_by_type( 0, MBHEX, pents[3] );RR;
3243 for( int i = 2; i >= 0; i-- )
3244 {
3245 result = mbImpl->get_adjacencies( pents[3], 2, false, pents[2], Interface::UNION );RR;
3246 }
3247
3248
3249 #define PRENT( ent ) CN::EntityTypeName( TYPE_FROM_HANDLE( ent ) ) << " " << ID_FROM_HANDLE( ent )
3250 ErrorCode overall_result = MB_SUCCESS;
3251 for( int pd = 1; pd <= 3; pd++ )
3252 {
3253 for( Range::iterator prit = pents[pd].begin(); prit != pents[pd].end(); ++prit )
3254 {
3255
3256 EntityHandle dual_ent = get_dual_entity( *prit );
3257 if( 0 == dual_ent ) std::cerr << "Problem getting dual entity for " << PRENT( *prit ) << std::endl;
3258
3259
3260 for( int sd = 0; sd < pd; sd++ )
3261 {
3262 Range R1, R2, R3;
3263
3264 result = mbImpl->get_adjacencies( &( *prit ), 1, sd, false, R1 );RR;
3265
3266
3267 result = mbImpl->get_adjacencies( &dual_ent, 1, 3 - sd, false, R2 );RR;
3268
3269 if( R1.size() != R2.size() )
3270 {
3271 std::cerr << PRENT( *prit ) << ": number of adj ents in "
3272 << "primal/dual don't agree for dimension " << sd << "." << std::endl;
3273 overall_result = MB_FAILURE;
3274 }
3275
3276
3277 for( Range::iterator r1it = R1.begin(); r1it != R1.end(); ++r1it )
3278 {
3279 EntityHandle tmp_dual = get_dual_entity( *r1it );
3280 if( R2.find( tmp_dual ) == R2.end() )
3281 {
3282 std::cerr << PRENT( *prit ) << ": adj entity " << PRENT( *r1it ) << " isn't adjacent in dual."
3283 << std::endl;
3284 overall_result = MB_FAILURE;
3285 }
3286 }
3287
3288 for( Range::iterator r2it = R2.begin(); r2it != R2.end(); ++r2it )
3289 {
3290 EntityHandle tmp_prim = get_dual_entity( *r2it );
3291 if( R1.find( tmp_prim ) == R1.end() )
3292 {
3293 std::cerr << PRENT( *prit ) << ": adj entity " << PRENT( *r2it ) << " isn't adjacent in primal."
3294 << std::endl;
3295 overall_result = MB_FAILURE;
3296 }
3297 }
3298 }
3299 }
3300 }
3301
3302 return overall_result;
3303 }
3304
3305 }