MOAB: Mesh Oriented datABase
(version 5.4.1)
|
00001 #include <iostream> 00002 #include <map> 00003 00004 #include "moab/FBEngine.hpp" 00005 #include "moab/Interface.hpp" 00006 #include "moab/GeomTopoTool.hpp" 00007 #include "moab/GeomUtil.hpp" 00008 #include "moab/OrientedBoxTreeTool.hpp" 00009 00010 #include <cstdlib> 00011 #include <cstring> 00012 #include <map> 00013 #include <set> 00014 #include <queue> 00015 #include <algorithm> 00016 #include <cassert> 00017 00018 #include "SmoothCurve.hpp" 00019 #include "SmoothFace.hpp" 00020 00021 // this is just to replace MBI with moab interface, which is _mbImpl in this class 00022 #define MBI _mbImpl 00023 #define MBERRORR( rval, STR ) \ 00024 { \ 00025 if( MB_SUCCESS != ( rval ) ) \ 00026 { \ 00027 std::cout << ( STR ) << std::endl; \ 00028 return rval; \ 00029 } \ 00030 } 00031 00032 namespace moab 00033 { 00034 00035 // some tolerances for ray tracing and geometry intersections 00036 // these are involved in ray tracing, at least 00037 00038 double tolerance = 0.01; // TODO: how is this used ???? 00039 double tolerance_segment = 0.01; // for segments intersection, points collapse, area coordinates for triangles 00040 // it should be a relative, not an absolute value 00041 // as this splitting operation can create small edges, it should be relatively high 00042 // or, it should be coordinated with the decimation errors 00043 // we really just want to preserve the integrity of the mesh, we should avoid creating small edges 00044 // or angles 00045 const bool Debug_surf_eval = false; 00046 bool debug_splits = false; 00047 00048 // will compute intersection between a segment and slice of a plane 00049 // output is the intersection point 00050 bool intersect_segment_and_plane_slice( CartVect& from, 00051 CartVect& to, 00052 CartVect& p1, 00053 CartVect& p2, 00054 CartVect&, 00055 CartVect& normPlane, 00056 CartVect& intx_point, 00057 double& parPos ) 00058 { 00059 // 00060 // plane eq is normPlane % r + d = 0, or normPlane % r - normPlane%p1 = 0 00061 double dd = -normPlane % p1; 00062 double valFrom = normPlane % from + dd; 00063 double valTo = normPlane % to + dd; 00064 00065 if( fabs( valFrom ) < tolerance_segment ) 00066 { 00067 intx_point = from; 00068 parPos = 0.; 00069 double proj1 = ( intx_point - p1 ) % ( p2 - p1 ); 00070 double proj2 = ( intx_point - p2 ) % ( p1 - p2 ); 00071 if( proj1 <= -tolerance_segment || proj2 <= -tolerance_segment ) return false; 00072 if( debug_splits ) std::cout << "intx : " << intx_point << "\n"; 00073 return true; 00074 } 00075 if( fabs( valTo ) < tolerance_segment ) 00076 { 00077 intx_point = to; 00078 parPos = 1; 00079 double proj1 = ( intx_point - p1 ) % ( p2 - p1 ); 00080 double proj2 = ( intx_point - p2 ) % ( p1 - p2 ); 00081 if( proj1 <= -tolerance_segment || proj2 <= -tolerance_segment ) return false; 00082 if( debug_splits ) std::cout << "intx : " << intx_point << "\n"; 00083 return true; 00084 } 00085 if( valFrom * valTo > 0 ) return false; // no intersection, although it could be very close 00086 // else, it could intersect the plane; check for the slice too. 00087 parPos = valFrom / ( valFrom - valTo ); // this is 0 for valFrom 0, 1 for valTo 0 00088 intx_point = from + ( to - from ) * parPos; 00089 // now check if the intx_point is indeed between p1 and p2 in the slice. 00090 double proj1 = ( intx_point - p1 ) % ( p2 - p1 ); 00091 double proj2 = ( intx_point - p2 ) % ( p1 - p2 ); 00092 if( proj1 <= -tolerance_segment || proj2 <= -tolerance_segment ) return false; 00093 00094 if( debug_splits ) std::cout << "intx : " << intx_point << "\n"; 00095 return true; 00096 } 00097 00098 ErrorCode area_coordinates( Interface* mbi, 00099 EntityHandle tri, 00100 CartVect& pnt, 00101 double* area_coord, 00102 EntityHandle& boundary_handle ) 00103 { 00104 00105 int nnodes; 00106 const EntityHandle* conn3; 00107 ErrorCode rval = mbi->get_connectivity( tri, conn3, nnodes ); 00108 MBERRORR( rval, "Failed to get connectivity" ); 00109 assert( 3 == nnodes ); 00110 CartVect P[3]; 00111 rval = mbi->get_coords( conn3, nnodes, (double*)&P[0] ); 00112 MBERRORR( rval, "Failed to get coordinates" ); 00113 00114 CartVect r0( P[0] - pnt ); 00115 CartVect r1( P[1] - pnt ); 00116 CartVect r2( P[2] - pnt ); 00117 if( debug_splits ) 00118 { 00119 std::cout << " nodes:" << conn3[0] << " " << conn3[1] << " " << conn3[2] << "\n"; 00120 std::cout << " distances: " << r0.length() << " " << r1.length() << " " << r2.length() << "\n"; 00121 } 00122 if( r0.length() < tolerance_segment ) 00123 { 00124 area_coord[0] = 1.; 00125 area_coord[1] = 0.; 00126 area_coord[2] = 0.; 00127 boundary_handle = conn3[0]; 00128 return MB_SUCCESS; 00129 } 00130 if( r1.length() < tolerance_segment ) 00131 { 00132 area_coord[0] = 0.; 00133 area_coord[1] = 1.; 00134 area_coord[2] = 0.; 00135 boundary_handle = conn3[1]; 00136 return MB_SUCCESS; 00137 } 00138 if( r2.length() < tolerance_segment ) 00139 { 00140 area_coord[0] = 0.; 00141 area_coord[1] = 0.; 00142 area_coord[2] = 1.; 00143 boundary_handle = conn3[2]; 00144 return MB_SUCCESS; 00145 } 00146 00147 CartVect v1( P[1] - P[0] ); 00148 CartVect v2( P[2] - P[0] ); 00149 00150 double areaDouble = ( v1 * v2 ).length(); // the same for CartVect 00151 if( areaDouble < tolerance_segment * tolerance_segment ) 00152 { 00153 MBERRORR( MB_FAILURE, "area of triangle too small" ); 00154 } 00155 area_coord[0] = ( r1 * r2 ).length() / areaDouble; 00156 area_coord[1] = ( r2 * r0 ).length() / areaDouble; 00157 area_coord[2] = ( r0 * r1 ).length() / areaDouble; 00158 00159 if( fabs( area_coord[0] + area_coord[1] + area_coord[2] - 1 ) > tolerance_segment ) 00160 { 00161 MBERRORR( MB_FAILURE, "point outside triangle" ); 00162 } 00163 // the tolerance is used here for area coordinates (0 to 1), and in other 00164 // parts it is used as an absolute distance; pretty inconsistent. 00165 bool side0 = ( area_coord[0] < tolerance_segment ); 00166 bool side1 = ( area_coord[1] < tolerance_segment ); 00167 bool side2 = ( area_coord[2] < tolerance_segment ); 00168 if( !side0 && !side1 && !side2 ) return MB_SUCCESS; // interior point 00169 // now, find out what boundary is in question 00170 // first, get all edges, in order 00171 std::vector< EntityHandle > edges; 00172 EntityHandle nn2[2]; 00173 for( int i = 0; i < 3; i++ ) 00174 { 00175 nn2[0] = conn3[( i + 1 ) % 3]; 00176 nn2[1] = conn3[( i + 2 ) % 3]; 00177 std::vector< EntityHandle > adjacent; 00178 rval = mbi->get_adjacencies( nn2, 2, 1, false, adjacent, Interface::INTERSECT ); 00179 MBERRORR( rval, "Failed to get edges" ); 00180 if( adjacent.size() != 1 ) MBERRORR( MB_FAILURE, "Failed to get adjacent edges" ); 00181 // should be only one edge here 00182 edges.push_back( adjacent[0] ); 00183 } 00184 00185 if( side0 ) boundary_handle = edges[0]; 00186 if( side1 ) boundary_handle = edges[1]; 00187 if( side2 ) boundary_handle = edges[2]; 00188 00189 return MB_SUCCESS; 00190 } 00191 00192 FBEngine::FBEngine( Interface* impl, GeomTopoTool* topoTool, const bool smooth ) 00193 : _mbImpl( impl ), _my_geomTopoTool( topoTool ), _t_created( false ), _smooth( smooth ), _initialized( false ), 00194 _smthFace( NULL ), _smthCurve( NULL ) 00195 { 00196 if( !_my_geomTopoTool ) 00197 { 00198 _my_geomTopoTool = new GeomTopoTool( _mbImpl ); 00199 _t_created = true; 00200 } 00201 // should this be part of the constructor or not? 00202 // Init(); 00203 } 00204 FBEngine::~FBEngine() 00205 { 00206 clean(); 00207 _smooth = false; 00208 } 00209 00210 void FBEngine::clean() 00211 { 00212 if( _smooth ) 00213 { 00214 _faces.clear(); 00215 _edges.clear(); 00216 int size1 = _my_gsets[1].size(); 00217 int i = 0; 00218 for( i = 0; i < size1; i++ ) 00219 delete _smthCurve[i]; 00220 delete[] _smthCurve; 00221 _smthCurve = NULL; 00222 size1 = _my_gsets[2].size(); 00223 for( i = 0; i < size1; i++ ) 00224 delete _smthFace[i]; 00225 delete[] _smthFace; 00226 _smthFace = NULL; 00227 //_smooth = false; 00228 } 00229 00230 for( int j = 0; j < 5; j++ ) 00231 _my_gsets[j].clear(); 00232 if( _t_created ) delete _my_geomTopoTool; 00233 _my_geomTopoTool = NULL; 00234 _t_created = false; 00235 } 00236 00237 ErrorCode FBEngine::Init() 00238 { 00239 if( !_initialized ) 00240 { 00241 if( !_my_geomTopoTool ) return MB_FAILURE; 00242 00243 ErrorCode rval = _my_geomTopoTool->find_geomsets( _my_gsets ); 00244 assert( rval == MB_SUCCESS ); 00245 if( MB_SUCCESS != rval ) 00246 { 00247 return rval; 00248 } 00249 00250 rval = split_quads(); 00251 assert( rval == MB_SUCCESS ); 00252 00253 rval = _my_geomTopoTool->construct_obb_trees(); 00254 assert( rval == MB_SUCCESS ); 00255 00256 if( _smooth ) rval = initializeSmoothing(); 00257 assert( rval == MB_SUCCESS ); 00258 00259 _initialized = true; 00260 } 00261 return MB_SUCCESS; 00262 } 00263 ErrorCode FBEngine::initializeSmoothing() 00264 { 00265 // 00266 /*ErrorCode rval = Init(); 00267 MBERRORR(rval, "failed initialize");*/ 00268 // first of all, we need to retrieve all the surfaces from the (root) set 00269 // in icesheet_test we use iGeom, but maybe that is a stretch 00270 // get directly the sets with geom dim 2, and from there create the SmoothFace 00271 Tag geom_tag; 00272 ErrorCode rval = MBI->tag_get_handle( GEOM_DIMENSION_TAG_NAME, 1, MB_TYPE_INTEGER, geom_tag ); 00273 MBERRORR( rval, "can't get geom tag" ); 00274 00275 int numSurfaces = _my_gsets[2].size(); 00276 // SmoothFace ** smthFace = new SmoothFace *[numSurfaces]; 00277 _smthFace = new SmoothFace*[numSurfaces]; 00278 00279 // there should also be a map from surfaces to evaluators 00280 // std::map<MBEntityHandle, SmoothFace*> mapSurfaces; 00281 00282 int i = 0; 00283 Range::iterator it; 00284 for( it = _my_gsets[2].begin(); it != _my_gsets[2].end(); ++it, i++ ) 00285 { 00286 EntityHandle face = *it; 00287 _smthFace[i] = new SmoothFace( MBI, face, _my_geomTopoTool ); // geom topo tool will be used for searching, 00288 // among other things; also for senses in edge sets... 00289 _faces[face] = _smthFace[i]; 00290 } 00291 00292 int numCurves = _my_gsets[1].size(); // csets.size(); 00293 // SmoothCurve ** smthCurve = new SmoothCurve *[numCurves]; 00294 _smthCurve = new SmoothCurve*[numCurves]; 00295 // there should also be a map from surfaces to evaluators 00296 // std::map<MBEntityHandle, SmoothCurve*> mapCurves; 00297 00298 i = 0; 00299 for( it = _my_gsets[1].begin(); it != _my_gsets[1].end(); ++it, i++ ) 00300 { 00301 EntityHandle curve = *it; 00302 _smthCurve[i] = new SmoothCurve( MBI, curve, _my_geomTopoTool ); 00303 _edges[curve] = _smthCurve[i]; 00304 } 00305 00306 for( i = 0; i < numSurfaces; i++ ) 00307 { 00308 _smthFace[i]->init_gradient(); // this will also retrieve the triangles in each surface 00309 _smthFace[i]->compute_tangents_for_each_edge(); // this one will consider all edges 00310 // internal, so the 00311 // tangents are all in the direction of the edge; a little bit of waste, as we store 00312 // one tangent for each edge node , even though they are equal here... 00313 // no loops are considered 00314 } 00315 00316 // this will be used to mark boundary edges, so for them the control points are computed earlier 00317 unsigned char value = 0; // default value is "not used"=0 for the tag 00318 // unsigned char def_data_bit = 1;// valid by default 00319 // rval = mb->tag_create("valid", 1, MB_TAG_BIT, validTag, &def_data_bit); 00320 Tag markTag; 00321 rval = MBI->tag_get_handle( "MARKER", 1, MB_TYPE_BIT, markTag, MB_TAG_EXCL | MB_TAG_BIT, 00322 &value ); // default value : 0 = not computed yet 00323 // each feature edge will need to have a way to retrieve at every moment the surfaces it belongs 00324 // to from edge sets, using the sense tag, we can get faces, and from each face, using the map, 00325 // we can get the SmoothFace (surface evaluator), that has everything, including the normals!!! 00326 assert( rval == MB_SUCCESS ); 00327 00328 // create the tag also for control points on the edges 00329 double defCtrlPoints[9] = { 0., 0., 0., 0., 0., 0., 0., 0., 0. }; 00330 Tag edgeCtrlTag; 00331 rval = MBI->tag_get_handle( "CONTROLEDGE", 9, MB_TYPE_DOUBLE, edgeCtrlTag, MB_TAG_DENSE | MB_TAG_CREAT, 00332 &defCtrlPoints ); 00333 assert( rval == MB_SUCCESS ); 00334 00335 Tag facetCtrlTag; 00336 double defControls[18] = { 0. }; 00337 rval = MBI->tag_get_handle( "CONTROLFACE", 18, MB_TYPE_DOUBLE, facetCtrlTag, MB_TAG_CREAT | MB_TAG_DENSE, 00338 &defControls ); 00339 assert( rval == MB_SUCCESS ); 00340 00341 Tag facetEdgeCtrlTag; 00342 double defControls2[27] = { 0. }; // corresponding to 9 control points on edges, in order 00343 // from edge 0, 1, 2 ( 1-2, 2-0, 0-1 ) 00344 rval = MBI->tag_get_handle( "CONTROLEDGEFACE", 27, MB_TYPE_DOUBLE, facetEdgeCtrlTag, MB_TAG_CREAT | MB_TAG_DENSE, 00345 &defControls2 ); 00346 assert( rval == MB_SUCCESS ); 00347 // if the 00348 double min_dot = -1.0; // depends on _angle, but now we ignore it, for the time being 00349 for( i = 0; i < numCurves; i++ ) 00350 { 00351 _smthCurve[i]->compute_tangents_for_each_edge(); // do we need surfaces now? or just the chains? 00352 // the computed edges will be marked accordingly; later one, only internal edges to surfaces 00353 // are left 00354 _smthCurve[i]->compute_control_points_on_boundary_edges( min_dot, _faces, edgeCtrlTag, markTag ); 00355 } 00356 00357 // when done with boundary edges, compute the control points on all edges in the surfaces 00358 00359 for( i = 0; i < numSurfaces; i++ ) 00360 { 00361 // also pass the tags for 00362 _smthFace[i]->compute_control_points_on_edges( min_dot, edgeCtrlTag, markTag ); 00363 } 00364 00365 // now we should be able to compute the control points for the facets 00366 00367 for( i = 0; i < numSurfaces; i++ ) 00368 { 00369 // also pass the tags for edge and facet control points 00370 _smthFace[i]->compute_internal_control_points_on_facets( min_dot, facetCtrlTag, facetEdgeCtrlTag ); 00371 } 00372 // we will need to compute the tangents for all edges in the model 00373 // they will be needed for control points for each edge 00374 // the boundary edges and the feature edges are more complicated 00375 // the boundary edges need to consider their loops, but feature edges need to consider loops and 00376 // the normals on each connected surface 00377 00378 // some control points 00379 if( Debug_surf_eval ) 00380 for( i = 0; i < numSurfaces; i++ ) 00381 _smthFace[i]->DumpModelControlPoints(); 00382 00383 return MB_SUCCESS; 00384 } 00385 00386 // clean up the smooth tags data if created, so the files will be smaller 00387 // if saved 00388 // also, recompute the tags if topology is modified 00389 void FBEngine::delete_smooth_tags() 00390 { 00391 // get all tags from database that are created for smooth data, and 00392 // delete them; it will delete all data associated with them 00393 // first tags from faces, edges: 00394 std::vector< Tag > smoothTags; 00395 int size1 = (int)_my_gsets[2].size(); 00396 00397 for( int i = 0; i < size1; i++ ) 00398 { 00399 // these 2 will append gradient tag and plane tag 00400 _smthFace[i]->append_smooth_tags( smoothTags ); 00401 } 00402 // then , get other tags: 00403 // "TANGENTS", "MARKER", "CONTROLEDGE", "CONTROLFACE", "CONTROLEDGEFACE" 00404 Tag tag_handle; 00405 ErrorCode rval = _mbImpl->tag_get_handle( "TANGENTS", 6, MB_TYPE_DOUBLE, tag_handle ); 00406 if( rval != MB_TAG_NOT_FOUND ) smoothTags.push_back( tag_handle ); 00407 00408 rval = _mbImpl->tag_get_handle( "MARKER", 1, MB_TYPE_BIT, tag_handle ); 00409 if( rval != MB_TAG_NOT_FOUND ) smoothTags.push_back( tag_handle ); 00410 00411 rval = _mbImpl->tag_get_handle( "CONTROLEDGE", 9, MB_TYPE_DOUBLE, tag_handle ); 00412 if( rval != MB_TAG_NOT_FOUND ) smoothTags.push_back( tag_handle ); 00413 00414 rval = _mbImpl->tag_get_handle( "CONTROLFACE", 18, MB_TYPE_DOUBLE, tag_handle ); 00415 if( rval != MB_TAG_NOT_FOUND ) smoothTags.push_back( tag_handle ); 00416 00417 rval = _mbImpl->tag_get_handle( "CONTROLEDGEFACE", 27, MB_TYPE_DOUBLE, tag_handle ); 00418 if( rval != MB_TAG_NOT_FOUND ) smoothTags.push_back( tag_handle ); 00419 00420 // a lot of tags, delete them 00421 for( unsigned int k = 0; k < smoothTags.size(); k++ ) 00422 { 00423 // could be a lot of data 00424 _mbImpl->tag_delete( smoothTags[k] ); 00425 } 00426 } 00427 /* 00428 #define COPY_RANGE(r, vec) { \ 00429 EntityHandle *tmp_ptr = reinterpret_cast<EntityHandle*>(vec); \ 00430 std::copy(r.begin(), r.end(), tmp_ptr);} 00431 */ 00432 00433 /*static inline void 00434 ProcessError(const char* desc);*/ 00435 00436 ErrorCode FBEngine::getRootSet( EntityHandle* root_set ) 00437 { 00438 *root_set = _my_geomTopoTool->get_root_model_set(); 00439 return MB_SUCCESS; 00440 } 00441 00442 ErrorCode FBEngine::getNumEntSets( EntityHandle set, int num_hops, int* all_sets ) 00443 { 00444 ErrorCode rval = MBI->num_contained_meshsets( set, all_sets, num_hops + 1 ); 00445 return rval; 00446 } 00447 00448 ErrorCode FBEngine::createEntSet( int isList, EntityHandle* pSet ) 00449 { 00450 ErrorCode rval; 00451 00452 if( isList ) 00453 rval = MBI->create_meshset( MESHSET_ORDERED, *pSet ); 00454 else 00455 rval = MBI->create_meshset( MESHSET_SET, *pSet ); 00456 00457 return rval; 00458 } 00459 00460 ErrorCode FBEngine::getEntities( EntityHandle set_handle, int entity_type, Range& gentities ) 00461 { 00462 int i; 00463 if( 0 > entity_type || 4 < entity_type ) 00464 { 00465 return MB_FAILURE; 00466 } 00467 else if( entity_type < 4 ) 00468 { // 4 means all entities 00469 gentities = _my_geomTopoTool->geoRanges()[entity_type]; // all from root set! 00470 } 00471 else 00472 { 00473 gentities.clear(); 00474 for( i = 0; i < 4; i++ ) 00475 { 00476 gentities.merge( _my_geomTopoTool->geoRanges()[i] ); 00477 } 00478 } 00479 Range sets; 00480 // see now if they are in the set passed as input or not 00481 ErrorCode rval = MBI->get_entities_by_type( set_handle, MBENTITYSET, sets ); 00482 MBERRORR( rval, "can't get sets in the initial set" ); 00483 gentities = intersect( gentities, sets ); 00484 00485 return MB_SUCCESS; 00486 } 00487 00488 ErrorCode FBEngine::addEntArrToSet( const Range& entities, EntityHandle set ) 00489 { 00490 return MBI->add_entities( set, entities ); 00491 } 00492 00493 ErrorCode FBEngine::addEntSet( EntityHandle entity_set_to_add, EntityHandle entity_set_handle ) 00494 { 00495 return MBI->add_entities( entity_set_handle, &entity_set_to_add, 1 ); 00496 } 00497 00498 ErrorCode FBEngine::getNumOfType( EntityHandle set, int ent_type, int* pNum ) 00499 { 00500 if( 0 > ent_type || 4 < ent_type ) 00501 { 00502 std::cout << "Invalid type\n"; 00503 return MB_FAILURE; 00504 } 00505 // get sets of geom dimension tag from here, and intersect with the gentities from geo 00506 // ranges 00507 00508 // get the geom dimensions sets in the set (AKA gentities) 00509 Range geom_sets; 00510 Tag geom_tag; 00511 ErrorCode rval = 00512 _mbImpl->tag_get_handle( GEOM_DIMENSION_TAG_NAME, 1, MB_TYPE_INTEGER, geom_tag, MB_TAG_SPARSE | MB_TAG_CREAT ); 00513 MBERRORR( rval, "Failed to get geom tag." ); 00514 rval = _mbImpl->get_entities_by_type_and_tag( set, MBENTITYSET, &geom_tag, NULL, 1, geom_sets, Interface::UNION ); 00515 MBERRORR( rval, "Failed to get gentities from set" ); 00516 00517 if( ent_type == 4 ) 00518 { 00519 *pNum = 0; 00520 for( int k = 0; k <= 3; k++ ) 00521 { 00522 Range gEntsOfTypeK = intersect( geom_sets, _my_geomTopoTool->geoRanges()[k] ); 00523 *pNum += (int)gEntsOfTypeK.size(); 00524 } 00525 } 00526 else 00527 { 00528 Range gEntsOfType = intersect( geom_sets, _my_geomTopoTool->geoRanges()[ent_type] ); 00529 *pNum = (int)gEntsOfType.size(); 00530 } 00531 // we do not really check if it is in the set or not; 00532 // _my_gsets[i].find(gent) != _my_gsets[i].end() 00533 return MB_SUCCESS; 00534 } 00535 00536 ErrorCode FBEngine::getEntType( EntityHandle gent, int* type ) 00537 { 00538 for( int i = 0; i < 4; i++ ) 00539 { 00540 if( _my_geomTopoTool->geoRanges()[i].find( gent ) != _my_geomTopoTool->geoRanges()[i].end() ) 00541 { 00542 *type = i; 00543 return MB_SUCCESS; 00544 } 00545 } 00546 *type = -1; // failure 00547 return MB_FAILURE; 00548 } 00549 ErrorCode FBEngine::getEntBoundBox( EntityHandle gent, 00550 double* min_x, 00551 double* min_y, 00552 double* min_z, 00553 double* max_x, 00554 double* max_y, 00555 double* max_z ) 00556 { 00557 ErrorCode rval; 00558 int type; 00559 rval = getEntType( gent, &type ); 00560 MBERRORR( rval, "Failed to get entity type." ); 00561 00562 if( type == 0 ) 00563 { 00564 rval = getVtxCoord( gent, min_x, min_y, min_z ); 00565 MBERRORR( rval, "Failed to get vertex coordinates." ); 00566 max_x = min_x; 00567 max_y = min_y; 00568 max_z = min_z; 00569 } 00570 else if( type == 1 ) 00571 { 00572 MBERRORR( MB_FAILURE, "iGeom_getEntBoundBox is not supported for Edge entity type." ); 00573 } 00574 else if( type == 2 || type == 3 ) 00575 { 00576 00577 EntityHandle root; 00578 CartVect center, axis[3]; 00579 rval = _my_geomTopoTool->get_root( gent, root ); 00580 MBERRORR( rval, "Failed to get tree root in iGeom_getEntBoundBox." ); 00581 rval = _my_geomTopoTool->obb_tree()->box( root, center.array(), axis[0].array(), axis[1].array(), 00582 axis[2].array() ); 00583 MBERRORR( rval, "Failed to get closest point in iGeom_getEntBoundBox." ); 00584 00585 CartVect absv[3]; 00586 for( int i = 0; i < 3; i++ ) 00587 { 00588 absv[i] = CartVect( fabs( axis[i][0] ), fabs( axis[i][1] ), fabs( axis[i][2] ) ); 00589 } 00590 CartVect min, max; 00591 min = center - absv[0] - absv[1] - absv[2]; 00592 max = center + absv[0] + absv[1] + absv[2]; 00593 *min_x = min[0]; 00594 *min_y = min[1]; 00595 *min_z = min[2]; 00596 *max_x = max[0]; 00597 *max_y = max[1]; 00598 *max_z = max[2]; 00599 } 00600 else 00601 return MB_FAILURE; 00602 00603 return MB_SUCCESS; 00604 } 00605 ErrorCode FBEngine::getEntClosestPt( EntityHandle this_gent, 00606 double near_x, 00607 double near_y, 00608 double near_z, 00609 double* on_x, 00610 double* on_y, 00611 double* on_z ) 00612 { 00613 ErrorCode rval; 00614 int type; 00615 rval = getEntType( this_gent, &type ); 00616 MBERRORR( rval, "Failed to get entity type." ); 00617 00618 if( type == 0 ) 00619 { 00620 rval = getVtxCoord( this_gent, on_x, on_y, on_z ); 00621 MBERRORR( rval, "Failed to get vertex coordinates." ); 00622 } 00623 else if( _smooth && type == 1 ) 00624 { 00625 *on_x = near_x; 00626 *on_y = near_y; 00627 *on_z = near_z; 00628 SmoothCurve* smthcurve = _edges[this_gent]; 00629 // call the new method from smooth edge 00630 smthcurve->move_to_curve( *on_x, *on_y, *on_z ); 00631 } 00632 else if( type == 2 || type == 3 ) 00633 { 00634 double point[3] = { near_x, near_y, near_z }; 00635 double point_out[3]; 00636 EntityHandle root, facet_out; 00637 if( _smooth && 2 == type ) 00638 { 00639 SmoothFace* smthFace = _faces[this_gent]; 00640 *on_x = near_x; 00641 *on_y = near_y; 00642 *on_z = near_z; 00643 smthFace->move_to_surface( *on_x, *on_y, *on_z ); 00644 } 00645 else 00646 { 00647 rval = _my_geomTopoTool->get_root( this_gent, root ); 00648 MBERRORR( rval, "Failed to get tree root in iGeom_getEntClosestPt." ); 00649 rval = _my_geomTopoTool->obb_tree()->closest_to_location( point, root, point_out, facet_out ); 00650 MBERRORR( rval, "Failed to get closest point in iGeom_getEntClosestPt." ); 00651 00652 *on_x = point_out[0]; 00653 *on_y = point_out[1]; 00654 *on_z = point_out[2]; 00655 } 00656 } 00657 else 00658 return MB_TYPE_OUT_OF_RANGE; 00659 00660 return MB_SUCCESS; 00661 } 00662 00663 ErrorCode FBEngine::getVtxCoord( EntityHandle vertex_handle, double* x0, double* y0, double* z0 ) 00664 { 00665 int type; 00666 ErrorCode rval = getEntType( vertex_handle, &type ); 00667 MBERRORR( rval, "Failed to get entity type in getVtxCoord." ); 00668 00669 if( type != 0 ) 00670 { 00671 MBERRORR( MB_FAILURE, "Entity is not a vertex type." ); 00672 } 00673 00674 Range entities; 00675 rval = MBI->get_entities_by_type( vertex_handle, MBVERTEX, entities ); 00676 MBERRORR( rval, "can't get nodes in vertex set." ); 00677 00678 if( entities.size() != 1 ) 00679 { 00680 MBERRORR( MB_FAILURE, "Vertex has multiple points." ); 00681 } 00682 double coords[3]; 00683 EntityHandle node = entities[0]; 00684 rval = MBI->get_coords( &node, 1, coords ); 00685 MBERRORR( rval, "can't get coordinates." ); 00686 *x0 = coords[0]; 00687 *y0 = coords[1]; 00688 *z0 = coords[2]; 00689 00690 return MB_SUCCESS; 00691 } 00692 00693 ErrorCode FBEngine::gsubtract( EntityHandle entity_set_1, EntityHandle entity_set_2, EntityHandle result_entity_set ) 00694 { 00695 /*result_entity_set = subtract(entity_set_1, entity_set_2);*/ 00696 Range ents1, ents2; 00697 ErrorCode rval = MBI->get_entities_by_type( entity_set_1, MBENTITYSET, ents1 ); 00698 MBERRORR( rval, "can't get entities from set 1." ); 00699 00700 rval = MBI->get_entities_by_type( entity_set_2, MBENTITYSET, ents2 ); 00701 MBERRORR( rval, "can't get entities from set 2." ); 00702 00703 ents1 = subtract( ents1, ents2 ); 00704 rval = MBI->clear_meshset( &result_entity_set, 1 ); 00705 MBERRORR( rval, "can't empty set." ); 00706 00707 rval = MBI->add_entities( result_entity_set, ents1 ); 00708 MBERRORR( rval, "can't add result to set." ); 00709 00710 return rval; 00711 } 00712 00713 ErrorCode FBEngine::getEntNrmlXYZ( EntityHandle entity_handle, 00714 double x, 00715 double y, 00716 double z, 00717 double* nrml_i, 00718 double* nrml_j, 00719 double* nrml_k ) 00720 { 00721 // just do for surface and volume 00722 int type; 00723 ErrorCode rval = getEntType( entity_handle, &type ); 00724 MBERRORR( rval, "Failed to get entity type in iGeom_getEntNrmlXYZ." ); 00725 00726 if( type != 2 && type != 3 ) 00727 { 00728 MBERRORR( MB_FAILURE, "Entities passed into gentityNormal must be face or volume." ); 00729 } 00730 00731 if( _smooth && 2 == type ) 00732 { 00733 SmoothFace* smthFace = _faces[entity_handle]; 00734 //*on_x = near_x; *on_y = near_y; *on_z = near_z; 00735 smthFace->normal_at( x, y, z, *nrml_i, *nrml_j, *nrml_k ); 00736 } 00737 else 00738 { 00739 // get closest location and facet 00740 double point[3] = { x, y, z }; 00741 double point_out[3]; 00742 EntityHandle root, facet_out; 00743 _my_geomTopoTool->get_root( entity_handle, root ); 00744 rval = _my_geomTopoTool->obb_tree()->closest_to_location( point, root, point_out, facet_out ); 00745 MBERRORR( rval, "Failed to get closest location in iGeom_getEntNrmlXYZ." ); 00746 00747 // get facet normal 00748 const EntityHandle* conn; 00749 int len; 00750 CartVect coords[3], normal; 00751 rval = MBI->get_connectivity( facet_out, conn, len ); 00752 MBERRORR( rval, "Failed to get triangle connectivity in iGeom_getEntNrmlXYZ." ); 00753 if( len != 3 ) MBERRORR( MB_FAILURE, " not a triangle, error " ); 00754 00755 rval = MBI->get_coords( conn, len, coords[0].array() ); 00756 MBERRORR( rval, "Failed to get triangle coordinates in iGeom_getEntNrmlXYZ." ); 00757 00758 coords[1] -= coords[0]; 00759 coords[2] -= coords[0]; 00760 normal = coords[1] * coords[2]; 00761 normal.normalize(); 00762 *nrml_i = normal[0]; 00763 *nrml_j = normal[1]; 00764 *nrml_k = normal[2]; 00765 } 00766 return MB_SUCCESS; 00767 } 00768 00769 ErrorCode FBEngine::getPntRayIntsct( double x, 00770 double y, 00771 double z, 00772 double dir_x, 00773 double dir_y, 00774 double dir_z, 00775 std::vector< EntityHandle >& intersect_entity_handles, 00776 /* int storage_order,*/ 00777 std::vector< double >& intersect_coords, 00778 std::vector< double >& param_coords ) 00779 { 00780 // this is pretty cool 00781 // we will return only surfaces (gentities ) 00782 // 00783 ErrorCode rval; 00784 00785 unsigned int numfaces = _my_gsets[2].size(); 00786 // do ray fire 00787 const double point[] = { x, y, z }; 00788 const double dir[] = { dir_x, dir_y, dir_z }; 00789 CartVect P( point ); 00790 CartVect V( dir ); 00791 00792 // std::vector<double> distances; 00793 std::vector< EntityHandle > facets; 00794 // std::vector<EntityHandle> sets; 00795 unsigned int i; 00796 for( i = 0; i < numfaces; i++ ) 00797 { 00798 EntityHandle face = _my_gsets[2][i]; 00799 EntityHandle rootForFace; 00800 rval = _my_geomTopoTool->get_root( face, rootForFace ); 00801 MBERRORR( rval, "Failed to get root of face." ); 00802 std::vector< double > distances_out; 00803 std::vector< EntityHandle > sets_out; 00804 std::vector< EntityHandle > facets_out; 00805 rval = _my_geomTopoTool->obb_tree()->ray_intersect_sets( distances_out, sets_out, facets_out, rootForFace, 00806 tolerance, point, dir ); 00807 unsigned int j; 00808 for( j = 0; j < distances_out.size(); j++ ) 00809 param_coords.push_back( distances_out[j] ); 00810 for( j = 0; j < sets_out.size(); j++ ) 00811 intersect_entity_handles.push_back( sets_out[j] ); 00812 for( j = 0; j < facets_out.size(); j++ ) 00813 facets.push_back( facets_out[j] ); 00814 00815 MBERRORR( rval, "Failed to get ray intersections." ); 00816 } 00817 // facets.size == distances.size()!! 00818 for( i = 0; i < param_coords.size(); i++ ) 00819 { 00820 CartVect intx = P + param_coords[i] * V; 00821 for( int j = 0; j < 3; j++ ) 00822 intersect_coords.push_back( intx[j] ); 00823 } 00824 if( _smooth ) 00825 { 00826 // correct the intersection point and the distance for smooth surfaces 00827 for( i = 0; i < intersect_entity_handles.size(); i++ ) 00828 { 00829 // EntityHandle geoSet = MBH_cast(sets[i]); 00830 SmoothFace* sFace = _faces[intersect_entity_handles[i]]; 00831 // correct coordinates and distance from point 00832 /*moab::ErrorCode ray_intersection_correct(moab::EntityHandle facet, // (IN) the facet 00833 where the patch is defined moab::CartVect &pt, // (IN) shoot from moab::CartVect &ray, 00834 // (IN) ray direction moab::CartVect &eval_pt, // (INOUT) The intersection point double 00835 & distance, // (IN OUT) the new distance bool &outside);*/ 00836 CartVect pos( &( intersect_coords[3 * i] ) ); 00837 double dist = param_coords[i]; 00838 bool outside = false; 00839 rval = sFace->ray_intersection_correct( facets[i], P, V, pos, dist, outside ); 00840 MBERRORR( rval, "Failed to get better point on ray." ); 00841 param_coords[i] = dist; 00842 00843 for( int j = 0; j < 3; j++ ) 00844 intersect_coords[3 * i + j] = pos[j]; 00845 } 00846 } 00847 return MB_SUCCESS; 00848 } 00849 00850 ErrorCode FBEngine::getAdjacentEntities( const EntityHandle from, const int to_dim, Range& adjs ) 00851 { 00852 int this_dim = -1; 00853 for( int i = 0; i < 4; i++ ) 00854 { 00855 if( _my_geomTopoTool->geoRanges()[i].find( from ) != _my_geomTopoTool->geoRanges()[i].end() ) 00856 { 00857 this_dim = i; 00858 break; 00859 } 00860 } 00861 00862 // check target dimension 00863 if( -1 == this_dim ) 00864 { 00865 // ProcessError(iBase_FAILURE, "Entity not a geometry entity."); 00866 return MB_FAILURE; 00867 } 00868 else if( 0 > to_dim || 3 < to_dim ) 00869 { 00870 // ProcessError(iBase_FAILURE, "To dimension must be between 0 and 3."); 00871 return MB_FAILURE; 00872 } 00873 else if( to_dim == this_dim ) 00874 { 00875 // ProcessError(iBase_FAILURE, 00876 // "To dimension must be different from entity dimension."); 00877 return MB_FAILURE; 00878 } 00879 00880 ErrorCode rval = MB_SUCCESS; 00881 adjs.clear(); 00882 if( to_dim > this_dim ) 00883 { 00884 int diffDim = to_dim - this_dim; 00885 rval = MBI->get_parent_meshsets( from, adjs, diffDim ); 00886 if( MB_SUCCESS != rval ) return rval; 00887 if( diffDim > 1 ) 00888 { 00889 // subtract the parents that come with diffDim-1 hops 00890 Range extra; 00891 rval = MBI->get_parent_meshsets( from, extra, diffDim - 1 ); 00892 if( MB_SUCCESS != rval ) return rval; 00893 adjs = subtract( adjs, extra ); 00894 } 00895 } 00896 else 00897 { 00898 int diffDim = this_dim - to_dim; 00899 rval = MBI->get_child_meshsets( from, adjs, diffDim ); 00900 if( MB_SUCCESS != rval ) return rval; 00901 if( diffDim > 1 ) 00902 { 00903 // subtract the children that come with diffDim-1 hops 00904 Range extra; 00905 rval = MBI->get_child_meshsets( from, extra, diffDim - 1 ); 00906 if( MB_SUCCESS != rval ) return rval; 00907 adjs = subtract( adjs, extra ); 00908 } 00909 } 00910 00911 return rval; 00912 } 00913 00914 // so far, this one is 00915 // used only for __MKModelEntityGeo tag 00916 00917 ErrorCode FBEngine::createTag( const char* tag_name, int tag_size, int tag_type, Tag& tag_handle_out ) 00918 { 00919 // this is copied from iMesh_MOAB.cpp; different name to not have trouble 00920 // with it 00921 // also, we do not want to depend on iMesh.h... 00922 // iMesh is more complicated, because of the options passed 00923 00924 DataType mb_data_type_table2[] = { MB_TYPE_OPAQUE, MB_TYPE_INTEGER, MB_TYPE_DOUBLE, MB_TYPE_HANDLE, 00925 MB_TYPE_HANDLE }; 00926 moab::TagType storage = MB_TAG_SPARSE; 00927 ErrorCode result; 00928 00929 result = 00930 MBI->tag_get_handle( tag_name, tag_size, mb_data_type_table2[tag_type], tag_handle_out, storage | MB_TAG_EXCL ); 00931 00932 if( MB_SUCCESS != result ) 00933 { 00934 std::string msg( "iMesh_createTag: " ); 00935 if( MB_ALREADY_ALLOCATED == result ) 00936 { 00937 msg += "Tag already exists with name: \""; 00938 msg += tag_name; 00939 std::cout << msg << "\n"; 00940 } 00941 else 00942 { 00943 std::cout << "Failed to create tag with name: " << tag_name << "\n"; 00944 return MB_FAILURE; 00945 } 00946 } 00947 00948 // end copy 00949 return MB_SUCCESS; 00950 } 00951 00952 ErrorCode FBEngine::getArrData( const EntityHandle* entity_handles, 00953 int entity_handles_size, 00954 Tag tag_handle, 00955 void* tag_values_out ) 00956 { 00957 // responsibility of the user to have tag_values_out properly allocated 00958 // only some types of Tags are possible (double, int, etc) 00959 return MBI->tag_get_data( tag_handle, entity_handles, entity_handles_size, tag_values_out ); 00960 } 00961 00962 ErrorCode FBEngine::setArrData( const EntityHandle* entity_handles, 00963 int entity_handles_size, 00964 Tag tag_handle, 00965 const void* tag_values ) 00966 { 00967 // responsibility of the user to have tag_values_out properly allocated 00968 // only some types of Tags are possible (double, int, etc) 00969 return MBI->tag_set_data( tag_handle, entity_handles, entity_handles_size, tag_values ); 00970 } 00971 00972 ErrorCode FBEngine::getEntAdj( EntityHandle handle, int type_requested, Range& adjEnts ) 00973 { 00974 return getAdjacentEntities( handle, type_requested, adjEnts ); 00975 } 00976 00977 ErrorCode FBEngine::getEgFcSense( EntityHandle mbedge, EntityHandle mbface, int& sense_out ) 00978 { 00979 00980 // this one is important, for establishing the orientation of the edges in faces 00981 // use senses 00982 std::vector< EntityHandle > faces; 00983 std::vector< int > senses; // 0 is forward and 1 is backward 00984 ErrorCode rval = _my_geomTopoTool->get_senses( mbedge, faces, senses ); 00985 if( MB_SUCCESS != rval ) return rval; 00986 00987 for( unsigned int i = 0; i < faces.size(); i++ ) 00988 { 00989 if( faces[i] == mbface ) 00990 { 00991 sense_out = senses[i]; 00992 return MB_SUCCESS; 00993 } 00994 } 00995 return MB_FAILURE; 00996 } 00997 // we assume the measures array was allocated correctly 00998 ErrorCode FBEngine::measure( const EntityHandle* moab_entities, int entities_size, double* measures ) 00999 { 01000 ErrorCode rval; 01001 for( int i = 0; i < entities_size; i++ ) 01002 { 01003 measures[i] = 0.; 01004 01005 int type; 01006 EntityHandle gset = moab_entities[i]; 01007 rval = getEntType( gset, &type ); 01008 if( MB_SUCCESS != rval ) return rval; 01009 if( type == 1 ) 01010 { // edge: get all edges part of the edge set 01011 Range entities; 01012 rval = MBI->get_entities_by_type( gset, MBEDGE, entities ); 01013 if( MB_SUCCESS != rval ) return rval; 01014 01015 for( Range::iterator it = entities.begin(); it != entities.end(); ++it ) 01016 { 01017 EntityHandle edge = *it; 01018 CartVect vv[2]; 01019 const EntityHandle* conn2 = NULL; 01020 int num_nodes; 01021 rval = MBI->get_connectivity( edge, conn2, num_nodes ); 01022 if( MB_SUCCESS != rval || num_nodes != 2 ) return MB_FAILURE; 01023 rval = MBI->get_coords( conn2, 2, (double*)&( vv[0][0] ) ); 01024 if( MB_SUCCESS != rval ) return rval; 01025 01026 vv[0] = vv[1] - vv[0]; 01027 measures[i] += vv[0].length(); 01028 } 01029 } 01030 if( type == 2 ) 01031 { // surface 01032 // get triangles in surface; TODO: quads! 01033 Range entities; 01034 rval = MBI->get_entities_by_type( gset, MBTRI, entities ); 01035 if( MB_SUCCESS != rval ) return rval; 01036 01037 for( Range::iterator it = entities.begin(); it != entities.end(); ++it ) 01038 { 01039 EntityHandle tri = *it; 01040 CartVect vv[3]; 01041 const EntityHandle* conn3 = NULL; 01042 int num_nodes; 01043 rval = MBI->get_connectivity( tri, conn3, num_nodes ); 01044 if( MB_SUCCESS != rval || num_nodes != 3 ) return MB_FAILURE; 01045 rval = MBI->get_coords( conn3, 3, (double*)&( vv[0][0] ) ); 01046 if( MB_SUCCESS != rval ) return rval; 01047 01048 vv[1] = vv[1] - vv[0]; 01049 vv[2] = vv[2] - vv[0]; 01050 vv[0] = vv[1] * vv[2]; 01051 measures[i] += vv[0].length() / 2; // area of triangle 01052 } 01053 } 01054 } 01055 return MB_SUCCESS; 01056 } 01057 01058 ErrorCode FBEngine::getEntNrmlSense( EntityHandle /*face*/, EntityHandle /*region*/, int& /*sense*/ ) 01059 { 01060 return MB_NOT_IMPLEMENTED; // not implemented 01061 } 01062 01063 ErrorCode FBEngine::getEgEvalXYZ( EntityHandle /*edge*/, 01064 double /*x*/, 01065 double /*y*/, 01066 double /*z*/, 01067 double& /*on_x*/, 01068 double& /*on_y*/, 01069 double& /*on_z*/, 01070 double& /*tngt_i*/, 01071 double& /*tngt_j*/, 01072 double& /*tngt_k*/, 01073 double& /*cvtr_i*/, 01074 double& /*cvtr_j*/, 01075 double& /*cvtr_k*/ ) 01076 { 01077 return MB_NOT_IMPLEMENTED; // not implemented 01078 } 01079 ErrorCode FBEngine::getFcEvalXYZ( EntityHandle /*face*/, 01080 double /*x*/, 01081 double /*y*/, 01082 double /*z*/, 01083 double& /*on_x*/, 01084 double& /*on_y*/, 01085 double& /*on_z*/, 01086 double& /*nrml_i*/, 01087 double& /*nrml_j*/, 01088 double& /*nrml_k*/, 01089 double& /*cvtr1_i*/, 01090 double& /*cvtr1_j*/, 01091 double& /*cvtr1_k*/, 01092 double& /*cvtr2_i*/, 01093 double& /*cvtr2_j*/, 01094 double& /*cvtr2_k*/ ) 01095 { 01096 return MB_NOT_IMPLEMENTED; // not implemented 01097 } 01098 01099 ErrorCode FBEngine::getEgVtxSense( EntityHandle edge, EntityHandle vtx1, EntityHandle vtx2, int& sense ) 01100 { 01101 // need to decide first or second vertex 01102 // important for moab 01103 int type; 01104 01105 EntityHandle v1, v2; 01106 ErrorCode rval = getEntType( vtx1, &type ); 01107 if( MB_SUCCESS != rval || type != 0 ) return MB_FAILURE; 01108 // edge: get one vertex as part of the vertex set 01109 Range entities; 01110 rval = MBI->get_entities_by_type( vtx1, MBVERTEX, entities ); 01111 if( MB_SUCCESS != rval ) return rval; 01112 if( entities.size() < 1 ) return MB_FAILURE; 01113 v1 = entities[0]; // the first vertex 01114 entities.clear(); 01115 rval = getEntType( vtx2, &type ); 01116 if( MB_SUCCESS != rval || type != 0 ) return MB_FAILURE; 01117 rval = MBI->get_entities_by_type( vtx2, MBVERTEX, entities ); 01118 if( MB_SUCCESS != rval ) return rval; 01119 if( entities.size() < 1 ) return MB_FAILURE; 01120 v2 = entities[0]; // the first vertex 01121 entities.clear(); 01122 // now get the edges, and get the first node and the last node in sequence of edges 01123 // the order is important... 01124 // these are ordered sets !! 01125 std::vector< EntityHandle > ents; 01126 rval = MBI->get_entities_by_type( edge, MBEDGE, ents ); 01127 if( MB_SUCCESS != rval ) return rval; 01128 if( ents.size() < 1 ) return MB_FAILURE; 01129 01130 const EntityHandle* conn = NULL; 01131 int len; 01132 EntityHandle startNode, endNode; 01133 rval = MBI->get_connectivity( ents[0], conn, len ); 01134 if( MB_SUCCESS != rval ) return rval; 01135 startNode = conn[0]; 01136 rval = MBI->get_connectivity( ents[ents.size() - 1], conn, len ); 01137 if( MB_SUCCESS != rval ) return rval; 01138 01139 endNode = conn[1]; 01140 sense = 1; // 01141 if( ( startNode == endNode ) && ( v1 == startNode ) ) 01142 { 01143 sense = 0; // periodic 01144 } 01145 if( ( startNode == v1 ) && ( endNode == v2 ) ) 01146 { 01147 sense = 1; // forward 01148 } 01149 if( ( startNode == v2 ) && ( endNode == v1 ) ) 01150 { 01151 sense = -1; // reverse 01152 } 01153 return MB_SUCCESS; 01154 } 01155 01156 ErrorCode FBEngine::getEntURange( EntityHandle edge, double& u_min, double& u_max ) 01157 { 01158 SmoothCurve* smoothCurve = _edges[edge]; // this is a map 01159 // now, call smoothCurve methods 01160 smoothCurve->get_param_range( u_min, u_max ); 01161 return MB_SUCCESS; 01162 } 01163 01164 ErrorCode FBEngine::getEntUtoXYZ( EntityHandle edge, double u, double& x, double& y, double& z ) 01165 { 01166 SmoothCurve* smoothCurve = _edges[edge]; // this is a map 01167 // now, call smoothCurve methods 01168 smoothCurve->position_from_u( u, x, y, z ); 01169 return MB_SUCCESS; 01170 } 01171 01172 ErrorCode FBEngine::getEntTgntU( EntityHandle edge, double u, double& i, double& j, double& k ) 01173 { 01174 SmoothCurve* smoothCurve = _edges[edge]; // this is a map 01175 // now, call smoothCurve methods 01176 double tg[3]; 01177 double x, y, z; 01178 smoothCurve->position_from_u( u, x, y, z, tg ); 01179 i = tg[0]; 01180 j = tg[1]; 01181 k = tg[2]; 01182 return MB_SUCCESS; 01183 } 01184 ErrorCode FBEngine::isEntAdj( EntityHandle entity1, EntityHandle entity2, bool& adjacent_out ) 01185 { 01186 int type1, type2; 01187 ErrorCode rval = getEntType( entity1, &type1 ); 01188 if( MB_SUCCESS != rval ) return rval; 01189 rval = getEntType( entity2, &type2 ); 01190 if( MB_SUCCESS != rval ) return rval; 01191 01192 Range adjs; 01193 if( type1 < type2 ) 01194 { 01195 rval = MBI->get_parent_meshsets( entity1, adjs, type2 - type1 ); 01196 if( MB_SUCCESS != rval ) return rval; // MBERRORR("Failed to get parent meshsets in iGeom_isEntAdj."); 01197 } 01198 else 01199 { 01200 // note: if they ave the same type, they will not be adjacent, in our definition 01201 rval = MBI->get_child_meshsets( entity1, adjs, type1 - type2 ); 01202 if( MB_SUCCESS != rval ) return rval; // MBERRORR("Failed to get child meshsets in iGeom_isEntAdj."); 01203 } 01204 01205 // adjacent_out = adjs.find(entity2) != _my_gsets[type2].end(); 01206 // hmmm, possible bug here; is this called? 01207 adjacent_out = adjs.find( entity2 ) != adjs.end(); 01208 01209 return MB_SUCCESS; 01210 } 01211 01212 ErrorCode FBEngine::split_surface_with_direction( EntityHandle face, 01213 std::vector< double >& xyz, 01214 double* direction, 01215 int closed, 01216 double min_dot, 01217 EntityHandle& oNewFace ) 01218 { 01219 01220 // first of all, find all intersection points (piercing in the face along the direction) 01221 // assume it is robust; what if it is not sufficiently robust? 01222 // if the polyline is open, find the intersection with the boundary edges, of the 01223 // polyline extruded at ends 01224 01225 ErrorCode rval; 01226 01227 // then find the position 01228 int numIniPoints = (int)xyz.size() / 3; 01229 if( ( closed && numIniPoints < 3 ) || ( !closed && numIniPoints < 2 ) ) 01230 MBERRORR( MB_FAILURE, "not enough polyline points " ); 01231 EntityHandle rootForFace; 01232 01233 rval = _my_geomTopoTool->get_root( face, rootForFace ); 01234 MBERRORR( rval, "Failed to get root of face." ); 01235 01236 const double dir[] = { direction[0], direction[1], direction[2] }; 01237 std::vector< EntityHandle > nodes; // get the nodes closest to the ray traces of interest 01238 01239 // these are nodes on the boundary of original face; 01240 // if the cutting line is not closed, the starting - ending vertices of the 01241 // polygonal line must come from this list 01242 01243 std::vector< CartVect > b_pos; 01244 std::vector< EntityHandle > boundary_nodes; 01245 std::vector< EntityHandle > splittingNodes; 01246 Range boundary_mesh_edges; 01247 if( !closed ) 01248 { 01249 rval = boundary_nodes_on_face( face, boundary_nodes ); 01250 MBERRORR( rval, "Failed to get boundary nodes." ); 01251 b_pos.resize( boundary_nodes.size() ); 01252 rval = _mbImpl->get_coords( &( boundary_nodes[0] ), boundary_nodes.size(), (double*)( &b_pos[0][0] ) ); 01253 MBERRORR( rval, "Failed to get coordinates for boundary nodes." ); 01254 rval = boundary_mesh_edges_on_face( face, boundary_mesh_edges ); 01255 MBERRORR( rval, "Failed to get mesh boundary edges for face." ); 01256 } 01257 // 01258 int i = 0; 01259 CartVect dirct( direction ); 01260 dirct.normalize(); // maybe an overkill? 01261 for( ; i < numIniPoints; i++ ) 01262 { 01263 01264 const double point[] = { xyz[3 * i], xyz[3 * i + 1], xyz[3 * i + 2] }; // or even point( &(xyz[3*i]) ); // 01265 CartVect p1( point ); 01266 if( !closed && ( ( 0 == i ) || ( numIniPoints - 1 == i ) ) ) 01267 { 01268 01269 // find the intersection point between a plane and boundary mesh edges 01270 // this will be the closest point on the boundary of face 01271 /// the segment is the first or last segment in the polyline 01272 int i1 = i + 1; 01273 if( i == numIniPoints - 1 ) i1 = i - 1; // previous point if the last 01274 // the direction is from point to point1 01275 const double point1[] = { xyz[3 * i1], xyz[3 * i1 + 1], xyz[3 * i1 + 2] }; 01276 CartVect p2( point1 ); 01277 CartVect normPlane = ( p2 - p1 ) * dirct; 01278 normPlane.normalize(); 01279 //(roughly, from p1 to p2, perpendicular to dirct, in the "xy" plane 01280 // if the intx point is "outside" p1 - p2, skip if the intx point is closer to p2 01281 CartVect perpDir = dirct * normPlane; 01282 Range::iterator ite = boundary_mesh_edges.begin(); 01283 // do a linear search for the best intersection point position (on a boundary edge) 01284 if( debug_splits ) 01285 { 01286 std::cout << " p1:" << p1 << "\n"; 01287 std::cout << " p2:" << p2 << "\n"; 01288 std::cout << " perpDir:" << perpDir << "\n"; 01289 std::cout << " boundary edges size:" << boundary_mesh_edges.size() << "\n"; 01290 } 01291 for( ; ite != boundary_mesh_edges.end(); ++ite ) 01292 { 01293 EntityHandle candidateEdge = *ite; 01294 const EntityHandle* conn2; 01295 int nno; 01296 rval = _mbImpl->get_connectivity( candidateEdge, conn2, nno ); 01297 MBERRORR( rval, "Failed to get conn for boundary edge" ); 01298 CartVect pts[2]; 01299 rval = _mbImpl->get_coords( conn2, 2, &( pts[0][0] ) ); 01300 MBERRORR( rval, "Failed to get coords of nodes for boundary edge" ); 01301 CartVect intx_point; 01302 double parPos; 01303 bool intersect = 01304 intersect_segment_and_plane_slice( pts[0], pts[1], p1, p2, dirct, normPlane, intx_point, parPos ); 01305 if( debug_splits ) 01306 { 01307 std::cout << " Edge:" << _mbImpl->id_from_handle( candidateEdge ) << "\n"; 01308 std::cout << " Node 1:" << _mbImpl->id_from_handle( conn2[0] ) << pts[0] << "\n"; 01309 std::cout << " Node 2:" << _mbImpl->id_from_handle( conn2[1] ) << pts[1] << "\n"; 01310 std::cout << " Intersect bool:" << intersect << "\n"; 01311 } 01312 if( intersect ) 01313 { 01314 double proj1 = ( intx_point - p1 ) % perpDir; 01315 double proj2 = ( intx_point - p2 ) % perpDir; 01316 if( ( fabs( proj1 ) > fabs( proj2 ) ) // this means it is closer to p2 than p1 01317 ) 01318 continue; // basically, this means the intersection point is with a 01319 // boundary edge on the other side, closer to p2 than p1, so we 01320 // skip it 01321 if( parPos == 0 ) 01322 { 01323 // close to vertex 1, nothing to do 01324 nodes.push_back( conn2[0] ); 01325 splittingNodes.push_back( conn2[0] ); 01326 } 01327 else if( parPos == 1. ) 01328 { 01329 // close to vertex 2, nothing to do 01330 nodes.push_back( conn2[1] ); 01331 splittingNodes.push_back( conn2[1] ); 01332 } 01333 else 01334 { 01335 // break the edge, create a new node at intersection point (will be smoothed 01336 // out) 01337 EntityHandle newVertex; 01338 rval = _mbImpl->create_vertex( &( intx_point[0] ), newVertex ); 01339 MBERRORR( rval, "can't create vertex" ); 01340 nodes.push_back( newVertex ); 01341 split_internal_edge( candidateEdge, newVertex ); 01342 splittingNodes.push_back( newVertex ); 01343 _brokenEdges[newVertex] = candidateEdge; 01344 _piercedEdges.insert( candidateEdge ); 01345 } 01346 break; // break from the loop over boundary edges, we are interested in the 01347 // first 01348 // split (hopefully, the only split) 01349 } 01350 } 01351 if( ite == boundary_mesh_edges.end() ) 01352 MBERRORR( MB_FAILURE, "Failed to find boundary intersection edge. Bail out" ); 01353 } 01354 else 01355 { 01356 std::vector< double > distances_out; 01357 std::vector< EntityHandle > sets_out; 01358 std::vector< EntityHandle > facets_out; 01359 rval = _my_geomTopoTool->obb_tree()->ray_intersect_sets( distances_out, sets_out, facets_out, rootForFace, 01360 tolerance, point, dir ); 01361 MBERRORR( rval, "Failed to get ray intersections." ); 01362 if( distances_out.size() < 1 ) 01363 MBERRORR( MB_FAILURE, "Failed to get one intersection point, bad direction." ); 01364 01365 if( distances_out.size() > 1 ) 01366 { 01367 std::cout << " too many intersection points. Only the first one considered\n"; 01368 } 01369 std::vector< EntityHandle >::iterator pFace = std::find( sets_out.begin(), sets_out.end(), face ); 01370 01371 if( pFace == sets_out.end() ) MBERRORR( MB_FAILURE, "Failed to intersect given face, bad direction." ); 01372 unsigned int index = pFace - sets_out.begin(); 01373 // get the closest node of the triangle, and modify locally the triangle(s), so the 01374 // intersection point is at a new vertex, if needed 01375 CartVect P( point ); 01376 CartVect Dir( dir ); 01377 CartVect newPoint = P + distances_out[index] * Dir; 01378 // get the triangle coordinates 01379 01380 double area_coord[3]; 01381 EntityHandle boundary_handle = 0; // if 0, not on a boundary 01382 rval = area_coordinates( _mbImpl, facets_out[index], newPoint, area_coord, boundary_handle ); 01383 MBERRORR( rval, "Failed to get area coordinates" ); 01384 01385 if( debug_splits ) 01386 { 01387 std::cout << " int point:" << newPoint << " area coord " << area_coord[0] << " " << area_coord[1] << " " 01388 << area_coord[2] << "\n"; 01389 std::cout << " triangle: " << _mbImpl->id_from_handle( facets_out[index] ) 01390 << " boundary:" << boundary_handle << "\n"; 01391 } 01392 EntityType type; 01393 if( boundary_handle ) type = _mbImpl->type_from_handle( boundary_handle ); 01394 if( boundary_handle && ( type == MBVERTEX ) ) 01395 { 01396 // nothing to do, we are happy 01397 nodes.push_back( boundary_handle ); 01398 } 01399 else 01400 { 01401 // for an edge, we will split 2 triangles 01402 // for interior point, we will create 3 triangles out of one 01403 // create a new vertex 01404 EntityHandle newVertex; 01405 rval = _mbImpl->create_vertex( &( newPoint[0] ), newVertex ); 01406 if( boundary_handle ) // this is edge 01407 { 01408 split_internal_edge( boundary_handle, newVertex ); 01409 _piercedEdges.insert( boundary_handle ); // to be removed at the end 01410 } 01411 else 01412 divide_triangle( facets_out[index], newVertex ); 01413 01414 nodes.push_back( newVertex ); 01415 } 01416 } 01417 } 01418 // now, we have to find more intersection points, either interior to triangles, or on edges, or 01419 // on vertices use the same tolerance as before starting from 2 points on 2 triangles, and 01420 // having the direction, get more intersection points between the plane formed by direction and 01421 // those 2 points, and edges from triangulation (the triangles involved will be part of the same 01422 // gentity , original face ( moab set) 01423 // int closed = 1;// closed = 0 if the polyline is not closed 01424 01425 CartVect Dir( direction ); 01426 std::vector< EntityHandle > chainedEdges; 01427 01428 for( i = 0; i < numIniPoints - 1 + closed; i++ ) 01429 { 01430 int nextIndex = ( i + 1 ) % numIniPoints; 01431 std::vector< EntityHandle > trianglesAlong; 01432 std::vector< CartVect > points; 01433 // otherwise to edges or even nodes 01434 std::vector< EntityHandle > entities; 01435 // start with initial points, intersect along the direction, find the facets 01436 rval = compute_intersection_points( face, nodes[i], nodes[nextIndex], Dir, points, entities, trianglesAlong ); 01437 MBERRORR( rval, "can't get intersection points along a line" ); 01438 std::vector< EntityHandle > nodesAlongPolyline; 01439 // refactor code; move some edge creation for each 2 intersection points 01440 nodesAlongPolyline.push_back( entities[0] ); // it is for sure a node 01441 int num_points = (int)points.size(); // it should be num_triangles + 1 01442 for( int j = 0; j < num_points - 1; j++ ) 01443 { 01444 EntityHandle tri = trianglesAlong[j]; // this is happening in trianglesAlong i 01445 EntityHandle e1 = entities[j]; 01446 EntityHandle e2 = entities[j + 1]; 01447 EntityType et1 = _mbImpl->type_from_handle( e1 ); 01448 // EntityHandle vertex1 = nodesAlongPolyline[i];// irrespective of the entity type i, 01449 // we already have the vertex there 01450 EntityType et2 = _mbImpl->type_from_handle( e2 ); 01451 if( et2 == MBVERTEX ) 01452 { 01453 nodesAlongPolyline.push_back( e2 ); 01454 } 01455 else // if (et2==MBEDGE) 01456 { 01457 CartVect coord_vert = points[j + 1]; 01458 EntityHandle newVertex; 01459 rval = _mbImpl->create_vertex( (double*)&coord_vert, newVertex ); 01460 MBERRORR( rval, "can't create vertex" ); 01461 nodesAlongPolyline.push_back( newVertex ); 01462 } 01463 // if vertices, do not split anything, just get the edge for polyline 01464 if( et2 == MBVERTEX && et1 == MBVERTEX ) 01465 { 01466 // nothing to do, just continue; 01467 continue; // continue the for loop 01468 } 01469 01470 if( debug_splits ) 01471 { 01472 std::cout << "tri: type: " << _mbImpl->type_from_handle( tri ) 01473 << " id:" << _mbImpl->id_from_handle( tri ) << "\n e1:" << e1 01474 << " id:" << _mbImpl->id_from_handle( e1 ) << " e2:" << e2 01475 << " id:" << _mbImpl->id_from_handle( e2 ) << "\n"; 01476 } 01477 // here, at least one is an edge 01478 rval = BreakTriangle2( tri, e1, e2, nodesAlongPolyline[j], nodesAlongPolyline[j + 1] ); 01479 MBERRORR( rval, "can't break triangle 2" ); 01480 if( et2 == MBEDGE ) _piercedEdges.insert( e2 ); 01481 _piercedTriangles.insert( tri ); 01482 } 01483 // nodesAlongPolyline will define a new geometric edge 01484 if( debug_splits ) 01485 { 01486 std::cout << "nodesAlongPolyline: " << nodesAlongPolyline.size() << "\n"; 01487 std::cout << "points: " << num_points << "\n"; 01488 } 01489 // if needed, create edges along polyline, or revert the existing ones, to 01490 // put them in a new edge set 01491 EntityHandle new_geo_edge; 01492 rval = create_new_gedge( nodesAlongPolyline, new_geo_edge ); 01493 MBERRORR( rval, "can't create a new edge" ); 01494 chainedEdges.push_back( new_geo_edge ); 01495 // end copy 01496 } 01497 // the segment between point_i and point_i+1 is in trianglesAlong_i 01498 // points_i is on entities_i 01499 // all these edges are oriented correctly 01500 rval = split_surface( face, chainedEdges, splittingNodes, oNewFace ); 01501 MBERRORR( rval, "can't split surface" ); 01502 // 01503 rval = chain_edges( min_dot ); // acos(0.8)~= 36 degrees 01504 MBERRORR( rval, "can't chain edges" ); 01505 return MB_SUCCESS; 01506 } 01507 /** 01508 * this method splits along the polyline defined by points and entities 01509 * the polyline will be defined with 01510 * // the entities are now only nodes and edges, no triangles!!! 01511 * the first and last ones are also nodes for sure 01512 */ 01513 ErrorCode FBEngine::split_surface( EntityHandle face, 01514 std::vector< EntityHandle >& chainedEdges, 01515 std::vector< EntityHandle >& splittingNodes, 01516 EntityHandle& newFace ) 01517 { 01518 // use now the chained edges to create a new face (loop or clean split) 01519 // use a fill to determine the new sets, up to the polyline 01520 // points on the polyline will be moved to the closest point location, with some constraints 01521 // then the sets will be reset, geometry recomputed. new vertices, new edges, etc. 01522 01523 Range iniTris; 01524 ErrorCode rval; 01525 rval = _mbImpl->get_entities_by_type( face, MBTRI, iniTris ); 01526 MBERRORR( rval, "can't get initial triangles" ); 01527 01528 // start from a triangle that is not in the triangles to delete 01529 // flood fill 01530 01531 bool closed = splittingNodes.size() == 0; 01532 if( !closed ) 01533 { 01534 // 01535 if( splittingNodes.size() != 2 ) MBERRORR( MB_FAILURE, "need to have exactly 2 nodes for splitting" ); 01536 // we will have to split the boundary edges 01537 // first, find the actual boundary, and try to split with the 2 end points (nodes) 01538 // get the adjacent edges, and see which one has the end nodes 01539 rval = split_boundary( face, splittingNodes[0] ); 01540 MBERRORR( rval, "can't split with first node" ); 01541 rval = split_boundary( face, splittingNodes[1] ); 01542 MBERRORR( rval, "can't split with second node)" ); 01543 } 01544 // we will separate triangles to delete, unaffected, new_triangles, 01545 // nodesAlongPolyline, 01546 Range first, second; 01547 rval = separate( face, chainedEdges, first, second ); 01548 01549 // now, we are done with the computations; 01550 // we need to put the new nodes on the smooth surface 01551 if( this->_smooth ) 01552 { 01553 rval = smooth_new_intx_points( face, chainedEdges ); 01554 MBERRORR( rval, "can't smooth new points" ); 01555 } 01556 01557 // create the new set 01558 rval = _mbImpl->create_meshset( MESHSET_SET, newFace ); 01559 MBERRORR( rval, "can't create a new face" ); 01560 01561 _my_geomTopoTool->add_geo_set( newFace, 2 ); 01562 01563 // the new face will have the first set (positive sense triangles, to the left) 01564 rval = _mbImpl->add_entities( newFace, first ); 01565 MBERRORR( rval, "can't add first range triangles to new face" ); 01566 01567 for( unsigned int j = 0; j < chainedEdges.size(); j++ ) 01568 { 01569 EntityHandle new_geo_edge = chainedEdges[j]; 01570 // both faces will have the edge now 01571 rval = _mbImpl->add_parent_child( face, new_geo_edge ); 01572 MBERRORR( rval, "can't add parent child relations for new edge" ); 01573 01574 rval = _mbImpl->add_parent_child( newFace, new_geo_edge ); 01575 MBERRORR( rval, "can't add parent child relations for new edge" ); 01576 // add senses 01577 // sense newFace is 1, old face is -1 01578 rval = _my_geomTopoTool->set_sense( new_geo_edge, newFace, 1 ); 01579 MBERRORR( rval, "can't set sense for new edge" ); 01580 01581 rval = _my_geomTopoTool->set_sense( new_geo_edge, face, -1 ); 01582 MBERRORR( rval, "can't set sense for new edge in original face" ); 01583 } 01584 01585 rval = set_neumann_tags( face, newFace ); 01586 MBERRORR( rval, "can't set NEUMANN set tags" ); 01587 01588 // now, we should remove from the original set all tris, and put the "second" range 01589 rval = _mbImpl->remove_entities( face, iniTris ); 01590 MBERRORR( rval, "can't remove original tris from initial face set" ); 01591 01592 rval = _mbImpl->add_entities( face, second ); 01593 MBERRORR( rval, "can't add second range to the original set" ); 01594 01595 if( !closed ) 01596 { 01597 rval = redistribute_boundary_edges_to_faces( face, newFace, chainedEdges ); 01598 MBERRORR( rval, "fail to reset the proper boundary faces" ); 01599 } 01600 01601 /*if (_smooth) 01602 delete_smooth_tags();// they need to be recomputed, anyway 01603 // this will remove the extra smooth faces and edges 01604 clean();*/ 01605 // also, these nodes need to be moved to the smooth surface, sometimes before deleting the old 01606 // triangles 01607 // remove the triangles from the set, then delete triangles (also some edges need to be 01608 // deleted!) 01609 rval = _mbImpl->delete_entities( _piercedTriangles ); 01610 01611 MBERRORR( rval, "can't delete triangles" ); 01612 _piercedTriangles.clear(); 01613 // delete edges that are broke up in 2 01614 rval = _mbImpl->delete_entities( _piercedEdges ); 01615 MBERRORR( rval, "can't delete edges" ); 01616 _piercedEdges.clear(); 01617 01618 if( debug_splits ) 01619 { 01620 _mbImpl->write_file( "newFace.vtk", "vtk", 0, &newFace, 1 ); 01621 _mbImpl->write_file( "leftoverFace.vtk", "vtk", 0, &face, 1 ); 01622 } 01623 return MB_SUCCESS; 01624 } 01625 01626 ErrorCode FBEngine::smooth_new_intx_points( EntityHandle face, std::vector< EntityHandle >& chainedEdges ) 01627 { 01628 01629 // do not move nodes from the original face 01630 // first get all triangles, and then all nodes from those triangles 01631 01632 Range tris; 01633 ErrorCode rval = _mbImpl->get_entities_by_type( face, MBTRI, tris ); 01634 MBERRORR( rval, "can't get triangles" ); 01635 01636 Range ini_nodes; 01637 rval = _mbImpl->get_connectivity( tris, ini_nodes ); 01638 MBERRORR( rval, "can't get connectivities" ); 01639 01640 SmoothFace* smthFace = _faces[face]; 01641 01642 // get all nodes from chained edges 01643 Range mesh_edges; 01644 for( unsigned int j = 0; j < chainedEdges.size(); j++ ) 01645 { 01646 // keep adding to the range of mesh edges 01647 rval = _mbImpl->get_entities_by_dimension( chainedEdges[j], 1, mesh_edges ); 01648 MBERRORR( rval, "can't get mesh edges" ); 01649 } 01650 // nodes along polyline 01651 Range nodes_on_polyline; 01652 rval = _mbImpl->get_connectivity( mesh_edges, nodes_on_polyline, true ); // corners only 01653 MBERRORR( rval, "can't get nodes on the polyline" ); 01654 01655 Range new_intx_nodes = subtract( nodes_on_polyline, ini_nodes ); 01656 01657 std::vector< double > ini_coords; 01658 int num_points = (int)new_intx_nodes.size(); 01659 ini_coords.resize( 3 * num_points ); 01660 rval = _mbImpl->get_coords( new_intx_nodes, &( ini_coords[0] ) ); 01661 MBERRORR( rval, "can't get coordinates" ); 01662 01663 int i = 0; 01664 for( Range::iterator it = new_intx_nodes.begin(); it != new_intx_nodes.end(); ++it ) 01665 { 01666 /*EntityHandle node = *it;*/ 01667 int i3 = 3 * i; 01668 smthFace->move_to_surface( ini_coords[i3], ini_coords[i3 + 1], ini_coords[i3 + 2] ); 01669 // reset the coordinates of this node 01670 ++i; 01671 } 01672 rval = _mbImpl->set_coords( new_intx_nodes, &( ini_coords[0] ) ); 01673 MBERRORR( rval, "can't set smoothed coordinates for the new nodes" ); 01674 01675 return MB_SUCCESS; 01676 } 01677 // we will use the fact that the splitting edge is oriented right now 01678 // to the left will be new face, to the right, old face 01679 // (to the left, positively oriented triangles) 01680 ErrorCode FBEngine::separate( EntityHandle face, 01681 std::vector< EntityHandle >& chainedEdges, 01682 Range& first, 01683 Range& second ) 01684 { 01685 // Range unaffectedTriangles = subtract(iniTriangles, _piercedTriangles); 01686 // insert in each 01687 // start with a new triangle, and flood to get the first range; what is left is the 01688 // second range 01689 // flood fill is considering edges adjacent to seed triangles; if there is 01690 // an edge in the new_geo_edge, it is skipped; triangles in the 01691 // triangles to delete are not added 01692 // first, create all edges of the new triangles 01693 01694 // 01695 // new face will have the new edge oriented positively 01696 // get mesh edges from geo edge (splitting gedge); 01697 01698 Range mesh_edges; 01699 ErrorCode rval; 01700 // mesh_edges 01701 for( unsigned int j = 0; j < chainedEdges.size(); j++ ) 01702 { 01703 // this will keep adding edges to the mesh_edges range 01704 // when we get out, the mesh_edges will be in this range, but not ordered 01705 rval = _mbImpl->get_entities_by_type( chainedEdges[j], MBEDGE, mesh_edges ); 01706 MBERRORR( rval, "can't get new polyline edges" ); 01707 if( debug_splits ) 01708 { 01709 std::cout << " At chained edge " << j << " " << _mbImpl->id_from_handle( chainedEdges[j] ) 01710 << " mesh_edges Range size:" << mesh_edges.size() << "\n"; 01711 } 01712 } 01713 01714 // get a positive triangle adjacent to mesh_edge[0] 01715 // add to first triangles to the left, second triangles to the right of the mesh_edges ; 01716 01717 // create a temp tag, and when done, delete it 01718 // default value: 0 01719 // 3 to be deleted, pierced 01720 // 1 first set 01721 // 2 second set 01722 // create the tag also for control points on the edges 01723 int defVal = 0; 01724 Tag separateTag; 01725 rval = MBI->tag_get_handle( "SEPARATE_TAG", 1, MB_TYPE_INTEGER, separateTag, MB_TAG_DENSE | MB_TAG_CREAT, &defVal ); 01726 MBERRORR( rval, "can't create temp tag for separation" ); 01727 // the deleted triangles will get a value 3, from start 01728 int delVal = 3; 01729 for( Range::iterator it1 = this->_piercedTriangles.begin(); it1 != _piercedTriangles.end(); ++it1 ) 01730 { 01731 EntityHandle trToDelete = *it1; 01732 rval = _mbImpl->tag_set_data( separateTag, &trToDelete, 1, &delVal ); 01733 MBERRORR( rval, "can't set delete tag value" ); 01734 } 01735 01736 // find a triangle that will be in the first range, positively oriented about the splitting edge 01737 EntityHandle seed1 = 0; 01738 for( Range::iterator it = mesh_edges.begin(); it != mesh_edges.end() && !seed1; ++it ) 01739 { 01740 EntityHandle meshEdge = *it; 01741 Range adj_tri; 01742 rval = _mbImpl->get_adjacencies( &meshEdge, 1, 2, false, adj_tri ); 01743 MBERRORR( rval, "can't get adj_tris to mesh edge" ); 01744 01745 for( Range::iterator it2 = adj_tri.begin(); it2 != adj_tri.end(); ++it2 ) 01746 { 01747 EntityHandle tr = *it2; 01748 if( _piercedTriangles.find( tr ) != _piercedTriangles.end() ) 01749 continue; // do not attach pierced triangles, they are not good 01750 int num1, sense, offset; 01751 rval = _mbImpl->side_number( tr, meshEdge, num1, sense, offset ); 01752 MBERRORR( rval, "edge not adjacent" ); 01753 if( sense == 1 ) 01754 { 01755 // firstSet.insert(tr); 01756 if( !seed1 ) 01757 { 01758 seed1 = tr; 01759 break; 01760 } 01761 } 01762 } 01763 } 01764 01765 // flood fill first set, the rest will be in second set 01766 // the edges from new_geo_edge will not be crossed 01767 01768 // get edges of face (adjacencies) 01769 // also get the old boundary edges, from face; they will be edges to not cross, too 01770 Range bound_edges; 01771 rval = getAdjacentEntities( face, 1, bound_edges ); 01772 MBERRORR( rval, "can't get boundary edges" ); 01773 01774 // add to the do not cross edges range, all edges from initial boundary 01775 Range initialBoundaryEdges; 01776 for( Range::iterator it = bound_edges.begin(); it != bound_edges.end(); ++it ) 01777 { 01778 EntityHandle bound_edge = *it; 01779 rval = _mbImpl->get_entities_by_dimension( bound_edge, 1, initialBoundaryEdges ); 01780 } 01781 01782 Range doNotCrossEdges = unite( initialBoundaryEdges, mesh_edges ); // add the splitting edges ! 01783 01784 // use a second method, with tags 01785 // 01786 std::queue< EntityHandle > queue1; 01787 queue1.push( seed1 ); 01788 std::vector< EntityHandle > arr1; 01789 while( !queue1.empty() ) 01790 { 01791 // start copy 01792 EntityHandle currentTriangle = queue1.front(); 01793 queue1.pop(); 01794 arr1.push_back( currentTriangle ); 01795 // add new triangles that share an edge 01796 Range currentEdges; 01797 rval = _mbImpl->get_adjacencies( ¤tTriangle, 1, 1, true, currentEdges, Interface::UNION ); 01798 MBERRORR( rval, "can't get adjacencies" ); 01799 for( Range::iterator it = currentEdges.begin(); it != currentEdges.end(); ++it ) 01800 { 01801 EntityHandle frontEdge = *it; 01802 if( doNotCrossEdges.find( frontEdge ) == doNotCrossEdges.end() ) 01803 { 01804 // this is an edge that can be crossed 01805 Range adj_tri; 01806 rval = _mbImpl->get_adjacencies( &frontEdge, 1, 2, false, adj_tri, Interface::UNION ); 01807 MBERRORR( rval, "can't get adj_tris" ); 01808 // if the triangle is not in first range, add it to the queue 01809 for( Range::iterator it2 = adj_tri.begin(); it2 != adj_tri.end(); ++it2 ) 01810 { 01811 EntityHandle tri2 = *it2; 01812 int val = 0; 01813 rval = _mbImpl->tag_get_data( separateTag, &tri2, 1, &val ); 01814 MBERRORR( rval, "can't get tag value" ); 01815 if( val ) continue; 01816 // else, set it to 1 01817 val = 1; 01818 rval = _mbImpl->tag_set_data( separateTag, &tri2, 1, &val ); 01819 MBERRORR( rval, "can't get tag value" ); 01820 01821 queue1.push( tri2 ); 01822 } 01823 } // end edge do not cross 01824 } // end while 01825 } 01826 01827 std::sort( arr1.begin(), arr1.end() ); 01828 // Range first1; 01829 std::copy( arr1.rbegin(), arr1.rend(), range_inserter( first ) ); 01830 01831 // std::cout<< "\n first1.size() " << first1.size() << " first.size(): " << first.size() << 01832 // "\n"; 01833 if( debug_splits ) 01834 { 01835 EntityHandle tmpSet; 01836 _mbImpl->create_meshset( MESHSET_SET, tmpSet ); 01837 _mbImpl->add_entities( tmpSet, first ); 01838 _mbImpl->write_file( "dbg1.vtk", "vtk", 0, &tmpSet, 1 ); 01839 } 01840 // now, decide the set 2: 01841 // first, get all ini tris 01842 Range initr; 01843 rval = _mbImpl->get_entities_by_type( face, MBTRI, initr ); 01844 MBERRORR( rval, "can't get tris " ); 01845 second = unite( initr, _newTriangles ); 01846 Range second2 = subtract( second, _piercedTriangles ); 01847 second = subtract( second2, first ); 01848 _newTriangles.clear(); 01849 if( debug_splits ) 01850 { 01851 std::cout << "\n second.size() " << second.size() << " first.size(): " << first.size() << "\n"; 01852 // debugging code 01853 EntityHandle tmpSet2; 01854 _mbImpl->create_meshset( MESHSET_SET, tmpSet2 ); 01855 _mbImpl->add_entities( tmpSet2, second ); 01856 _mbImpl->write_file( "dbg2.vtk", "vtk", 0, &tmpSet2, 1 ); 01857 } 01858 /*Range intex = intersect(first, second); 01859 if (!intex.empty() && debug_splits) 01860 { 01861 std::cout << "error, the sets should be disjoint\n"; 01862 for (Range::iterator it1=intex.begin(); it1!=intex.end(); ++it1) 01863 { 01864 std::cout<<_mbImpl->id_from_handle(*it1) << "\n"; 01865 } 01866 }*/ 01867 rval = _mbImpl->tag_delete( separateTag ); 01868 MBERRORR( rval, "can't delete tag " ); 01869 return MB_SUCCESS; 01870 } 01871 // if there is an edge between 2 nodes, then check it's orientation, and revert it if needed 01872 ErrorCode FBEngine::create_new_gedge( std::vector< EntityHandle >& nodesAlongPolyline, EntityHandle& new_geo_edge ) 01873 { 01874 01875 ErrorCode rval = _mbImpl->create_meshset( MESHSET_ORDERED, new_geo_edge ); 01876 MBERRORR( rval, "can't create geo edge" ); 01877 01878 // now, get the edges, or create if not existing 01879 std::vector< EntityHandle > mesh_edges; 01880 for( unsigned int i = 0; i < nodesAlongPolyline.size() - 1; i++ ) 01881 { 01882 EntityHandle n1 = nodesAlongPolyline[i], n2 = nodesAlongPolyline[i + 1]; 01883 01884 EntityHandle nn2[2]; 01885 nn2[0] = n1; 01886 nn2[1] = n2; 01887 01888 std::vector< EntityHandle > adjacent; 01889 rval = _mbImpl->get_adjacencies( nn2, 2, 1, false, adjacent, Interface::INTERSECT ); 01890 // see if there is an edge between those 2 already, and if it is oriented as we like 01891 bool new_edge = true; 01892 if( adjacent.size() >= 1 ) 01893 { 01894 // check the orientation 01895 const EntityHandle* conn2 = NULL; 01896 int nnodes = 0; 01897 rval = _mbImpl->get_connectivity( adjacent[0], conn2, nnodes ); 01898 MBERRORR( rval, "can't get connectivity" ); 01899 if( conn2[0] == nn2[0] && conn2[1] == nn2[1] ) 01900 { 01901 // everything is fine 01902 mesh_edges.push_back( adjacent[0] ); 01903 new_edge = false; // we found one that's good, no need to create a new one 01904 } 01905 else 01906 { 01907 _piercedEdges.insert( adjacent[0] ); // we want to remove this one, it will be not needed 01908 } 01909 } 01910 if( new_edge ) 01911 { 01912 // there is no edge between n1 and n2, create one 01913 EntityHandle mesh_edge; 01914 rval = _mbImpl->create_element( MBEDGE, nn2, 2, mesh_edge ); 01915 MBERRORR( rval, "Failed to create a new edge" ); 01916 mesh_edges.push_back( mesh_edge ); 01917 } 01918 } 01919 01920 // add loops edges to the edge set 01921 rval = _mbImpl->add_entities( new_geo_edge, &mesh_edges[0], 01922 mesh_edges.size() ); // only one edge 01923 MBERRORR( rval, "can't add edges to new_geo_set" ); 01924 // check vertex sets for vertex 1 and vertex 2? 01925 // get all sets of dimension 0 from database, and see if our ends are here or not 01926 01927 Range ends_geo_edge; 01928 ends_geo_edge.insert( nodesAlongPolyline[0] ); 01929 ends_geo_edge.insert( nodesAlongPolyline[nodesAlongPolyline.size() - 1] ); 01930 01931 for( unsigned int k = 0; k < ends_geo_edge.size(); k++ ) 01932 { 01933 EntityHandle node = ends_geo_edge[k]; 01934 EntityHandle nodeSet; 01935 bool found = find_vertex_set_for_node( node, nodeSet ); 01936 01937 if( !found ) 01938 { 01939 // create a node set and add the node 01940 01941 rval = _mbImpl->create_meshset( MESHSET_SET, nodeSet ); 01942 MBERRORR( rval, "Failed to create a new vertex set" ); 01943 01944 rval = _mbImpl->add_entities( nodeSet, &node, 1 ); 01945 MBERRORR( rval, "Failed to add the node to the set" ); 01946 01947 rval = _my_geomTopoTool->add_geo_set( nodeSet, 0 ); // 01948 MBERRORR( rval, "Failed to commit the node set" ); 01949 01950 if( debug_splits ) 01951 { 01952 std::cout << " create a vertex set " << _mbImpl->id_from_handle( nodeSet ) 01953 << " global id:" << this->_my_geomTopoTool->global_id( nodeSet ) << " for node " << node 01954 << "\n"; 01955 } 01956 } 01957 01958 rval = _mbImpl->add_parent_child( new_geo_edge, nodeSet ); 01959 MBERRORR( rval, "Failed to add parent child relation" ); 01960 } 01961 // finally, put the edge in the range of edges 01962 rval = _my_geomTopoTool->add_geo_set( new_geo_edge, 1 );MB_CHK_ERR( rval ); 01963 01964 return rval; 01965 } 01966 01967 void FBEngine::print_debug_triangle( EntityHandle t ) 01968 { 01969 std::cout << " triangle id:" << _mbImpl->id_from_handle( t ) << "\n"; 01970 const EntityHandle* conn3 = NULL; 01971 int nnodes = 0; 01972 _mbImpl->get_connectivity( t, conn3, nnodes ); 01973 // get coords 01974 CartVect P[3]; 01975 _mbImpl->get_coords( conn3, 3, (double*)&P[0] ); 01976 std::cout << " nodes:" << conn3[0] << " " << conn3[1] << " " << conn3[2] << "\n"; 01977 CartVect PP[3]; 01978 PP[0] = P[1] - P[0]; 01979 PP[1] = P[2] - P[1]; 01980 PP[2] = P[0] - P[2]; 01981 01982 std::cout << " pos:" << P[0] << " " << P[1] << " " << P[2] << "\n"; 01983 std::cout << " x,y diffs " << PP[0][0] << " " << PP[0][1] << ", " << PP[1][0] << " " << PP[1][1] << ", " 01984 << PP[2][0] << " " << PP[2][1] << "\n"; 01985 return; 01986 } 01987 // actual breaking of triangles 01988 // case 1: n2 interior to triangle 01989 ErrorCode FBEngine::BreakTriangle( EntityHandle, EntityHandle, EntityHandle, EntityHandle, EntityHandle, EntityHandle ) 01990 { 01991 std::cout << "FBEngine::BreakTriangle not implemented yet\n"; 01992 return MB_FAILURE; 01993 } 01994 // case 2, n1 and n2 on boundary 01995 ErrorCode FBEngine::BreakTriangle2( EntityHandle tri, 01996 EntityHandle e1, 01997 EntityHandle e2, 01998 EntityHandle n1, 01999 EntityHandle n2 ) // nodesAlongPolyline are on entities! 02000 { 02001 // we have the nodes, we just need to reconnect to form new triangles 02002 ErrorCode rval; 02003 const EntityHandle* conn3 = NULL; 02004 int nnodes = 0; 02005 rval = _mbImpl->get_connectivity( tri, conn3, nnodes ); 02006 MBERRORR( rval, "Failed to get connectivity" ); 02007 assert( 3 == nnodes ); 02008 02009 EntityType et1 = _mbImpl->type_from_handle( e1 ); 02010 EntityType et2 = _mbImpl->type_from_handle( e2 ); 02011 02012 if( MBVERTEX == et1 ) 02013 { 02014 // find the vertex in conn3, and form 2 other triangles 02015 int index = -1; 02016 for( index = 0; index < 3; index++ ) 02017 { 02018 if( conn3[index] == e1 ) // also n1 02019 break; 02020 } 02021 if( index == 3 ) return MB_FAILURE; 02022 // 2 triangles: n1, index+1, n2, and n1, n2, index+2 02023 EntityHandle conn[6] = { n1, conn3[( index + 1 ) % 3], n2, n1, n2, conn3[( index + 2 ) % 3] }; 02024 EntityHandle newTriangle; 02025 rval = _mbImpl->create_element( MBTRI, conn, 3, newTriangle ); 02026 MBERRORR( rval, "Failed to create a new triangle" ); 02027 _newTriangles.insert( newTriangle ); 02028 if( debug_splits ) print_debug_triangle( newTriangle ); 02029 rval = _mbImpl->create_element( MBTRI, conn + 3, 3, newTriangle ); // the second triangle 02030 MBERRORR( rval, "Failed to create a new triangle" ); 02031 _newTriangles.insert( newTriangle ); 02032 if( debug_splits ) print_debug_triangle( newTriangle ); 02033 } 02034 else if( MBVERTEX == et2 ) 02035 { 02036 int index = -1; 02037 for( index = 0; index < 3; index++ ) 02038 { 02039 if( conn3[index] == e2 ) // also n2 02040 break; 02041 } 02042 if( index == 3 ) return MB_FAILURE; 02043 // 2 triangles: n1, index+1, n2, and n1, n2, index+2 02044 EntityHandle conn[6] = { n2, conn3[( index + 1 ) % 3], n1, n2, n1, conn3[( index + 2 ) % 3] }; 02045 EntityHandle newTriangle; 02046 rval = _mbImpl->create_element( MBTRI, conn, 3, newTriangle ); 02047 MBERRORR( rval, "Failed to create a new triangle" ); 02048 _newTriangles.insert( newTriangle ); 02049 if( debug_splits ) print_debug_triangle( newTriangle ); 02050 rval = _mbImpl->create_element( MBTRI, conn + 3, 3, newTriangle ); // the second triangle 02051 MBERRORR( rval, "Failed to create a new triangle" ); 02052 _newTriangles.insert( newTriangle ); 02053 if( debug_splits ) print_debug_triangle( newTriangle ); 02054 } 02055 else 02056 { 02057 // both are edges adjacent to triangle tri 02058 // there are several configurations possible for n1, n2, between conn3 nodes. 02059 int num1, num2, sense, offset; 02060 rval = _mbImpl->side_number( tri, e1, num1, sense, offset ); 02061 MBERRORR( rval, "edge not adjacent" ); 02062 02063 rval = _mbImpl->side_number( tri, e2, num2, sense, offset ); 02064 MBERRORR( rval, "edge not adjacent" ); 02065 02066 const EntityHandle* conn12; // connectivity for edge 1 02067 const EntityHandle* conn22; // connectivity for edge 2 02068 // int nnodes; 02069 rval = _mbImpl->get_connectivity( e1, conn12, nnodes ); 02070 MBERRORR( rval, "Failed to get connectivity of edge 1" ); 02071 assert( 2 == nnodes ); 02072 rval = _mbImpl->get_connectivity( e2, conn22, nnodes ); 02073 MBERRORR( rval, "Failed to get connectivity of edge 2" ); 02074 assert( 2 == nnodes ); 02075 // now, having the side number, work through 02076 if( debug_splits ) 02077 { 02078 std::cout << "tri conn3:" << conn3[0] << " " << conn3[1] << " " << conn3[2] << "\n"; 02079 std::cout << " edge1: conn12:" << conn12[0] << " " << conn12[1] << " side: " << num1 << "\n"; 02080 std::cout << " edge2: conn22:" << conn22[0] << " " << conn22[1] << " side: " << num2 << "\n"; 02081 } 02082 int unaffectedSide = 3 - num1 - num2; 02083 int i3 = ( unaffectedSide + 2 ) % 3; // to 0 is 2, to 1 is 0, to 2 is 1 02084 // triangles will be formed with triVertexIndex , n1, n2 (in what order?) 02085 EntityHandle v1, v2; // to hold the 2 nodes on edges 02086 if( num1 == i3 ) 02087 { 02088 v1 = n1; 02089 v2 = n2; 02090 } 02091 else // if (num2==i3) 02092 { 02093 v1 = n2; 02094 v2 = n1; 02095 } 02096 // three triangles are formed 02097 int i1 = ( i3 + 1 ) % 3; 02098 int i2 = ( i3 + 2 ) % 3; 02099 // we could break the surface differently 02100 EntityHandle conn[9] = { conn3[i3], v1, v2, v1, conn3[i1], conn3[i2], v2, v1, conn3[i2] }; 02101 EntityHandle newTriangle; 02102 if( debug_splits ) std::cout << "Split 2 edges :\n"; 02103 rval = _mbImpl->create_element( MBTRI, conn, 3, newTriangle ); 02104 MBERRORR( rval, "Failed to create a new triangle" ); 02105 _newTriangles.insert( newTriangle ); 02106 if( debug_splits ) print_debug_triangle( newTriangle ); 02107 rval = _mbImpl->create_element( MBTRI, conn + 3, 3, newTriangle ); // the second triangle 02108 MBERRORR( rval, "Failed to create a new triangle" ); 02109 _newTriangles.insert( newTriangle ); 02110 if( debug_splits ) print_debug_triangle( newTriangle ); 02111 rval = _mbImpl->create_element( MBTRI, conn + 6, 3, newTriangle ); // the second triangle 02112 MBERRORR( rval, "Failed to create a new triangle" ); 02113 _newTriangles.insert( newTriangle ); 02114 if( debug_splits ) print_debug_triangle( newTriangle ); 02115 } 02116 02117 return MB_SUCCESS; 02118 } 02119 02120 // build the list of intx points and entities from database involved 02121 // vertices, edges, triangles 02122 // it could be just a list of vertices (easiest case to handle after) 02123 02124 ErrorCode FBEngine::compute_intersection_points( EntityHandle&, 02125 EntityHandle from, 02126 EntityHandle to, 02127 CartVect& Dir, 02128 std::vector< CartVect >& points, 02129 std::vector< EntityHandle >& entities, 02130 std::vector< EntityHandle >& triangles ) 02131 { 02132 // keep a stack of triangles to process, and do not add those already processed 02133 // either mark them, or maybe keep them in a local set? 02134 // from and to are now nodes, start from them 02135 CartVect p1, p2; // the position of from and to 02136 ErrorCode rval = _mbImpl->get_coords( &from, 1, (double*)&p1 ); 02137 MBERRORR( rval, "failed to get 'from' coordinates" ); 02138 rval = _mbImpl->get_coords( &to, 1, (double*)&p2 ); 02139 MBERRORR( rval, "failed to get 'from' coordinates" ); 02140 02141 CartVect vect( p2 - p1 ); 02142 double dist2 = vect.length(); 02143 if( dist2 < tolerance_segment ) 02144 { 02145 // we are done, return 02146 return MB_SUCCESS; 02147 } 02148 CartVect normPlane = Dir * vect; 02149 normPlane.normalize(); 02150 std::set< EntityHandle > visitedTriangles; 02151 CartVect currentPoint = p1; 02152 // push the current point if it is empty 02153 if( points.size() == 0 ) 02154 { 02155 points.push_back( p1 ); 02156 entities.push_back( from ); // this is a node now 02157 } 02158 02159 // these will be used in many loops 02160 CartVect intx = p1; // somewhere to start 02161 double param = -1.; 02162 02163 // first intersection 02164 EntityHandle currentBoundary = from; // it is a node, in the beginning 02165 02166 vect = p2 - currentPoint; 02167 while( vect.length() > 0. ) 02168 { 02169 // advance towards "to" node, from boundary handle 02170 EntityType etype = _mbImpl->type_from_handle( currentBoundary ); 02171 // if vertex, look for other triangles connected which intersect our plane (defined by p1, 02172 // p2, dir) 02173 std::vector< EntityHandle > adj_tri; 02174 rval = _mbImpl->get_adjacencies( ¤tBoundary, 1, 2, false, adj_tri ); 02175 unsigned int j = 0; 02176 EntityHandle tri; 02177 for( ; j < adj_tri.size(); j++ ) 02178 { 02179 tri = adj_tri[j]; 02180 if( visitedTriangles.find( tri ) != visitedTriangles.end() ) 02181 continue; // get another triangle, this one was already visited 02182 // check if it is one of the triangles that was pierced already 02183 if( _piercedTriangles.find( tri ) != _piercedTriangles.end() ) continue; 02184 // if vertex, look for opposite edge 02185 // if edge, look for 2 opposite edges 02186 // get vertices 02187 int nnodes; 02188 const EntityHandle* conn3; 02189 rval = _mbImpl->get_connectivity( tri, conn3, nnodes ); 02190 MBERRORR( rval, "Failed to get connectivity" ); 02191 // if one of the nodes is to, stop right there 02192 { 02193 if( conn3[0] == to || conn3[1] == to || conn3[2] == to ) 02194 { 02195 visitedTriangles.insert( tri ); 02196 triangles.push_back( tri ); 02197 currentPoint = p2; 02198 points.push_back( p2 ); 02199 entities.push_back( to ); // we are done 02200 break; // this is break from for loop, we still need to get out of while 02201 // we will get out, because vect will become 0, (p2-p2) 02202 } 02203 } 02204 EntityHandle nn2[2]; 02205 if( MBVERTEX == etype ) 02206 { 02207 nn2[0] = conn3[0]; 02208 nn2[1] = conn3[1]; 02209 if( nn2[0] == currentBoundary ) nn2[0] = conn3[2]; 02210 if( nn2[1] == currentBoundary ) nn2[1] = conn3[2]; 02211 // get coordinates 02212 CartVect Pt[2]; 02213 02214 rval = _mbImpl->get_coords( nn2, 2, (double*)&Pt[0] ); 02215 MBERRORR( rval, "Failed to get coordinates" ); 02216 // see the intersection 02217 if( intersect_segment_and_plane_slice( Pt[0], Pt[1], currentPoint, p2, Dir, normPlane, intx, param ) ) 02218 { 02219 // we should stop for loop, and decide if it is edge or vertex 02220 if( param == 0. ) 02221 currentBoundary = nn2[0]; 02222 else 02223 { 02224 if( param == 1. ) 02225 currentBoundary = nn2[1]; 02226 else // param between 0 and 1, so edge 02227 { 02228 // find the edge between vertices 02229 std::vector< EntityHandle > edges1; 02230 // change the create flag to true, because that edge must exist in 02231 // current triangle if we want to advance; nn2 are 2 nodes in current 02232 // triangle!! 02233 rval = _mbImpl->get_adjacencies( nn2, 2, 1, true, edges1, Interface::INTERSECT ); 02234 MBERRORR( rval, "Failed to get edges" ); 02235 if( edges1.size() != 1 ) MBERRORR( MB_FAILURE, "Failed to get adjacent edges to 2 nodes" ); 02236 currentBoundary = edges1[0]; 02237 } 02238 } 02239 visitedTriangles.insert( tri ); 02240 currentPoint = intx; 02241 points.push_back( intx ); 02242 entities.push_back( currentBoundary ); 02243 triangles.push_back( tri ); 02244 if( debug_splits ) 02245 std::cout << "vtx new tri : " << _mbImpl->id_from_handle( tri ) 02246 << " type bdy:" << _mbImpl->type_from_handle( currentBoundary ) << "\n"; 02247 break; // out of for loop over triangles 02248 } 02249 } 02250 else // this is MBEDGE, we have the other triangle to try out 02251 { 02252 // first find the nodes from existing boundary 02253 int nnodes2; 02254 const EntityHandle* conn2; 02255 rval = _mbImpl->get_connectivity( currentBoundary, conn2, nnodes2 ); 02256 MBERRORR( rval, "Failed to get connectivity" ); 02257 int thirdIndex = -1; 02258 for( int tj = 0; tj < 3; tj++ ) 02259 { 02260 if( ( conn3[tj] != conn2[0] ) && ( conn3[tj] != conn2[1] ) ) 02261 { 02262 thirdIndex = tj; 02263 break; 02264 } 02265 } 02266 if( -1 == thirdIndex ) MBERRORR( MB_FAILURE, " can't get third node" ); 02267 CartVect Pt[3]; 02268 rval = _mbImpl->get_coords( conn3, 3, (double*)&Pt[0] ); 02269 MBERRORR( rval, "Failed to get coords" ); 02270 int indexFirst = ( thirdIndex + 1 ) % 3; 02271 int indexSecond = ( thirdIndex + 2 ) % 3; 02272 int index[2] = { indexFirst, indexSecond }; 02273 for( int k = 0; k < 2; k++ ) 02274 { 02275 nn2[0] = conn3[index[k]], nn2[1] = conn3[thirdIndex]; 02276 if( intersect_segment_and_plane_slice( Pt[index[k]], Pt[thirdIndex], currentPoint, p2, Dir, 02277 normPlane, intx, param ) ) 02278 { 02279 // we should stop for loop, and decide if it is edge or vertex 02280 if( param == 0. ) 02281 currentBoundary = conn3[index[k]]; // it is not really possible 02282 else 02283 { 02284 if( param == 1. ) 02285 currentBoundary = conn3[thirdIndex]; 02286 else // param between 0 and 1, so edge is fine 02287 { 02288 // find the edge between vertices 02289 std::vector< EntityHandle > edges1; 02290 // change the create flag to true, because that edge must exist in 02291 // current triangle if we want to advance; nn2 are 2 nodes in 02292 // current triangle!! 02293 rval = _mbImpl->get_adjacencies( nn2, 2, 1, true, edges1, Interface::INTERSECT ); 02294 MBERRORR( rval, "Failed to get edges" ); 02295 if( edges1.size() != 1 ) 02296 MBERRORR( MB_FAILURE, "Failed to get adjacent edges to 2 nodes" ); 02297 currentBoundary = edges1[0]; 02298 } 02299 } 02300 visitedTriangles.insert( tri ); 02301 currentPoint = intx; 02302 points.push_back( intx ); 02303 entities.push_back( currentBoundary ); 02304 triangles.push_back( tri ); 02305 if( debug_splits ) 02306 { 02307 std::cout << "edge new tri : " << _mbImpl->id_from_handle( tri ) 02308 << " type bdy: " << _mbImpl->type_from_handle( currentBoundary ) 02309 << " id: " << _mbImpl->id_from_handle( currentBoundary ) << "\n"; 02310 _mbImpl->list_entity( currentBoundary ); 02311 } 02312 break; // out of for loop over triangles 02313 } 02314 // we should not reach here 02315 } 02316 } 02317 } 02318 /*if (j==adj_tri.size()) 02319 { 02320 MBERRORR(MB_FAILURE, "did not advance"); 02321 }*/ 02322 vect = p2 - currentPoint; 02323 } 02324 02325 if( debug_splits ) 02326 std::cout << "nb entities: " << entities.size() << " triangles:" << triangles.size() 02327 << " points.size(): " << points.size() << "\n"; 02328 02329 return MB_SUCCESS; 02330 } 02331 02332 ErrorCode FBEngine::split_edge_at_point( EntityHandle edge, CartVect& point, EntityHandle& new_edge ) 02333 { 02334 // return MB_NOT_IMPLEMENTED; 02335 // first, we need to find the closest point on the smooth edge, then 02336 // split the smooth edge, then call the split_edge_at_mesh_node 02337 // or maybe just find the closest node?? 02338 // first of all, we need to find a point on the smooth edge, close by 02339 // then split the mesh edge (if needed) 02340 // this would be quite a drama, as the new edge has to be inserted in 02341 // order for proper geo edge definition 02342 02343 // first of all, find a closest point 02344 // usually called for 02345 if( debug_splits ) 02346 { 02347 std::cout << "Split edge " << _mbImpl->id_from_handle( edge ) << " at point:" << point << "\n"; 02348 } 02349 int dim = _my_geomTopoTool->dimension( edge ); 02350 if( dim != 1 ) return MB_FAILURE; 02351 if( !_smooth ) return MB_FAILURE; // call it only for smooth option... 02352 // maybe we should do something for linear too 02353 02354 SmoothCurve* curve = this->_edges[edge]; 02355 EntityHandle closeNode; 02356 int edgeIndex; 02357 double u = curve->u_from_position( point[0], point[1], point[2], closeNode, edgeIndex ); 02358 if( 0 == closeNode ) 02359 { 02360 // we really need to split an existing edge 02361 // do not do that yet 02362 // evaluate from u: 02363 /*double pos[3]; 02364 curve->position_from_u(u, pos[0], pos[1], pos[2] );*/ 02365 // create a new node here, and split one edge 02366 // change also connectivity, create new triangles on both sides ... 02367 std::cout << "not found a close node, u is: " << u << " edge index: " << edgeIndex << "\n"; 02368 return MB_FAILURE; // not implemented yet 02369 } 02370 return split_edge_at_mesh_node( edge, closeNode, new_edge ); 02371 } 02372 02373 ErrorCode FBEngine::split_edge_at_mesh_node( EntityHandle edge, EntityHandle node, EntityHandle& new_edge ) 02374 { 02375 // the node should be in the list of nodes 02376 02377 int dim = _my_geomTopoTool->dimension( edge ); 02378 if( dim != 1 ) return MB_FAILURE; // not an edge 02379 02380 if( debug_splits ) 02381 { 02382 std::cout << "Split edge " << _mbImpl->id_from_handle( edge ) 02383 << " with global id: " << _my_geomTopoTool->global_id( edge ) 02384 << " at node:" << _mbImpl->id_from_handle( node ) << "\n"; 02385 } 02386 02387 // now get the edges 02388 // the order is important... 02389 // these are ordered sets !! 02390 std::vector< EntityHandle > ents; 02391 ErrorCode rval = _mbImpl->get_entities_by_type( edge, MBEDGE, ents ); 02392 if( MB_SUCCESS != rval ) return rval; 02393 if( ents.size() < 1 ) return MB_FAILURE; // no edges 02394 02395 const EntityHandle* conn = NULL; 02396 int len; 02397 // find the edge connected to the splitting node 02398 int num_mesh_edges = (int)ents.size(); 02399 int index_edge; 02400 EntityHandle firstNode = 0; 02401 for( index_edge = 0; index_edge < num_mesh_edges; index_edge++ ) 02402 { 02403 rval = MBI->get_connectivity( ents[index_edge], conn, len ); 02404 if( MB_SUCCESS != rval ) return rval; 02405 if( index_edge == 0 ) firstNode = conn[0]; // will be used to decide vertex sets adjacencies 02406 if( conn[0] == node ) 02407 { 02408 if( index_edge == 0 ) 02409 { 02410 new_edge = 0; // no need to split, it is the first node 02411 return MB_SUCCESS; // no split 02412 } 02413 else 02414 return MB_FAILURE; // we should have found the node already , wrong 02415 // connectivity 02416 } 02417 else if( conn[1] == node ) 02418 { 02419 // we found the index of interest 02420 break; 02421 } 02422 } 02423 if( index_edge == num_mesh_edges - 1 ) 02424 { 02425 new_edge = 0; // no need to split, it is the last node 02426 return MB_SUCCESS; // no split 02427 } 02428 02429 // here, we have 0 ... index_edge edges in the first set, 02430 // create a vertex set and add the node to it 02431 02432 if( debug_splits ) 02433 { 02434 std::cout << "Split edge with " << num_mesh_edges << " mesh edges, at index (0 based) " << index_edge << "\n"; 02435 } 02436 02437 // at this moment, the node set should have been already created in new_geo_edge 02438 EntityHandle nodeSet; // the node set that has the node (find it!) 02439 bool found = find_vertex_set_for_node( node, nodeSet ); 02440 02441 if( !found ) 02442 { 02443 // create a node set and add the node 02444 02445 // must be an error, but create one nevertheless 02446 rval = _mbImpl->create_meshset( MESHSET_SET, nodeSet ); 02447 MBERRORR( rval, "Failed to create a new vertex set" ); 02448 02449 rval = _mbImpl->add_entities( nodeSet, &node, 1 ); 02450 MBERRORR( rval, "Failed to add the node to the set" ); 02451 02452 rval = _my_geomTopoTool->add_geo_set( nodeSet, 0 ); // 02453 MBERRORR( rval, "Failed to commit the node set" ); 02454 02455 if( debug_splits ) 02456 { 02457 std::cout << " create a vertex set (this should have been created before!)" 02458 << _mbImpl->id_from_handle( nodeSet ) 02459 << " global id:" << this->_my_geomTopoTool->global_id( nodeSet ) << "\n"; 02460 } 02461 } 02462 02463 // we need to remove the remaining mesh edges from first set, and add it 02464 // to the second set, in order 02465 02466 rval = _mbImpl->create_meshset( MESHSET_ORDERED, new_edge ); 02467 MBERRORR( rval, "can't create geo edge" ); 02468 02469 int remaining = num_mesh_edges - 1 - index_edge; 02470 02471 // add edges to the edge set 02472 rval = _mbImpl->add_entities( new_edge, &ents[index_edge + 1], remaining ); 02473 MBERRORR( rval, "can't add edges to the new edge" ); 02474 02475 // also, remove the second node set from old edge 02476 // remove the edges index_edge+1 and up 02477 02478 rval = _mbImpl->remove_entities( edge, &ents[index_edge + 1], remaining ); 02479 MBERRORR( rval, "can't remove edges from the old edge" ); 02480 02481 // need to find the adjacent vertex sets 02482 Range vertexRange; 02483 rval = getAdjacentEntities( edge, 0, vertexRange ); 02484 02485 EntityHandle secondSet; 02486 if( vertexRange.size() == 1 ) 02487 { 02488 // initially a periodic edge, OK to add the new set to both edges, and the 02489 // second set 02490 secondSet = vertexRange[0]; 02491 } 02492 else 02493 { 02494 if( vertexRange.size() > 2 ) return MB_FAILURE; // something must be wrong with too many vertices 02495 // find first node 02496 int k; 02497 for( k = 0; k < 2; k++ ) 02498 { 02499 Range verts; 02500 rval = _mbImpl->get_entities_by_type( vertexRange[k], MBVERTEX, verts ); 02501 02502 MBERRORR( rval, "can't get vertices from vertex set" ); 02503 if( verts.size() != 1 ) MBERRORR( MB_FAILURE, " node set not defined well" ); 02504 if( firstNode == verts[0] ) 02505 { 02506 secondSet = vertexRange[1 - k]; // the other set; it is 1 or 0 02507 break; 02508 } 02509 } 02510 if( k >= 2 ) 02511 { 02512 // it means we didn't find the right node set 02513 MBERRORR( MB_FAILURE, " can't find the right vertex" ); 02514 } 02515 // remove the second set from the connectivity with the 02516 // edge (parent-child relation) 02517 // remove_parent_child( EntityHandle parent, 02518 // EntityHandle child ) 02519 rval = _mbImpl->remove_parent_child( edge, secondSet ); 02520 MBERRORR( rval, " can't remove the second vertex from edge" ); 02521 } 02522 // at this point, we just need to add to both edges the new node set (vertex) 02523 rval = _mbImpl->add_parent_child( edge, nodeSet ); 02524 MBERRORR( rval, " can't add new vertex to old edge" ); 02525 02526 rval = _mbImpl->add_parent_child( new_edge, nodeSet ); 02527 MBERRORR( rval, " can't add new vertex to new edge" ); 02528 02529 // one thing that I forgot: add the secondSet as a child to new edge!!! 02530 // (so far, the new edge has only one end vertex!) 02531 rval = _mbImpl->add_parent_child( new_edge, secondSet ); 02532 MBERRORR( rval, " can't add second vertex to new edge" ); 02533 02534 // now, add the edge and vertex to geo tool 02535 02536 rval = _my_geomTopoTool->add_geo_set( new_edge, 1 ); 02537 MBERRORR( rval, " can't add new edge" ); 02538 02539 // next, get the adjacent faces to initial edge, and add them as parents 02540 // to the new edge 02541 02542 // need to find the adjacent face sets 02543 Range faceRange; 02544 rval = getAdjacentEntities( edge, 2, faceRange ); 02545 02546 // these faces will be adjacent to the new edge too! 02547 // need to set the senses of new edge within faces 02548 02549 for( Range::iterator it = faceRange.begin(); it != faceRange.end(); ++it ) 02550 { 02551 EntityHandle face = *it; 02552 rval = _mbImpl->add_parent_child( face, new_edge ); 02553 MBERRORR( rval, " can't add new edge - face parent relation" ); 02554 int sense; 02555 rval = _my_geomTopoTool->get_sense( edge, face, sense ); 02556 MBERRORR( rval, " can't get initial sense of edge in the adjacent face" ); 02557 // keep the same sense for the new edge within the faces 02558 rval = _my_geomTopoTool->set_sense( new_edge, face, sense ); 02559 MBERRORR( rval, " can't set sense of new edge in the adjacent face" ); 02560 } 02561 02562 return MB_SUCCESS; 02563 } 02564 02565 ErrorCode FBEngine::split_bedge_at_new_mesh_node( EntityHandle edge, 02566 EntityHandle node, 02567 EntityHandle brokenEdge, 02568 EntityHandle& new_edge ) 02569 { 02570 // the node should be in the list of nodes 02571 02572 int dim = _my_geomTopoTool->dimension( edge ); 02573 if( dim != 1 ) return MB_FAILURE; // not an edge 02574 02575 if( debug_splits ) 02576 { 02577 std::cout << "Split edge " << _mbImpl->id_from_handle( edge ) 02578 << " with global id: " << _my_geomTopoTool->global_id( edge ) 02579 << " at new node:" << _mbImpl->id_from_handle( node ) << "breaking mesh edge" 02580 << _mbImpl->id_from_handle( brokenEdge ) << "\n"; 02581 } 02582 02583 // now get the edges 02584 // the order is important... 02585 // these are ordered sets !! 02586 std::vector< EntityHandle > ents; 02587 ErrorCode rval = _mbImpl->get_entities_by_type( edge, MBEDGE, ents ); 02588 if( MB_SUCCESS != rval ) return rval; 02589 if( ents.size() < 1 ) return MB_FAILURE; // no edges 02590 02591 const EntityHandle* conn = NULL; 02592 int len; 02593 // the edge connected to the splitting node is brokenEdge 02594 // find the small edges it is broken into, which are connected to 02595 // new vertex (node) and its ends; also, if necessary, reorient these small edges 02596 // for proper orientation 02597 rval = _mbImpl->get_connectivity( brokenEdge, conn, len ); 02598 MBERRORR( rval, "Failed to get connectivity of broken edge" ); 02599 02600 // we already created the new edges, make sure they are oriented fine; if not, revert them 02601 EntityHandle conn02[] = { conn[0], node }; // first node and new node 02602 // default, intersect 02603 std::vector< EntityHandle > adj_edges; 02604 rval = _mbImpl->get_adjacencies( conn02, 2, 1, false, adj_edges ); 02605 if( adj_edges.size() < 1 || rval != MB_SUCCESS ) MBERRORR( MB_FAILURE, " Can't find small split edge" ); 02606 02607 // get this edge connectivity; 02608 EntityHandle firstEdge = adj_edges[0]; 02609 const EntityHandle* connActual = NULL; 02610 rval = _mbImpl->get_connectivity( firstEdge, connActual, len ); 02611 MBERRORR( rval, "Failed to get connectivity of first split edge" ); 02612 // if it is the same as conn02, we are happy 02613 if( conn02[0] != connActual[0] ) 02614 { 02615 // reset connectivity of edge 02616 rval = _mbImpl->set_connectivity( firstEdge, conn02, 2 ); 02617 MBERRORR( rval, "Failed to reset connectivity of first split edge" ); 02618 } 02619 // now treat the second edge 02620 adj_edges.clear(); // 02621 EntityHandle conn21[] = { node, conn[1] }; // new node and second node 02622 rval = _mbImpl->get_adjacencies( conn21, 2, 1, false, adj_edges ); 02623 if( adj_edges.size() < 1 || rval != MB_SUCCESS ) MBERRORR( MB_FAILURE, " Can't find second small split edge" ); 02624 02625 // get this edge connectivity; 02626 EntityHandle secondEdge = adj_edges[0]; 02627 rval = _mbImpl->get_connectivity( firstEdge, connActual, len ); 02628 MBERRORR( rval, "Failed to get connectivity of first split edge" ); 02629 // if it is the same as conn21, we are happy 02630 if( conn21[0] != connActual[0] ) 02631 { 02632 // reset connectivity of edge 02633 rval = _mbImpl->set_connectivity( secondEdge, conn21, 2 ); 02634 MBERRORR( rval, "Failed to reset connectivity of first split edge" ); 02635 } 02636 02637 int num_mesh_edges = (int)ents.size(); 02638 int index_edge; // this is the index of the edge that will be removed (because it is split) 02639 // the rest of edges will be put in order in the (remaining) edge and new edge 02640 02641 for( index_edge = 0; index_edge < num_mesh_edges; index_edge++ ) 02642 if( brokenEdge == ents[index_edge] ) break; 02643 if( index_edge >= num_mesh_edges ) MBERRORR( MB_FAILURE, "can't find the broken edge" ); 02644 02645 // so the edges up to index_edge and firstEdge, will form the "old" edge 02646 // the edges secondEdge and from index_edge+1 to end will form the new_edge 02647 02648 // here, we have 0 ... index_edge edges in the first set, 02649 // create a vertex set and add the node to it 02650 02651 if( debug_splits ) 02652 { 02653 std::cout << "Split edge with " << num_mesh_edges << " mesh edges, at index (0 based) " << index_edge << "\n"; 02654 } 02655 02656 // at this moment, the node set should have been already created in new_geo_edge 02657 EntityHandle nodeSet; // the node set that has the node (find it!) 02658 bool found = find_vertex_set_for_node( node, nodeSet ); 02659 02660 if( !found ) 02661 { 02662 // create a node set and add the node 02663 02664 // must be an error, but create one nevertheless 02665 rval = _mbImpl->create_meshset( MESHSET_SET, nodeSet ); 02666 MBERRORR( rval, "Failed to create a new vertex set" ); 02667 02668 rval = _mbImpl->add_entities( nodeSet, &node, 1 ); 02669 MBERRORR( rval, "Failed to add the node to the set" ); 02670 02671 rval = _my_geomTopoTool->add_geo_set( nodeSet, 0 ); // 02672 MBERRORR( rval, "Failed to commit the node set" ); 02673 02674 if( debug_splits ) 02675 { 02676 std::cout << " create a vertex set (this should have been created before!)" 02677 << _mbImpl->id_from_handle( nodeSet ) 02678 << " global id:" << this->_my_geomTopoTool->global_id( nodeSet ) << "\n"; 02679 } 02680 } 02681 02682 // we need to remove the remaining mesh edges from first set, and add it 02683 // to the second set, in order 02684 02685 rval = _mbImpl->create_meshset( MESHSET_ORDERED, new_edge ); 02686 MBERRORR( rval, "can't create geo edge" ); 02687 02688 int remaining = num_mesh_edges - 1 - index_edge; 02689 02690 // add edges to the new edge set 02691 rval = _mbImpl->add_entities( new_edge, &secondEdge, 1 ); // add the second split edge to new edge 02692 MBERRORR( rval, "can't add second split edge to the new edge" ); 02693 // then add the rest 02694 rval = _mbImpl->add_entities( new_edge, &ents[index_edge + 1], remaining ); 02695 MBERRORR( rval, "can't add edges to the new edge" ); 02696 02697 // also, remove the second node set from old edge 02698 // remove the edges index_edge and up 02699 02700 rval = _mbImpl->remove_entities( edge, &ents[index_edge], remaining + 1 ); // include the 02701 MBERRORR( rval, "can't remove edges from the old edge" ); 02702 // add the firstEdge too 02703 rval = _mbImpl->add_entities( edge, &firstEdge, 1 ); // add the second split edge to new edge 02704 MBERRORR( rval, "can't add first split edge to the old edge" ); 02705 02706 // need to find the adjacent vertex sets 02707 Range vertexRange; 02708 rval = getAdjacentEntities( edge, 0, vertexRange ); 02709 02710 EntityHandle secondSet; 02711 if( vertexRange.size() == 1 ) 02712 { 02713 // initially a periodic edge, OK to add the new set to both edges, and the 02714 // second set 02715 secondSet = vertexRange[0]; 02716 } 02717 else 02718 { 02719 if( vertexRange.size() > 2 ) return MB_FAILURE; // something must be wrong with too many vertices 02720 // find first node 02721 EntityHandle firstNode; 02722 02723 rval = MBI->get_connectivity( ents[0], conn, len ); 02724 if( MB_SUCCESS != rval ) return rval; 02725 firstNode = conn[0]; // this is the first node of the initial edge 02726 // we will use it to identify the vertex set associated with it 02727 int k; 02728 for( k = 0; k < 2; k++ ) 02729 { 02730 Range verts; 02731 rval = _mbImpl->get_entities_by_type( vertexRange[k], MBVERTEX, verts ); 02732 02733 MBERRORR( rval, "can't get vertices from vertex set" ); 02734 if( verts.size() != 1 ) MBERRORR( MB_FAILURE, " node set not defined well" ); 02735 if( firstNode == verts[0] ) 02736 { 02737 secondSet = vertexRange[1 - k]; // the other set; it is 1 or 0 02738 break; 02739 } 02740 } 02741 if( k >= 2 ) 02742 { 02743 // it means we didn't find the right node set 02744 MBERRORR( MB_FAILURE, " can't find the right vertex" ); 02745 } 02746 // remove the second set from the connectivity with the 02747 // edge (parent-child relation) 02748 // remove_parent_child( EntityHandle parent, 02749 // EntityHandle child ) 02750 rval = _mbImpl->remove_parent_child( edge, secondSet ); 02751 MBERRORR( rval, " can't remove the second vertex from edge" ); 02752 } 02753 // at this point, we just need to add to both edges the new node set (vertex) 02754 rval = _mbImpl->add_parent_child( edge, nodeSet ); 02755 MBERRORR( rval, " can't add new vertex to old edge" ); 02756 02757 rval = _mbImpl->add_parent_child( new_edge, nodeSet ); 02758 MBERRORR( rval, " can't add new vertex to new edge" ); 02759 02760 // one thing that I forgot: add the secondSet as a child to new edge!!! 02761 // (so far, the new edge has only one end vertex!) 02762 rval = _mbImpl->add_parent_child( new_edge, secondSet ); 02763 MBERRORR( rval, " can't add second vertex to new edge" ); 02764 02765 // now, add the edge and vertex to geo tool 02766 02767 rval = _my_geomTopoTool->add_geo_set( new_edge, 1 ); 02768 MBERRORR( rval, " can't add new edge" ); 02769 02770 // next, get the adjacent faces to initial edge, and add them as parents 02771 // to the new edge 02772 02773 // need to find the adjacent face sets 02774 Range faceRange; 02775 rval = getAdjacentEntities( edge, 2, faceRange ); 02776 02777 // these faces will be adjacent to the new edge too! 02778 // need to set the senses of new edge within faces 02779 02780 for( Range::iterator it = faceRange.begin(); it != faceRange.end(); ++it ) 02781 { 02782 EntityHandle face = *it; 02783 rval = _mbImpl->add_parent_child( face, new_edge ); 02784 MBERRORR( rval, " can't add new edge - face parent relation" ); 02785 int sense; 02786 rval = _my_geomTopoTool->get_sense( edge, face, sense ); 02787 MBERRORR( rval, " can't get initial sense of edge in the adjacent face" ); 02788 // keep the same sense for the new edge within the faces 02789 rval = _my_geomTopoTool->set_sense( new_edge, face, sense ); 02790 MBERRORR( rval, " can't set sense of new edge in the adjacent face" ); 02791 } 02792 02793 return MB_SUCCESS; 02794 } 02795 02796 ErrorCode FBEngine::split_boundary( EntityHandle face, EntityHandle atNode ) 02797 { 02798 // find the boundary edges, and split the one that we find it is a part of 02799 if( debug_splits ) 02800 { 02801 std::cout << "Split face " << _mbImpl->id_from_handle( face ) 02802 << " at node:" << _mbImpl->id_from_handle( atNode ) << "\n"; 02803 } 02804 Range bound_edges; 02805 ErrorCode rval = getAdjacentEntities( face, 1, bound_edges ); 02806 MBERRORR( rval, " can't get boundary edges" ); 02807 bool brokEdge = _brokenEdges.find( atNode ) != _brokenEdges.end(); 02808 02809 for( Range::iterator it = bound_edges.begin(); it != bound_edges.end(); ++it ) 02810 { 02811 EntityHandle b_edge = *it; 02812 // get all edges in range 02813 Range mesh_edges; 02814 rval = _mbImpl->get_entities_by_dimension( b_edge, 1, mesh_edges ); 02815 MBERRORR( rval, " can't get mesh edges" ); 02816 if( brokEdge ) 02817 { 02818 EntityHandle brokenEdge = _brokenEdges[atNode]; 02819 if( mesh_edges.find( brokenEdge ) != mesh_edges.end() ) 02820 { 02821 EntityHandle new_edge; 02822 rval = split_bedge_at_new_mesh_node( b_edge, atNode, brokenEdge, new_edge ); 02823 return rval; 02824 } 02825 } 02826 else 02827 { 02828 Range nodes; 02829 rval = _mbImpl->get_connectivity( mesh_edges, nodes ); 02830 MBERRORR( rval, " can't get nodes from mesh edges" ); 02831 02832 if( nodes.find( atNode ) != nodes.end() ) 02833 { 02834 // we found our boundary edge candidate 02835 EntityHandle new_edge; 02836 rval = split_edge_at_mesh_node( b_edge, atNode, new_edge ); 02837 return rval; 02838 } 02839 } 02840 } 02841 // if the node was not found in any "current" boundary, it broke an existing 02842 // boundary edge 02843 MBERRORR( MB_FAILURE, " we did not find an appropriate boundary edge" ); 02844 ; // 02845 } 02846 02847 bool FBEngine::find_vertex_set_for_node( EntityHandle iNode, EntityHandle& oVertexSet ) 02848 { 02849 bool found = false; 02850 Range vertex_sets; 02851 02852 const int zero = 0; 02853 const void* const zero_val[] = { &zero }; 02854 Tag geom_tag; 02855 ErrorCode rval = MBI->tag_get_handle( GEOM_DIMENSION_TAG_NAME, 1, MB_TYPE_INTEGER, geom_tag ); 02856 if( MB_SUCCESS != rval ) return false; 02857 rval = _mbImpl->get_entities_by_type_and_tag( 0, MBENTITYSET, &geom_tag, zero_val, 1, vertex_sets ); 02858 if( MB_SUCCESS != rval ) return false; 02859 // local _gsets, as we might have not updated the local lists 02860 // see if ends of geo edge generated is in a geo set 0 or not 02861 02862 for( Range::iterator vsit = vertex_sets.begin(); vsit != vertex_sets.end(); ++vsit ) 02863 { 02864 EntityHandle vset = *vsit; 02865 // is the node part of this set? 02866 if( _mbImpl->contains_entities( vset, &iNode, 1 ) ) 02867 { 02868 02869 found = true; 02870 oVertexSet = vset; 02871 break; 02872 } 02873 } 02874 return found; 02875 } 02876 ErrorCode FBEngine::redistribute_boundary_edges_to_faces( EntityHandle face, 02877 EntityHandle newFace, 02878 std::vector< EntityHandle >& chainedEdges ) 02879 { 02880 02881 // so far, original boundary edges are all parent/child relations for face 02882 // we should get them all, and see if they are truly adjacent to face or newFace 02883 // decide also on the orientation/sense with respect to the triangles 02884 Range r1; // range in old face 02885 Range r2; // range of tris in new face 02886 ErrorCode rval = _mbImpl->get_entities_by_dimension( face, 2, r1 ); 02887 MBERRORR( rval, " can't get triangles from old face" ); 02888 rval = _mbImpl->get_entities_by_dimension( newFace, 2, r2 ); 02889 MBERRORR( rval, " can't get triangles from new face" ); 02890 // right now, all boundary edges are children of face 02891 // we need to get them all, and verify if they indeed are adjacent to face 02892 Range children; 02893 rval = _mbImpl->get_child_meshsets( face, children ); // only direct children are of interest 02894 MBERRORR( rval, " can't get children sets from face" ); 02895 02896 for( Range::iterator it = children.begin(); it != children.end(); ++it ) 02897 { 02898 EntityHandle edge = *it; 02899 if( std::find( chainedEdges.begin(), chainedEdges.end(), edge ) != chainedEdges.end() ) 02900 continue; // we already set this one fine 02901 // get one mesh edge from the edge; we have to get all of them!! 02902 if( _my_geomTopoTool->dimension( edge ) != 1 ) continue; // not an edge 02903 Range mesh_edges; 02904 rval = _mbImpl->get_entities_by_handle( edge, mesh_edges ); 02905 MBERRORR( rval, " can't get mesh edges from edge" ); 02906 if( mesh_edges.empty() ) MBERRORR( MB_FAILURE, " no mesh edges" ); 02907 EntityHandle mesh_edge = mesh_edges[0]; // first one is enough 02908 // get its triangles; see which one is in r1 or r2; it should not be in both 02909 Range triangles; 02910 rval = _mbImpl->get_adjacencies( &mesh_edge, 1, 2, false, triangles ); 02911 MBERRORR( rval, " can't get adjacent triangles" ); 02912 Range intx1 = intersect( triangles, r1 ); 02913 Range intx2 = intersect( triangles, r2 ); 02914 if( !intx1.empty() && !intx2.empty() ) MBERRORR( MB_FAILURE, " at least one should be empty" ); 02915 02916 if( intx2.empty() ) 02917 { 02918 // it means it is in the range r1; the sense should be fine, no need to reset 02919 // the sense should have been fine, also 02920 continue; 02921 } 02922 // so it must be a triangle in r2; 02923 EntityHandle triangle = intx2[0]; // one triangle only 02924 // remove the edge from boundary of face, and add it to the boundary of newFace 02925 // remove_parent_child( EntityHandle parent, EntityHandle child ) 02926 rval = _mbImpl->remove_parent_child( face, edge ); 02927 MBERRORR( rval, " can't remove parent child relation for edge" ); 02928 // add to the new face 02929 rval = _mbImpl->add_parent_child( newFace, edge ); 02930 MBERRORR( rval, " can't add parent child relation for edge" ); 02931 02932 // set some sense, based on the sense of the mesh_edge in triangle 02933 int num1, sense, offset; 02934 rval = _mbImpl->side_number( triangle, mesh_edge, num1, sense, offset ); 02935 MBERRORR( rval, "mesh edge not adjacent to triangle" ); 02936 02937 rval = this->_my_geomTopoTool->set_sense( edge, newFace, sense ); 02938 MBERRORR( rval, "can't set proper sense of edge in face" ); 02939 } 02940 02941 return MB_SUCCESS; 02942 } 02943 02944 ErrorCode FBEngine::set_neumann_tags( EntityHandle face, EntityHandle newFace ) 02945 { 02946 // these are for debugging purposes only 02947 // check the initial tag, then 02948 Tag ntag; 02949 ErrorCode rval = _mbImpl->tag_get_handle( NEUMANN_SET_TAG_NAME, 1, MB_TYPE_INTEGER, ntag ); 02950 MBERRORR( rval, "can't get tag handle" ); 02951 // check the value for face 02952 int nval; 02953 rval = _mbImpl->tag_get_data( ntag, &face, 1, &nval ); 02954 if( MB_SUCCESS == rval ) 02955 { 02956 nval++; 02957 } 02958 else 02959 { 02960 nval = 1; 02961 rval = _mbImpl->tag_set_data( ntag, &face, 1, &nval ); 02962 MBERRORR( rval, "can't set tag" ); 02963 nval = 2; 02964 } 02965 rval = _mbImpl->tag_set_data( ntag, &newFace, 1, &nval ); 02966 MBERRORR( rval, "can't set tag" ); 02967 02968 return MB_SUCCESS; 02969 } 02970 02971 // split the quads if needed; it will create a new gtt, which will 02972 // contain triangles instead of quads 02973 ErrorCode FBEngine::split_quads() 02974 { 02975 // first see if we have any quads in the 2d faces 02976 // _my_gsets[2] is a range of surfaces (moab sets of dimension 2) 02977 int num_quads = 0; 02978 for( Range::iterator it = _my_gsets[2].begin(); it != _my_gsets[2].end(); ++it ) 02979 { 02980 EntityHandle surface = *it; 02981 int num_q = 0; 02982 _mbImpl->get_number_entities_by_type( surface, MBQUAD, num_q ); 02983 num_quads += num_q; 02984 } 02985 02986 if( num_quads == 0 ) return MB_SUCCESS; // nothing to do 02987 02988 GeomTopoTool* new_gtt = NULL; 02989 ErrorCode rval = _my_geomTopoTool->duplicate_model( new_gtt ); 02990 MBERRORR( rval, "can't duplicate model" ); 02991 if( this->_t_created ) delete _my_geomTopoTool; 02992 02993 _t_created = true; // this one is for sure created here, even if the original gtt was not 02994 02995 // if we were using smart pointers, we would decrease the reference to the _my_geomTopoTool, at 02996 // least 02997 _my_geomTopoTool = new_gtt; 02998 02999 // replace the _my_gsets with the new ones, from the new set 03000 _my_geomTopoTool->find_geomsets( _my_gsets ); 03001 03002 // we have duplicated now the model, and the quads are part of the new _my_gsets[2] 03003 // we will split them now, by creating triangles along the smallest diagonal 03004 // maybe we will come up with a better criteria, but for the time being, it should be fine. 03005 // what we will do: we will remove all quads from the surface sets, and split them 03006 03007 for( Range::iterator it2 = _my_gsets[2].begin(); it2 != _my_gsets[2].end(); ++it2 ) 03008 { 03009 EntityHandle surface = *it2; 03010 Range quads; 03011 rval = _mbImpl->get_entities_by_type( surface, MBQUAD, quads ); 03012 MBERRORR( rval, "can't get quads from the surface set" ); 03013 rval = _mbImpl->remove_entities( surface, quads ); 03014 MBERRORR( rval, "can't remove quads from the surface set" ); // they are not deleted, just 03015 // removed from the set 03016 for( Range::iterator it = quads.begin(); it != quads.end(); ++it ) 03017 { 03018 EntityHandle quad = *it; 03019 int nnodes; 03020 const EntityHandle* conn; 03021 rval = _mbImpl->get_connectivity( quad, conn, nnodes ); 03022 MBERRORR( rval, "can't get quad connectivity" ); 03023 // get all vertices position, to see which one is the shortest diagonal 03024 CartVect pos[4]; 03025 rval = _mbImpl->get_coords( conn, 4, (double*)&pos[0] ); 03026 MBERRORR( rval, "can't get node coordinates" ); 03027 bool diag1 = ( ( pos[2] - pos[0] ).length_squared() < ( pos[3] - pos[1] ).length_squared() ); 03028 EntityHandle newTris[2]; 03029 EntityHandle tri1[3] = { conn[0], conn[1], conn[2] }; 03030 EntityHandle tri2[3] = { conn[0], conn[2], conn[3] }; 03031 if( !diag1 ) 03032 { 03033 tri1[2] = conn[3]; 03034 tri2[0] = conn[1]; 03035 } 03036 rval = _mbImpl->create_element( MBTRI, tri1, 3, newTris[0] ); 03037 MBERRORR( rval, "can't create triangle 1" ); 03038 rval = _mbImpl->create_element( MBTRI, tri2, 3, newTris[1] ); 03039 MBERRORR( rval, "can't create triangle 2" ); 03040 rval = _mbImpl->add_entities( surface, newTris, 2 ); 03041 MBERRORR( rval, "can't add triangles to the set" ); 03042 } 03043 // 03044 } 03045 return MB_SUCCESS; 03046 } 03047 ErrorCode FBEngine::boundary_mesh_edges_on_face( EntityHandle face, Range& boundary_mesh_edges ) 03048 { 03049 // this list is used only for finding the intersecting mesh edge for starting the 03050 // polygonal cutting line at boundary (if !closed) 03051 Range bound_edges; 03052 ErrorCode rval = getAdjacentEntities( face, 1, bound_edges ); 03053 MBERRORR( rval, " can't get boundary edges" ); 03054 for( Range::iterator it = bound_edges.begin(); it != bound_edges.end(); ++it ) 03055 { 03056 EntityHandle b_edge = *it; 03057 // get all edges in range 03058 // Range mesh_edges; 03059 rval = _mbImpl->get_entities_by_dimension( b_edge, 1, boundary_mesh_edges ); 03060 MBERRORR( rval, " can't get mesh edges" ); 03061 } 03062 return MB_SUCCESS; 03063 } 03064 ErrorCode FBEngine::boundary_nodes_on_face( EntityHandle face, std::vector< EntityHandle >& boundary_nodes ) 03065 { 03066 // even if we repeat some nodes, it is OK 03067 // this list is used only for finding the closest boundary node for starting the 03068 // polygonal cutting line at boundary (if !closed) 03069 Range bound_edges; 03070 ErrorCode rval = getAdjacentEntities( face, 1, bound_edges ); 03071 MBERRORR( rval, " can't get boundary edges" ); 03072 Range b_nodes; 03073 for( Range::iterator it = bound_edges.begin(); it != bound_edges.end(); ++it ) 03074 { 03075 EntityHandle b_edge = *it; 03076 // get all edges in range 03077 Range mesh_edges; 03078 rval = _mbImpl->get_entities_by_dimension( b_edge, 1, mesh_edges ); 03079 MBERRORR( rval, " can't get mesh edges" ); 03080 rval = _mbImpl->get_connectivity( mesh_edges, b_nodes ); 03081 MBERRORR( rval, " can't get nodes from mesh edges" ); 03082 } 03083 // create now a vector based on Range of nodes 03084 boundary_nodes.resize( b_nodes.size() ); 03085 std::copy( b_nodes.begin(), b_nodes.end(), boundary_nodes.begin() ); 03086 return MB_SUCCESS; 03087 } 03088 // used for splitting an edge 03089 ErrorCode FBEngine::split_internal_edge( EntityHandle& edge, EntityHandle& newVertex ) 03090 { 03091 // split the edge, and form 4 new triangles and 2 edges 03092 // get 2 triangles adjacent to edge 03093 Range adj_tri; 03094 ErrorCode rval = _mbImpl->get_adjacencies( &edge, 1, 2, false, adj_tri ); 03095 MBERRORR( rval, "can't get adj_tris" ); 03096 adj_tri = subtract( adj_tri, _piercedTriangles ); 03097 if( adj_tri.size() >= 3 ) 03098 { 03099 std::cout << "WARNING: non manifold geometry. Are you sure?"; 03100 } 03101 for( Range::iterator it = adj_tri.begin(); it != adj_tri.end(); ++it ) 03102 { 03103 EntityHandle tri = *it; 03104 _piercedTriangles.insert( tri ); 03105 const EntityHandle* conn3; 03106 int nnodes; 03107 rval = _mbImpl->get_connectivity( tri, conn3, nnodes ); 03108 MBERRORR( rval, "can't get nodes" ); 03109 int num1, sense, offset; 03110 rval = _mbImpl->side_number( tri, edge, num1, sense, offset ); 03111 MBERRORR( rval, "can't get side number" ); 03112 // after we know the side number, we can split in 2 triangles 03113 // node i is opposite to edge i 03114 int num2 = ( num1 + 1 ) % 3; 03115 int num3 = ( num2 + 1 ) % 3; 03116 // the edge from num1 to num2 is split into 2 edges 03117 EntityHandle t1[] = { conn3[num2], conn3[num3], newVertex }; 03118 EntityHandle t2[] = { conn3[num1], newVertex, conn3[num3] }; 03119 EntityHandle newTriangle, newTriangle2; 03120 rval = _mbImpl->create_element( MBTRI, t1, 3, newTriangle ); 03121 MBERRORR( rval, "can't create triangle" ); 03122 _newTriangles.insert( newTriangle ); 03123 rval = _mbImpl->create_element( MBTRI, t2, 3, newTriangle2 ); 03124 MBERRORR( rval, "can't create triangle" ); 03125 _newTriangles.insert( newTriangle2 ); 03126 // create edges with this, indirectly 03127 std::vector< EntityHandle > edges0; 03128 rval = _mbImpl->get_adjacencies( &newTriangle, 1, 1, true, edges0 ); 03129 MBERRORR( rval, "can't get new edges" ); 03130 edges0.clear(); 03131 rval = _mbImpl->get_adjacencies( &newTriangle2, 1, 1, true, edges0 ); 03132 MBERRORR( rval, "can't get new edges" ); 03133 if( debug_splits ) 03134 { 03135 std::cout << "2 (out of 4) triangles formed:\n"; 03136 _mbImpl->list_entity( newTriangle ); 03137 print_debug_triangle( newTriangle ); 03138 _mbImpl->list_entity( newTriangle2 ); 03139 print_debug_triangle( newTriangle2 ); 03140 } 03141 } 03142 return MB_SUCCESS; 03143 } 03144 // triangle split 03145 ErrorCode FBEngine::divide_triangle( EntityHandle triangle, EntityHandle& newVertex ) 03146 { 03147 // 03148 _piercedTriangles.insert( triangle ); 03149 int nnodes = 0; 03150 const EntityHandle* conn3 = NULL; 03151 ErrorCode rval = _mbImpl->get_connectivity( triangle, conn3, nnodes ); 03152 MBERRORR( rval, "can't get nodes" ); 03153 EntityHandle t1[] = { conn3[0], conn3[1], newVertex }; 03154 EntityHandle t2[] = { conn3[1], conn3[2], newVertex }; 03155 EntityHandle t3[] = { conn3[2], conn3[0], newVertex }; 03156 EntityHandle newTriangle, newTriangle2, newTriangle3; 03157 rval = _mbImpl->create_element( MBTRI, t1, 3, newTriangle ); 03158 MBERRORR( rval, "can't create triangle" ); 03159 _newTriangles.insert( newTriangle ); 03160 rval = _mbImpl->create_element( MBTRI, t2, 3, newTriangle3 ); 03161 MBERRORR( rval, "can't create triangle" ); 03162 _newTriangles.insert( newTriangle3 ); 03163 rval = _mbImpl->create_element( MBTRI, t3, 3, newTriangle2 ); 03164 MBERRORR( rval, "can't create triangle" ); 03165 _newTriangles.insert( newTriangle2 ); 03166 03167 // create all edges 03168 std::vector< EntityHandle > edges0; 03169 rval = _mbImpl->get_adjacencies( &newTriangle, 1, 1, true, edges0 ); 03170 MBERRORR( rval, "can't get new edges" ); 03171 edges0.clear(); 03172 rval = _mbImpl->get_adjacencies( &newTriangle2, 1, 1, true, edges0 ); 03173 MBERRORR( rval, "can't get new edges" ); 03174 if( debug_splits ) 03175 { 03176 std::cout << "3 triangles formed:\n"; 03177 _mbImpl->list_entity( newTriangle ); 03178 print_debug_triangle( newTriangle ); 03179 _mbImpl->list_entity( newTriangle3 ); 03180 print_debug_triangle( newTriangle3 ); 03181 _mbImpl->list_entity( newTriangle2 ); 03182 print_debug_triangle( newTriangle2 ); 03183 std::cout << "original nodes in tri:\n"; 03184 _mbImpl->list_entity( conn3[0] ); 03185 _mbImpl->list_entity( conn3[1] ); 03186 _mbImpl->list_entity( conn3[2] ); 03187 } 03188 return MB_SUCCESS; 03189 } 03190 03191 ErrorCode FBEngine::create_volume_with_direction( EntityHandle newFace1, 03192 EntityHandle newFace2, 03193 double* direction, 03194 EntityHandle& volume ) 03195 { 03196 03197 // MESHSET 03198 // ErrorCode rval = _mbImpl->create_meshset(MESHSET_ORDERED, new_geo_edge); 03199 ErrorCode rval = _mbImpl->create_meshset( MESHSET_SET, volume ); 03200 MBERRORR( rval, "can't create volume" ); 03201 03202 int volumeMatId = 1; // just give a mat id, for debugging, mostly 03203 Tag matTag; 03204 rval = _mbImpl->tag_get_handle( MATERIAL_SET_TAG_NAME, 1, MB_TYPE_INTEGER, matTag ); 03205 MBERRORR( rval, "can't get material tag" ); 03206 03207 rval = _mbImpl->tag_set_data( matTag, &volume, 1, &volumeMatId ); 03208 MBERRORR( rval, "can't set material tag value on volume" ); 03209 03210 // get the edges of those 2 faces, and get the vertices of those edges 03211 // in order, they should be created in the same order (?); check for that, anyway 03212 rval = _mbImpl->add_parent_child( volume, newFace1 ); 03213 MBERRORR( rval, "can't add first face to volume" ); 03214 03215 rval = _mbImpl->add_parent_child( volume, newFace2 ); 03216 MBERRORR( rval, "can't add second face to volume" ); 03217 03218 // first is bottom, so it is negatively oriented 03219 rval = _my_geomTopoTool->add_geo_set( volume, 3 ); 03220 MBERRORR( rval, "can't add volume to the gtt" ); 03221 03222 // set senses 03223 // bottom face is negatively oriented, its normal is toward interior of the volume 03224 rval = _my_geomTopoTool->set_sense( newFace1, volume, -1 ); 03225 MBERRORR( rval, "can't set bottom face sense to the volume" ); 03226 03227 // the top face is positively oriented 03228 rval = _my_geomTopoTool->set_sense( newFace2, volume, 1 ); 03229 MBERRORR( rval, "can't set top face sense to the volume" ); 03230 03231 // the children should be in the same direction 03232 // get the side edges of each face, and form lateral faces, along direction 03233 std::vector< EntityHandle > edges1; 03234 std::vector< EntityHandle > edges2; 03235 03236 rval = _mbImpl->get_child_meshsets( newFace1, edges1 ); // no hops 03237 MBERRORR( rval, "can't get children edges or first face, bottom" ); 03238 03239 rval = _mbImpl->get_child_meshsets( newFace2, edges2 ); // no hops 03240 MBERRORR( rval, "can't get children edges for second face, top" ); 03241 03242 if( edges1.size() != edges2.size() ) MBERRORR( MB_FAILURE, "wrong correspondence " ); 03243 03244 for( unsigned int i = 0; i < edges1.size(); ++i ) 03245 { 03246 EntityHandle newLatFace; 03247 rval = weave_lateral_face_from_edges( edges1[i], edges2[i], direction, newLatFace ); 03248 MBERRORR( rval, "can't weave lateral face" ); 03249 rval = _mbImpl->add_parent_child( volume, newLatFace ); 03250 MBERRORR( rval, "can't add lateral face to volume" ); 03251 03252 // set sense as positive 03253 rval = _my_geomTopoTool->set_sense( newLatFace, volume, 1 ); 03254 MBERRORR( rval, "can't set lateral face sense to the volume" ); 03255 } 03256 03257 rval = set_default_neumann_tags(); 03258 MBERRORR( rval, "can't set new neumann tags" ); 03259 03260 return MB_SUCCESS; 03261 } 03262 03263 ErrorCode FBEngine::get_nodes_from_edge( EntityHandle gedge, std::vector< EntityHandle >& nodes ) 03264 { 03265 std::vector< EntityHandle > ents; 03266 ErrorCode rval = _mbImpl->get_entities_by_type( gedge, MBEDGE, ents ); 03267 if( MB_SUCCESS != rval ) return rval; 03268 if( ents.size() < 1 ) return MB_FAILURE; 03269 03270 nodes.resize( ents.size() + 1 ); 03271 const EntityHandle* conn = NULL; 03272 int len; 03273 for( unsigned int i = 0; i < ents.size(); ++i ) 03274 { 03275 rval = _mbImpl->get_connectivity( ents[i], conn, len ); 03276 MBERRORR( rval, "can't get edge connectivity" ); 03277 nodes[i] = conn[0]; 03278 } 03279 // the last one is conn[1] 03280 nodes[ents.size()] = conn[1]; 03281 return MB_SUCCESS; 03282 } 03283 ErrorCode FBEngine::weave_lateral_face_from_edges( EntityHandle bEdge, 03284 EntityHandle tEdge, 03285 double* direction, 03286 EntityHandle& newLatFace ) 03287 { 03288 // in weird cases might need to create new vertices in the interior; 03289 // in most cases, it is OK 03290 03291 ErrorCode rval = _mbImpl->create_meshset( MESHSET_SET, newLatFace ); 03292 MBERRORR( rval, "can't create new lateral face" ); 03293 03294 EntityHandle v[4]; // vertex sets 03295 // bot edge will be v1->v2 03296 // top edge will be v3->v4 03297 // we need to create edges from v1 to v3 and from v2 to v4 03298 std::vector< EntityHandle > adj; 03299 rval = _mbImpl->get_child_meshsets( bEdge, adj ); 03300 MBERRORR( rval, "can't get children nodes" ); 03301 bool periodic = false; 03302 if( adj.size() == 1 ) 03303 { 03304 v[0] = v[1] = adj[0]; 03305 periodic = true; 03306 } 03307 else 03308 { 03309 v[0] = adj[0]; 03310 v[1] = adj[1]; 03311 } 03312 int senseB; 03313 rval = getEgVtxSense( bEdge, v[0], v[1], senseB ); 03314 MBERRORR( rval, "can't get bottom edge sense" ); 03315 if( -1 == senseB ) 03316 { 03317 v[1] = adj[0]; // so , bEdge will be oriented from v[0] to v[1], and will start at 03318 // nodes1, coords1.. 03319 v[0] = adj[1]; 03320 } 03321 adj.clear(); 03322 rval = _mbImpl->get_child_meshsets( tEdge, adj ); 03323 MBERRORR( rval, "can't get children nodes" ); 03324 if( adj.size() == 1 ) 03325 { 03326 v[2] = v[3] = adj[0]; 03327 if( !periodic ) MBERRORR( MB_FAILURE, "top edge is periodic, but bottom edge is not" ); 03328 } 03329 else 03330 { 03331 v[2] = adj[0]; 03332 v[3] = adj[1]; 03333 if( periodic ) MBERRORR( MB_FAILURE, "top edge is not periodic, but bottom edge is" ); 03334 } 03335 03336 // now, using nodes on bottom edge and top edge, create triangles, oriented outwards the 03337 // volume (sense positive on bottom edge) 03338 std::vector< EntityHandle > nodes1; 03339 rval = get_nodes_from_edge( bEdge, nodes1 ); 03340 MBERRORR( rval, "can't get nodes from bott edge" ); 03341 03342 std::vector< EntityHandle > nodes2; 03343 rval = get_nodes_from_edge( tEdge, nodes2 ); 03344 MBERRORR( rval, "can't get nodes from top edge" ); 03345 03346 std::vector< CartVect > coords1, coords2; 03347 coords1.resize( nodes1.size() ); 03348 coords2.resize( nodes2.size() ); 03349 03350 int N1 = (int)nodes1.size(); 03351 int N2 = (int)nodes2.size(); 03352 03353 rval = _mbImpl->get_coords( &( nodes1[0] ), nodes1.size(), (double*)&( coords1[0] ) ); 03354 MBERRORR( rval, "can't get coords of nodes from bott edge" ); 03355 03356 rval = _mbImpl->get_coords( &( nodes2[0] ), nodes2.size(), (double*)&( coords2[0] ) ); 03357 MBERRORR( rval, "can't get coords of nodes from top edge" ); 03358 CartVect up( direction ); 03359 03360 // see if the start and end coordinates are matching, if not, reverse edge 2 nodes and 03361 // coordinates 03362 CartVect v1 = ( coords1[0] - coords2[0] ) * up; 03363 CartVect v2 = ( coords1[0] - coords2[N2 - 1] ) * up; 03364 if( v1.length_squared() > v2.length_squared() ) 03365 { 03366 // we need to reverse coords2 and node2, as nodes are not above each other 03367 // the edges need to be found between v0 and v3, v1 and v2! 03368 for( unsigned int k = 0; k < nodes2.size() / 2; k++ ) 03369 { 03370 EntityHandle tmp = nodes2[k]; 03371 nodes2[k] = nodes2[N2 - 1 - k]; 03372 nodes2[N2 - 1 - k] = tmp; 03373 CartVect tv = coords2[k]; 03374 coords2[k] = coords2[N2 - 1 - k]; 03375 coords2[N2 - 1 - k] = tv; 03376 } 03377 } 03378 // make sure v[2] has nodes2[0], if not, reverse v[2] and v[3] 03379 if( !_mbImpl->contains_entities( v[2], &( nodes2[0] ), 1 ) ) 03380 { 03381 // reverse v[2] and v[3], so v[2] will be above v[0] 03382 EntityHandle tmp = v[2]; 03383 v[2] = v[3]; 03384 v[3] = tmp; 03385 } 03386 // now we know that v[0]--v[3] will be vertex sets in the order we want 03387 EntityHandle nd[4] = { nodes1[0], nodes1[N1 - 1], nodes2[0], nodes2[N2 - 1] }; 03388 03389 adj.clear(); 03390 EntityHandle e1, e2; 03391 // find edge 1 between v[0] and v[2], and e2 between v[1] and v[3] 03392 rval = _mbImpl->get_parent_meshsets( v[0], adj ); 03393 MBERRORR( rval, "can't get edges connected to vertex set 1" ); 03394 bool found = false; 03395 for( unsigned int j = 0; j < adj.size(); j++ ) 03396 { 03397 EntityHandle ed = adj[j]; 03398 Range vertices; 03399 rval = _mbImpl->get_child_meshsets( ed, vertices ); 03400 if( vertices.find( v[2] ) != vertices.end() ) 03401 { 03402 found = true; 03403 e1 = ed; 03404 break; 03405 } 03406 } 03407 if( !found ) 03408 { 03409 // create an edge from v[0] to v[2] 03410 rval = _mbImpl->create_meshset( MESHSET_SET, e1 ); 03411 MBERRORR( rval, "can't create edge 1" ); 03412 03413 rval = _mbImpl->add_parent_child( e1, v[0] ); 03414 MBERRORR( rval, "can't add parent - child relation" ); 03415 03416 rval = _mbImpl->add_parent_child( e1, v[2] ); 03417 MBERRORR( rval, "can't add parent - child relation" ); 03418 03419 EntityHandle nn2[2] = { nd[0], nd[2] }; 03420 EntityHandle medge; 03421 rval = _mbImpl->create_element( MBEDGE, nn2, 2, medge ); 03422 MBERRORR( rval, "can't create mesh edge" ); 03423 03424 rval = _mbImpl->add_entities( e1, &medge, 1 ); 03425 MBERRORR( rval, "can't add mesh edge to geo edge" ); 03426 03427 rval = this->_my_geomTopoTool->add_geo_set( e1, 1 ); 03428 MBERRORR( rval, "can't add edge to gtt" ); 03429 } 03430 03431 // find the edge from v2 to v4 (if not, create one) 03432 rval = _mbImpl->get_parent_meshsets( v[1], adj ); 03433 MBERRORR( rval, "can't get edges connected to vertex set 2" ); 03434 found = false; 03435 for( unsigned int i = 0; i < adj.size(); i++ ) 03436 { 03437 EntityHandle ed = adj[i]; 03438 Range vertices; 03439 rval = _mbImpl->get_child_meshsets( ed, vertices ); 03440 if( vertices.find( v[3] ) != vertices.end() ) 03441 { 03442 found = true; 03443 e2 = ed; 03444 break; 03445 } 03446 } 03447 if( !found ) 03448 { 03449 // create an edge from v2 to v4 03450 rval = _mbImpl->create_meshset( MESHSET_SET, e2 ); 03451 MBERRORR( rval, "can't create edge 1" ); 03452 03453 rval = _mbImpl->add_parent_child( e2, v[1] ); 03454 MBERRORR( rval, "can't add parent - child relation" ); 03455 03456 rval = _mbImpl->add_parent_child( e2, v[3] ); 03457 MBERRORR( rval, "can't add parent - child relation" ); 03458 03459 EntityHandle nn2[2] = { nd[1], nd[3] }; 03460 EntityHandle medge; 03461 rval = _mbImpl->create_element( MBEDGE, nn2, 2, medge ); 03462 MBERRORR( rval, "can't create mesh edge" ); 03463 03464 rval = _mbImpl->add_entities( e2, &medge, 1 ); 03465 MBERRORR( rval, "can't add mesh edge to geo edge" ); 03466 03467 rval = _my_geomTopoTool->add_geo_set( e2, 1 ); 03468 MBERRORR( rval, "can't add edge to gtt" ); 03469 } 03470 03471 // now we have the four edges, add them to the face, as children 03472 03473 // add children to face 03474 rval = _mbImpl->add_parent_child( newLatFace, bEdge ); 03475 MBERRORR( rval, "can't add parent - child relation" ); 03476 03477 rval = _mbImpl->add_parent_child( newLatFace, tEdge ); 03478 MBERRORR( rval, "can't add parent - child relation" ); 03479 03480 rval = _mbImpl->add_parent_child( newLatFace, e1 ); 03481 MBERRORR( rval, "can't add parent - child relation" ); 03482 03483 rval = _mbImpl->add_parent_child( newLatFace, e2 ); 03484 MBERRORR( rval, "can't add parent - child relation" ); 03485 03486 rval = _my_geomTopoTool->add_geo_set( newLatFace, 2 ); 03487 MBERRORR( rval, "can't add face to gtt" ); 03488 // add senses 03489 // 03490 rval = _my_geomTopoTool->set_sense( bEdge, newLatFace, 1 ); 03491 MBERRORR( rval, "can't set bottom edge sense to the lateral face" ); 03492 03493 int Tsense; 03494 rval = getEgVtxSense( tEdge, v[3], v[2], Tsense ); 03495 MBERRORR( rval, "can't get top edge sense" ); 03496 // we need to see what sense has topEdge in face 03497 rval = _my_geomTopoTool->set_sense( tEdge, newLatFace, Tsense ); 03498 MBERRORR( rval, "can't set top edge sense to the lateral face" ); 03499 03500 rval = _my_geomTopoTool->set_sense( e1, newLatFace, -1 ); 03501 MBERRORR( rval, "can't set first vert edge sense" ); 03502 03503 rval = _my_geomTopoTool->set_sense( e2, newLatFace, 1 ); 03504 MBERRORR( rval, "can't set second edge sense to the lateral face" ); 03505 // first, create edges along direction, for the 03506 03507 int indexB = 0, indexT = 0; // indices of the current nodes in the weaving process 03508 // weaving is either up or down; the triangles are oriented positively either way 03509 // up is nodes1[indexB], nodes2[indexT+1], nodes2[indexT] 03510 // down is nodes1[indexB], nodes1[indexB+1], nodes2[indexT] 03511 // the decision to weave up or down is based on which one is closer to the direction normal 03512 /* 03513 * 03514 * --------*------*-----------* ^ 03515 * / . \ . . ------> dir1 | up 03516 * /. \ . . | 03517 * -----*------------*----* 03518 * 03519 */ 03520 // we have to change the logic to account for cases when the curve in xy plane is not straight 03521 // (for example, when merging curves with a min_dot < -0.5, which means that the edges 03522 // could be even closed (periodic), with one vertex 03523 // the top and bottom curves should follow the same path in the "xy" plane (better to say 03524 // the plane perpendicular to the direction of weaving) 03525 // in this logic, the vector dir1 varies along the curve !!! 03526 CartVect dir1 = coords1[1] - coords1[0]; // we should have at least 2 nodes, N1>=2!! 03527 03528 CartVect planeNormal = dir1 * up; 03529 dir1 = up * planeNormal; 03530 dir1.normalize(); 03531 // this direction will be updated constantly with the direction of last edge added 03532 bool weaveDown = true; 03533 03534 CartVect startP = coords1[0]; // used for origin of comparisons 03535 while( 1 ) 03536 { 03537 if( ( indexB == N1 - 1 ) && ( indexT == N2 - 1 ) ) break; // we cannot advance anymore 03538 if( indexB == N1 - 1 ) 03539 { 03540 weaveDown = false; 03541 } 03542 else if( indexT == N2 - 1 ) 03543 { 03544 weaveDown = true; 03545 } 03546 else 03547 { 03548 // none are at the end, we have to decide which way to go, based on which index + 1 is 03549 // closer 03550 double proj1 = ( coords1[indexB + 1] - startP ) % dir1; 03551 double proj2 = ( coords2[indexT + 1] - startP ) % dir1; 03552 if( proj1 < proj2 ) 03553 weaveDown = true; 03554 else 03555 weaveDown = false; 03556 } 03557 EntityHandle nTri[3] = { nodes1[indexB], 0, nodes2[indexT] }; 03558 if( weaveDown ) 03559 { 03560 nTri[1] = nodes1[indexB + 1]; 03561 nTri[2] = nodes2[indexT]; 03562 indexB++; 03563 } 03564 else 03565 { 03566 nTri[1] = nodes2[indexT + 1]; 03567 indexT++; 03568 } 03569 EntityHandle triangle; 03570 rval = _mbImpl->create_element( MBTRI, nTri, 3, triangle ); 03571 MBERRORR( rval, "can't create triangle" ); 03572 03573 rval = _mbImpl->add_entities( newLatFace, &triangle, 1 ); 03574 MBERRORR( rval, "can't add triangle to face set" ); 03575 if( weaveDown ) 03576 { 03577 // increase was from nodes1[indexB-1] to nodes1[indexb] 03578 dir1 = coords1[indexB] - coords1[indexB - 1]; // we should have at least 2 nodes, N1>=2!! 03579 } 03580 else 03581 { 03582 dir1 = coords2[indexT] - coords2[indexT - 1]; 03583 } 03584 dir1 = up * ( dir1 * up ); 03585 dir1.normalize(); 03586 } 03587 // we do not check yet if the triangles are inverted 03588 // if yes, we should correct them. HOW? 03589 // we probably need a better meshing strategy, one that can overcome really bad meshes. 03590 // again, these faces are not what we should use for geometry, maybe we should use the 03591 // extruded quads, identified AFTER hexa are created. 03592 // right now, I see only a cosmetic use of these lateral faces 03593 // the whole idea of volume maybe is overrated 03594 // volume should be just quads extruded from bottom ? 03595 // 03596 return MB_SUCCESS; 03597 } 03598 // this will be used during creation of the volume, to set unique 03599 // tags on all surfaces 03600 // it is changing original tags, so do not use it if you want to preserve 03601 // initial neumann tags 03602 ErrorCode FBEngine::set_default_neumann_tags() 03603 { 03604 // these are for debugging purposes only 03605 // check the initial tag, then 03606 Tag ntag; 03607 ErrorCode rval = _mbImpl->tag_get_handle( NEUMANN_SET_TAG_NAME, 1, MB_TYPE_INTEGER, ntag ); 03608 MBERRORR( rval, "can't get tag handle" ); 03609 // get all surfaces in the model now 03610 Range sets[5]; 03611 rval = _my_geomTopoTool->find_geomsets( sets ); 03612 MBERRORR( rval, "can't get geo sets" ); 03613 int nfaces = (int)sets[2].size(); 03614 int* vals = new int[nfaces]; 03615 for( int i = 0; i < nfaces; i++ ) 03616 { 03617 vals[i] = i + 1; 03618 } 03619 rval = _mbImpl->tag_set_data( ntag, sets[2], (void*)vals ); 03620 MBERRORR( rval, "can't set tag values for neumann sets" ); 03621 03622 delete[] vals; 03623 03624 return MB_SUCCESS; 03625 } 03626 // a reverse operation for splitting an gedge at a mesh node 03627 ErrorCode FBEngine::chain_edges( double min_dot ) 03628 { 03629 Range sets[5]; 03630 ErrorCode rval; 03631 while( 1 ) // break out only if no edges are chained 03632 { 03633 rval = _my_geomTopoTool->find_geomsets( sets ); 03634 MBERRORR( rval, "can't get geo sets" ); 03635 // these gentities are "always" current, while the ones in this-> _my_gsets[0:4] are 03636 // the "originals" before FBEngine modifications 03637 int nedges = (int)sets[1].size(); 03638 // as long as we have chainable edges, continue; 03639 bool chain = false; 03640 for( int i = 0; i < nedges; i++ ) 03641 { 03642 EntityHandle edge = sets[1][i]; 03643 EntityHandle next_edge; 03644 bool chainable = false; 03645 rval = chain_able_edge( edge, min_dot, next_edge, chainable ); 03646 MBERRORR( rval, "can't determine chain-ability" ); 03647 if( chainable ) 03648 { 03649 rval = chain_two_edges( edge, next_edge ); 03650 MBERRORR( rval, "can't chain 2 edges" ); 03651 chain = true; 03652 break; // interrupt for loop 03653 } 03654 } 03655 if( !chain ) 03656 { 03657 break; // break out of while loop 03658 } 03659 } 03660 return MB_SUCCESS; 03661 } 03662 03663 // determine if from the end of edge we can extend with another edge; return also the 03664 // extension edge (next_edge) 03665 ErrorCode FBEngine::chain_able_edge( EntityHandle edge, double min_dot, EntityHandle& next_edge, bool& chainable ) 03666 { 03667 // get the end, then get all parents of end 03668 // see if some are the starts of 03669 chainable = false; 03670 EntityHandle v1, v2; 03671 ErrorCode rval = get_vert_edges( edge, v1, v2 ); 03672 MBERRORR( rval, "can't get vertices" ); 03673 if( v1 == v2 ) return MB_SUCCESS; // it is periodic, can't chain it with another edge! 03674 03675 // v2 is a set, get its parents, which should be edges 03676 Range edges; 03677 rval = _mbImpl->get_parent_meshsets( v2, edges ); 03678 MBERRORR( rval, "can't get parents of vertex set" ); 03679 // get parents of current edge (faces) 03680 Range faces; 03681 rval = _mbImpl->get_parent_meshsets( edge, faces ); 03682 MBERRORR( rval, "can't get parents of edge set" ); 03683 // get also the last edge "tangent" at the vertex 03684 std::vector< EntityHandle > mesh_edges; 03685 rval = _mbImpl->get_entities_by_type( edge, MBEDGE, mesh_edges ); 03686 MBERRORR( rval, "can't get mesh edges from edge set" ); 03687 EntityHandle lastMeshEdge = mesh_edges[mesh_edges.size() - 1]; 03688 const EntityHandle* conn2 = NULL; 03689 int len = 0; 03690 rval = _mbImpl->get_connectivity( lastMeshEdge, conn2, len ); 03691 MBERRORR( rval, "can't connectivity of last mesh edge" ); 03692 // get the coordinates of last edge 03693 if( len != 2 ) MBERRORR( MB_FAILURE, "bad number of vertices" ); 03694 CartVect P[2]; 03695 rval = _mbImpl->get_coords( conn2, len, (double*)&P[0] ); 03696 MBERRORR( rval, "Failed to get coordinates" ); 03697 03698 CartVect vec1( P[1] - P[0] ); 03699 vec1.normalize(); 03700 for( Range::iterator edgeIter = edges.begin(); edgeIter != edges.end(); ++edgeIter ) 03701 { 03702 EntityHandle otherEdge = *edgeIter; 03703 if( edge == otherEdge ) continue; 03704 // get faces parents of this edge 03705 Range faces2; 03706 rval = _mbImpl->get_parent_meshsets( otherEdge, faces2 ); 03707 MBERRORR( rval, "can't get parents of other edge set" ); 03708 if( faces != faces2 ) continue; 03709 // now, if the first mesh edge is within given angle, we can go on 03710 std::vector< EntityHandle > mesh_edges2; 03711 rval = _mbImpl->get_entities_by_type( otherEdge, MBEDGE, mesh_edges2 ); 03712 MBERRORR( rval, "can't get mesh edges from other edge set" ); 03713 EntityHandle firstMeshEdge = mesh_edges2[0]; 03714 const EntityHandle* conn22; 03715 int len2; 03716 rval = _mbImpl->get_connectivity( firstMeshEdge, conn22, len2 ); 03717 MBERRORR( rval, "can't connectivity of first mesh edge" ); 03718 if( len2 != 2 ) MBERRORR( MB_FAILURE, "bad number of vertices" ); 03719 if( conn2[1] != conn22[0] ) continue; // the mesh edges are not one after the other 03720 // get the coordinates of first edge 03721 03722 // CartVect P2[2]; 03723 rval = _mbImpl->get_coords( conn22, len, (double*)&P[0] ); 03724 CartVect vec2( P[1] - P[0] ); 03725 vec2.normalize(); 03726 if( vec1 % vec2 < min_dot ) continue; 03727 // we found our edge, victory! we can get out 03728 next_edge = otherEdge; 03729 chainable = true; 03730 return MB_SUCCESS; 03731 } 03732 03733 return MB_SUCCESS; // in general, hard to come by chain-able edges 03734 } 03735 ErrorCode FBEngine::chain_two_edges( EntityHandle edge, EntityHandle next_edge ) 03736 { 03737 // the biggest thing is to see the sense tags; or maybe not... 03738 // they should be correct :) 03739 // get the vertex sets 03740 EntityHandle v11, v12, v21, v22; 03741 ErrorCode rval = get_vert_edges( edge, v11, v12 ); 03742 MBERRORR( rval, "can't get vert sets" ); 03743 rval = get_vert_edges( next_edge, v21, v22 ); 03744 MBERRORR( rval, "can't get vert sets" ); 03745 assert( v12 == v21 ); 03746 std::vector< EntityHandle > mesh_edges; 03747 rval = MBI->get_entities_by_type( next_edge, MBEDGE, mesh_edges ); 03748 MBERRORR( rval, "can't get mesh edges" ); 03749 03750 rval = _mbImpl->add_entities( edge, &mesh_edges[0], (int)mesh_edges.size() ); 03751 MBERRORR( rval, "can't add new mesh edges" ); 03752 // remove the child - parent relation for second vertex of first edge 03753 rval = _mbImpl->remove_parent_child( edge, v12 ); 03754 MBERRORR( rval, "can't remove parent - child relation between first edge and middle vertex" ); 03755 03756 if( v22 != v11 ) // the edge would become periodic, do not add again the relationship 03757 { 03758 rval = _mbImpl->add_parent_child( edge, v22 ); 03759 MBERRORR( rval, "can't add second vertex to edge " ); 03760 } 03761 // we can now safely eliminate next_edge 03762 rval = _mbImpl->remove_parent_child( next_edge, v21 ); 03763 MBERRORR( rval, "can't remove child - parent relation " ); 03764 03765 rval = _mbImpl->remove_parent_child( next_edge, v22 ); 03766 MBERRORR( rval, "can't remove child - parent relation " ); 03767 03768 // remove the next_edge relation to the faces 03769 Range faces; 03770 rval = _mbImpl->get_parent_meshsets( next_edge, faces ); 03771 MBERRORR( rval, "can't get parent faces " ); 03772 03773 for( Range::iterator it = faces.begin(); it != faces.end(); ++it ) 03774 { 03775 EntityHandle ff = *it; 03776 rval = _mbImpl->remove_parent_child( ff, next_edge ); 03777 MBERRORR( rval, "can't remove parent-edge rel " ); 03778 } 03779 03780 rval = _mbImpl->delete_entities( &next_edge, 1 ); 03781 MBERRORR( rval, "can't remove edge set " ); 03782 03783 // delete the vertex set that is idle now (v12 = v21) 03784 rval = _mbImpl->delete_entities( &v12, 1 ); 03785 MBERRORR( rval, "can't remove edge set " ); 03786 return MB_SUCCESS; 03787 } 03788 ErrorCode FBEngine::get_vert_edges( EntityHandle edge, EntityHandle& v1, EntityHandle& v2 ) 03789 { 03790 // need to decide first or second vertex 03791 // important for moab 03792 03793 Range children; 03794 // EntityHandle v1, v2; 03795 ErrorCode rval = _mbImpl->get_child_meshsets( edge, children ); 03796 MBERRORR( rval, "can't get child meshsets" ); 03797 if( children.size() == 1 ) 03798 { 03799 // this is periodic edge, get out early 03800 v1 = children[0]; 03801 v2 = v1; 03802 return MB_SUCCESS; 03803 } 03804 else if( children.size() > 2 ) 03805 MBERRORR( MB_FAILURE, "too many vertices in one edge" ); 03806 // edge: get one vertex as part of the vertex set 03807 Range entities; 03808 rval = MBI->get_entities_by_type( children[0], MBVERTEX, entities ); 03809 MBERRORR( rval, "can't get entities from vertex set" ); 03810 if( entities.size() < 1 ) MBERRORR( MB_FAILURE, "no mesh nodes in vertex set" ); 03811 EntityHandle node0 = entities[0]; // the first vertex 03812 entities.clear(); 03813 03814 // now get the edges, and get the first node and the last node in sequence of edges 03815 // the order is important... 03816 // these are ordered sets !! 03817 std::vector< EntityHandle > ents; 03818 rval = MBI->get_entities_by_type( edge, MBEDGE, ents ); 03819 MBERRORR( rval, "can't get mesh edges" ); 03820 if( ents.size() < 1 ) MBERRORR( MB_FAILURE, "no mesh edges in edge set" ); 03821 03822 const EntityHandle* conn = NULL; 03823 int len; 03824 rval = MBI->get_connectivity( ents[0], conn, len ); 03825 MBERRORR( rval, "can't connectivity of first mesh edge" ); 03826 03827 if( conn[0] == node0 ) 03828 { 03829 v1 = children[0]; 03830 v2 = children[1]; 03831 } 03832 else // the other way around, although we should check (we are paranoid) 03833 { 03834 v2 = children[0]; 03835 v1 = children[1]; 03836 } 03837 03838 return MB_SUCCESS; 03839 } 03840 } // namespace moab