moab
|
Tools for constructing and working with mesh duals (both tet- and hex-based, though some functions may not make sense for tet duals) More...
#include <DualTool.hpp>
Classes | |
class | GraphicsPoint |
struct for storing a graphics pt More... | |
Public Member Functions | |
DualTool (Interface *impl) | |
~DualTool () | |
ErrorCode | construct_dual (EntityHandle *entities, const int num_entities) |
construct the dual entities for the entire mesh | |
ErrorCode | construct_hex_dual (EntityHandle *entities, const int num_entities) |
construct the dual entities for a hex mesh, including dual surfaces & curves | |
ErrorCode | construct_hex_dual (Range &entities) |
construct the dual entities for a hex mesh, including dual surfaces & curves | |
ErrorCode | get_dual_entities (const int dim, EntityHandle *entities, const int num_entities, Range &dual_ents) |
get the dual entities; if non-null, only dual of entities passed in are returned | |
ErrorCode | get_dual_entities (const int dim, EntityHandle *entities, const int num_entities, std::vector< EntityHandle > &dual_ents) |
get the dual entities; if non-null, only dual of entities passed in are returned | |
EntityHandle | get_dual_entity (const EntityHandle this_ent) const |
return the corresponding dual entity | |
EntityHandle | get_extra_dual_entity (const EntityHandle this_ent) |
return the corresponding extra dual entity | |
ErrorCode | get_graphics_points (EntityHandle dual_ent, std::vector< int > &npts, std::vector< GraphicsPoint > &gpoints) |
ErrorCode | get_graphics_points (const Range &in_range, std::vector< GraphicsPoint > &gpoints, const bool assign_ids=false, const int start_id=0) |
EntityHandle | next_loop_vertex (const EntityHandle last_v, const EntityHandle this_v, const EntityHandle dual_surf) |
Tag | dualSurface_tag () const |
get/set the tag for dual surfaces | |
ErrorCode | dualSurface_tag (const Tag tag) |
get/set the tag for dual surfaces | |
Tag | dualCurve_tag () const |
get/set the tag for dual curves | |
ErrorCode | dualCurve_tag (const Tag tag) |
get/set the tag for dual curves | |
Tag | isDualCell_tag () const |
get/set the tag for dual cells | |
ErrorCode | isDualCell_tag (const Tag tag) |
get/set the tag for dual cells | |
Tag | dualEntity_tag () const |
get/set the tag for dual entities | |
ErrorCode | dualEntity_tag (const Tag tag) |
get/set the tag for dual entities | |
Tag | extraDualEntity_tag () const |
get/set the tag for dual entities | |
ErrorCode | extraDualEntity_tag (const Tag tag) |
get/set the tag for dual entities | |
Tag | dualGraphicsPoint_tag () const |
get/set the tag for dual entities | |
ErrorCode | dualGraphicsPoint_tag (const Tag tag) |
get/set the tag for dual entities | |
Tag | globalId_tag () const |
get/set the global id tag | |
ErrorCode | globalId_tag (const Tag tag) |
get/set the tag for dual entities | |
EntityHandle | get_dual_hyperplane (const EntityHandle ncell) |
given an entity, return any dual surface or curve it's in | |
bool | is_blind (const EntityHandle chord) |
returns true if first & last vertices are dual to hexes (not faces) | |
ErrorCode | set_dual_surface_or_curve (EntityHandle entity, const EntityHandle dual_hyperplane, const int dimension) |
set the dual surface or curve for an entity | |
ErrorCode | atomic_pillow (EntityHandle odedge, EntityHandle &quad1, EntityHandle &quad2) |
effect atomic pillow operation | |
ErrorCode | rev_atomic_pillow (EntityHandle pillow, Range &chords) |
effect reverse atomic pillow operation | |
ErrorCode | face_shrink (EntityHandle odedge) |
effect face shrink operation | |
ErrorCode | rev_face_shrink (EntityHandle edge) |
effect reverse atomic pillow operation | |
ErrorCode | face_open_collapse (EntityHandle ocl, EntityHandle ocr) |
effect a face open-collapse operation | |
ErrorCode | foc_get_ents (EntityHandle ocl, EntityHandle ocr, EntityHandle *quads, EntityHandle *split_edges, EntityHandle *split_nodes, Range &hexes, EntityHandle *other_edges, EntityHandle *other_nodes) |
ErrorCode | get_opposite_verts (const EntityHandle middle_edge, const EntityHandle chord, EntityHandle *verts) |
ErrorCode | get_dual_entities (const EntityHandle dual_ent, Range *dcells, Range *dedges, Range *dverts, Range *dverts_loop, Range *dedges_loop) |
ErrorCode | list_entities (const Range &entities) const |
ErrorCode | list_entities (const EntityHandle *entities, const int num_entities) const |
ErrorCode | delete_whole_dual () |
delete all the dual data | |
ErrorCode | check_dual_adjs () |
check dual-primal adjacencies | |
Static Public Member Functions | |
static ErrorCode | get_dual_hyperplanes (const Interface *impl, const int dim, Range &dual_ents) |
Static Public Attributes | |
static const char * | DUAL_SURFACE_TAG_NAME = "DUAL_SURFACE" |
tag name for dual surfaces | |
static const char * | DUAL_CURVE_TAG_NAME = "DUAL_CURVE" |
tag name for dual curves | |
static const char * | IS_DUAL_CELL_TAG_NAME = "__IS_DUAL_CELL" |
tag name for dual cells | |
static const char * | DUAL_ENTITY_TAG_NAME = "__DUAL_ENTITY" |
tag name for dual entitys | |
static const char * | EXTRA_DUAL_ENTITY_TAG_NAME = "__EXTRA_DUAL_ENTITY" |
tag name for dual entitys | |
static const char * | DUAL_GRAPHICS_POINT_TAG_NAME = "__DUAL_GRAPHICS_POINT" |
tag name for dual entitys | |
Private Types | |
enum | { GP_SIZE = 20 } |
static constant number of points bounding any cell More... | |
Private Member Functions | |
ErrorCode | construct_dual_vertices (const Range &all_regions, Range &new_dual_ents) |
construct dual vertices for specified regions | |
ErrorCode | construct_dual_edges (const Range &all_faces, Range &new_dual_ents) |
construct dual edges for specified faces | |
ErrorCode | construct_dual_faces (const Range &all_edges, Range &new_dual_ents) |
construct dual faces for specified edges | |
ErrorCode | construct_dual_cells (const Range &all_verts, Range &new_dual_ents) |
construct dual cells for specified vertices | |
ErrorCode | construct_dual_hyperplanes (const int dim, EntityHandle *entities, const int num_entities) |
ErrorCode | order_chord (EntityHandle chord_set) |
order 1cells on a chord | |
ErrorCode | construct_new_hyperplane (const int dim, EntityHandle &new_hyperplane, int &id) |
ErrorCode | traverse_hyperplane (const Tag hp_tag, EntityHandle &this_hp, EntityHandle this_ent) |
ErrorCode | construct_hp_parent_child () |
connect dual surfaces with dual curves using parent/child connections | |
ErrorCode | get_radial_dverts (const EntityHandle edge, std::vector< EntityHandle > &rad_verts, bool &bdy_edge) |
ErrorCode | construct_dual_vertex (EntityHandle entity, EntityHandle &dual_ent, const bool extra=false, const bool add_graphics_pt=true) |
ErrorCode | add_graphics_point (EntityHandle entity, double *avg_pos=NULL) |
add a graphics point to an entity (on a tag) | |
ErrorCode | get_cell_points (EntityHandle dual_ent, std::vector< int > &npts, std::vector< GraphicsPoint > &points) |
get points defining facets of a 2cell | |
bool | check_1d_loop_edge (EntityHandle this_ent) |
ErrorCode | check_dual_equiv_edges (Range &dual_edges) |
ErrorCode | delete_dual_entities (EntityHandle *entities, const int num_entities) |
delete a dual entity; updates primal to no longer point to it | |
ErrorCode | delete_dual_entities (Range &entities) |
delete a range of dual entities; updates primal to no longer point to them | |
ErrorCode | fs_check_quad_sense (EntityHandle hex0, EntityHandle quad0, std::vector< EntityHandle > *connects) |
check sense of connect arrays, and reverse/rotate if necessary | |
ErrorCode | fs_get_quads (EntityHandle odedge, EntityHandle *quads, EntityHandle *hexes, std::vector< EntityHandle > *connects) |
ErrorCode | fs_get_quad_loops (EntityHandle *hexes, std::vector< EntityHandle > *connects, std::vector< EntityHandle > *side_quads) |
get loops of quads around 2 hexes, ordered similarly to vertex loops | |
ErrorCode | fsr_get_fourth_quad (std::vector< EntityHandle > *connects, std::vector< EntityHandle > *side_quads) |
ErrorCode | foc_delete_dual (EntityHandle *split_quads, EntityHandle *split_edges, Range &hexes) |
ErrorCode | split_pair_nonmanifold (EntityHandle *split_quads, EntityHandle *split_edges, EntityHandle *split_nodes, std::vector< EntityHandle > *star_dp1, std::vector< EntityHandle > *star_dp2, EntityHandle *other_edges, EntityHandle *other_nodes, EntityHandle *new_quads, EntityHandle *new_edges, EntityHandle *new_nodes) |
split a pair of quads and the edge(s) shared by them | |
ErrorCode | foc_get_addl_ents (std::vector< EntityHandle > *star_dp1, std::vector< EntityHandle > *star_dp2, EntityHandle *split_edges, EntityHandle split_node, Range *addl_ents) |
ErrorCode | foc_get_stars (EntityHandle *split_quads, EntityHandle *split_edges, std::vector< EntityHandle > *star_dp1, std::vector< EntityHandle > *star_dp2) |
void | print_cell (EntityHandle cell) |
Private Attributes | |
Interface * | mbImpl |
private copy of interface * | |
Tag | dualCurveTag |
tags used for dual surfaces, curves, cells, entities | |
Tag | dualSurfaceTag |
Tag | isDualCellTag |
Tag | dualEntityTag |
Tag | extraDualEntityTag |
Tag | dualGraphicsPointTag |
Tag | categoryTag |
Tag | globalIdTag |
int | maxHexId |
Tools for constructing and working with mesh duals (both tet- and hex-based, though some functions may not make sense for tet duals)
Definition at line 31 of file DualTool.hpp.
anonymous enum [private] |
static constant number of points bounding any cell
Definition at line 371 of file DualTool.hpp.
{ GP_SIZE=20 };
moab::DualTool::DualTool | ( | Interface * | impl | ) |
Definition at line 61 of file DualTool.cpp.
: mbImpl(impl) { EntityHandle dum_handle = 0; ErrorCode result; result = mbImpl->tag_get_handle( DUAL_SURFACE_TAG_NAME, 1, MB_TYPE_HANDLE, dualSurfaceTag, MB_TAG_SPARSE|MB_TAG_CREAT, &dum_handle ); assert(MB_SUCCESS == result); result = mbImpl->tag_get_handle( DUAL_CURVE_TAG_NAME, 1, MB_TYPE_HANDLE, dualCurveTag, MB_TAG_SPARSE|MB_TAG_CREAT, &dum_handle ); assert(MB_SUCCESS == result); unsigned int dummy = 0; result = mbImpl->tag_get_handle( IS_DUAL_CELL_TAG_NAME, 1, MB_TYPE_INTEGER, isDualCellTag, MB_TAG_SPARSE|MB_TAG_CREAT, &dummy); assert(MB_SUCCESS == result); result = mbImpl->tag_get_handle( DUAL_ENTITY_TAG_NAME, 1, MB_TYPE_HANDLE, dualEntityTag, MB_TAG_DENSE|MB_TAG_CREAT, &dum_handle ); assert(MB_SUCCESS == result); result = mbImpl->tag_get_handle( EXTRA_DUAL_ENTITY_TAG_NAME, 1, MB_TYPE_HANDLE, extraDualEntityTag, MB_TAG_SPARSE|MB_TAG_CREAT, &dum_handle ); assert(MB_SUCCESS == result); static const char dum_name[CATEGORY_TAG_SIZE] = {0}; result = mbImpl->tag_get_handle( CATEGORY_TAG_NAME, CATEGORY_TAG_SIZE, MB_TYPE_OPAQUE, categoryTag, MB_TAG_SPARSE|MB_TAG_CREAT, dum_name ); assert(MB_SUCCESS == result); DualTool::GraphicsPoint dum_pt(0.0, 0.0, 0.0, -1); result = mbImpl->tag_get_handle(DUAL_GRAPHICS_POINT_TAG_NAME, sizeof(DualTool::GraphicsPoint), MB_TYPE_DOUBLE, dualGraphicsPointTag, MB_TAG_DENSE|MB_TAG_CREAT|MB_TAG_BYTES, &dum_pt); assert(MB_SUCCESS == result); int dum_int = 0; result = mbImpl->tag_get_handle( GLOBAL_ID_TAG_NAME, 1, MB_TYPE_INTEGER, globalIdTag, MB_TAG_SPARSE|MB_TAG_CREAT, &dum_int); assert(MB_SUCCESS == result); if (MB_SUCCESS == result) {} // empty statement to get rid of warning. maxHexId = -1; }
Definition at line 131 of file DualTool.cpp.
{}
ErrorCode moab::DualTool::add_graphics_point | ( | EntityHandle | entity, |
double * | avg_pos = NULL |
||
) | [private] |
add a graphics point to an entity (on a tag)
Definition at line 295 of file DualTool.cpp.
{ // add a graphics pt, placed at the same position as the vertex double my_pos[3]; ErrorCode result; if (NULL == avg_pos) { result = MeshTopoUtil(mbImpl).get_average_position(entity, my_pos); if (MB_SUCCESS != result) return result; } else for (int i = 0; i < 3; i++) my_pos[i] = avg_pos[i]; DualTool::GraphicsPoint dum_pt(my_pos, -1); result = mbImpl->tag_set_data(dualGraphicsPoint_tag(), &entity, 1, &dum_pt); return result; }
ErrorCode moab::DualTool::atomic_pillow | ( | EntityHandle | odedge, |
EntityHandle & | quad1, | ||
EntityHandle & | quad2 | ||
) |
effect atomic pillow operation
Definition at line 1443 of file DualTool.cpp.
{ if (debug_ap) ((Core*)mbImpl)->check_adjacencies(); if (debug_ap) { Range sets; Tag ms_tag; ErrorCode result = mbImpl->tag_get_handle("MATERIAL_SET", 1, MB_TYPE_INTEGER, ms_tag); if (MB_SUCCESS == result) { result = mbImpl->get_entities_by_type_and_tag(0, MBENTITYSET, &ms_tag, NULL, 1, sets); if (MB_SUCCESS == result) result = mbImpl->delete_entities(sets); } } std::cout << "-AP("; print_cell(odedge); std::cout << ")" << std::endl; // perform an atomic pillow operation around dedge // grab the quad before deleting the odedge quad1 = get_dual_entity(odedge); assert(0 != quad1); // 0. get star 2cells around odedge (before odedge changes) and 3cells around // those 2cells (going to delete the 2cells, therefore need to delete the 3cells // that depend on those too) MeshTopoUtil mtu(mbImpl); Range star_cells, tmp_cells; ErrorCode result = mbImpl->get_adjacencies(&odedge, 1, 2, false, star_cells); RR; result = mbImpl->get_adjacencies(star_cells, 3, false, tmp_cells, Interface::UNION); RR; star_cells.merge(tmp_cells); star_cells.insert(odedge); // tear down the dual entities which will be modified by the ap first result = delete_dual_entities(star_cells); RR; // now change the quad to an ap std::vector<EntityHandle> verts; result = mbImpl->get_connectivity(&quad1, 1, verts); RR; // get average position of vertices double coords[12], avg[3] = {0.0, 0.0, 0.0}; result = mbImpl->get_coords(&verts[0], verts.size(), coords); RR; for (int i = 0; i < 4; i++) { avg[0] += coords[3*i]; avg[1] += coords[3*i+1]; avg[2] += coords[3*i+2]; } for (int i = 0; i < 3; i++) avg[i] *= 0.25; // for each position, get a corresponding position 1/2 way to avg double new_coords[12]; for (int i = 0; i < 4; i++) { new_coords[3*i] = avg[0] + .5*(coords[3*i]-avg[0]); new_coords[3*i+1] = avg[1] + .5*(coords[3*i+1]-avg[1]); new_coords[3*i+2] = avg[2] + .5*(coords[3*i+2]-avg[2]); } // make the 4 new vertices; store in vector long enough for hex connectivity for (int i = 0; i < 4; i++) { verts.push_back(0); result = mbImpl->create_vertex(&new_coords[3*i], verts[4+i]); RR; } // get the hexes connected to the quad Range hexes; result = mbImpl->get_adjacencies(&quad1, 1, 3, false, hexes); RR; assert(hexes.size() <= 2); // remove any explicit adjacency from the first hex, since that'll get connected // to the new quad; add adjacency between quad and second hex, if there is a 2nd result = mbImpl->remove_adjacencies(quad1, &(*hexes.begin()), 1); RR; if (hexes.size() == 2) { result = mbImpl->add_adjacencies(quad1, &(*hexes.rbegin()), 1, false); RR; } // create the new, inner quad, and make it explicitly adjacent to 1st hex; // make the connectivity of this quad same as the original one std::vector<EntityHandle> tmp_verts; std::copy(verts.begin(), verts.end(), std::back_inserter(tmp_verts)); result = mbImpl->create_element(MBQUAD, &tmp_verts[0], 4, quad2); RR; result = mbImpl->add_adjacencies(quad2, &(*hexes.begin()), 1, false); RR; // reverse the connectivity of the 1st hex std::reverse(verts.begin(), verts.begin()+4); std::reverse(verts.begin()+4, verts.end()); // now make two inner hexes; note connectivity array is flipped for the two hexes EntityHandle new_hexes[2]; result = mbImpl->create_element(MBHEX, &verts[0], 8, new_hexes[0]); RR; result = mbImpl->create_element(MBHEX, &tmp_verts[0], 8, new_hexes[1]); RR; // set the global id tag on the new hexes int new_hex_ids[2] = {++maxHexId, ++maxHexId}; result = mbImpl->tag_set_data(globalId_tag(), new_hexes, 2, new_hex_ids); if (MB_SUCCESS != result) return result; // by definition, quad1 is adj to new_hexes[0] result = mbImpl->add_adjacencies(quad1, &new_hexes[0], 1, false); RR; result = mbImpl->add_adjacencies(quad2, &new_hexes[1], 1, false); RR; if (debug_ap) ((Core*)mbImpl)->check_adjacencies(); // now update the dual result = construct_hex_dual(&new_hexes[0], 2); RR; // get the new dual surface, by getting one of the edges between the center // and outer vertex rings Range new_edge; verts[1] = verts[4]; result = mbImpl->get_adjacencies(&verts[0], 2, 1, false, new_edge); if (MB_SUCCESS != result || new_edge.size() != 1) return result; return MB_SUCCESS; }
bool moab::DualTool::check_1d_loop_edge | ( | EntityHandle | this_ent | ) | [private] |
if this_ent is an edge, is a dual entity, and has quads as its vertices' dual entities, return true, otherwise false
Definition at line 1124 of file DualTool.cpp.
{ // make sure it's an edge if (MBEDGE != mbImpl->type_from_handle(this_ent)) return false; // also has to be a dual entity unsigned int dum; ErrorCode result = mbImpl->tag_get_data(isDualCell_tag(), &this_ent, 1, &dum); if (MB_SUCCESS != result || dum != 0x1) return false; const EntityHandle *verts; EntityHandle vert_tags[2]; int num_verts; result = mbImpl->get_connectivity(this_ent, verts, num_verts); if (MB_SUCCESS != result) return false; result = mbImpl->tag_get_data(dualEntity_tag(), verts, 2, vert_tags); if (MB_SUCCESS != result || mbImpl->type_from_handle(vert_tags[0]) != MBQUAD || mbImpl->type_from_handle(vert_tags[1]) != MBQUAD) return false; else return true; }
check dual-primal adjacencies
Definition at line 3160 of file DualTool.cpp.
{ // check primal-dual correspondence // get the primal entities Range pents[4]; ErrorCode result = mbImpl->get_entities_by_type(0, MBHEX, pents[3]); RR; for (int i = 2; i >= 0; i--) { result = mbImpl->get_adjacencies(pents[3], 2, false, pents[2], Interface::UNION); RR; } // for each primal entity of dimension pd #define PRENT(ent) CN::EntityTypeName(TYPE_FROM_HANDLE(ent)) << " " \ << ID_FROM_HANDLE(ent) ErrorCode overall_result = MB_SUCCESS; for (int pd = 1; pd <= 3; pd++) { for (Range::iterator prit = pents[pd].begin(); prit != pents[pd].end(); prit++) { // get corresponding dual entity of dimension dd = 3-pd EntityHandle dual_ent = get_dual_entity(*prit); if (0 == dual_ent) std::cerr << "Problem getting dual entity for " << PRENT(*prit) << std::endl; // for each sub dimension sd = 0..pd-1 for (int sd = 0; sd < pd; sd++) { Range R1, R2, R3; // R1 = entities bounding primal entity of dim sd result = mbImpl->get_adjacencies(&(*prit), 1, sd, false, R1); RR; // R2 = entities bounded by dual entity, of dim 3-sd result = mbImpl->get_adjacencies(&dual_ent, 1, 3-sd, false, R2); RR; if (R1.size() != R2.size()) { std::cerr << PRENT(*prit) << ": number of adj ents in " << "primal/dual don't agree for dimension " << sd << "." << std::endl; overall_result = MB_FAILURE; } // for each entity in R1, get its dual and look for it in R2 for (Range::iterator r1it = R1.begin(); r1it != R1.end(); r1it++) { EntityHandle tmp_dual = get_dual_entity(*r1it); if (R2.find(tmp_dual) == R2.end()) { std::cerr << PRENT(*prit) << ": adj entity " << PRENT(*r1it) << " isn't adjacent in dual." << std::endl; overall_result = MB_FAILURE; } } // ditto for R2 for (Range::iterator r2it = R2.begin(); r2it != R2.end(); r2it++) { EntityHandle tmp_prim = get_dual_entity(*r2it); if (R1.find(tmp_prim) == R1.end()) { std::cerr << PRENT(*prit) << ": adj entity " << PRENT(*r2it) << " isn't adjacent in primal." << std::endl; overall_result = MB_FAILURE; } } } } } return overall_result; }
ErrorCode moab::DualTool::check_dual_equiv_edges | ( | Range & | dual_edges | ) | [private] |
go through potential dual equivalent edges (edges whose nodes define multiple edges), and add explicit adjacencies to corrent 2cells
Definition at line 479 of file DualTool.cpp.
{ // fix equivalent dual edges (i.e. edges whose vertices define multiple edges) // by explicitly adding adjacencies to containing polygons; adjacent polygons // found by going through primal ErrorCode tmp_result, result = MB_SUCCESS; Range all_dedges(dual_edges); // first, go through all dual edges and find equivalent edges (by looking for // up-adjacent edges on the vertices of each edge) for (Range::iterator rit = dual_edges.begin(); rit != dual_edges.end(); rit++) { Range connect, dum_range(*rit, *rit); tmp_result = mbImpl->get_adjacencies(dum_range, 0, false, connect); if (MB_SUCCESS != tmp_result) continue; tmp_result = mbImpl->get_adjacencies(connect, 1, false, all_dedges, Interface::UNION); if (MB_SUCCESS != tmp_result) continue; } // save a copy for checking later Range save_all_2cells; // go through each edge while (!all_dedges.empty()) { EntityHandle this_edge = *all_dedges.begin(); all_dedges.erase(all_dedges.begin()); const EntityHandle *connect; int num_connect; result = mbImpl->get_connectivity(this_edge, connect, num_connect); if (MB_SUCCESS != result) continue; Range dum_edges, verts; verts.insert(connect[0]); verts.insert(connect[1]); tmp_result = mbImpl->get_adjacencies(verts, 1, false, dum_edges); if (MB_SUCCESS != tmp_result) { result = tmp_result; continue; } if (dum_edges.size() == 1) { // not an equiv edge - already removed from list, so just continue continue; } // ok, have an equiv entity - fix by looking through primal // pre-get the primal of these EntityHandle dedge_quad; tmp_result = mbImpl->tag_get_data(dualEntity_tag(), &this_edge, 1, &dedge_quad); if (MB_SUCCESS != tmp_result) { result = tmp_result; continue; } if (MBQUAD == mbImpl->type_from_handle(dedge_quad)) { // get the primal edges adj to quad Range dum_quad_range(dedge_quad, dedge_quad), adj_pedges; tmp_result = mbImpl->get_adjacencies(dum_quad_range, 1, false, adj_pedges); if (MB_SUCCESS != tmp_result) { result = tmp_result; continue; } // get the dual 2cells corresponding to those pedges std::vector<EntityHandle> dcells; dcells.resize(adj_pedges.size()); tmp_result = mbImpl->tag_get_data(dualEntity_tag(), adj_pedges, &dcells[0]); if (MB_SUCCESS != tmp_result) { result = tmp_result; continue; } // now add explicit adjacencies from the dedge to those dcells std::vector<EntityHandle>::iterator vit; for (vit = dcells.begin(); vit != dcells.end(); vit++) { save_all_2cells.insert(*vit); assert(MBPOLYGON == mbImpl->type_from_handle(*vit)); tmp_result = mbImpl->add_adjacencies(this_edge, &(*vit), 1, false); if (MB_SUCCESS != tmp_result) { result = tmp_result; continue; } // check that there are really adjacencies and *vit is in them const EntityHandle *adjs; int num_adjs; tmp_result = reinterpret_cast<Core*>(mbImpl)->a_entity_factory()-> get_adjacencies(this_edge, adjs, num_adjs); if (NULL == adjs || std::find(adjs, adjs+num_adjs, *vit) == adjs+num_adjs) std::cout << "Add_adjacencies failed in construct_dual_faces." << std::endl; } } else { // else, have a dual edge representing a bdy edge - tie directly to // dual entity if its dual entity EntityHandle bdy_dcell; tmp_result = mbImpl->tag_get_data(dualEntity_tag(), &dedge_quad, 1, &bdy_dcell); TRC assert(MBPOLYGON == mbImpl->type_from_handle(bdy_dcell)); tmp_result = mbImpl->add_adjacencies(this_edge, &bdy_dcell, 1, false); if (MB_SUCCESS != tmp_result) { result = tmp_result; continue; } } } // sanity check - look for adj edges again, and check for equiv entities for (Range::iterator vit = save_all_2cells.begin(); vit != save_all_2cells.end(); vit++) { Range adj_edges, dum_quad_range; dum_quad_range.insert(*vit); assert(MBPOLYGON == mbImpl->type_from_handle(*vit)); tmp_result = mbImpl->get_adjacencies(dum_quad_range, 1, false, adj_edges); if (MB_MULTIPLE_ENTITIES_FOUND == tmp_result) { std::cout << "Multiple entities returned for polygon " << mbImpl->id_from_handle(*vit) << "." << std::endl; continue; } } // success! return result; }
ErrorCode moab::DualTool::construct_dual | ( | EntityHandle * | entities, |
const int | num_entities | ||
) |
construct the dual entities for the entire mesh
Definition at line 135 of file DualTool.cpp.
{ // allocate a dual entity for each primal entity in the mesh, starting // with highest dimension and working downward; do each dimension in a separate code // block, since they're all handled slightly differently Range regions, faces, edges, vertices; ErrorCode result; if (NULL == entities || 0 == num_entities) { // first, construct all the aentities, since they're currently needed to // compute the dual result = mbImpl->get_entities_by_dimension(0, 0, vertices); if (MB_SUCCESS != result) return result; result = MeshTopoUtil(mbImpl).construct_aentities(vertices); if (MB_SUCCESS != result) return result; // get all edges, faces and regions now, so we don't need to filter out dual // entities later result = mbImpl->get_entities_by_dimension(0, 1, edges); if (MB_SUCCESS != result) return result; result = mbImpl->get_entities_by_dimension(0, 2, faces); if (MB_SUCCESS != result) return result; result = mbImpl->get_entities_by_dimension(0, 3, regions); if (MB_SUCCESS != result) return result; // get the max global id for hexes, we'll need for modification ops std::vector<int> gid_vec(regions.size()); result = mbImpl->tag_get_data(globalId_tag(), regions, &gid_vec[0]); if (MB_SUCCESS != result) return result; maxHexId = -1; Range::iterator rit; unsigned int i; for (rit = regions.begin(), i = 0; rit != regions.end(); rit++, i++) { if (gid_vec[i] > maxHexId && mbImpl->type_from_handle(*rit) == MBHEX) maxHexId = gid_vec[i]; } } else { // get entities of various dimensions adjacent to these result = mbImpl->get_adjacencies(entities, num_entities, 0, true, vertices, Interface::UNION); if (MB_SUCCESS != result) return result; result = mbImpl->get_adjacencies(entities, num_entities, 1, true, edges, Interface::UNION); if (MB_SUCCESS != result) return result; result = mbImpl->get_adjacencies(entities, num_entities, 2, true, faces, Interface::UNION); if (MB_SUCCESS != result) return result; result = mbImpl->get_adjacencies(entities, num_entities, 3, true, regions, Interface::UNION); if (MB_SUCCESS != result) return result; } Range dual_verts; result = construct_dual_vertices(regions, dual_verts); if (MB_SUCCESS != result || dual_verts.size() != regions.size()) return result; if (debug) std::cout << "Constructed " << dual_verts.size() << " dual vertices." << std::endl; // don't really need dual edges, but construct 'em anyway Range dual_edges; result = construct_dual_edges(faces, dual_edges); if (MB_SUCCESS != result || dual_edges.size() != faces.size()) return result; if (debug) std::cout << "Constructed " << dual_edges.size() << " dual edges." << std::endl; // construct dual faces Range dual_faces; result = construct_dual_faces(edges, dual_faces); if (MB_SUCCESS != result || dual_faces.size() != edges.size()) return result; if (debug) std::cout << "Constructed " << dual_faces.size() << " dual faces." << std::endl; // construct dual cells Range dual_cells; result = construct_dual_cells(vertices, dual_cells); if (MB_SUCCESS != result || dual_cells.size() != vertices.size()) return result; if (debug) std::cout << "Constructed " << dual_cells.size() << " dual cells." << std::endl; return MB_SUCCESS; }
ErrorCode moab::DualTool::construct_dual_cells | ( | const Range & | all_verts, |
Range & | new_dual_ents | ||
) | [private] |
construct dual cells for specified vertices
Definition at line 602 of file DualTool.cpp.
{ if (all_verts.empty()) return MB_SUCCESS; // make sure they're all edges assert(0 == CN::Dimension(TYPE_FROM_HANDLE(*all_verts.begin())) && 0 == CN::Dimension(TYPE_FROM_HANDLE(*all_verts.rbegin()))); Range::const_iterator rit; EntityHandle dual_ent; unsigned int is_dual = 0x1; ErrorCode tmp_result = MB_SUCCESS; ErrorCode result = MB_SUCCESS; std::vector<EntityHandle> edges, dfaces; for (rit = all_verts.begin(); rit != all_verts.end(); rit++) { if (tmp_result != MB_SUCCESS) result = tmp_result; tmp_result = mbImpl->tag_get_data(dualEntity_tag(), &(*rit), 1, &dual_ent); if (MB_SUCCESS == tmp_result && 0 != dual_ent) { dual_ents.insert(dual_ent); continue; } // no dual entity; construct one; get the edges bounding the vertex edges.clear(); dfaces.clear(); tmp_result = mbImpl->get_adjacencies(&(*rit), 1, 1, false, edges); if (MB_SUCCESS != tmp_result) continue; // get the dual faces corresponding to the edges dfaces.resize(edges.size()); tmp_result = mbImpl->tag_get_data(dualEntity_tag(), &edges[0], edges.size(), &dfaces[0]); if (MB_SUCCESS != tmp_result) continue; // create the dual cell from those faces tmp_result = mbImpl->create_element(MBPOLYHEDRON, &dfaces[0], dfaces.size(), dual_ent); if (MB_SUCCESS != tmp_result || 0 == dual_ent) continue; // save it in the list of new dual ents dual_ents.insert(dual_ent); // tag it indicating it's a dual entity tmp_result = mbImpl->tag_set_data(isDualCell_tag(), &dual_ent, 1, &is_dual); if (MB_SUCCESS != tmp_result) continue; // tag the primal entity with its dual entity and vica versa tmp_result = mbImpl->tag_set_data(dualEntity_tag(), &(*rit), 1, &dual_ent); if (MB_SUCCESS != tmp_result) continue; tmp_result = mbImpl->tag_set_data(dualEntity_tag(), &dual_ent, 1, &(*rit)); if (MB_SUCCESS != tmp_result) continue; } return result; }
ErrorCode moab::DualTool::construct_dual_edges | ( | const Range & | all_faces, |
Range & | new_dual_ents | ||
) | [private] |
construct dual edges for specified faces
Definition at line 315 of file DualTool.cpp.
{ if (all_faces.empty()) return MB_SUCCESS; // make sure they're all faces assert(2 == CN::Dimension(TYPE_FROM_HANDLE(*all_faces.begin())) && 2 == CN::Dimension(TYPE_FROM_HANDLE(*all_faces.rbegin()))); Range::const_iterator rit; EntityHandle dual_ent; unsigned int is_dual = 0x1; ErrorCode tmp_result = MB_SUCCESS; ErrorCode result = MB_SUCCESS; for (rit = all_faces.begin(); rit != all_faces.end(); rit++) { if (tmp_result != MB_SUCCESS) result = tmp_result; tmp_result = mbImpl->tag_get_data(dualEntity_tag(), &(*rit), 1, &dual_ent); if (MB_SUCCESS == tmp_result && 0 != dual_ent) { dual_ents.insert(dual_ent); continue; } // no dual entity; construct one; get the bounding regions std::vector<EntityHandle> in_ents, out_ents; tmp_result = mbImpl->get_adjacencies(&(*rit), 1, 3, false, out_ents); if (MB_SUCCESS != tmp_result || out_ents.empty()) continue; // get the dual vertices std::vector<EntityHandle> dual_verts(out_ents.size()); tmp_result = mbImpl->tag_get_data(dualEntity_tag(), &out_ents[0], out_ents.size(), &dual_verts[0]); if (MB_SUCCESS != tmp_result) continue; assert(dual_verts.size() <= 2); double avg_pos[3]; bool bdy_face = (dual_verts.size() == 1 ? true : false); if (bdy_face) { // boundary face - make a dual vertex at the face center and put in list tmp_result = construct_dual_vertex(*rit, dual_ent, true, true); // put it on vertex list dual_verts.push_back(dual_ent); } assert(dual_verts.size() == 2); // now create the dual edge tmp_result = mbImpl->create_element(MBEDGE, &dual_verts[0], 2, dual_ent); if (MB_SUCCESS != tmp_result || 0 == dual_ent) continue; // save it in the list of new dual ents dual_ents.insert(dual_ent); // tag the primal entity with its dual entity and vica versa tmp_result = mbImpl->tag_set_data(dualEntity_tag(), &(*rit), 1, &dual_ent); if (MB_SUCCESS != tmp_result) continue; tmp_result = mbImpl->tag_set_data(dualEntity_tag(), &dual_ent, 1, &(*rit)); if (MB_SUCCESS != tmp_result) continue; // tag the edge indicating it's a dual entity tmp_result = mbImpl->tag_set_data(isDualCell_tag(), &dual_ent, 1, &is_dual); if (MB_SUCCESS != tmp_result) continue; // add a graphics point to the edge; position depends on whether it's a // bdy face (mid-pt of dual edge) or not (mid-pt of primal face) if (bdy_face) tmp_result = add_graphics_point(dual_ent); else { // get the face's position tmp_result = MeshTopoUtil(mbImpl).get_average_position(*rit, avg_pos); if (MB_SUCCESS != tmp_result) continue; tmp_result = add_graphics_point(dual_ent, avg_pos); } if (MB_SUCCESS != tmp_result) continue; } return result; }
ErrorCode moab::DualTool::construct_dual_faces | ( | const Range & | all_edges, |
Range & | new_dual_ents | ||
) | [private] |
construct dual faces for specified edges
Definition at line 397 of file DualTool.cpp.
{ if (all_edges.empty()) return MB_SUCCESS; // make sure they're all edges assert(1 == CN::Dimension(TYPE_FROM_HANDLE(*all_edges.begin())) && 1 == CN::Dimension(TYPE_FROM_HANDLE(*all_edges.rbegin()))); Range::const_iterator rit; EntityHandle dual_ent; unsigned int is_dual = 0x1; ErrorCode tmp_result = MB_SUCCESS; ErrorCode result = MB_SUCCESS; Range equiv_edges; #define TRC if (MB_SUCCESS != tmp_result) {result = tmp_result; continue;} for (rit = all_edges.begin(); rit != all_edges.end(); rit++) { tmp_result = mbImpl->tag_get_data(dualEntity_tag(), &(*rit), 1, &dual_ent); if (MB_SUCCESS == tmp_result && 0 != dual_ent) { dual_ents.insert(dual_ent); continue; } // no dual entity; construct one; get the dual vertices bounding the edge in radial order, // then construct the dual face std::vector<EntityHandle> rad_dverts; bool bdy_edge; tmp_result = get_radial_dverts(*rit, rad_dverts, bdy_edge);TRC if (rad_dverts.empty()) continue; tmp_result = mbImpl->create_element(MBPOLYGON, &rad_dverts[0], rad_dverts.size(), dual_ent);TRC // tag it indicating it's a dual entity, and tag primal/dual with dual/primal tmp_result = mbImpl->tag_set_data(isDualCell_tag(), &dual_ent, 1, &is_dual);TRC tmp_result = mbImpl->tag_set_data(dualEntity_tag(), &(*rit), 1, &dual_ent);TRC tmp_result = mbImpl->tag_set_data(dualEntity_tag(), &dual_ent, 1, &(*rit));TRC // save it in the list of new dual ents dual_ents.insert(dual_ent); // add a graphics point to the cell; position depends on whether it's a // bdy cell (mid-pt of cell's vertices) or not (mid-pt of primal edge) double avg_pos[3]; tmp_result = MeshTopoUtil(mbImpl).get_average_position(*rit, avg_pos);TRC if (bdy_edge) { // add a new dual edge betw last 2 verts EntityHandle new_edge; tmp_result = mbImpl->create_element(MBEDGE, &rad_dverts[rad_dverts.size()-2], 2, new_edge);TRC tmp_result = mbImpl->tag_set_data(isDualCell_tag(), &new_edge, 1, &is_dual);TRC // tag the new dual edge with the primal edge as it's dual entity; primal // edge IS NOT likewise tagged, since it's already tagged with the 2cell tmp_result = mbImpl->tag_set_data(dualEntity_tag(), &new_edge, 1, &(*rit)); TRC // add a graphics pt, position is center of primal edge tmp_result = add_graphics_point(dual_ent);TRC tmp_result = add_graphics_point(new_edge, avg_pos);TRC } else { // if inside, point goes on the 2cell, at primal edge mid-pt tmp_result = add_graphics_point(dual_ent, avg_pos);TRC } // check to see whether we have equiv entities; if we find any, save for later fixup Range dum_edges, dum_poly(dual_ent, dual_ent); tmp_result = mbImpl->get_adjacencies(dum_poly, 1, false, dum_edges); if (MB_MULTIPLE_ENTITIES_FOUND == tmp_result) { // we do - need to add adjacencies to disambiguate; use the primal equiv_edges.merge(dum_edges); } } if (!equiv_edges.empty()) result = check_dual_equiv_edges(equiv_edges); return result; }
ErrorCode moab::DualTool::construct_dual_hyperplanes | ( | const int | dim, |
EntityHandle * | entities, | ||
const int | num_entities | ||
) | [private] |
traverse dual faces of input dimension, constructing dual hyperplanes of them in sets as it goes
Definition at line 832 of file DualTool.cpp.
{ // this function traverses dual faces of input dimension, constructing // dual hyperplanes of them in sets as it goes // check various inputs int num_quads, num_hexes; if ( // this function only makes sense for dim == 1 or dim == 2 (dim != 1 && dim != 2) || // should either be quads or hexes around mbImpl->get_number_entities_by_type(0, MBQUAD, num_quads) != MB_SUCCESS || mbImpl->get_number_entities_by_type(0, MBHEX, num_hexes) != MB_SUCCESS || // if we're asking for 1d dual ents, should be quads around (num_quads == 0 && dim == 1) || // if we're asking for 2d dual ents, should be hexes around (num_hexes == 0 && dim == 2)) return MB_FAILURE; // get tag name for this dimension hyperplane Tag gid_tag; int dum = 0; ErrorCode result = mbImpl->tag_get_handle(GLOBAL_ID_TAG_NAME, 1, MB_TYPE_INTEGER, gid_tag, MB_TAG_CREAT|MB_TAG_DENSE, &dum); if (MB_SUCCESS != result) return result; Tag hp_tag = (1 == dim ? dualCurve_tag() : dualSurface_tag()); // two stacks: one completely untreated entities, and the other untreated // entities on the current dual hyperplane std::vector<EntityHandle> tot_untreated; // put dual entities of this dimension on the untreated list result = get_dual_entities(dim, entities, num_entities, tot_untreated); if (MB_SUCCESS != result) return result; // main part of traversal loop EntityHandle this_ent; EntityHandle this_hp; std::vector<EntityHandle> parents; while (!tot_untreated.empty()) { if (debug && dim == 2 /*(tot_untreated.size()%report == 0)*/) std::cout << "Untreated list size " << tot_untreated.size() << "." << std::endl; this_ent = tot_untreated.back(); tot_untreated.pop_back(); result = mbImpl->tag_get_data(hp_tag, &this_ent, 1, &this_hp); if (MB_SUCCESS != result && MB_TAG_NOT_FOUND != result) return result; // d for this entity having a hyperplane assignment already else if (this_hp != 0) continue; if (1 == dim && check_1d_loop_edge(this_ent)) continue; // inner loop: traverse the hyperplane 'till we don't have any more result = traverse_hyperplane(hp_tag, this_hp, this_ent); if (MB_SUCCESS != result) { std::cout << "Failed to traverse hyperplane "; if (this_hp) std::cout << mbImpl->id_from_handle(this_hp) << "." << std::endl; else std::cout << "0." << std::endl; return result; } // ok, now order the edges if it's a chord if (1 == dim) order_chord(this_hp); } return MB_SUCCESS; }
ErrorCode moab::DualTool::construct_dual_vertex | ( | EntityHandle | entity, |
EntityHandle & | dual_ent, | ||
const bool | extra = false , |
||
const bool | add_graphics_pt = true |
||
) | [private] |
Definition at line 259 of file DualTool.cpp.
{ // no dual entity; construct one; first need the avg coordinates unsigned int is_dual = 0x1; double avg_pos[3]; ErrorCode result = MeshTopoUtil(mbImpl).get_average_position(entity, avg_pos); if (MB_SUCCESS != result) return result; // now construct the new dual entity result = mbImpl->create_vertex(avg_pos, dual_ent); if (MB_SUCCESS != result) return result; // tag it indicating it's a dual entity result = mbImpl->tag_set_data(isDualCell_tag(), &dual_ent, 1, &is_dual); if (MB_SUCCESS != result) return result; // tag the primal entity with its dual entity and vica versa if (extra) result = mbImpl->tag_set_data(extraDualEntity_tag(), &(entity), 1, &dual_ent); else result = mbImpl->tag_set_data(dualEntity_tag(), &(entity), 1, &dual_ent); if (MB_SUCCESS != result) return result; result = mbImpl->tag_set_data(dualEntity_tag(), &dual_ent, 1, &(entity)); if (MB_SUCCESS != result) return result; if (add_graphics_pt) // put a graphics point on that vertex too result = add_graphics_point(dual_ent, avg_pos); return result; }
ErrorCode moab::DualTool::construct_dual_vertices | ( | const Range & | all_regions, |
Range & | new_dual_ents | ||
) | [private] |
construct dual vertices for specified regions
Definition at line 224 of file DualTool.cpp.
{ if (all_regions.empty()) return MB_SUCCESS; // make sure they're all regions assert(3 == CN::Dimension(TYPE_FROM_HANDLE(*all_regions.begin())) && 3 == CN::Dimension(TYPE_FROM_HANDLE(*all_regions.rbegin()))); Range::const_iterator rit; EntityHandle dual_ent; ErrorCode tmp_result = MB_SUCCESS; ErrorCode result = MB_SUCCESS; for (rit = all_regions.begin(); rit != all_regions.end(); rit++) { if (tmp_result != MB_SUCCESS) result = tmp_result; tmp_result = mbImpl->tag_get_data(dualEntity_tag(), &(*rit), 1, &dual_ent); if (MB_SUCCESS == tmp_result && 0 != dual_ent) { dual_ents.insert(dual_ent); continue; } else if (MB_SUCCESS != tmp_result) continue; tmp_result = construct_dual_vertex(*rit, dual_ent, false, true); if (MB_SUCCESS != tmp_result) continue; // save it in the list of new dual ents dual_ents.insert(dual_ent); } return result; }
ErrorCode moab::DualTool::construct_hex_dual | ( | EntityHandle * | entities, |
const int | num_entities | ||
) |
construct the dual entities for a hex mesh, including dual surfaces & curves
Definition at line 713 of file DualTool.cpp.
{ // really quite simple: // construct the dual... ErrorCode result = construct_dual(entities, num_entities); if (MB_SUCCESS != result) { std::cerr << "Error constructing dual entities for primal entities." << std::endl; return result; } // now traverse to build 1d and 2d hyperplanes result = construct_dual_hyperplanes(1, entities, num_entities); if (MB_SUCCESS != result) { std::cerr << "Problem traversing 1d hyperplanes." << std::endl; return result; } if (MB_SUCCESS != result) return result; result = construct_dual_hyperplanes(2, entities, num_entities); if (MB_SUCCESS != result) { std::cerr << "Problem traversing 2d hyperplanes." << std::endl; return result; } if (MB_SUCCESS != result) return result; result = construct_hp_parent_child(); if (MB_SUCCESS != result) { std::cerr << "Problem constructing parent/child relations between hyperplanes." << std::endl; return result; } if (MB_SUCCESS != result) return result; // see? simple, just like I said return MB_SUCCESS; }
ErrorCode moab::DualTool::construct_hex_dual | ( | Range & | entities | ) |
construct the dual entities for a hex mesh, including dual surfaces & curves
Definition at line 705 of file DualTool.cpp.
{ std::vector<EntityHandle> evec; std::copy(entities.begin(), entities.end(), std::back_inserter(evec)); return construct_hex_dual(&evec[0], evec.size()); }
ErrorCode moab::DualTool::construct_hp_parent_child | ( | ) | [private] |
connect dual surfaces with dual curves using parent/child connections
Definition at line 1148 of file DualTool.cpp.
{ Range dual_surfs, dual_cells, dual_edges; ErrorCode result = this->get_dual_hyperplanes(mbImpl, 2, dual_surfs); if (MB_SUCCESS != result || dual_surfs.empty()) return result; std::vector<EntityHandle> dual_curve_sets; for (Range::iterator surf_it = dual_surfs.begin(); surf_it != dual_surfs.end(); surf_it++) { // get all the cells, edges in those cells, and chords for those edges dual_cells.clear(); result = mbImpl->get_entities_by_handle(*surf_it, dual_cells); if (MB_SUCCESS != result) return result; dual_edges.clear(); result = mbImpl->get_adjacencies(dual_cells, 1, false, dual_edges, Interface::UNION); if (MB_SUCCESS != result) return result; dual_curve_sets.reserve(dual_edges.size()); result = mbImpl->tag_get_data(dualCurve_tag(), dual_edges, &dual_curve_sets[0]); if (MB_SUCCESS != result) return result; // reuse dual_cells to get unique list of chord sets dual_cells.clear(); for (unsigned int i = 0; i < dual_edges.size(); i++) if (dual_curve_sets[i] != 0) dual_cells.insert(dual_curve_sets[i]); // now connect up this dual surf with all the 1d ones for (Range::iterator rit = dual_cells.begin(); rit != dual_cells.end(); rit++) { result = mbImpl->add_parent_child(*surf_it, *rit); if (MB_SUCCESS != result) return result; } } return MB_SUCCESS; }
ErrorCode moab::DualTool::construct_new_hyperplane | ( | const int | dim, |
EntityHandle & | new_hyperplane, | ||
int & | id | ||
) | [private] |
make a new dual hyperplane with the specified id; if the id specified is -1, set the new one's id to the max found
Definition at line 1087 of file DualTool.cpp.
{ ErrorCode result; if (1 == dim) result = mbImpl->create_meshset((MESHSET_ORDERED | MESHSET_TRACK_OWNER), new_hyperplane); else result = mbImpl->create_meshset((MESHSET_SET | MESHSET_TRACK_OWNER), new_hyperplane); if (MB_SUCCESS != result) return result; if (-1 == id) { Range all_hyperplanes; result = get_dual_hyperplanes(mbImpl, dim, all_hyperplanes); RR; std::vector<int> gids(all_hyperplanes.size()); result = mbImpl->tag_get_data(globalIdTag, all_hyperplanes, &gids[0]); RR; for (unsigned int i = 0; i < gids.size(); i++) if (gids[i] > id) id = gids[i]; id++; if (0 == id) id++; } result = mbImpl->tag_set_data(globalId_tag(), &new_hyperplane, 1, &id); RR; Tag hp_tag = (1 == dim ? dualCurve_tag() : dualSurface_tag()); result = mbImpl->tag_set_data(hp_tag, &new_hyperplane, 1, &new_hyperplane); // assign a category name to these sets static const char dual_category_names[2][CATEGORY_TAG_SIZE] = {"Chord\0", "Sheet\0"}; result = mbImpl->tag_set_data(categoryTag, &new_hyperplane, 1, dual_category_names[dim-1]); return result; }
ErrorCode moab::DualTool::delete_dual_entities | ( | EntityHandle * | entities, |
const int | num_entities | ||
) | [private] |
delete a dual entity; updates primal to no longer point to it
Definition at line 1637 of file DualTool.cpp.
{ Range tmp_ents; std::copy(entities, entities+num_entities, range_inserter(tmp_ents)); return delete_dual_entities(tmp_ents); }
ErrorCode moab::DualTool::delete_dual_entities | ( | Range & | entities | ) | [private] |
delete a range of dual entities; updates primal to no longer point to them
Definition at line 1645 of file DualTool.cpp.
{ if (entities.empty()) return delete_whole_dual(); EntityHandle null_entity = 0; ErrorCode result; Range ents_to_delete; while (!entities.empty()) { EntityHandle this_entity = entities.pop_back(); // reset the primal's dual entity EntityHandle primal = get_dual_entity(this_entity); if (get_dual_entity(primal) == this_entity) { result = mbImpl->tag_set_data(dualEntity_tag(), &primal, 1, &null_entity); RR; } EntityHandle extra = get_extra_dual_entity(primal); if (0 != extra) { result = mbImpl->tag_set_data(extraDualEntity_tag(), &primal, 1, &null_entity); RR; } ents_to_delete.insert(this_entity); // check for extra dual entities if (mbImpl->type_from_handle(this_entity) == MBPOLYGON) { // for 2cell, might be a loop edge Range loop_edges; result = mbImpl->get_adjacencies(&this_entity, 1, 1, false, loop_edges); for (Range::iterator rit = loop_edges.begin(); rit != loop_edges.end(); rit++) if (check_1d_loop_edge(*rit)) entities.insert(*rit); } else if (extra && extra != this_entity) // just put it on the list; primal for which we're extra has already been // reset to not point to extra entity ents_to_delete.insert(extra); } // now delete the entities (sheets and chords will be updated automatically) return mbImpl->delete_entities(ents_to_delete); }
delete all the dual data
Definition at line 3107 of file DualTool.cpp.
{ // delete dual hyperplanes Range dual_surfs, dual_curves; ErrorCode result = this->get_dual_hyperplanes(mbImpl, 2, dual_surfs); RR; result = mbImpl->delete_entities(dual_surfs); RR; result = this->get_dual_hyperplanes(mbImpl, 1, dual_curves); RR; result = mbImpl->delete_entities(dual_curves); RR; // gather up all dual entities Range dual_ents; result = mbImpl->get_entities_by_type_and_tag(0, MBVERTEX, &isDualCellTag, NULL, 1, dual_ents, Interface::UNION); RR; result = mbImpl->get_entities_by_type_and_tag(0, MBEDGE, &isDualCellTag, NULL, 1, dual_ents, Interface::UNION); RR; result = mbImpl->get_entities_by_type_and_tag(0, MBPOLYGON, &isDualCellTag, NULL, 1, dual_ents, Interface::UNION); RR; result = mbImpl->get_entities_by_type_and_tag(0, MBPOLYHEDRON, &isDualCellTag, NULL, 1, dual_ents, Interface::UNION); RR; // delete them, in reverse order of dimension ErrorCode tmp_result; for (Range::reverse_iterator rit = dual_ents.rbegin(); rit != dual_ents.rend(); rit++) { tmp_result = mbImpl->delete_entities(&(*rit), 1); if (MB_SUCCESS != tmp_result) result = tmp_result; } RR; // delete dual-related tags if (0 != dualSurfaceTag) { tmp_result = mbImpl->tag_delete(dualSurfaceTag); if (MB_SUCCESS != tmp_result && MB_TAG_NOT_FOUND != tmp_result) result = tmp_result; } if (0 != dualCurveTag) { tmp_result = mbImpl->tag_delete(dualCurveTag); if (MB_SUCCESS != tmp_result && MB_TAG_NOT_FOUND != tmp_result) result = tmp_result; } if (0 != dualEntityTag) { tmp_result = mbImpl->tag_delete(dualEntityTag); if (MB_SUCCESS != tmp_result && MB_TAG_NOT_FOUND != tmp_result) result = tmp_result; } if (0 != extraDualEntityTag) { tmp_result = mbImpl->tag_delete(extraDualEntityTag); if (MB_SUCCESS != tmp_result && MB_TAG_NOT_FOUND != tmp_result) result = tmp_result; } if (0 != dualGraphicsPointTag) { tmp_result = mbImpl->tag_delete(dualGraphicsPointTag); if (MB_SUCCESS != tmp_result && MB_TAG_NOT_FOUND != tmp_result) result = tmp_result; } return MB_SUCCESS; }
Tag moab::DualTool::dualCurve_tag | ( | ) | const [inline] |
get/set the tag for dual curves
Definition at line 394 of file DualTool.hpp.
{ return dualCurveTag; }
ErrorCode moab::DualTool::dualCurve_tag | ( | const Tag | tag | ) | [inline] |
get/set the tag for dual curves
Definition at line 437 of file DualTool.hpp.
{ ErrorCode result = MB_FAILURE; if ((0 == dualCurveTag && tag) || dualCurveTag != tag) { dualCurveTag = tag; result = MB_SUCCESS; } return result; }
Tag moab::DualTool::dualEntity_tag | ( | ) | const [inline] |
get/set the tag for dual entities
Definition at line 404 of file DualTool.hpp.
{ return dualEntityTag; }
ErrorCode moab::DualTool::dualEntity_tag | ( | const Tag | tag | ) | [inline] |
get/set the tag for dual entities
Definition at line 461 of file DualTool.hpp.
{ ErrorCode result = MB_FAILURE; if ((0 == dualEntityTag && tag) || dualEntityTag != tag) { dualEntityTag = tag; result = MB_SUCCESS; } return result; }
Tag moab::DualTool::dualGraphicsPoint_tag | ( | ) | const [inline] |
get/set the tag for dual entities
Definition at line 414 of file DualTool.hpp.
{ return dualGraphicsPointTag; }
ErrorCode moab::DualTool::dualGraphicsPoint_tag | ( | const Tag | tag | ) | [inline] |
get/set the tag for dual entities
Definition at line 485 of file DualTool.hpp.
{ ErrorCode result = MB_FAILURE; if ((0 == dualGraphicsPointTag && tag) || dualGraphicsPointTag != tag) { dualGraphicsPointTag = tag; result = MB_SUCCESS; } return result; }
Tag moab::DualTool::dualSurface_tag | ( | ) | const [inline] |
get/set the tag for dual surfaces
Definition at line 389 of file DualTool.hpp.
{ return dualSurfaceTag; }
ErrorCode moab::DualTool::dualSurface_tag | ( | const Tag | tag | ) | [inline] |
get/set the tag for dual surfaces
Definition at line 425 of file DualTool.hpp.
{ ErrorCode result = MB_FAILURE; if ((0 == dualSurfaceTag && tag) || dualSurfaceTag != tag) { dualSurfaceTag = tag; result = MB_SUCCESS; } return result; }
Tag moab::DualTool::extraDualEntity_tag | ( | ) | const [inline] |
get/set the tag for dual entities
Definition at line 409 of file DualTool.hpp.
{ return extraDualEntityTag; }
ErrorCode moab::DualTool::extraDualEntity_tag | ( | const Tag | tag | ) | [inline] |
get/set the tag for dual entities
Definition at line 473 of file DualTool.hpp.
{ ErrorCode result = MB_FAILURE; if ((0 == extraDualEntityTag && tag) || extraDualEntityTag != tag) { extraDualEntityTag = tag; result = MB_SUCCESS; } return result; }
effect a face open-collapse operation
Definition at line 1715 of file DualTool.cpp.
{ if (debug_ap) ((Core*)mbImpl)->check_adjacencies(); MeshTopoUtil mtu(mbImpl); std::cout << "OC("; print_cell(ocl); std::cout << ")-("; print_cell(ocr); std::cout << ")" << std::endl; // get the primal entities we're dealing with EntityHandle split_quads[2] = {0}, split_edges[3] = {0}, split_nodes[2] = {0}, other_edges[6] = {0}, other_nodes[6] = {0}; Range hexes; ErrorCode result = foc_get_ents(ocl, ocr, split_quads, split_edges, split_nodes, hexes, other_edges, other_nodes); RR; // get star entities around edges, separated into halves std::vector<EntityHandle> star_dp1[2], star_dp2[2]; result = foc_get_stars(split_quads, split_edges, star_dp1, star_dp2); RR; if (MBQUAD != mbImpl->type_from_handle(split_quads[0]) || MBQUAD != mbImpl->type_from_handle(split_quads[1])) return MB_TYPE_OUT_OF_RANGE; result = foc_delete_dual(split_quads, split_edges, hexes); if (MB_SUCCESS != result) return result; EntityHandle new_quads[2], new_edges[3], new_nodes[2]; result = split_pair_nonmanifold(split_quads, split_edges, split_nodes, star_dp1, star_dp2, other_edges, other_nodes, new_quads, new_edges, new_nodes); if (MB_SUCCESS != result) return result; // now merge entities, the C of foc EntityHandle keepit, deleteit; #define MIN(a,b) (a < b ? a : b) #define MAX(a,b) (a > b ? a : b) #define KEEP_DELETE(a,b,c,d) {c = MIN(a,b); d = MAX(a,b);} // find how many shared edges there were int num_shared_edges = (split_edges[2] ? 3 : (split_edges[1] ? 2 : 1)); // first the node(s) for (int i = 0; i < 3-num_shared_edges; i++) { KEEP_DELETE(other_nodes[2+2*i], other_nodes[3+2*i], keepit, deleteit); result = mbImpl->merge_entities(keepit, deleteit, false, true); RR; } // now the edges for (int i = 0; i < 4-num_shared_edges; i++) { KEEP_DELETE(other_edges[2*i], other_edges[2*i+1], keepit, deleteit); result = mbImpl->merge_entities(keepit, deleteit, false, true); RR; } // now the faces KEEP_DELETE(split_quads[0], split_quads[1], keepit, deleteit); result = mbImpl->merge_entities(keepit, deleteit, false, true); RR; result = mbImpl->merge_entities(new_quads[0], new_quads[1], false, true); RR; if (debug_ap) ((Core*)mbImpl)->check_adjacencies(); // reconstruct dual result = construct_hex_dual(hexes); if (MB_SUCCESS != result) return result; return check_dual_adjs(); }
ErrorCode moab::DualTool::face_shrink | ( | EntityHandle | odedge | ) |
effect face shrink operation
Definition at line 2590 of file DualTool.cpp.
{ // some preliminary checking if (mbImpl->type_from_handle(odedge) != MBEDGE) return MB_TYPE_OUT_OF_RANGE; if (debug_ap) ((Core*)mbImpl)->check_adjacencies(); std::cout << "FS("; print_cell(odedge); std::cout << ")" << std::endl; EntityHandle quads[4], hexes[2]; std::vector<EntityHandle> connects[4], side_quads[2]; // get the quads along the chord through the 2 hexes, and the vertices // for those quads ErrorCode result = fs_get_quads(odedge, quads, hexes, connects); if (MB_SUCCESS != result) return result; // flip/rotate connect arrays so they align & are same sense result = fs_check_quad_sense(hexes[0], quads[0], connects); if (MB_SUCCESS != result) return result; // get the quad loops along the "side" surfaces result = fs_get_quad_loops(hexes, connects, side_quads); if (MB_SUCCESS != result) return result; // ok, done with setup; now delete dual entities affected by this operation, // which is all the entities adjacent to vertices of dual edge Range adj_verts, adj_edges, dual_ents, cells1or2; MeshTopoUtil mtu(mbImpl); result = mtu.get_bridge_adjacencies(odedge, 0, 1, adj_edges); if (MB_SUCCESS != result) return result; result = mbImpl->get_adjacencies(adj_edges, 0, false, adj_verts, Interface::UNION); if (MB_SUCCESS != result) return result; for (int i = 1; i <= 3; i++) { result = mbImpl->get_adjacencies(adj_verts, i, false, dual_ents, Interface::UNION); if (MB_SUCCESS != result) return result; } // before deleting dual, grab the 1- and 2-cells for (Range::iterator rit = dual_ents.begin(); rit != dual_ents.end(); rit++) { int dim = mbImpl->dimension_from_handle(*rit); if (1 == dim || 2 == dim) cells1or2.insert(*rit); } Range dual_hps; for (Range::iterator rit = cells1or2.begin(); rit != cells1or2.end(); rit++) dual_hps.insert(get_dual_hyperplane(*rit)); dual_ents.insert(odedge); result = delete_dual_entities(dual_ents); if (MB_SUCCESS != result) return result; // after deleting cells, check for empty chords & sheets, and delete those too for (Range::iterator rit = dual_hps.begin(); rit != dual_hps.end(); rit++) { Range tmp_ents; result = mbImpl->get_entities_by_handle(*rit, tmp_ents); if (MB_SUCCESS != result) return result; if (tmp_ents.empty()) { result = mbImpl->delete_entities(&(*rit), 1); if (MB_SUCCESS != result) return result; } } // remove any explicit adjacencies between side quads and hexes; don't check // for error, since there might not be adjacencies for (int i = 0; i < 4; i++) { for (int j = 0; j < 2; j++) { result = mbImpl->remove_adjacencies(side_quads[j][i], &hexes[j], 1); } } // make inner ring of vertices // get centroid of quad2 double q2coords[12], avg[3] = {0.0, 0.0, 0.0}; result = mbImpl->get_coords(&connects[1][0], 4, q2coords); if (MB_SUCCESS != result) return result; for (int i = 0; i < 4; i++) { avg[0] += q2coords[3*i]; avg[1] += q2coords[3*i+1]; avg[2] += q2coords[3*i+2]; } avg[0] *= .25; avg[1] *= .25; avg[2] *= .25; // position new vertices connects[3].resize(4); for (int i = 0; i < 4; i++) { q2coords[3*i] = avg[0] + .25*(q2coords[3*i]-avg[0]); q2coords[3*i+1] = avg[1] + .25*(q2coords[3*i+1]-avg[1]); q2coords[3*i+2] = avg[2] + .25*(q2coords[3*i+2]-avg[2]); result = mbImpl->create_vertex(&q2coords[3*i], connects[3][i]); if (MB_SUCCESS != result) return result; } // ok, now have the 4 connectivity arrays for 4 quads; construct hexes EntityHandle hconnect[8], new_hexes[4]; int new_hex_ids[4]; for (int i = 0; i < 4; i++) { int i1 = i, i2 = (i+1)%4; hconnect[0] = connects[0][i1]; hconnect[1] = connects[0][i2]; hconnect[2] = connects[3][i2]; hconnect[3] = connects[3][i1]; hconnect[4] = connects[1][i1]; hconnect[5] = connects[1][i2]; hconnect[6] = connects[2][i2]; hconnect[7] = connects[2][i1]; result = mbImpl->create_element(MBHEX, hconnect, 8, new_hexes[i]); if (MB_SUCCESS != result) return result; // test for equiv entities from the side quads, and make explicit adjacencies // if there are any for (int j = 0; j < 2; j++) { if (mtu.equivalent_entities(side_quads[j][i])) { result = mbImpl->add_adjacencies(side_quads[j][i], &new_hexes[i], 1, false); if (MB_SUCCESS != result) return result; } } new_hex_ids[i] = ++maxHexId; } // set the global id tag on the new hexes result = mbImpl->tag_set_data(globalId_tag(), new_hexes, 4, new_hex_ids); if (MB_SUCCESS != result) return result; // now fixup other two hexes; start by getting hex through quads 0, 1 // make this first hex switch to the other side, to make the dual look like // a hex push int tmp_ids[2]; result = mbImpl->tag_get_data(globalId_tag(), hexes, 2, tmp_ids); if (MB_SUCCESS != result) return result; result = mbImpl->delete_entities(hexes, 2); if (MB_SUCCESS != result) return result; result = mbImpl->delete_entities(&quads[1], 1); if (MB_SUCCESS != result) return result; for (int i = 0; i < 4; i++) { hconnect[i] = connects[3][i]; hconnect[4+i] = connects[2][i]; } result = mbImpl->create_element(MBHEX, hconnect, 8, hexes[0]); if (MB_SUCCESS != result) return result; for (int i = 0; i < 4; i++) { hconnect[i] = connects[0][i]; hconnect[4+i] = connects[3][i]; } result = mbImpl->create_element(MBHEX, hconnect, 8, hexes[1]); if (MB_SUCCESS != result) return result; // check for and fix any explicit adjacencies on either end quad if (mtu.equivalent_entities(quads[0])) mbImpl->add_adjacencies(quads[0], &hexes[1], 1, false); if (mtu.equivalent_entities(quads[2])) mbImpl->add_adjacencies(quads[2], &hexes[0], 1, false); // re-set the global ids for the hexes to what they were result = mbImpl->tag_set_data(globalId_tag(), hexes, 2, tmp_ids); if (MB_SUCCESS != result) return result; if (debug_ap) ((Core*)mbImpl)->check_adjacencies(); // now update the dual Range tmph; result = mtu.get_bridge_adjacencies(hexes[0], 0, 3, tmph); if (MB_SUCCESS != result) return result; result = mtu.get_bridge_adjacencies(hexes[1], 0, 3, tmph); if (MB_SUCCESS != result) return result; tmph.insert(hexes[1]); result = construct_hex_dual(tmph); if (MB_SUCCESS != result) return result; return result; }
ErrorCode moab::DualTool::foc_delete_dual | ( | EntityHandle * | split_quads, |
EntityHandle * | split_edges, | ||
Range & | hexes | ||
) | [private] |
function for deleting dual prior to foc operation; special because in many cases need to delete a sheet in preparation for merging onto another
Definition at line 2267 of file DualTool.cpp.
{ // special delete dual procedure, because in some cases we need to delete // a sheet too since it'll get merged into another // figure out whether we'll need to delete a sheet EntityHandle sheet1, sheet2 = 0; sheet1 = get_dual_hyperplane(get_dual_entity(split_edges[0])); if (split_edges[1]) sheet1 = get_dual_hyperplane(get_dual_entity(split_edges[1])); EntityHandle chordl = get_dual_hyperplane(get_dual_entity(split_quads[0])); EntityHandle chordr = get_dual_hyperplane(get_dual_entity(split_quads[1])); assert(0 != sheet1 && 0 != chordl && 0 != chordr); Range parentsl, parentsr; ErrorCode result = mbImpl->get_parent_meshsets(chordl, parentsl); if (MB_SUCCESS != result) return result; result = mbImpl->get_parent_meshsets(chordr, parentsr); if (MB_SUCCESS != result) return result; parentsl.erase(sheet1); parentsr.erase(sheet1); if (sheet2) parentsl.erase(sheet1), parentsr.erase(sheet1); // before deciding which one to delete, collect the other cells which must // be deleted, and all the chords/sheets they're on Range adj_ents, dual_ents, cells1or2; for (int i = 0; i < 3; i++) { result = mbImpl->get_adjacencies(hexes, i, false, adj_ents, Interface::UNION); if (MB_SUCCESS != result) return result; } // cache any adjacent hexes, for rebuilding the dual later result = mbImpl->get_adjacencies(adj_ents, 3, false, hexes, Interface::UNION); if (MB_SUCCESS != result) return result; for (Range::iterator rit = adj_ents.begin(); rit != adj_ents.end(); rit++) { EntityHandle this_ent = get_dual_entity(*rit); dual_ents.insert(this_ent); int dim = mbImpl->dimension_from_handle(this_ent); if (1 == dim || 2 == dim) cells1or2.insert(this_ent); } Range dual_hps; for (Range::iterator rit = cells1or2.begin(); rit != cells1or2.end(); rit++) dual_hps.insert(get_dual_hyperplane(*rit)); result = delete_dual_entities(dual_ents); if (MB_SUCCESS != result) return result; // now decide which sheet to delete (to be merged into the other) EntityHandle sheet_delete = 0; if (is_blind(*parentsl.begin())) sheet_delete = *parentsl.begin(); else if (is_blind(*parentsr.begin())) sheet_delete = *parentsr.begin(); else { // neither is blind, take the one with fewer cells Range tmp_ents; int numl, numr; result = mbImpl->get_number_entities_by_handle(*parentsl.begin(), numl); if (MB_SUCCESS != result) return result; result = mbImpl->get_number_entities_by_handle(*parentsr.begin(), numr); if (MB_SUCCESS != result) return result; sheet_delete = (numl > numr ? *parentsr.begin() : *parentsl.begin()); } assert(0 != sheet_delete); // after deleting cells, check for empty chords & sheets, and delete those too for (Range::iterator rit = dual_hps.begin(); rit != dual_hps.end(); rit++) { Range tmp_ents; result = mbImpl->get_entities_by_handle(*rit, tmp_ents); if (MB_SUCCESS != result) return result; if (tmp_ents.empty()) { result = mbImpl->delete_entities(&(*rit), 1); if (MB_SUCCESS != result) return result; } else if (*rit == sheet_delete) { // delete the sheet result = mbImpl->delete_entities(&(*rit), 1); if (MB_SUCCESS != result) return result; } } // now just to be safe, add the hexes bridge-adjacent across vertices // to the hexes we already have Range tmp_hexes; MeshTopoUtil mtu(mbImpl); for (Range::iterator rit = hexes.begin(); rit != hexes.end(); rit++) { result = mtu.get_bridge_adjacencies(*rit, 0, 3, tmp_hexes); if (MB_SUCCESS != result) return result; } hexes.merge(tmp_hexes); return MB_SUCCESS; }
ErrorCode moab::DualTool::foc_get_addl_ents | ( | std::vector< EntityHandle > * | star_dp1, |
std::vector< EntityHandle > * | star_dp2, | ||
EntityHandle * | split_edges, | ||
EntityHandle | split_node, | ||
Range * | addl_ents | ||
) | [private] |
for foc's splitting two shared edges, there might be additional entities connected to the split node that also have to be updated
Definition at line 2088 of file DualTool.cpp.
{ // if we're splitting 2 edges, there might be other edges that have the split // node; also need to know which side they're on // algorithm: for a given star_dp1 (faces) on a side: // - get all edges adj to all faces -> R1 // - get all edges adj to split_node -> R2 // - R3 = R1 & R2 (edges connected to split_node & adj to a star face) // - R3 -= split_edges (take split edges off addl_ents) Range R2; MeshTopoUtil mtu(mbImpl); ErrorCode result = mbImpl->get_adjacencies(&split_node, 1, 1, false, R2); RR; Range::iterator rit; for (int i = 0; i < 2; i++) { Range R1, R3; result = mbImpl->get_adjacencies(&star_dp1[i][0], star_dp1[i].size(), 1, false, R1, Interface::UNION); RR; R3 = intersect( R1, R2); for (int j = 0; j < 3; j++) if (split_edges[j]) R3.erase(split_edges[j]); addl_ents[i].merge(R3); } return MB_SUCCESS; }
ErrorCode moab::DualTool::foc_get_ents | ( | EntityHandle | ocl, |
EntityHandle | ocr, | ||
EntityHandle * | quads, | ||
EntityHandle * | split_edges, | ||
EntityHandle * | split_nodes, | ||
Range & | hexes, | ||
EntityHandle * | other_edges, | ||
EntityHandle * | other_nodes | ||
) |
given the two 1-cells involved in the foc, get entities associated with the quads being opened/collapsed; see implementation for more details
Definition at line 1787 of file DualTool.cpp.
{ // get the entities used for foc; ocl and ocr are dual 1-cells // representing quads to be split; returned from this function: // quads[2] - 2 quads to be split // split_edges[2] - edge(s) to be split (2nd is 0 if only one) // split_node - node to be split, if any (otherwise 0) // hexes - connected hexes to split_edges // other_edges[0], [1] - edges in quads[0] and [1] sharing node with // one end of split_edges[0] // other_edges[2], [3] - other end of split_edges[0] (or [1] if 2 // split_edges) // other_edges[4], [5] - edges in quads[0], [1] opposite to split_edges[0] // other_nodes[0], [1] - nodes on other_edges[0], [1] not shared with // split_edges[0] // other_nodes[2], [3] - nodes on other_edges[2], [3] not shared with // split_edges[0] (if 2 split_edges, there's only 1 opposite node // in each split quad) // (for diagram, see Tim's notes from 11/12/07) split_quads[0] = get_dual_entity(ocl); split_quads[1] = get_dual_entity(ocr); if (MBQUAD != mbImpl->type_from_handle(split_quads[0]) || MBQUAD != mbImpl->type_from_handle(split_quads[1])) return MB_TYPE_OUT_OF_RANGE; Range common_edges; ErrorCode result = mbImpl->get_adjacencies(split_quads, 2, 1, false, common_edges); if (MB_SUCCESS != result) return result; if (common_edges.empty()) return MB_FAILURE; for (unsigned int i = 0; i < common_edges.size(); i++) split_edges[i] = common_edges[i]; MeshTopoUtil mtu(mbImpl); if (common_edges.size() == 3) { // find other (non-shared) edges for (int i = 0; i < 2; i++) { Range tmp_edges; result = mbImpl->get_adjacencies(&split_quads[i], 1, 1, false, tmp_edges); if (MB_SUCCESS != result) return result; tmp_edges = subtract( tmp_edges, common_edges); assert(tmp_edges.size() == 1); other_edges[i] = *tmp_edges.begin(); } assert(other_edges[0] && other_edges[1] && other_edges[0] != other_edges[1]); // arrange common edges so middle is in middle result = mtu.opposite_entity(split_quads[0], other_edges[0], split_edges[1]); RR; common_edges.erase(split_edges[1]); split_edges[0] = *common_edges.begin(); split_edges[2] = *common_edges.rbegin(); common_edges.insert(split_edges[1]); // get split nodes and other nodes split_nodes[0] = mtu.common_entity(split_edges[0], split_edges[1], 0); split_nodes[1] = mtu.common_entity(split_edges[2], split_edges[1], 0); other_nodes[0] = mtu.common_entity(split_edges[0], other_edges[0], 0); other_nodes[1] = mtu.common_entity(split_edges[2], other_edges[1], 0); assert(other_nodes[0] && other_nodes[1] && split_nodes[0] && split_nodes[1]); assert(split_edges[0] && split_edges[1] && split_edges[2] && split_edges[0] != split_edges[1] && split_edges[1] != split_edges[2] && split_edges[0] != split_edges[2]); } else if (common_edges.size() == 2) { // split node is shared by split edges split_nodes[0] = mtu.common_entity(split_edges[0], split_edges[1], 0); if (0 == split_nodes[0]) return MB_FAILURE; // first two other nodes are on split edges opposite split node result = mtu.opposite_entity(split_edges[0], split_nodes[0], other_nodes[0]); RR; result = mtu.opposite_entity(split_edges[1], split_nodes[0], other_nodes[1]); RR; // over split quads: for (int i = 0; i < 2; i++) { // 1st other edge is opposite second split edge result = mtu.opposite_entity(split_quads[i], split_edges[1], other_edges[i]); RR; // 2nd other edge is opposite first split edge result = mtu.opposite_entity(split_quads[i], split_edges[0], other_edges[2+i]); RR; // last other node is opposite split node on split quad result = mtu.opposite_entity(split_quads[i], split_nodes[0], other_nodes[2+i]); RR; } } else { const EntityHandle *connect; int num_connect; result = mbImpl->get_connectivity(split_edges[0], connect, num_connect); if (MB_SUCCESS != result) return result; // other_nodes[0], [1] are on split edge other_nodes[0] = connect[0]; other_nodes[1] = connect[1]; // for each of the split quads for (int i = 0; i < 2; i++) { // get the other edge on the split quad adj to node 0 on the split edge, by getting // edges adj to split quad and node and removing split edge; that's other_edge[i] Range tmp_range1, tmp_range2; tmp_range1.insert(connect[0]); tmp_range1.insert(split_quads[i]); result = mbImpl->get_adjacencies(tmp_range1, 1, false, tmp_range2); if (MB_SUCCESS != result) return result; tmp_range2.erase(split_edges[0]); assert(tmp_range2.size() == 1); other_edges[i] = *tmp_range2.begin(); // get edge connected to other node on split edge & split quad; that's // opposite prev other_edges on the split quad; that's other_edges[4+i] result = mtu.opposite_entity(split_quads[i], other_edges[i], other_edges[4+i]); RR; // get the edge on the split quad opposite the split edge; that's other_edges[2+i] result = mtu.opposite_entity(split_quads[i], split_edges[0], other_edges[2+i]); RR; // get nodes on other side of split quad from split edge, by getting common // node between top/bottom edge and opposite edge other_nodes[2+i] = mtu.common_entity(other_edges[i], other_edges[2+i], 0); other_nodes[4+i] = mtu.common_entity(other_edges[4+i], other_edges[2+i], 0); if (0 == other_nodes[2+i] || 0 == other_nodes[4+i]) return MB_FAILURE; } } result = mbImpl->get_adjacencies(split_edges, common_edges.size(), 3, false, hexes, Interface::UNION); if (MB_SUCCESS != result) return result; assert("split node not in other_nodes" && other_nodes[0] != split_nodes[0] && other_nodes[0] != split_nodes[1] && other_nodes[1] != split_nodes[0] && other_nodes[1] != split_nodes[1]); assert("each split node on an end of a split edge" && mtu.common_entity(other_nodes[0], split_edges[0], 0) && (((split_edges[2] && mtu.common_entity(other_nodes[1], split_edges[2], 0)) || (split_edges[1] && mtu.common_entity(other_nodes[1], split_edges[1], 0)) || mtu.common_entity(other_nodes[1], split_edges[0], 0)))); assert("opposite other edges meet at an other node" && (mtu.common_entity(other_edges[0], other_edges[1], 0) == other_nodes[0] || (split_edges[2] && mtu.common_entity(other_edges[0], other_edges[1], 0) == other_nodes[1])) && (split_edges[2] || (split_edges[1] && mtu.common_entity(other_edges[2], other_edges[3], 0) == other_nodes[1]) || mtu.common_entity(other_edges[4], other_edges[5], 0) == other_nodes[1])); return MB_SUCCESS; }
ErrorCode moab::DualTool::foc_get_stars | ( | EntityHandle * | split_quads, |
EntityHandle * | split_edges, | ||
std::vector< EntityHandle > * | star_dp1, | ||
std::vector< EntityHandle > * | star_dp2 | ||
) | [private] |
given the split quads and edges, get the face and hex stars around the edge(s), separated into halves, each of which goes with the new or old entities after the split
Definition at line 2121 of file DualTool.cpp.
{ bool on_bdy = false, on_bdy_tmp; ErrorCode result; MeshTopoUtil mtu(mbImpl); // get the star around the split_edge std::vector<EntityHandle> qstar, hstar; unsigned int qpos = 0; for (int i = 0; i < 3; i++) { if (!split_edges[i]) break; // get the star around this split edge unsigned int qpos_tmp = 0; std::vector<EntityHandle> qstar_tmp, hstar_tmp; result = mtu.star_entities(split_edges[i], qstar_tmp, on_bdy_tmp, 0, &hstar_tmp); RR; // if we're on the bdy, add a null to the hex star too if (on_bdy_tmp) { assert(hstar_tmp.size() == qstar_tmp.size()-1); hstar_tmp.push_back(0); on_bdy = true; } // get the position of first split quad in star while (qpos_tmp < qstar_tmp.size() && qstar_tmp[qpos_tmp] != split_quads[0]) qpos_tmp++; if (qpos_tmp == qstar_tmp.size()) return MB_FAILURE; bool forward; // 1st iteration is forward by definition if (0 == i) forward = true; // need to be careful about direction on later iters else if (hstar[qpos] == hstar_tmp[qpos_tmp]) forward = true; else if (hstar[qpos] == hstar_tmp[(qpos_tmp+qstar_tmp.size()-1)%qstar_tmp.size()] && hstar_tmp[qpos_tmp] == hstar[(qpos+qstar.size()-1)%qstar.size()]) forward = false; else return MB_FAILURE; if (forward) { // 1st half of star // save hex right after split_quad[0] first star_dp2[0].push_back(hstar_tmp[qpos_tmp]); qpos_tmp = (qpos_tmp+1)%qstar_tmp.size(); while (qstar_tmp[qpos_tmp] != split_quads[1]) { star_dp1[0].push_back(qstar_tmp[qpos_tmp]); star_dp2[0].push_back(hstar_tmp[qpos_tmp]); qpos_tmp = (qpos_tmp+1)%qstar_tmp.size(); } // 2nd half of star // save hex right after split_quad[1] first star_dp2[1].push_back(hstar_tmp[qpos_tmp]); qpos_tmp = (qpos_tmp+1)%qstar_tmp.size(); while (qstar_tmp[qpos_tmp] != split_quads[0]) { star_dp1[1].push_back(qstar_tmp[qpos_tmp]); star_dp2[1].push_back(hstar_tmp[qpos_tmp]); qpos_tmp = (qpos_tmp+1)%qstar_tmp.size(); } } else { // go in reverse - take prev hex instead of current // one, and step in reverse // save hex right after split_quad[0] first qpos_tmp = (qpos_tmp+qstar_tmp.size()-1)%qstar_tmp.size(); star_dp2[0].push_back(hstar_tmp[qpos_tmp]); while (qstar_tmp[qpos_tmp] != split_quads[1]) { star_dp1[0].push_back(qstar_tmp[qpos_tmp]); qpos_tmp = (qpos_tmp+qstar_tmp.size()-1)%qstar_tmp.size(); star_dp2[0].push_back(hstar_tmp[qpos_tmp]); } // 2nd half of star // save hex right after split_quad[1] first qpos_tmp = (qpos_tmp+qstar_tmp.size()-1)%qstar_tmp.size(); star_dp2[1].push_back(hstar_tmp[qpos_tmp]); while (qstar_tmp[qpos_tmp] != split_quads[0]) { star_dp1[1].push_back(qstar_tmp[qpos_tmp]); qpos_tmp = (qpos_tmp+qstar_tmp.size()-1)%qstar_tmp.size(); star_dp2[1].push_back(hstar_tmp[qpos_tmp]); } } if (0 == i) { // if we're on the first iteration, save results and continue, other iters // get compared to this one qstar.swap(qstar_tmp); hstar.swap(hstar_tmp); on_bdy = on_bdy_tmp; qpos = qpos_tmp; } } // split quads go on list with NULLs, if any, otherwise on 2nd if (on_bdy) { if (std::find(star_dp2[0].begin(), star_dp2[0].end(), 0) != star_dp2[0].end()) { // remove *all* the zeros star_dp2[0].erase(std::remove(star_dp2[0].begin(), star_dp2[0].end(), 0), star_dp2[0].end()); // put the split quads on this half star_dp1[0].push_back(split_quads[0]); star_dp1[0].push_back(split_quads[1]); } else { star_dp2[1].erase(std::remove(star_dp2[1].begin(), star_dp2[1].end(), 0), star_dp2[1].end()); // put the split quads on this half star_dp1[1].push_back(split_quads[0]); star_dp1[1].push_back(split_quads[1]); } } else { star_dp1[1].push_back(split_quads[0]); star_dp1[1].push_back(split_quads[1]); } // some error checking if (!(((std::find(star_dp1[0].begin(), star_dp1[0].end(), split_quads[0]) == star_dp1[0].end() && std::find(star_dp1[0].begin(), star_dp1[0].end(), split_quads[1]) == star_dp1[0].end() && std::find(star_dp1[1].begin(), star_dp1[1].end(), split_quads[0]) != star_dp1[1].end() && std::find(star_dp1[1].begin(), star_dp1[1].end(), split_quads[1]) != star_dp1[1].end()) || (std::find(star_dp1[1].begin(), star_dp1[1].end(), split_quads[0]) == star_dp1[1].end() && std::find(star_dp1[1].begin(), star_dp1[1].end(), split_quads[1]) == star_dp1[1].end() && std::find(star_dp1[0].begin(), star_dp1[0].end(), split_quads[0]) != star_dp1[0].end() && std::find(star_dp1[0].begin(), star_dp1[0].end(), split_quads[1]) != star_dp1[0].end())) )) { std::cerr << "foc_get_stars: both split quads should be on the same star list half and not " << "on the other, failed" << std::endl; return MB_FAILURE; } if (!(std::find(star_dp2[0].begin(), star_dp2[0].end(), 0) == star_dp2[0].end() && std::find(star_dp2[1].begin(), star_dp2[1].end(), 0) == star_dp2[1].end())) { std::cerr << "foc_get_stars: no NULLs on the hstar lists, failed"; return MB_FAILURE; } return MB_SUCCESS; }
ErrorCode moab::DualTool::fs_check_quad_sense | ( | EntityHandle | hex0, |
EntityHandle | quad0, | ||
std::vector< EntityHandle > * | connects | ||
) | [private] |
check sense of connect arrays, and reverse/rotate if necessary
Definition at line 2792 of file DualTool.cpp.
{ // check sense of 0th quad wrt hex; since sense is out of element, // switch if quad is NOT reversed wrt hex int dum1, dum2, sense = 0; ErrorCode result = mbImpl->side_number(hex0, quad0, dum1, sense, dum2); if (MB_SUCCESS != result) return result; assert(0 != sense); if (1 == sense) { // just switch sense of this one; others will get switched next EntityHandle dum = connects[0][0]; connects[0][0] = connects[0][2]; connects[0][2] = dum; } // check sense of 1st, 2nd quads, rotate if necessary to align connect arrays int index0 = -1, index2 = -1, sense0 = 0, sense2 = 0; MeshTopoUtil mtu(mbImpl); for (int i = 0; i < 4; i++) { if (0 != mtu.common_entity(connects[0][0], connects[1][i], 1)) { index0 = i; if (0 != mtu.common_entity(connects[0][1], connects[1][(i+1)%4], 1)) sense0 = 1; else if (0 != mtu.common_entity(connects[0][1], connects[1][(i+4-1)%4], 1)) sense0 = -1; break; } } assert(index0 != -1 && sense0 != 0); if (sense0 == -1) { EntityHandle dumh = connects[1][0]; connects[1][0] = connects[1][2]; connects[1][2] = dumh; if (index0%2 == 0) index0 = (index0+2)%4; } if (index0 != 0) { std::vector<EntityHandle> tmpc; for (int i = 0; i < 4; i++) tmpc.push_back(connects[1][(index0+i)%4]); connects[1].swap(tmpc); } for (int i = 0; i < 4; i++) { if (0 != mtu.common_entity(connects[1][0], connects[2][i], 1)) { index2 = i; if (0 != mtu.common_entity(connects[1][1], connects[2][(i+1)%4], 1)) sense2 = 1; else if (0 != mtu.common_entity(connects[1][1], connects[2][(i+4-1)%4], 1)) sense2 = -1; break; } } assert(index2 != -1 && sense2 != 0); if (sense2 == -1) { EntityHandle dumh = connects[2][0]; connects[2][0] = connects[2][2]; connects[2][2] = dumh; if (index2%2 == 0) index2 = (index2+2)%4; } if (index2 != 0) { std::vector<EntityHandle> tmpc; for (int i = 0; i < 4; i++) tmpc.push_back(connects[2][(index2+i)%4]); connects[2].swap(tmpc); } return MB_SUCCESS; }
ErrorCode moab::DualTool::fs_get_quad_loops | ( | EntityHandle * | hexes, |
std::vector< EntityHandle > * | connects, | ||
std::vector< EntityHandle > * | side_quads | ||
) | [private] |
get loops of quads around 2 hexes, ordered similarly to vertex loops
Definition at line 2769 of file DualTool.cpp.
{ for (int i = 0; i < 4; i++) { for (int j = 0; j < 2; j++) { Range adj_ents, dum_quads; adj_ents.insert(hexes[j]); adj_ents.insert(connects[j][i]); adj_ents.insert(connects[j][(i+1)%4]); adj_ents.insert(connects[j+1][i]); adj_ents.insert(connects[j+1][(i+1)%4]); ErrorCode result = mbImpl->get_adjacencies(adj_ents, 2, false, dum_quads); if (MB_SUCCESS != result) return result; assert(1 == dum_quads.size()); side_quads[j].push_back(*dum_quads.begin()); } } return MB_SUCCESS; }
ErrorCode moab::DualTool::fs_get_quads | ( | EntityHandle | odedge, |
EntityHandle * | quads, | ||
EntityHandle * | hexes, | ||
std::vector< EntityHandle > * | connects | ||
) | [private] |
get the three quads for a face shrink, the two hexes, and the connectivity of the three quads
Definition at line 3065 of file DualTool.cpp.
{ // need to get the three quads along the chord EntityHandle chord = get_dual_hyperplane(odedge); if (0 == chord) return MB_FAILURE; std::vector<EntityHandle> edges; ErrorCode result = mbImpl->get_entities_by_handle(chord, edges); if (MB_FAILURE == result) return result; std::vector<EntityHandle>::iterator vit = std::find(edges.begin(), edges.end(), odedge); // shouldn't be first or last edge on chord if (vit == edges.end() || *edges.begin() == *vit || *edges.rbegin() == *vit) return MB_FAILURE; // get quads/connectivity for first 3 quads quads[0] = get_dual_entity(*(vit-1)); quads[1] = get_dual_entity(*vit); quads[2] = get_dual_entity(*(vit+1)); for (int i = 0; i < 3; i++) { result = mbImpl->get_connectivity(&quads[i], 1, connects[i], true); if (MB_SUCCESS != result) return result; } Range tmph; result = mbImpl->get_adjacencies(quads, 2, 3, false, tmph); if (MB_SUCCESS != result) return result; assert(tmph.size() == 1); hexes[0] = *tmph.begin(); tmph.clear(); result = mbImpl->get_adjacencies(&quads[1], 2, 3, false, tmph); if (MB_SUCCESS != result) return result; assert(tmph.size() == 1); hexes[1] = *tmph.begin(); return MB_SUCCESS; }
ErrorCode moab::DualTool::fsr_get_fourth_quad | ( | std::vector< EntityHandle > * | connects, |
std::vector< EntityHandle > * | side_quads | ||
) | [private] |
given connectivity of first 3 quads for reverse face shrink, get fourth (outer 4 verts to be shared by two inner hexes) and quads around the side of the structure
Definition at line 3012 of file DualTool.cpp.
{ // given the first three quad connectivities in ordered vectors, get the fourth, // where the fourth is really the 4 vertices originally shared by the 2 hexes // before the face shrink on them // vertex on 4th quad is in quad adj to other 3 verts for (int i = 0; i < 4; i++) { Range start_verts, tmp_verts, quads; for (int j = 0; j < 3; j++) start_verts.insert(connects[j][i]); ErrorCode result = mbImpl->get_adjacencies(start_verts, 2, false, quads); if (MB_SUCCESS != result) return result; assert(quads.size() == 1); result = mbImpl->get_adjacencies(&(*quads.begin()), 1, 0, false, tmp_verts); RR; tmp_verts = subtract( tmp_verts, start_verts); assert(1 == tmp_verts.size()); connects[3].push_back(*tmp_verts.begin()); } // now get the side quads for (int i = 0; i < 4; i++) { Range dum_ents, hexes; dum_ents.insert(connects[1][i]); dum_ents.insert(connects[1][(i+1)%4]); dum_ents.insert(connects[3][i]); ErrorCode result = mbImpl->get_adjacencies(dum_ents, 3, false, hexes); if (MB_SUCCESS != result) return result; assert(1 == hexes.size()); hexes.insert(connects[0][i]); hexes.insert(connects[0][(i+1)%4]); hexes.insert(connects[3][i]); hexes.insert(connects[3][(i+1)%4]); dum_ents.clear(); result = mbImpl->get_adjacencies(hexes, 2, false, dum_ents); if (MB_SUCCESS != result) return result; assert(dum_ents.size() == 1); side_quads[0].push_back(*dum_ents.begin()); hexes.erase(connects[0][i]); hexes.erase(connects[0][(i+1)%4]); hexes.insert(connects[2][i]); hexes.insert(connects[2][(i+1)%4]); dum_ents.clear(); result = mbImpl->get_adjacencies(hexes, 2, false, dum_ents); if (MB_SUCCESS != result) return result; side_quads[1].push_back(*dum_ents.begin()); } return MB_SUCCESS; }
ErrorCode moab::DualTool::get_cell_points | ( | EntityHandle | dual_ent, |
std::vector< int > & | npts, | ||
std::vector< GraphicsPoint > & | points | ||
) | [private] |
get points defining facets of a 2cell
Definition at line 1236 of file DualTool.cpp.
{ assert(MBPOLYGON == mbImpl->type_from_handle(dual_ent)); // get the 1cells in this 2cell Range one_cells; Range tc_range; tc_range.insert(dual_ent); ErrorCode result = mbImpl->get_adjacencies(tc_range, 1, false, one_cells, Interface::UNION); RR; int num_edges = one_cells.size(); std::vector<GraphicsPoint> dum_gps(num_edges+1); // get graphics points for 0cells and for this cell result = mbImpl->tag_get_data(dualGraphicsPoint_tag(), one_cells, &dum_gps[0]); RR; result = mbImpl->tag_get_data(dualGraphicsPoint_tag(), &dual_ent, 1, &(dum_gps[num_edges])); RR; Range::iterator eit; const EntityHandle *connect; int num_connect; GraphicsPoint vert_gps[2]; int i; for (i = 0, eit = one_cells.begin(); i < num_edges; i++, eit++) { // get the vertices and the graphics points for them result = mbImpl->get_connectivity(*eit, connect, num_connect); RR; result = mbImpl->tag_get_data(dualGraphicsPoint_tag(), connect, 2, vert_gps); RR; // make the 2 tris corresponding to this edge; don't worry about order // for now npts.push_back(3); points.push_back(dum_gps[num_edges]); points.push_back(vert_gps[0]); points.push_back(dum_gps[i]); npts.push_back(3); points.push_back(dum_gps[num_edges]); points.push_back(dum_gps[i]); points.push_back(vert_gps[1]); } return result; }
ErrorCode moab::DualTool::get_dual_entities | ( | const int | dim, |
EntityHandle * | entities, | ||
const int | num_entities, | ||
Range & | dual_ents | ||
) |
get the dual entities; if non-null, only dual of entities passed in are returned
get the cells of the dual
Definition at line 753 of file DualTool.cpp.
{ if (0 == isDualCell_tag()) return MB_SUCCESS; if (0 > dim || 3 < dim) return MB_INDEX_OUT_OF_RANGE; unsigned int dum = 0x1; const void *dum_ptr = &dum; static EntityType dual_type[] = {MBVERTEX, MBEDGE, MBPOLYGON, MBPOLYHEDRON}; Range dim_ents; ErrorCode result; if (0 == entities || 0 == num_entities) { // just get all the dual entities of this dimension result = mbImpl->get_entities_by_type_and_tag(0, dual_type[dim], &isDualCellTag, &dum_ptr, 1, dual_ents); } else { // else look for specific dual entities result = mbImpl->get_adjacencies(entities, num_entities, 3-dim, false, dim_ents, Interface::UNION); if (MB_SUCCESS != result) return result; std::vector<EntityHandle> dual_ents_vec(dim_ents.size()); result = mbImpl->tag_get_data(dualEntity_tag(), dim_ents, &dual_ents_vec[0]); if (MB_SUCCESS != result) return result; std::copy(dual_ents_vec.begin(), dual_ents_vec.end(), range_inserter(dual_ents)); } return result; }
ErrorCode moab::DualTool::get_dual_entities | ( | const int | dim, |
EntityHandle * | entities, | ||
const int | num_entities, | ||
std::vector< EntityHandle > & | dual_ents | ||
) |
get the dual entities; if non-null, only dual of entities passed in are returned
get the faces of the dual
Definition at line 791 of file DualTool.cpp.
{ Range tmp_range; ErrorCode result = get_dual_entities(dim, entities, num_entities, tmp_range); if (MB_SUCCESS != result) return result; // dual_ents.insert(dual_ents.end(), tmp_range.begin(), tmp_range.end()); dual_ents.reserve(dual_ents.size() + tmp_range.size()); for (Range::const_iterator it = tmp_range.begin(); it != tmp_range.end(); ++it) { dual_ents.push_back(*it); } return MB_SUCCESS; }
ErrorCode moab::DualTool::get_dual_entities | ( | const EntityHandle | dual_ent, |
Range * | dcells, | ||
Range * | dedges, | ||
Range * | dverts, | ||
Range * | dverts_loop, | ||
Range * | dedges_loop | ||
) |
given a dual surface or curve, return the 2-cells, 1-cells, 0-cells, and loop 0/1-cells, if requested; any of those range pointers can be NULL, in which case that range isn't returned
Definition at line 2465 of file DualTool.cpp.
{ ErrorCode result = MB_SUCCESS; if (NULL != dcells) { result = mbImpl->get_entities_by_type(dual_ent, MBPOLYGON, *dcells); if (MB_SUCCESS != result) return result; } if (NULL != dedges) { if (NULL != dcells) result = mbImpl->get_adjacencies(*dcells, 1, false, *dedges, Interface::UNION); else result = mbImpl->get_entities_by_type(dual_ent, MBEDGE, *dedges); if (MB_SUCCESS != result) return result; } if (NULL != dverts) { if (NULL != dcells) result = mbImpl->get_adjacencies(*dcells, 0, false, *dverts, Interface::UNION); else if (NULL != dedges) result = mbImpl->get_adjacencies(*dedges, 0, false, *dverts, Interface::UNION); else { Range all_ents; result = mbImpl->get_entities_by_handle(dual_ent, all_ents); RR; result = mbImpl->get_adjacencies(all_ents, 0, false, *dverts, Interface::UNION); } if (MB_SUCCESS != result) return result; } if (NULL != dverts_loop && NULL != dverts) { static std::vector<EntityHandle> dual_ents; dual_ents.reserve(dverts->size()); result = mbImpl->tag_get_data(dualEntity_tag(), *dverts, &dual_ents[0]); if (MB_SUCCESS != result) return result; Range::iterator rit; unsigned int i; for (rit = dverts->begin(), i = 0; rit != dverts->end(); rit++, i++) if (0 != dual_ents[i] && mbImpl->type_from_handle(dual_ents[i]) == MBQUAD) dverts_loop->insert(*rit); } if (NULL != dedges_loop && NULL != dedges) { static std::vector<EntityHandle> dual_ents; dual_ents.reserve(dedges->size()); result = mbImpl->tag_get_data(dualEntity_tag(), *dedges, &dual_ents[0]); if (MB_SUCCESS != result) return result; Range::iterator rit; unsigned int i; for (rit = dedges->begin(), i = 0; rit != dedges->end(); rit++, i++) if (0 != dual_ents[i] && mbImpl->type_from_handle(dual_ents[i]) == MBEDGE) dedges_loop->insert(*rit); } return result; }
EntityHandle moab::DualTool::get_dual_entity | ( | const EntityHandle | this_ent | ) | const |
return the corresponding dual entity
Definition at line 1426 of file DualTool.cpp.
{ EntityHandle dual_ent; ErrorCode result = mbImpl->tag_get_data(dualEntity_tag(), &this_ent, 1, &dual_ent); if (MB_SUCCESS != result || MB_TAG_NOT_FOUND == result) return 0; else return dual_ent; }
EntityHandle moab::DualTool::get_dual_hyperplane | ( | const EntityHandle | ncell | ) |
given an entity, return any dual surface or curve it's in
Definition at line 1392 of file DualTool.cpp.
{ // get the sheet or chord it's in std::vector<EntityHandle> adj_sets; ErrorCode result = mbImpl->get_adjacencies(&ncell, 1, 4, false, adj_sets); if (MB_SUCCESS != result) return 0; EntityHandle dum_set; for (std::vector<EntityHandle>::iterator vit = adj_sets.begin(); vit != adj_sets.end(); vit++) { if (mbImpl->tag_get_data(dualCurve_tag(), &(*vit), 1, &dum_set) != MB_TAG_NOT_FOUND || mbImpl->tag_get_data(dualSurface_tag(), &(*vit), 1, &dum_set) != MB_TAG_NOT_FOUND) return *vit; } return 0; }
ErrorCode moab::DualTool::get_dual_hyperplanes | ( | const Interface * | impl, |
const int | dim, | ||
Range & | dual_ents | ||
) | [static] |
get the d-dimensional hyperplane sets; static 'cuz it's easy to do without an active dualtool
Definition at line 812 of file DualTool.cpp.
{ if (dim != 1 && dim != 2) return MB_INDEX_OUT_OF_RANGE; Tag dual_tag; ErrorCode result; if (dim == 1) result = impl->tag_get_handle(DUAL_CURVE_TAG_NAME, 1, MB_TYPE_HANDLE, dual_tag ); else result = impl->tag_get_handle(DUAL_SURFACE_TAG_NAME, 1, MB_TYPE_HANDLE, dual_tag ); if (MB_SUCCESS == result) result = impl->get_entities_by_type_and_tag(0, MBENTITYSET, &dual_tag, NULL, 1, dual_ents, Interface::UNION); return result; }
EntityHandle moab::DualTool::get_extra_dual_entity | ( | const EntityHandle | this_ent | ) |
return the corresponding extra dual entity
return the corresponding dual entity
Definition at line 1435 of file DualTool.cpp.
{ EntityHandle dual_ent; ErrorCode result = mbImpl->tag_get_data(extraDualEntity_tag(), &this_ent, 1, &dual_ent); if (MB_SUCCESS != result || MB_TAG_NOT_FOUND == result) return 0; else return dual_ent; }
ErrorCode moab::DualTool::get_graphics_points | ( | EntityHandle | dual_ent, |
std::vector< int > & | npts, | ||
std::vector< GraphicsPoint > & | gpoints | ||
) |
get the graphics points for single entity (dual_ent CAN'T be a set); returns multiple facets, each with npts[i] points
Definition at line 1183 of file DualTool.cpp.
{ // shouldn't be a set assert(MBENTITYSET != mbImpl->type_from_handle(dual_ent)); // get the graphics points comprising the given entity GraphicsPoint gp_array[DualTool::GP_SIZE]; ErrorCode result = MB_SUCCESS; // switch based on topological dimension switch (mbImpl->dimension_from_handle(dual_ent)) { case 0: // just return the vertex point result = mbImpl->tag_get_data(dualGraphicsPoint_tag(), &dual_ent, 1, gp_array); if (MB_SUCCESS == result) points.push_back(gp_array[0]); break; case 1: // get my graphics point then those of my vertices const EntityHandle *connect; int num_connect; result = mbImpl->get_connectivity(dual_ent, connect, num_connect); if (MB_SUCCESS != result) break; result = mbImpl->tag_get_data(dualGraphicsPoint_tag(), connect, 2, gp_array); if (MB_SUCCESS == result) { points.push_back(gp_array[0]); points.push_back(gp_array[0]); points.push_back(gp_array[1]); result = mbImpl->tag_get_data(dualGraphicsPoint_tag(), &dual_ent, 1, gp_array); if (MB_SUCCESS == result) points[1] = gp_array[0]; } npts.push_back(3); break; case 2: result = get_cell_points(dual_ent, npts, points); break; } return result; }
ErrorCode moab::DualTool::get_graphics_points | ( | const Range & | in_range, |
std::vector< GraphicsPoint > & | gpoints, | ||
const bool | assign_ids = false , |
||
const int | start_id = 0 |
||
) |
get the graphics points for a range of entities or sets (if set, the entities in those sets); optionally reset ids on points
Definition at line 1285 of file DualTool.cpp.
{ // return graphics points on dual entities in in_range or in entities // in sets in in_range ErrorCode result; // for each dual hyperplane set: Range::const_iterator rit; Range two_cells, all_cells; for (rit = in_range.begin(); rit != in_range.end(); rit++) { // for each entity: two_cells.clear(); EntityType this_type = mbImpl->type_from_handle(*rit); if (MBENTITYSET == this_type) { result = mbImpl->get_entities_by_handle(*rit, two_cells); RR; std::copy(two_cells.begin(), two_cells.end(), range_inserter(all_cells)); } else { two_cells.insert(*rit); assert(this_type == MBVERTEX || this_type == MBEDGE || this_type == MBPOLYGON || this_type == MBPOLYHEDRON); } result = mbImpl->get_adjacencies(two_cells, 0, false, all_cells, Interface::UNION); RR; result = mbImpl->get_adjacencies(two_cells, 1, false, all_cells, Interface::UNION); RR; } // get graphics points points.resize(all_cells.size()); result = mbImpl->tag_get_data(dualGraphicsPointTag, all_cells, &points[0]); RR; if (assign_ids) { int i = start_id; for (std::vector<GraphicsPoint>::iterator vit = points.begin(); vit != points.end(); vit++) vit->id = i++; result = mbImpl->tag_set_data(dualGraphicsPoint_tag(), all_cells, &points[0]); RR; } return result; }
ErrorCode moab::DualTool::get_opposite_verts | ( | const EntityHandle | middle_edge, |
const EntityHandle | chord, | ||
EntityHandle * | verts | ||
) |
given a 1-cell and a chord, return the neighboring vertices on the chord, in the same order as the 1-cell's vertices
Definition at line 2388 of file DualTool.cpp.
{ // get the edges on the chord, in order, and move to middle_edge std::vector<EntityHandle> chord_edges; const EntityHandle *connect; int num_connect; ErrorCode result = mbImpl->get_entities_by_handle(chord, chord_edges); RR; std::vector<EntityHandle>::iterator vit = std::find(chord_edges.begin(), chord_edges.end(), middle_edge); result = mbImpl->get_connectivity(middle_edge, connect, num_connect); RR; if ( // middle_edge isn't on this chord vit == chord_edges.end() || // chord only has 1 edge chord_edges.size() == 1 || // middle_edge is at beginning or end and chord isn't blind ((vit == chord_edges.begin() || vit == chord_edges.end()-1) && !is_blind(chord))) return MB_FAILURE; else if (chord_edges.size() == 2) { // easier if it's a 2-edge blind chord, just get vertices in opposite order verts[0] = connect[1]; verts[1] = connect[0]; return MB_SUCCESS; } // get vertices with the prev edge & subtract vertices of 1-cell if (vit == chord_edges.begin()) vit = chord_edges.end() - 1; else vit--; Range dum_connect, middle_connect; result = mbImpl->get_connectivity(&middle_edge, 1, middle_connect); RR; result = mbImpl->get_connectivity(&(*vit), 1, dum_connect); RR; dum_connect = subtract( dum_connect, middle_connect); if (dum_connect.size() != 1) { std::cerr << "Trouble traversing chord." << std::endl; return MB_FAILURE; } // put in verts[0] verts[0] = *dum_connect.begin(); // same with prev edge vit++; if (vit == chord_edges.end()) vit = chord_edges.begin(); vit++; dum_connect.clear(); result = mbImpl->get_connectivity(&(*vit), 1, dum_connect); RR; dum_connect = subtract( dum_connect, middle_connect); if (dum_connect.size() != 1) { std::cerr << "Trouble traversing chord." << std::endl; return MB_FAILURE; } // put in verts[1] verts[1] = *dum_connect.begin(); // if verts[0] and 1st vertex of 1cell don't have common edge, switch verts MeshTopoUtil mtu(mbImpl); if (0 == mtu.common_entity(verts[0], connect[0], 1)) { EntityHandle dum_h = verts[0]; verts[0] = verts[1]; verts[1] = dum_h; } if (0 == mtu.common_entity(verts[0], connect[0], 1)) { std::cerr << "Trouble traversing chord." << std::endl; return MB_FAILURE; } return MB_SUCCESS; }
ErrorCode moab::DualTool::get_radial_dverts | ( | const EntityHandle | edge, |
std::vector< EntityHandle > & | rad_dverts, | ||
bool & | bdy_edge | ||
) | [private] |
given an edge handle, return a list of dual vertices in radial order around the edge; also returns whether this edge is on the boundary
given an edge handle, return a list of dual vertices in radial order around the edge
Definition at line 661 of file DualTool.cpp.
{ rad_dverts.clear(); std::vector<EntityHandle> rad_faces, rad_ents; ErrorCode result = MeshTopoUtil(mbImpl).star_entities(edge, rad_faces, bdy_edge, 0, &rad_ents); if (MB_SUCCESS != result) return result; if (bdy_edge) { // if we're a bdy edge, change the order back to what DualTool expects rad_ents.push_back(*rad_faces.rbegin()); rad_ents.push_back(*rad_faces.begin()); } rad_dverts.resize(rad_ents.size()); for (unsigned int i = 0; i < rad_ents.size(); i++) { EntityHandle dual_ent; result = mbImpl->tag_get_data(dualEntity_tag(), &rad_ents[i], 1, &dual_ent); if (!bdy_edge || i < rad_ents.size()-2) rad_dverts[i] = dual_ent; else { // fix up this entry assert(mbImpl->type_from_handle(dual_ent) == MBEDGE); // get connectivity of that edge const EntityHandle *connect; int num_connect; result = mbImpl->get_connectivity(dual_ent, connect, num_connect); if (MB_SUCCESS != result) return result; // we want the one that's not already on the list; reuse last_face int last_hex = (i == rad_ents.size()-1 ? 0 : i-1); EntityHandle last_face = (connect[0] == rad_dverts[last_hex] ? connect[1] : connect[0]); rad_dverts[i] = last_face; } } return result; }
Tag moab::DualTool::globalId_tag | ( | ) | const [inline] |
ErrorCode moab::DualTool::globalId_tag | ( | const Tag | tag | ) | [inline] |
get/set the tag for dual entities
Definition at line 497 of file DualTool.hpp.
{ ErrorCode result = MB_FAILURE; if ((0 == globalIdTag && tag) || globalIdTag != tag) { globalIdTag = tag; result = MB_SUCCESS; } return result; }
bool moab::DualTool::is_blind | ( | const EntityHandle | chord | ) |
returns true if first & last vertices are dual to hexes (not faces)
returns true if all vertices are dual to hexes (not faces)
Definition at line 2362 of file DualTool.cpp.
{ // must be an entity set if (TYPE_FROM_HANDLE(chord_or_sheet) != MBENTITYSET) return false; // get the vertices Range verts, ents; ErrorCode result = mbImpl->get_entities_by_handle(chord_or_sheet, ents); if (MB_SUCCESS != result || ents.empty()) return false; result = mbImpl->get_adjacencies(ents, 0, false, verts, Interface::UNION); if (MB_SUCCESS != result || verts.empty()) return false; for (Range::iterator rit = verts.begin(); rit != verts.end(); rit++) { // get dual entity for this vertex EntityHandle dual_ent = get_dual_entity(*rit); if (0 == dual_ent) continue; if (TYPE_FROM_HANDLE(dual_ent) == MBQUAD) return false; } // if none of the vertices' duals were quads, chord_or_sheet must be blind return true; }
Tag moab::DualTool::isDualCell_tag | ( | ) | const [inline] |
get/set the tag for dual cells
Definition at line 399 of file DualTool.hpp.
{ return isDualCellTag; }
ErrorCode moab::DualTool::isDualCell_tag | ( | const Tag | tag | ) | [inline] |
get/set the tag for dual cells
Definition at line 449 of file DualTool.hpp.
{ ErrorCode result = MB_FAILURE; if ((0 == isDualCellTag && tag) || isDualCellTag != tag) { isDualCellTag = tag; result = MB_SUCCESS; } return result; }
ErrorCode moab::DualTool::list_entities | ( | const Range & | entities | ) | const |
Definition at line 2554 of file DualTool.cpp.
{ // now print each entity, listing the dual information first then calling Interface to do // the rest ErrorCode result = MB_SUCCESS, tmp_result; for (Range::const_iterator iter = entities.begin(); iter != entities.end(); iter++) { EntityType this_type = TYPE_FROM_HANDLE(*iter); std::cout << CN::EntityTypeName(this_type) << " " << ID_FROM_HANDLE(*iter) << ":" << std::endl; EntityHandle dual_ent = get_dual_entity(*iter); if (0 != dual_ent) { std::cout << "Dual to " << CN::EntityTypeName(mbImpl->type_from_handle(dual_ent)) << " " << mbImpl->id_from_handle(dual_ent) << std::endl; } if (TYPE_FROM_HANDLE(*iter) == MBENTITYSET) { EntityHandle chord = 0, sheet = 0; int id; result = mbImpl->tag_get_data(dualCurve_tag(), &(*iter), 1, &chord); result = mbImpl->tag_get_data(dualSurface_tag(), &(*iter), 1, &sheet); result = mbImpl->tag_get_data(globalId_tag(), &(*iter), 1, &id); if (0 != chord) std::cout << "(Dual chord " << id << ")" << std::endl; if (0 != sheet) std::cout << "(Dual sheet " << id << ")" << std::endl; } tmp_result = mbImpl->list_entity(*iter); if (MB_SUCCESS != tmp_result) result = tmp_result; } return result; }
ErrorCode moab::DualTool::list_entities | ( | const EntityHandle * | entities, |
const int | num_entities | ||
) | const |
Definition at line 2529 of file DualTool.cpp.
{ Range temp_range; ErrorCode result; if (NULL == entities && 0 == num_entities) return mbImpl->list_entities(entities, num_entities); else if (NULL == entities && 0 < num_entities) { // list all entities of all types std::cout << std::endl; for (EntityType this_type = MBVERTEX; this_type < MBMAXTYPE; this_type++) { result = mbImpl->get_entities_by_type(0, this_type, temp_range); if (MB_SUCCESS != result) return result; } } else { std::copy(entities, entities+num_entities, range_inserter(temp_range)); } return list_entities(temp_range); }
EntityHandle moab::DualTool::next_loop_vertex | ( | const EntityHandle | last_v, |
const EntityHandle | this_v, | ||
const EntityHandle | dual_surf | ||
) |
given a last_v (possibly zero) and this_v, find the next loop vertex on this dual surface
Definition at line 1340 of file DualTool.cpp.
{ // given two vertices, find the next one on the loop; if one is a dual // surface, then just choose either one for that surface assert((0 == last_v || mbImpl->type_from_handle(last_v) == MBVERTEX) && mbImpl->type_from_handle(this_v) == MBVERTEX && mbImpl->type_from_handle(dual_surf) == MBENTITYSET); // get the connected vertices MeshTopoUtil tpu(mbImpl); Range other_verts; ErrorCode result = tpu.get_bridge_adjacencies(this_v, 1, 0, other_verts); if (MB_SUCCESS != result || other_verts.empty()) return 0; //if (mbImpl->type_from_handle(last_v) == MBENTITYSET) { // dual surface, choose either; first get a 2cell on this surface Range tcells, tcells2, verts; result = mbImpl->get_entities_by_type(dual_surf, MBPOLYGON, tcells); if (MB_SUCCESS != result || tcells.empty()) return 0; // ok, pay attention here: first get 2cells common to dual surface and this_v verts.insert(this_v); result = mbImpl->get_adjacencies(verts, 2, false, tcells); if (MB_SUCCESS != result || tcells.empty()) return 0; // next get vertices common to both 2cells and subtract from other_verts; also // remove last_v if it's non-zero verts.clear(); result = mbImpl->get_adjacencies(tcells, 0, false, verts); if (MB_SUCCESS != result || verts.empty()) return 0; Range tmp_verts = subtract( other_verts, verts); other_verts.swap(tmp_verts); if (0 != last_v) other_verts.erase(last_v); // now get intersection of remaining vertices and 2 2cells vertices // look at each one successively; should find one, maybe not on both tmp_verts = other_verts; Range tmp_faces(*tcells.begin(), *tcells.begin()); result = mbImpl->get_adjacencies(tmp_faces, 0, false, tmp_verts); if (MB_SUCCESS == result && !tmp_verts.empty()) return *tmp_verts.begin(); tmp_faces.clear(); tmp_faces.insert(*tcells.rbegin()); result = mbImpl->get_adjacencies(tmp_faces, 0, false, other_verts); if (MB_SUCCESS == result && !other_verts.empty()) return *other_verts.begin(); // if we got here, there isn't any return 0; }
ErrorCode moab::DualTool::order_chord | ( | EntityHandle | chord_set | ) | [private] |
order 1cells on a chord
Definition at line 1033 of file DualTool.cpp.
{ // re-order the 1cells in the set so they are in order along the chord // start by finding the vertex dual to a quad Range verts, one_cells; ErrorCode result = mbImpl->get_entities_by_dimension(chord_set, 1, one_cells); if (MB_SUCCESS != result || one_cells.empty()) return MB_FAILURE; result = mbImpl->get_adjacencies(one_cells, 0, false, verts, Interface::UNION); if (MB_SUCCESS != result || verts.empty()) return MB_FAILURE; EntityHandle last_vert = 0; for (Range::iterator rit = verts.begin(); rit != verts.end(); rit++) { if (TYPE_FROM_HANDLE(get_dual_entity(*rit)) == MBQUAD) { last_vert = *rit; break; } } // if there's no vertex owned by a quad, just start with 1st one if (0 == last_vert) last_vert = *verts.begin(); // now, skip from vertex to vertex, building a list of 1cells std::vector<EntityHandle> ordered_1cells; EntityHandle last_1cell = 0; Range dum1, dum2; const EntityHandle *connect; int num_connect; ErrorCode tmp_result = MB_SUCCESS; while(ordered_1cells.size() != one_cells.size()) { dum1 = one_cells; result = mbImpl->get_adjacencies(&last_vert, 1, 1, false, dum1); if (0 != last_1cell) dum1.erase(last_1cell); // assert(1 == dum1.size()); if (0 != last_1cell && 1 != dum1.size()) { std::cerr << "unexpected size traversing chord." << std::endl; tmp_result = MB_FAILURE; } last_1cell = *dum1.begin(); ordered_1cells.push_back(last_1cell); result = mbImpl->get_connectivity(last_1cell, connect, num_connect); RR; if (last_vert == connect[0]) last_vert = connect[1]; else last_vert = connect[0]; } // now have the 1cells in order, replace them in the set if (MB_SUCCESS == tmp_result) { result = mbImpl->remove_entities(chord_set, one_cells); RR; result = mbImpl->add_entities(chord_set, &ordered_1cells[0], ordered_1cells.size()); RR; } return MB_SUCCESS; }
void moab::DualTool::print_cell | ( | EntityHandle | cell | ) | [private] |
Definition at line 1686 of file DualTool.cpp.
{ const EntityHandle *connect; int num_connect; ErrorCode result = mbImpl->get_connectivity(cell, connect, num_connect); if (MB_SUCCESS != result) return; bool first = true; EntityHandle primals[20]; std::vector<int> ids; assert(num_connect < 20); result = mbImpl->tag_get_data(dualEntityTag, connect, num_connect, primals); ids.resize(num_connect); result = mbImpl->tag_get_data(globalIdTag, primals, num_connect, &ids[0]); for (int i = 0; i < num_connect; i++) { if (!first) std::cout << "-"; EntityType this_type = mbImpl->type_from_handle(primals[i]); if (this_type == MBHEX) std::cout << "h"; else if (this_type == MBQUAD) std::cout << "f"; else std::cout << "u"; if (ids[i] != 0) std::cout << ids[i]; else std::cout << mbImpl->id_from_handle(primals[i]); first = false; } }
ErrorCode moab::DualTool::rev_atomic_pillow | ( | EntityHandle | pillow, |
Range & | chords | ||
) |
effect reverse atomic pillow operation
Definition at line 1563 of file DualTool.cpp.
{ // get the dual entities associated with elements in the pillow; go through // the elements instead of the pillow sheet so you get all of them, not just // the ones on the sheet if (debug_ap) ((Core*)mbImpl)->check_adjacencies(); std::cout << "-AP("; print_cell(pillow); std::cout << ")" << std::endl; Range dverts; ErrorCode result = get_dual_entities(pillow, NULL, NULL, &dverts, NULL, NULL); if (MB_SUCCESS != result) return result; assert(2 == dverts.size()); EntityHandle hexes[2]; result = mbImpl->tag_get_data(dualEntity_tag(), dverts, hexes); RR; assert(hexes[0] != 0 && hexes[1] != 0); std::vector<EntityHandle> dcells[4]; Range pcells[4]; std::copy(hexes, hexes+2, range_inserter(pcells[3])); std::copy(dverts.begin(), dverts.end(), std::back_inserter(dcells[0])); for (int dim = 0; dim <= 2; dim++) { result = mbImpl->get_adjacencies(hexes, 2, dim, false, pcells[dim], Interface::UNION); RR; dcells[3-dim].resize(pcells[dim].size()); result = mbImpl->tag_get_data(dualEntity_tag(), pcells[dim], &dcells[3-dim][0]); RR; } // delete the dual entities which are part of the original pillow result = mbImpl->delete_entities(&pillow, 1); if (MB_SUCCESS != result) return result; result = mbImpl->delete_entities(chords); if (MB_SUCCESS != result) return result; for (int i = 3; i >= 0; i--) { result = delete_dual_entities(&dcells[i][0], dcells[i].size()); RR; } // delete the primal entities inserted by the ap; be careful to get the right // faces, edges and vertices Range del_faces, del_edges, del_verts, tmp_faces, tmp_verts; // faces are the shared 5 and the 1 other one with greater handle (which // we know will be later in the range) result = mbImpl->get_adjacencies(hexes, 2, 2, false, del_faces); RR; assert(5 == del_faces.size()); std::copy(pcells[2].begin(), pcells[2].end(), range_inserter(tmp_faces)); tmp_faces = subtract( tmp_faces, del_faces); del_faces.insert(*tmp_faces.rbegin()); result = mbImpl->get_adjacencies(tmp_faces, 0, false, tmp_verts); RR; std::copy(pcells[0].begin(), pcells[0].end(), range_inserter(del_verts)); del_verts = subtract( del_verts, tmp_verts); assert(4 == del_verts.size()); result = mbImpl->get_adjacencies(del_verts, 1, false, del_edges, Interface::UNION); RR; assert(8 == del_edges.size()); result = mbImpl->delete_entities(hexes, 2); RR; result = mbImpl->delete_entities(del_faces); RR; result = mbImpl->delete_entities(del_edges); RR; result = mbImpl->delete_entities(del_verts); RR; if (debug_ap) ((Core*)mbImpl)->check_adjacencies(); // recompute the dual for the hexes on either side of the quad affected // by the ap removal Range tmp_hexes; result = mbImpl->get_adjacencies(tmp_verts, 3, false, tmp_hexes, Interface::UNION); RR; result = construct_hex_dual(tmp_hexes); RR; return MB_SUCCESS; }
effect reverse atomic pillow operation
effect reverse face shrink operation
Definition at line 2872 of file DualTool.cpp.
{ if (debug_ap) ((Core*)mbImpl)->check_adjacencies(); // some preliminary checking if (mbImpl->type_from_handle(odedge) != MBEDGE) return MB_TYPE_OUT_OF_RANGE; std::cout << "-FS("; print_cell(odedge); std::cout << ")" << std::endl; EntityHandle quads[4], hexes[2]; std::vector<EntityHandle> connects[4], side_quads[2]; // get three quads (shared quad & 2 end quads), hexes, and quad // connects ErrorCode result = fs_get_quads(odedge, quads, hexes, connects); if (MB_SUCCESS != result) return result; // adjust sense & rotation so they're aligned, together & wrt first // hex result = fs_check_quad_sense(hexes[0], quads[0], connects); if (MB_SUCCESS != result) return result; result = fsr_get_fourth_quad(connects, side_quads); if (MB_SUCCESS != result) { std::cout << "Can't do -FS here, two hexes must be adjacent to ring of 4 hexes." << std::endl; return result; } Range adj_ents, outer_hexes, all_adjs; // first get the entities connected to interior 4 verts for (int i = 1; i <= 3; i++) { result = mbImpl->get_adjacencies(&connects[1][0], 4, i, false, adj_ents, Interface::UNION); if (MB_SUCCESS != result) return result; } // next get all entities adjacent to those; these will have their dual // entities deleted for (int i = 0; i < 3; i++) { result = mbImpl->get_adjacencies(adj_ents, i, false, all_adjs, Interface::UNION); if (MB_SUCCESS != result) return result; } // get the dual entities and delete them Range dual_ents, dual_hps; for (Range::iterator rit = all_adjs.begin(); rit != all_adjs.end(); rit++) { EntityHandle this_ent = get_dual_entity(*rit); dual_ents.insert(this_ent); } // before deleting dual, grab the 1- and 2-cells for (Range::iterator rit = dual_ents.begin(); rit != dual_ents.end(); rit++) { int dim = mbImpl->dimension_from_handle(*rit); if (1 == dim || 2 == dim) dual_hps.insert(get_dual_hyperplane(*rit)); } result = delete_dual_entities(dual_ents); if (MB_SUCCESS != result) return result; // after deleting cells, check for empty chords & sheets, and delete those too for (Range::iterator rit = dual_hps.begin(); rit != dual_hps.end(); rit++) { Range tmp_ents; result = mbImpl->get_entities_by_handle(*rit, tmp_ents); if (MB_SUCCESS != result) return result; if (tmp_ents.empty()) { result = mbImpl->delete_entities(&(*rit), 1); if (MB_SUCCESS != result) return result; } } // before re-connecting two hexes, check for existing quad on 4th quad vertices; // if there is a quad there, need to add explicit adjs to any adj hexes, since // by definition there'll be another quad on those vertices bool need_explicit = false; Range adj_quads; result = mbImpl->get_adjacencies(&connects[3][0], 4, 2, false, adj_quads); if (MB_MULTIPLE_ENTITIES_FOUND == result || !adj_quads.empty()) { // there's already a quad for these 4 vertices; by definition, // we'll be creating equivalent entities, so that original quad // needs explicit adj's to its bounding elements need_explicit = true; for (Range::iterator rit = adj_quads.begin(); rit != adj_quads.end(); rit++) { Range adj_hexes; result = mbImpl->get_adjacencies(&(*rit), 1, 3, false, adj_hexes); RR; result = mbImpl->add_adjacencies(*rit, adj_hexes, false); RR; } } // re-connect the two hexes std::vector<EntityHandle> new_connect; std::copy(connects[3].begin(), connects[3].end(), std::back_inserter(new_connect)); std::copy(connects[2].begin(), connects[2].end(), std::back_inserter(new_connect)); result = mbImpl->set_connectivity(hexes[0], &new_connect[0], 8); if (MB_SUCCESS != result) return result; new_connect.clear(); std::copy(connects[0].begin(), connects[0].end(), std::back_inserter(new_connect)); std::copy(connects[3].begin(), connects[3].end(), std::back_inserter(new_connect)); result = mbImpl->set_connectivity(hexes[1], &new_connect[0], 8); if (MB_SUCCESS != result) return result; // test for equiv entities from the side quads, and make explicit // adjacencies if there are any MeshTopoUtil mtu(mbImpl); for (int j = 0; j < 2; j++) { for (int i = 0; i < 4; i++) { if (mtu.equivalent_entities(side_quads[j][i])) { result = mbImpl->add_adjacencies(side_quads[j][i], &hexes[j], 1, false); if (MB_SUCCESS != result) return result; } } } // remove hexes we want to keep adj_ents.erase(hexes[0]); adj_ents.erase(hexes[1]); // delete the other interior entities result = mbImpl->delete_entities(adj_ents); if (MB_SUCCESS != result) return result; EntityHandle new_quad; result = mbImpl->create_element(MBQUAD, &connects[3][0], 4, new_quad); RR; if (need_explicit) { result = mbImpl->add_adjacencies(new_quad, hexes, 2, false); RR; } if (debug_ap) ((Core*)mbImpl)->check_adjacencies(); // now update the dual result = construct_hex_dual(hexes, 2); if (MB_SUCCESS != result) return result; return MB_SUCCESS; }
ErrorCode moab::DualTool::set_dual_surface_or_curve | ( | EntityHandle | entity, |
const EntityHandle | dual_hyperplane, | ||
const int | dimension | ||
) |
set the dual surface or curve for an entity
Definition at line 1411 of file DualTool.cpp.
{ if (1 == dual_entity_dimension) mbImpl->tag_set_data(dualCurve_tag(), &entity, 1, &dual_hyperplane); else if (2 == dual_entity_dimension) mbImpl->tag_set_data(dualSurface_tag(), &entity, 1, &dual_hyperplane); else return MB_INDEX_OUT_OF_RANGE; return MB_SUCCESS; }
ErrorCode moab::DualTool::split_pair_nonmanifold | ( | EntityHandle * | split_quads, |
EntityHandle * | split_edges, | ||
EntityHandle * | split_nodes, | ||
std::vector< EntityHandle > * | star_dp1, | ||
std::vector< EntityHandle > * | star_dp2, | ||
EntityHandle * | other_edges, | ||
EntityHandle * | other_nodes, | ||
EntityHandle * | new_quads, | ||
EntityHandle * | new_edges, | ||
EntityHandle * | new_nodes | ||
) | [private] |
split a pair of quads and the edge(s) shared by them
Definition at line 1946 of file DualTool.cpp.
{ // if there's a bdy in the star around the shared edge(s), get the quads on that // bdy so we know which edges to merge after the split-nonmanifold MeshTopoUtil mtu(mbImpl); ErrorCode result; // get which star the split faces are in, and choose the other one int new_side = -1; if (std::find(star_dp1[0].begin(), star_dp1[0].end(), split_quads[0]) != star_dp1[0].end()) new_side = 1; else if (std::find(star_dp1[1].begin(), star_dp1[1].end(), split_quads[0]) != star_dp1[1].end()) new_side = 0; assert(-1 != new_side); if (-1 == new_side) return MB_FAILURE; //=============== split faces for (int i = 0; i < 2; i++) { // get a hex in star_dp2[new_side] that's adj to this split quad, to tell // mtu which one the new quad should go with; there should be at least one, // if we have any hexes connected to the split quad EntityHandle gowith_hex = 0; for (std::vector<EntityHandle>::iterator vit = star_dp2[new_side].begin(); vit != star_dp2[new_side].end(); vit++) { if (mtu.common_entity(*vit, split_quads[i], 2)) { gowith_hex = *vit; break; } } assert(0 != gowith_hex); // split manifold each of the split_quads, and put the results on the merge list result = mtu.split_entities_manifold(split_quads+i, 1, new_quads+i, NULL, (gowith_hex ? &gowith_hex : NULL)); RR; } // make ranges of faces which need to be explicitly adj to old, new // edge; faces come from stars and new_quads (which weren't in the stars); // new_quads go with side j, which does not have split quads Range tmp_addl_faces[2], addl_faces[2]; for (int i = 0; i < 2; i++) { std::copy(star_dp1[i].begin(), star_dp1[i].end(), range_inserter(tmp_addl_faces[i])); tmp_addl_faces[new_side].insert(new_quads[i]); } #ifndef NDEBUG bool cond1 = ("split_quads on 1, new_quads on 0" && tmp_addl_faces[0].find(split_quads[0]) == tmp_addl_faces[0].end() && tmp_addl_faces[0].find(split_quads[1]) == tmp_addl_faces[0].end() && tmp_addl_faces[1].find(split_quads[0]) != tmp_addl_faces[1].end() && tmp_addl_faces[1].find(split_quads[1]) != tmp_addl_faces[1].end() && tmp_addl_faces[0].find(new_quads[0]) != tmp_addl_faces[0].end() && tmp_addl_faces[0].find(new_quads[1]) != tmp_addl_faces[0].end() && tmp_addl_faces[1].find(new_quads[0]) == tmp_addl_faces[1].end() && tmp_addl_faces[1].find(new_quads[1]) == tmp_addl_faces[1].end()), cond2 = ("split_quads on 0, new_quads on 1" && tmp_addl_faces[0].find(split_quads[0]) != tmp_addl_faces[0].end() && tmp_addl_faces[0].find(split_quads[1]) != tmp_addl_faces[0].end() && tmp_addl_faces[1].find(split_quads[0]) == tmp_addl_faces[1].end() && tmp_addl_faces[1].find(split_quads[1]) == tmp_addl_faces[1].end() && tmp_addl_faces[0].find(new_quads[0]) == tmp_addl_faces[0].end() && tmp_addl_faces[0].find(new_quads[1]) == tmp_addl_faces[0].end() && tmp_addl_faces[1].find(new_quads[0]) != tmp_addl_faces[1].end() && tmp_addl_faces[1].find(new_quads[1]) != tmp_addl_faces[1].end()); assert(cond1 || cond2); #endif //=============== split edge(s) for (int j = 0; j < 3; j++) { if (!split_edges[j]) break; // filter add'l faces to only those adj to split_edges[j] addl_faces[0] = tmp_addl_faces[0]; addl_faces[1] = tmp_addl_faces[1]; for (int i = 0; i < 2; i++) { result = mbImpl->get_adjacencies(&split_edges[j], 1, 2, false, addl_faces[i]); RR; } // split edge result = mtu.split_entity_nonmanifold(split_edges[j], addl_faces[1-new_side], addl_faces[new_side], new_edges[j]); RR; } //=============== split node(s) for (int j = 0; j < 2; j++) { if (!split_nodes[j]) break; // if we're splitting multiple edges, there might be other edges that have the split // node; also need to know which side they're on Range tmp_addl_edges[2]; result = foc_get_addl_ents(star_dp1, star_dp2, split_edges, split_nodes[j], tmp_addl_edges); RR; // also, we need to know which of the split/new edges go // with the split/new node; new edges go with side 0, split with 1 for (int i = 0; i < 3; i++) { if (!split_edges[i]) break; tmp_addl_edges[new_side].insert(new_edges[i]); tmp_addl_edges[1-new_side].insert(split_edges[i]); } // same for star faces and hexes for (int i = 0; i < 2; i++) { std::copy(star_dp1[i].begin(), star_dp1[i].end(), range_inserter(tmp_addl_edges[i])); std::copy(star_dp2[i].begin(), star_dp2[i].end(), range_inserter(tmp_addl_edges[i])); } // finally, new quads for (int i = 0; i < 2; i++) tmp_addl_edges[new_side].insert(new_quads[i]); // filter the entities, keeping only the ones adjacent to this node Range addl_edges[2]; for (int i = 0; i < 2; i++) { for (Range::reverse_iterator rit = tmp_addl_edges[i].rbegin(); rit != tmp_addl_edges[i].rend(); rit++) { if (mtu.common_entity(*rit, split_nodes[j], 0)) addl_edges[i].insert(*rit); } } // now split the node too result = mtu.split_entity_nonmanifold(split_nodes[j], addl_edges[1-new_side], addl_edges[new_side], new_nodes[j]); RR; } return MB_SUCCESS; }
ErrorCode moab::DualTool::traverse_hyperplane | ( | const Tag | hp_tag, |
EntityHandle & | this_hp, | ||
EntityHandle | this_ent | ||
) | [private] |
traverse the cells of a dual hyperplane, starting with this_ent (dimension of this_ent determines hyperplane dimension) simpler method for traversing hyperplane, using same basic algorithm but using MeshTopoUtil::get_bridge_adjacencies
Definition at line 911 of file DualTool.cpp.
{ Range tmp_star, star, tmp_range, new_hyperplane_ents; std::vector<EntityHandle> hp_untreated; int dim = mbImpl->dimension_from_handle(this_ent); MeshTopoUtil mtu(mbImpl); this_hp = 0; ErrorCode result; unsigned short mark_val = 0x0; Tag mark_tag; result = mbImpl->tag_get_handle("__hyperplane_mark", 1, MB_TYPE_BIT, mark_tag, MB_TAG_CREAT|MB_TAG_BIT); if (MB_SUCCESS != result) return result; mark_val = 0x1; while (0 != this_ent) { EntityHandle tmp_hp = get_dual_hyperplane(this_ent); if (0 == this_hp && 0 != tmp_hp) this_hp = tmp_hp; if (0 == tmp_hp) new_hyperplane_ents.insert(this_ent); if (debug && hp_untreated.size()%10 == 0) std::cout << "Dual surface " << this_hp << ", hp_untreated list size = " << hp_untreated.size() << "." << std::endl; // get the 2nd order adjacencies through lower dimension tmp_range.clear(); tmp_star.clear(); star.clear(); result = mtu.get_bridge_adjacencies(this_ent, dim-1, dim, star); RR; // get the bridge adjacencies through higher dimension result = mtu.get_bridge_adjacencies(this_ent, dim+1, dim, tmp_star); RR; tmp_range = subtract( star, tmp_star); for (Range::iterator rit = tmp_range.begin(); rit != tmp_range.end(); rit++) { if (new_hyperplane_ents.find(*rit) != new_hyperplane_ents.end()) continue; // check for tag first, 'cuz it's probably faster than checking adjacencies // assign to avoid valgrind warning unsigned short tmp_mark = 0x0; result = mbImpl->tag_get_data(mark_tag, &(*rit), 1, &tmp_mark); if (MB_SUCCESS == result && mark_val == tmp_mark) continue; // if it's on the loop, it's not eligible if (1 == dim && check_1d_loop_edge(*rit)) continue; // have one on this hp; just put it on the hp_untreated list for now, // will get tagged and put in the hp set later hp_untreated.push_back(*rit); result = mbImpl->tag_set_data(mark_tag, &(*rit), 1, &mark_val); if (MB_SUCCESS != result) return result; } // end of inner loop; get the next this_ent, or set to zero if (hp_untreated.empty()) this_ent = 0; else { this_ent = hp_untreated.back(); hp_untreated.pop_back(); } } if (debug_ap) { std::string hp_name; if (2 == dim) hp_name = "sheet"; else hp_name = "chord"; if (0 == this_hp) std::cout << "Constructed new " << hp_name << " with "; else { int this_id; result = mbImpl->tag_get_data(globalId_tag(), &this_hp, 1, &this_id); RR; std::cout << "Added to " << hp_name << " " << this_id << " "; } if (dim == 2) std::cout << "edges:" << std::endl; else std::cout << "quads:" << std::endl; std::vector<EntityHandle> pents(new_hyperplane_ents.size()); result = mbImpl->tag_get_data(dualEntity_tag(), new_hyperplane_ents, &pents[0]); RR; for (std::vector<EntityHandle>::iterator vit = pents.begin(); vit != pents.end(); vit++) { if (vit != pents.begin()) std::cout << ", "; std::cout << mbImpl->id_from_handle(*vit); } std::cout << std::endl; } if (0 == this_hp) { // ok, doesn't have one; make a new hyperplane int new_id = -1; result = construct_new_hyperplane(dim, this_hp, new_id); if (MB_SUCCESS != result) return result; if (debug_ap) { std::cout << "New "; if (2 == dim) std::cout << " sheet "; else std::cout << " chord "; std::cout << new_id << " constructed." << std::endl; } } // set the hp_val for entities which didn't have one before std::vector<EntityHandle> hp_tags(new_hyperplane_ents.size()); std::fill(hp_tags.begin(), hp_tags.end(), this_hp); result = mbImpl->tag_set_data(hp_tag, new_hyperplane_ents, &hp_tags[0]); if (MB_SUCCESS != result) return result; result = mbImpl->add_entities(this_hp, new_hyperplane_ents); if (MB_SUCCESS != result) return result; // unmark the entities by removing the tag result = mbImpl->tag_delete(mark_tag); if (MB_SUCCESS != result) return result; return MB_SUCCESS; }
Tag moab::DualTool::categoryTag [private] |
Definition at line 383 of file DualTool.hpp.
const char * moab::DualTool::DUAL_CURVE_TAG_NAME = "DUAL_CURVE" [static] |
tag name for dual curves
Definition at line 38 of file DualTool.hpp.
const char * moab::DualTool::DUAL_ENTITY_TAG_NAME = "__DUAL_ENTITY" [static] |
const char * moab::DualTool::DUAL_GRAPHICS_POINT_TAG_NAME = "__DUAL_GRAPHICS_POINT" [static] |
const char * moab::DualTool::DUAL_SURFACE_TAG_NAME = "DUAL_SURFACE" [static] |
tag name for dual surfaces
Definition at line 35 of file DualTool.hpp.
Tag moab::DualTool::dualCurveTag [private] |
tags used for dual surfaces, curves, cells, entities
Definition at line 377 of file DualTool.hpp.
Tag moab::DualTool::dualEntityTag [private] |
Definition at line 380 of file DualTool.hpp.
Tag moab::DualTool::dualGraphicsPointTag [private] |
Definition at line 382 of file DualTool.hpp.
Tag moab::DualTool::dualSurfaceTag [private] |
Definition at line 378 of file DualTool.hpp.
const char * moab::DualTool::EXTRA_DUAL_ENTITY_TAG_NAME = "__EXTRA_DUAL_ENTITY" [static] |
tag name for dual entitys
tag name for extra dual entities
Definition at line 47 of file DualTool.hpp.
Tag moab::DualTool::extraDualEntityTag [private] |
Definition at line 381 of file DualTool.hpp.
Tag moab::DualTool::globalIdTag [private] |
Definition at line 384 of file DualTool.hpp.
const char * moab::DualTool::IS_DUAL_CELL_TAG_NAME = "__IS_DUAL_CELL" [static] |
tag name for dual cells
Definition at line 41 of file DualTool.hpp.
Tag moab::DualTool::isDualCellTag [private] |
Definition at line 379 of file DualTool.hpp.
int moab::DualTool::maxHexId [private] |
Definition at line 386 of file DualTool.hpp.
Interface* moab::DualTool::mbImpl [private] |
private copy of interface *
Definition at line 368 of file DualTool.hpp.