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