[MOAB-dev] r1400 - in MOAB/trunk: . tools/qvdual
tautges at mcs.anl.gov
tautges at mcs.anl.gov
Fri Nov 16 09:29:37 CST 2007
Author: tautges
Date: 2007-11-16 09:29:36 -0600 (Fri, 16 Nov 2007)
New Revision: 1400
Modified:
MOAB/trunk/DualTool.cpp
MOAB/trunk/DualTool.hpp
MOAB/trunk/MBCN.cpp
MOAB/trunk/MBCN.hpp
MOAB/trunk/MeshTopoUtil.cpp
MOAB/trunk/MeshTopoUtil.hpp
MOAB/trunk/tools/qvdual/DrawDual.hpp
MOAB/trunk/tools/qvdual/uiQVDual.h
MOAB/trunk/tools/qvdual/uiQVDual.ui
MOAB/trunk/tools/qvdual/uiQVDual.ui.h
Log:
QVDual, DrawDual: adding ability to manually add picked 1- and 2-cells, by
filling in the string boxes in the gui
MeshTopoUtil:
- fixes to star_entities for non-manifold case
- added function opposite_entity, which for some specific parent and
child entities returns an opposite entity; functionality is obvious
for faces on hexes, nodes/edges on quads; for tris/tets, return
different-dimensional entities in some cases
- new implementation for split_entity_nonmanifold
DualTool:
- fixing bug in atomic pillow
- new implementation for face_open_collapse
MBCN: adding OppositeSide function, similar to MeshTopoUtil function
but in terms of entity types and indices
Modified: MOAB/trunk/DualTool.cpp
===================================================================
--- MOAB/trunk/DualTool.cpp 2007-11-16 15:18:33 UTC (rev 1399)
+++ MOAB/trunk/DualTool.cpp 2007-11-16 15:29:36 UTC (rev 1400)
@@ -1461,16 +1461,16 @@
// get the hexes connected to the quad
MBRange 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 outer quad; add adjacency between quad and other hex
- result = mbImpl->remove_adjacencies(quad1, &(*hexes.begin()), 1); RR;
+ // remove any explicit adjacency from the second hex, since that'll get connected
+ // to the new quad; add adjacency between quad and first hex
if (hexes.size() == 2) {
- result = mbImpl->add_adjacencies(quad1, &(*hexes.rbegin()), 1, false);
- RR;
+ result = mbImpl->remove_adjacencies(quad1, &(*hexes.rbegin()), 1); RR;
}
+ result = mbImpl->add_adjacencies(quad1, &(*hexes.begin()), 1, false); RR;
- // create the new, outer quad, and make it explicitly adjacent to 1st hex;
+ // create the new, outer quad, and make it explicitly adjacent to 2nd hex;
// make the connectivity of this quad reversed from the original one
std::vector<MBEntityHandle> tmp_verts;
std::copy(verts.begin(), verts.end(), std::back_inserter(tmp_verts));
@@ -1478,6 +1478,9 @@
std::reverse(tmp_verts.begin()+4, tmp_verts.end());
result = mbImpl->create_element(MBQUAD, &tmp_verts[0], 4, quad2); RR;
+ if (hexes.size() == 2) {
+ result = mbImpl->add_adjacencies(quad2, &(*hexes.rbegin()), 1, false); RR;
+ }
// now make two inner hexes; note connectivity array is flipped for the two hexes
MBEntityHandle new_hexes[2];
@@ -1488,16 +1491,6 @@
result = mbImpl->add_adjacencies(quad1, &new_hexes[0], 1, false); RR;
result = mbImpl->add_adjacencies(quad2, &new_hexes[1], 1, false); RR;
- // not sure for this one, should be opposite sense with quad
- int side_no, sense, offset;
- result = mbImpl->side_number(*hexes.begin(), quad1, side_no, sense, offset); RR;
- if (sense == 1) {
- result = mbImpl->add_adjacencies(quad1, &(*hexes.begin()), 1, false); RR;
- }
- else {
- result = mbImpl->add_adjacencies(quad2, &(*hexes.begin()), 1, false); RR;
- }
-
if (debug_ap) ((MBCore*)mbImpl)->check_adjacencies();
// now update the dual
@@ -1648,28 +1641,33 @@
MeshTopoUtil mtu(mbImpl);
// get the primal entities we're dealing with
- MBEntityHandle quads[2], edge;
- quads[0] = get_dual_entity(ocl);
- quads[1] = get_dual_entity(ocr);
- if (MBQUAD != mbImpl->type_from_handle(quads[0]) ||
- MBQUAD != mbImpl->type_from_handle(quads[1]))
+ MBEntityHandle split_quads[2], split_edges[2], split_node,
+ other_edges[6], other_nodes[6];
+ MBRange hexes;
+ MBErrorCode result = foc_get_ents(ocl, ocr, split_quads, split_edges, split_node,
+ hexes, other_edges, other_nodes); RR;
+
+ if (MBQUAD != mbImpl->type_from_handle(split_quads[0]) ||
+ MBQUAD != mbImpl->type_from_handle(split_quads[1]))
return MB_TYPE_OUT_OF_RANGE;
- edge = mtu.common_entity(quads[0], quads[1], 1);
- if (0 == edge) return MB_FAILURE;
-
- MBRange hexes;
- MBErrorCode result = mbImpl->get_adjacencies(quads, 2, 3, false, hexes, MBInterface::UNION);
+ result = foc_delete_dual(split_quads, split_edges, hexes);
if (MB_SUCCESS != result) return result;
- assert(4 >= hexes.size());
- result = foc_delete_dual(edge, ocl, ocr, hexes);
- if (MB_SUCCESS != result) return result;
-
std::vector<MBEntityHandle> merge_ents;
- result = split_pair_nonmanifold(quads, 2, merge_ents);
+ result = split_pair_nonmanifold(split_quads, split_edges, split_node, hexes,
+ other_edges, other_nodes, merge_ents);
if (MB_SUCCESS != result) return result;
+
+ // put the other entities to be merged on the list
+ for (int i = 0; i < 4; i++) merge_ents.push_back(other_edges[i]);
+ if (!split_node)
+ for (int i = 4; i < 6; i++) merge_ents.push_back(other_edges[i]);
+ for (int i = 2; i < 4; i++) merge_ents.push_back(other_nodes[i]);
+ if (!split_node)
+ for (int i = 4; i < 6; i++) merge_ents.push_back(other_nodes[i]);
+
// now merge them
for (std::vector<MBEntityHandle>::reverse_iterator vit = merge_ents.rbegin();
vit != merge_ents.rend(); vit+=2) {
@@ -1689,230 +1687,298 @@
return MB_SUCCESS;
}
-MBErrorCode DualTool::split_pair_nonmanifold(MBEntityHandle *ents,
- const int ents_size,
- std::vector<MBEntityHandle> &merge_ents)
+MBErrorCode DualTool::foc_get_ents(MBEntityHandle ocl,
+ MBEntityHandle ocr,
+ MBEntityHandle *split_quads,
+ MBEntityHandle *split_edges,
+ MBEntityHandle &split_node,
+ MBRange &hexes,
+ MBEntityHandle *other_edges,
+ MBEntityHandle *other_nodes)
{
+ // 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)
- // 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);
- MBRange shared_ents;
+ 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;
- int star_dim = mbImpl->dimension_from_handle(ents[0])-1;
- MBErrorCode result = mbImpl->get_adjacencies(ents, ents_size,
- star_dim, false, shared_ents);
+ MBRange common_edges;
+ MBErrorCode result = mbImpl->get_adjacencies(split_quads, 2, 1, false,
+ common_edges);
if (MB_SUCCESS != result) return result;
- else if (shared_ents.empty()) return MB_FAILURE;
- MBRange bdy_ents[3];
- int i;
- MBRange::iterator rit;
- for (rit = shared_ents.begin(), i = 0; i < 3; i++, rit++) {
- std::vector<MBEntityHandle> star_ents;
- bool on_bdy;
- result = mtu.star_entities(*rit, star_ents, on_bdy);
- if (MB_SUCCESS != result) return result;
- if (on_bdy) {
- bdy_ents[i].insert(*star_ents.begin());
- bdy_ents[i].insert(*star_ents.rbegin());
+ 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() > 1) {
+ split_node = mtu.common_entity(split_edges[0], split_edges[1], 0);
+ if (0 == split_node) return MB_FAILURE;
+ for (int i = 0; i < 2; i++) {
+ result = mtu.opposite_entity(split_quads[i],
+ split_edges[1-i], other_edges[i]); RR;
+ result = mtu.opposite_entity(split_quads[i],
+ split_edges[i], other_edges[2+i]); RR;
+ result = mtu.opposite_entity(split_quads[i], split_node,
+ other_nodes[i]); RR;
}
}
-
- // split manifold each of the entities
- std::vector<MBEntityHandle> new_ents(ents_size);
- result = mtu.split_entities_manifold(ents, ents_size, &new_ents[0], NULL);
- if (MB_SUCCESS != result) return result;
-
- // split non-manifold the shared entities between them
- MBRange new_shared_ents;
- for (rit = shared_ents.begin(), i = 0; rit != shared_ents.end(); rit++, i++) {
- new_shared_ents.clear();
- result = mtu.split_entity_nonmanifold(*rit, new_shared_ents);
+ else {
+ split_edges[1] = 0;
+ split_node = 0;
+ const MBEntityHandle *connect;
+ int num_connect;
+ result = mbImpl->get_connectivity(split_edges[0], connect, num_connect);
if (MB_SUCCESS != result) return result;
-
- if (new_shared_ents.size() > 2) {
- std::cerr << "Can't do split_pair_nonmanifold, too many new d-1 entities." << std::endl;
- return MB_FAILURE;
- }
- else if (new_shared_ents.size() == 2) {
- // need to merge 2 of the entities together, don't know which ones yet but they're adjacent
- // to bdy_ents and are either in new_shared_ents or are the original *rit
- assert(!bdy_ents[i].empty());
- MBRange dum_ents;
- result = mbImpl->get_adjacencies(bdy_ents[i], star_dim, false, dum_ents, MBInterface::UNION);
+
+ for (int i = 0; i < 2; i++) {
+ MBRange tmp_range1, tmp_range2;
+ tmp_range1.insert(connect[i]);
+ tmp_range1.insert(split_quads[i]);
+ result = mbImpl->get_adjacencies(tmp_range1, 1, false, tmp_range2);
if (MB_SUCCESS != result) return result;
- new_shared_ents.insert(*rit);
- dum_ents = dum_ents.intersect(new_shared_ents);
- assert(2 == dum_ents.size());
-
- // merge them together; will keep lower handle 'cuz they're in a range
- result = mbImpl->merge_entities(*dum_ents.begin(), *dum_ents.rbegin(), false, true);
- if (MB_SUCCESS != result) return result;
+ tmp_range2.erase(split_edges[0]);
+ assert(tmp_range2.size() == 1);
+ other_edges[i] = *tmp_range2.begin();
+ result = mtu.opposite_entity(other_edges[i], connect[i],
+ other_nodes[i]); RR;
+ result = mtu.opposite_entity(split_quads[i], split_edges[0],
+ other_edges[4+i]); RR;
}
- else {
- assert(1 == new_shared_ents.size());
- }
}
- if (shared_ents.size() != 1 && star_dim > 0) {
-
- // need to split-nonmanifold vertices too
- // get which vertices they are
- MBRange shared_verts;
- rit = shared_ents.begin();
- MBRange::iterator rit2 = rit; rit2++;
- for (; rit != shared_ents.end(); rit++, rit2++) {
- if (rit2 == shared_ents.end()) rit2 = shared_ents.begin();
- MBEntityHandle shared_vert = mtu.common_entity(*rit, *rit2, 0);
- if (0 != shared_vert) shared_verts.insert(shared_vert);
- }
- // now split them
- assert(shared_verts.size() == shared_ents.size()-1);
- for (rit = shared_verts.begin(); rit != shared_verts.end(); rit++) {
- MBRange dum_ents;
- result = mtu.split_entity_nonmanifold(*rit, dum_ents);
- if (MB_SUCCESS != result) return result;
- //assert(1 == dum_ents.size());
+ result = mbImpl->get_adjacencies(split_quads, 2, 3, false, hexes, MBInterface::UNION);
+ if (MB_SUCCESS != result) return result;
+ assert(4 >= hexes.size());
- // let's put new vertex in a sane position, too; get the bridge-adjacent vertices
- // across edges
- MBEntityHandle this_vert = *dum_ents.begin();
- dum_ents.clear();
- result = mtu.get_bridge_adjacencies(this_vert, 1, 0, dum_ents);
- if (MB_SUCCESS != result) return result;
- // add the original of the split vertex too
- dum_ents.insert(*rit);
- double avg_pos[3];
- result = mtu.get_average_position(dum_ents, avg_pos);
- if (MB_SUCCESS != result) return result;
- result = mbImpl->set_coords(&this_vert, 1, avg_pos);
- if (MB_SUCCESS != result) return result;
- }
- }
+ return MB_SUCCESS;
+}
+
+MBErrorCode DualTool::split_pair_nonmanifold(MBEntityHandle *split_quads,
+ MBEntityHandle *split_edges,
+ MBEntityHandle split_node,
+ MBRange hexes,
+ MBEntityHandle *other_edges,
+ MBEntityHandle *other_nodes,
+ std::vector<MBEntityHandle> &merge_ents)
+{
+
+ // 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);
+ MBErrorCode result;
+
+ // get star entities around edges, separated into halves
+ std::vector<MBEntityHandle> star_dp1[2], star_dp2[2];
+ result = foc_get_stars(split_quads, split_edges, star_dp1, star_dp2); RR;
- // now need to build vector of entity pairs to merge; this is computed by finding
- // the two ents from ents, new_ents which have common (d-1)-dimensional entities which
- // are in shared_ents, and similarly for those adjacent to entities in new_shared_ents
+ // split manifold each of the split_quads, and put the results on the merge list
+ MBEntityHandle new_quads[2];
+ result = mtu.split_entities_manifold(split_quads, 2, new_quads, NULL); RR;
+ for (int i = 0; i < 2; i++) merge_ents.push_back(split_quads[i]);
+ for (int i = 0; i < 2; i++) merge_ents.push_back(new_quads[i]);
- // group all ents, new_ents into a range, then intersect that with d-dimensional
- // entities adjacent to one of the original (d-1)-dimensional shared_ents; those will be
- // the first two mergeable d-dimensional entities
- MBRange dum_ents;
- dum_ents.insert(ents[0]); dum_ents.insert(ents[1]);
- dum_ents.insert(new_ents[0]); dum_ents.insert(new_ents[1]);
- MBRange other_dum_ents = dum_ents;
- result = mbImpl->get_adjacencies(&(*shared_ents.begin()), 1, star_dim+1, false, dum_ents);
- if (MB_SUCCESS != result) return result;
- assert(2 == dum_ents.size());
- other_dum_ents = other_dum_ents.subtract(dum_ents);
- assert(2 == other_dum_ents.size());
- merge_ents.push_back(*dum_ents.begin());
- merge_ents.push_back(*dum_ents.rbegin());
- if (0 != mtu.common_entity(merge_ents[0], *other_dum_ents.begin(), star_dim)) {
- merge_ents.push_back(*other_dum_ents.begin());
- merge_ents.push_back(*other_dum_ents.rbegin());
- }
- else {
- merge_ents.push_back(*other_dum_ents.rbegin());
- merge_ents.push_back(*other_dum_ents.begin());
- }
-
- // order shared_ents_vec and new_shared_ents_vec such that they're ready for merging
- // get all the non-shared edges
- MBRange unshared_edges;
- result = mbImpl->get_adjacencies(&merge_ents[0], 2, 1, false, unshared_edges,
- MBInterface::UNION);
- if (MB_SUCCESS != result) return result;
- shared_ents.clear();
- result = mbImpl->get_adjacencies(&merge_ents[0], 2, 1, false, shared_ents);
- if (MB_SUCCESS != result) return result;
- unshared_edges = unshared_edges.subtract(shared_ents);
- shared_ents.clear();
- result = mbImpl->get_adjacencies(&merge_ents[2], 2, 1, false, shared_ents);
- if (MB_SUCCESS != result) return result;
- unshared_edges = unshared_edges.subtract(shared_ents);
- assert(2 <= unshared_edges.size());
+
+ // 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
+ MBRange addl_ents[2];
+ result = foc_get_addl_ents(star_dp1, star_dp2, split_node, addl_ents); RR;
+
+ // now split the edges; just add the star ents to addl_ents to pass into
+ // split_nonmanifold
+ for (int i = 0; i < 2; i++)
+ std::copy(star_dp1[i].begin(), star_dp1[i].end(), mb_range_inserter(addl_ents[i]));
- if (2 == unshared_edges.size()) {
- // only 2, they must be the ones to merge, and no vertices
- merge_ents.push_back(*unshared_edges.begin());
- merge_ents.push_back(*unshared_edges.rbegin());
- return MB_SUCCESS;
- }
+ MBEntityHandle new_entity;
+ result = mtu.split_entity_nonmanifold(split_edges[0], addl_ents[0], addl_ents[1],
+ new_entity); RR;
+ addl_ents[0].insert(split_edges[0]); addl_ents[1].insert(new_entity);
- // otherwise, first ones are adjacent to either shared vertex
- int unshared_size = unshared_edges.size();
- dum_ents.clear();
- MBRange end_verts, all_edges;
- dum_ents.insert(merge_ents[0]);
- dum_ents.insert(merge_ents[3]);
- result = mbImpl->get_adjacencies(dum_ents, 0, false, end_verts);
- if (MB_SUCCESS != result) return result;
- assert(2 == end_verts.size());
+ if (split_edges[1]) {
+ result = mtu.split_entity_nonmanifold(split_edges[1], addl_ents[0], addl_ents[1],
+ new_entity); RR;
+ addl_ents[0].insert(split_edges[0]); addl_ents[1].insert(new_entity);
- for (rit = end_verts.begin(); rit != end_verts.end(); rit++) {
- // intersect the unshared edges with the edges adjacent to this vertex
- dum_ents = unshared_edges;
- result = mbImpl->get_adjacencies(&(*rit), 1, 1, false, dum_ents);
- if (MB_SUCCESS != result) return result;
- // by definition, there should only be 2, and they're to be merged
- assert(2 == dum_ents.size());
- merge_ents.push_back(*dum_ents.begin());
- merge_ents.push_back(*dum_ents.rbegin());
- // remove these from unshared_edges, since they don't need to be
- // considered any more
- unshared_edges = unshared_edges.subtract(dum_ents);
+ // now split the node too
+ result = mtu.split_entity_nonmanifold(split_node, addl_ents[0], addl_ents[1],
+ new_entity); RR;
}
- // if we have any unshared edges left, they should be merged too
- if (!unshared_edges.empty()) {
- assert(2 == unshared_edges.size());
- merge_ents.push_back(*unshared_edges.begin());
- merge_ents.push_back(*unshared_edges.rbegin());
+ return MB_SUCCESS;
+}
+
+MBErrorCode DualTool::foc_get_addl_ents(std::vector<MBEntityHandle> *star_dp1,
+ std::vector<MBEntityHandle> *star_dp2,
+ MBEntityHandle split_node,
+ MBRange *addl_ents)
+{
+ // 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:
+ // - start with star entities on search list
+ // - while (search list not empty):
+ // . take face off search list, put on result list
+ // . get all edge-adj faces also adj to split node
+ // . for each of these, if face is not on result list, put on search list
+ // - for each entity on result list:
+ // . get all entities also adj to split node & put on result list
+
+ MBRange node_faces;
+ MeshTopoUtil mtu(mbImpl);
+ MBErrorCode result = mbImpl->get_adjacencies(&split_node, 1, 2, false, node_faces); RR;
+ MBRange::iterator rit;
+
+ for (int i = 0; i < 2; i++) {
+ MBRange slist, rlist, tmp_list;
+ std::copy(star_dp1[i].begin(), star_dp1[i].end(), mb_range_inserter(slist));
+ while (!slist.empty()) {
+ MBEntityHandle this_ent = slist.pop_front();
+ rlist.insert(this_ent);
+ tmp_list.clear();
+ result = mtu.get_bridge_adjacencies(this_ent, 1, 2, tmp_list); RR;
+ tmp_list = tmp_list.intersect(node_faces);
+ for (rit = tmp_list.begin(); rit != tmp_list.end(); rit++)
+ if (rlist.find(*rit) == rlist.end()) slist.insert(*rit);
+ }
+ MBEntityHandle tmp_ents[2];
+ tmp_ents[0] = split_node;
+ MBRange rlist2;
+ for (rit = rlist.begin(); rit != rlist.end(); rit++) {
+ tmp_list.clear();
+ tmp_ents[1] = *rit;
+ result = mbImpl->get_adjacencies(tmp_ents, 2, 1, false, tmp_list); RR;
+ rlist2.merge(tmp_list);
+ tmp_list.clear();
+ result = mbImpl->get_adjacencies(tmp_ents, 2, 3, false, tmp_list); RR;
+ rlist2.merge(tmp_list);
+ }
+
+ for (rit = rlist.begin(); rit != rlist.end(); rit++)
+ if (std::find(star_dp1[i].begin(), star_dp1[i].end(), *rit) ==
+ star_dp1[i].end()) addl_ents[i].insert(*rit);
+ addl_ents[i].merge(rlist2);
}
- // now get the vertex or vertices which must also be merged
- MBEntityHandle ent1 = *merge_ents.rbegin(),
- ent2 = *(merge_ents.rbegin()+1);
-
- for (int i = 0; i < (unshared_size/2)-1; i++) {
- MBEntityHandle shared_ent = mtu.common_entity(merge_ents[4+2*i], ent1, 0);
- if (0 == shared_ent) shared_ent = mtu.common_entity(merge_ents[4+2*i], ent2, 0);
- assert(0 != shared_ent);
- merge_ents.push_back(shared_ent);
+ return MB_SUCCESS;
+}
- shared_ent = mtu.common_entity(merge_ents[4+2*i+1], ent1, 0);
- if (0 == shared_ent || shared_ent == *merge_ents.rbegin())
- shared_ent = mtu.common_entity(merge_ents[4+2*i+1], ent2, 0);
- assert(0 != shared_ent);
- merge_ents.push_back(shared_ent);
+MBErrorCode DualTool::foc_get_stars(MBEntityHandle *split_quads,
+ MBEntityHandle *split_edges,
+ std::vector<MBEntityHandle> *star_dp1,
+ std::vector<MBEntityHandle> *star_dp2)
+{
+
+ bool on_bdy;
+ MBErrorCode result;
+ MeshTopoUtil mtu(mbImpl);
+ for (int i = 0; i < 2; i++) {
+ // only do 2nd iteration if we have a 2nd edge
+ if (1 == i && !split_edges[1]) continue;
+
+ // get the star around the split_edge
+ std::vector<MBEntityHandle> star_tmp[2], split_qstar[2], split_hstar[2];
+ result = mtu.star_entities(split_edges[i], star_tmp[0], on_bdy, 0,
+ &star_tmp[1]); RR;
+ std::vector<MBEntityHandle>::iterator fit, hit;
+ bool inside = false;
+
+ // separate the star into halves; store faces in split_qstar[0],[1], and
+ // the hexes in split_hstar[0],[1]
+ for (fit = star_tmp[0].begin(), hit = star_tmp[1].begin(); fit != star_tmp[0].end();
+ fit++, hit++) {
+ if (!inside && (*fit == split_quads[0] || *fit == split_quads[1]))
+ inside = true;
+ if (inside) split_qstar[0].push_back(*fit);
+ else split_qstar[1].push_back(*fit);
+ // only save hex if we're not on the end with a bdy
+ if (!on_bdy || fit != star_tmp[0].end()) {
+ if (inside) split_hstar[0].push_back(*hit);
+ else split_hstar[1].push_back(*hit);
+ }
+ if (inside && *fit != *split_qstar[0].begin() &&
+ (*fit == split_quads[0] || *fit == split_quads[1]))
+ inside = false;
+ }
+
+ // if we're on edge 1, just put the halves into the result vectors
+ if (0 == i) {
+ star_dp1[0].swap(split_qstar[0]); star_dp1[1].swap(split_qstar[1]);
+ star_dp2[0].swap(split_hstar[0]); star_dp2[1].swap(split_hstar[1]);
+ }
+ // else, align the star halves then add them to the star_dpx lists
+ else {
+ // if the lists are aligned, the hex next to the first face on star_dp1[0]
+ // should also be next to that face on split_qstar, either the front or
+ // the back depending whether that face is 1st or last on split_qstar[0]
+ MBEntityHandle hex1 = *star_dp2[0].begin();
+ MBEntityHandle hex2 = 0;
+ if (*split_qstar[0].begin() == *star_dp1[0].begin())
+ hex2 = *split_hstar[0].begin();
+ else if (*split_qstar[0].rbegin() == *star_dp1[0].begin())
+ hex2 = *split_hstar[0].rbegin();
+ if (hex1 == hex2) {
+ for (int i = 0; i < 2; i++)
+ std::copy(split_qstar[i].begin(), split_qstar[i].end(),
+ std::back_inserter(star_dp1[i])),
+ std::copy(split_hstar[i].begin(), split_hstar[i].end(),
+ std::back_inserter(star_dp2[i]));
+ }
+ else {
+ for (int i = 0; i < 2; i++)
+ std::copy(split_qstar[(i+1)%2].begin(), split_qstar[(i+1)%2].end(),
+ std::back_inserter(star_dp1[i])),
+ std::copy(split_hstar[(i+1)%2].begin(), split_hstar[(i+1)%2].end(),
+ std::back_inserter(star_dp2[i]));
+ }
+ }
}
-
-
+
return MB_SUCCESS;
}
-MBErrorCode DualTool::foc_delete_dual(MBEntityHandle edge,
- MBEntityHandle ocl,
- MBEntityHandle ocr,
+MBErrorCode DualTool::foc_delete_dual(MBEntityHandle *split_quads,
+ MBEntityHandle *split_edges,
MBRange &hexes)
{
// 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
- MBEntityHandle sheet = get_dual_hyperplane(get_dual_entity(edge));
- MBEntityHandle chordl = get_dual_hyperplane(ocl);
- MBEntityHandle chordr = get_dual_hyperplane(ocr);
- assert(0 != sheet && 0 != chordl && 0 != chordr);
+ MBEntityHandle 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]));
+ MBEntityHandle chordl = get_dual_hyperplane(get_dual_entity(split_quads[0]));
+ MBEntityHandle chordr = get_dual_hyperplane(get_dual_entity(split_quads[1]));
+ assert(0 != sheet1 && 0 != chordl && 0 != chordr);
MBRange parentsl, parentsr;
MBErrorCode 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(sheet);
- parentsr.erase(sheet);
+ 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
@@ -1991,80 +2057,6 @@
return MB_SUCCESS;
}
-/*
-MBErrorCode DualTool::foc_get_merge_ents(MBEntityHandle *quads, MBEntityHandle *new_quads,
- MBRange &shared_edges, MBRange &new_shared_edges,
- std::vector<MBEntityHandle> &merge_ents)
-{
- MeshTopoUtil mtu(mbImpl);
-
- // get the two common vertices
- MBRange common_verts;
- MBErrorCode result = mbImpl->get_adjacencies(quads, 2, 0, false, common_verts);
- if (MB_SUCCESS != result) return result;
- result = mbImpl->get_adjacencies(new_quads, 2, 0, false, common_verts);
- if (MB_SUCCESS != result) return result;
- assert(2 == common_verts.size());
-
- // get the vertices to merge; each vertex pair is bridge-adjacent (across edges)
- // to one of the vertices of our edge, and is not the other vertex of our edge
- const MBEntityHandle *connect;
- int num_connect;
- result = mbImpl->get_connectivity(*shared_edges.begin(), connect, num_connect);
- if (MB_SUCCESS != result) return result;
-
- for (int i = 0; i < 2; i++) {
- MBRange tmp_verts;
- result = mtu.get_bridge_adjacencies(connect[i], 1, 0, tmp_verts);
- if (MB_SUCCESS != result) return result;
- tmp_verts = tmp_verts.intersect(all_verts);
-
- // bridge adjacencies don't include connect[i], but will include the other
- tmp_verts.erase(connect[(i+1)%2]);
- assert(2 == tmp_verts.size());
-
- merge_ents.push_back(*tmp_verts.begin());
- merge_ents.push_back(*tmp_verts.rbegin());
- }
-
- // now edges
- MBRange all_edges, saved_edges;
- result = mbImpl->get_adjacencies(quads, 2, 1, false, all_edges, MBInterface::UNION);
- if (MB_SUCCESS != result) return result;
- result = mbImpl->get_adjacencies(new_quads, 2, 1, false, all_edges, MBInterface::UNION);
- if (MB_SUCCESS != result) return result;
- all_edges.erase(*shared_edges.begin());
- all_edges.erase(new_edge);
- assert(6 == all_edges.size());
-
- // first the ones connected to each vertex of our edge but not edge or new_edge
- for (int i = 0; i < 2; i++) {
- MBRange tmp_edges;
- result = mbImpl->get_adjacencies(&connect[i], 1, 1, false, tmp_edges);
- if (MB_SUCCESS != result) return result;
- tmp_edges = tmp_edges.intersect(all_edges);
- assert(2 == tmp_edges.size());
- merge_ents.push_back(*tmp_edges.begin());
- merge_ents.push_back(*tmp_edges.rbegin());
- saved_edges.merge(tmp_edges);
- }
- // last two are the ones left over, not counting edge and new_edge
- all_edges = all_edges.subtract(saved_edges);
- assert(2 == all_edges.size());
- merge_ents.push_back(*all_edges.begin());
- merge_ents.push_back(*all_edges.rbegin());
-
- // now faces; already know which ones, because of code we used before to
- // store quads and new_quads
- merge_ents.push_back(quads[0]);
- merge_ents.push_back(new_quads[0]);
- merge_ents.push_back(quads[1]);
- merge_ents.push_back(new_quads[1]);
-
- return MB_SUCCESS;
-}
-*/
-
//! returns true if all vertices are dual to hexes (not faces)
bool DualTool::is_blind(const MBEntityHandle chord_or_sheet)
{
Modified: MOAB/trunk/DualTool.hpp
===================================================================
--- MOAB/trunk/DualTool.hpp 2007-11-16 15:18:33 UTC (rev 1399)
+++ MOAB/trunk/DualTool.hpp 2007-11-16 15:29:36 UTC (rev 1400)
@@ -182,6 +182,17 @@
//! effect a face open-collapse operation
MBErrorCode face_open_collapse(MBEntityHandle ocl, MBEntityHandle ocr);
+
+ //! given the two 1-cells involved in the foc, get entities associated with
+ //! the quads being opened/collapsed; see implementation for more details
+ MBErrorCode foc_get_ents(MBEntityHandle ocl,
+ MBEntityHandle ocr,
+ MBEntityHandle *quads,
+ MBEntityHandle *split_edges,
+ MBEntityHandle &split_node,
+ MBRange &hexes,
+ MBEntityHandle *other_edges,
+ MBEntityHandle *other_nodes);
//! given a 1-cell and a chord, return the neighboring vertices on the
//! chord, in the same order as the 1-cell's vertices
@@ -315,17 +326,34 @@
//! function for deleting dual prior to foc operation; special because in
//! many cases need to delete a sheet in preparation for merging onto another
- MBErrorCode foc_delete_dual(MBEntityHandle edge,
- MBEntityHandle ocl,
- MBEntityHandle ocr,
+ MBErrorCode foc_delete_dual(MBEntityHandle *split_quads,
+ MBEntityHandle *split_edges,
MBRange &hexes);
- //! split a pair of entities such that the new pair shares as many (d-1)-
- //! and (d-2)-dimensional entities as the original pair did
- MBErrorCode split_pair_nonmanifold(MBEntityHandle *ents,
- const int ents_size,
+ //! split a pair of quads and the edge(s) shared by them
+ MBErrorCode split_pair_nonmanifold(MBEntityHandle *split_quads,
+ MBEntityHandle *split_edges,
+ MBEntityHandle split_node,
+ MBRange hexes,
+ MBEntityHandle *other_edges,
+ MBEntityHandle *other_nodes,
std::vector<MBEntityHandle> &merge_ents);
+ //! for foc's splitting two shared edges, there might be additional entities
+ //! connected to the split node that also have to be updated
+ MBErrorCode foc_get_addl_ents(std::vector<MBEntityHandle> *star_dp1,
+ std::vector<MBEntityHandle> *star_dp2,
+ MBEntityHandle split_node,
+ MBRange *addl_ents);
+
+ //! 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
+ MBErrorCode foc_get_stars(MBEntityHandle *split_quads,
+ MBEntityHandle *split_edges,
+ std::vector<MBEntityHandle> *star_dp1,
+ std::vector<MBEntityHandle> *star_dp2);
+
//! private copy of interface *
MBInterface *mbImpl;
Modified: MOAB/trunk/MBCN.cpp
===================================================================
--- MOAB/trunk/MBCN.cpp 2007-11-16 15:18:33 UTC (rev 1399)
+++ MOAB/trunk/MBCN.cpp 2007-11-16 15:29:36 UTC (rev 1400)
@@ -286,6 +286,80 @@
return 0;
}
+ //! return the dimension and index of the opposite side, given parent entity type and child
+ //! dimension and index. This function is only defined for certain types of parent/child types:
+ //! (Parent, Child dim->Opposite dim):
+ //! (Tri, 1->0), (Tri, 0->1), (Quad, 1->1), (Quad, 0->0),
+ //! (Tet, 2->0), (Tet, 1->1), (Tet, 0->2),
+ //! (Hex, 2->2), (Hex, 1->1)(diagonally across element), (Hex, 0->0) (diagonally across element)
+ //! All other parent types and child dimensions return an error.
+ //!
+ //! \param parent_type The type of parent element
+ //! \param child_type The type of child element
+ //! \param child_index The index of the child element
+ //! \param opposite_index The index of the opposite element
+ //! \return status Returns 0 if successful, -1 if not
+int MBCN::OppositeSide(const MBEntityType parent_type,
+ const int child_index,
+ const int child_dim,
+ int &opposite_index,
+ int &opposite_dim)
+{
+ switch (parent_type) {
+ case MBTRI:
+ switch (child_dim) {
+ case 0:
+ opposite_dim = 1;
+ opposite_index = (child_index+1)%3;
+ break;
+ case 1:
+ opposite_dim = 0;
+ opposite_index = (child_index+2)%3;
+ break;
+ default:
+ return -1;
+ }
+ break;
+
+ case MBQUAD:
+ switch (child_dim) {
+ case 0:
+ case 1:
+ opposite_dim = child_dim;
+ opposite_index = (child_index+2)%4;
+ break;
+ default:
+ return -1;
+ }
+ break;
+
+ case MBTET:
+ switch (child_dim) {
+ case 0:
+ opposite_dim = 2;
+ opposite_index = (child_index+2)%3 + 2*(child_index/3);
+ break;
+ case 1:
+ opposite_dim = 1;
+ opposite_index = 3 + (child_index + 5)%3;
+ break;
+ case 2:
+ opposite_dim = 0;
+ opposite_index = (child_index+2)%3 + child_index/3;
+ break;
+ default:
+ return -1;
+ }
+ break;
+ case MBHEX:
+
+ default:
+ return -1;
+ }
+
+ return 0;
+}
+
template <typename T>
static inline bool connectivity_match( const T* conn1_i,
const T* conn2_i,
Modified: MOAB/trunk/MBCN.hpp
===================================================================
--- MOAB/trunk/MBCN.hpp 2007-11-16 15:18:33 UTC (rev 1399)
+++ MOAB/trunk/MBCN.hpp 2007-11-16 15:29:36 UTC (rev 1400)
@@ -222,6 +222,25 @@
const int child_dim,
int &side_number, int &sense, int &offset);
+ //! return the dimension and index of the opposite side, given parent entity type and child
+ //! dimension and index. This function is only defined for certain types of parent/child types:
+ //! (Parent, Child dim->Opposite dim):
+ //! (Tri, 1->0), (Tri, 0->1), (Quad, 1->1), (Quad, 0->0),
+ //! (Tet, 2->0), (Tet, 1->1), (Tet, 0->2),
+ //! (Hex, 2->2), (Hex, 1->1)(diagonally across element), (Hex, 0->0) (diagonally across element)
+ //! All other parent types and child dimensions return an error.
+ //!
+ //! \param parent_type The type of parent element
+ //! \param child_type The type of child element
+ //! \param child_index The index of the child element
+ //! \param opposite_index The index of the opposite element
+ //! \return status Returns 0 if successful, -1 if not
+ static int OppositeSide(const MBEntityType parent_type,
+ const int child_index,
+ const int child_dim,
+ int &opposite_index,
+ int &opposite_dim);
+
//! given two connectivity arrays, determine whether or not they represent the same entity.
//! \param conn1 Connectivity array of first entity
//! \param conn2 Connectivity array of second entity
Modified: MOAB/trunk/MeshTopoUtil.cpp
===================================================================
--- MOAB/trunk/MeshTopoUtil.cpp 2007-11-16 15:18:33 UTC (rev 1399)
+++ MOAB/trunk/MeshTopoUtil.cpp 2007-11-16 15:29:36 UTC (rev 1400)
@@ -25,6 +25,8 @@
#include <assert.h>
+#define RR {if (MB_SUCCESS != result) return result;}
+
//! generate all the AEntities bounding the vertices
MBErrorCode MeshTopoUtil::construct_aentities(const MBRange &vertices)
{
@@ -96,32 +98,41 @@
// given an entity, find the entities of next higher dimension around
// that entity, ordered by connection through next higher dimension entities;
- // if any of the star entities is in only entity of next higher dimension,
+ // if any of the star entities is in only one entity of next higher dimension,
// on_boundary is returned true
MBErrorCode MeshTopoUtil::star_entities(const MBEntityHandle star_center,
std::vector<MBEntityHandle> &star_entities,
bool &bdy_entity,
const MBEntityHandle starting_star_entity,
- std::vector<MBEntityHandle> *star_entities_dp1,
- MBRange *star_candidates_dp1)
+ std::vector<MBEntityHandle> *star_entities_dp2,
+ MBRange *star_candidates_dp2)
{
// now start the traversal
bdy_entity = false;
- MBEntityHandle last_entity = starting_star_entity, last_dp1 = 0, next_entity, next_dp1;
- std::vector<MBEntityHandle> star_dp1;
+ MBEntityHandle last_entity = starting_star_entity, last_dp2 = 0, next_entity, next_dp2;
+ std::vector<MBEntityHandle> star_dp2;
+ MBErrorCode result;
+ int center_dim = mbImpl->dimension_from_handle(star_center);
+
+ MBRange tmp_candidates_dp2;
+ if (NULL != star_candidates_dp2) tmp_candidates_dp2 = *star_candidates_dp2;
+ else {
+ result = mbImpl->get_adjacencies(&star_center, 1,
+ center_dim+2,
+ false, tmp_candidates_dp2);
+ if (MB_SUCCESS != result) return result;
+ }
do {
// get the next star entity
- MBErrorCode result = star_next_entity(star_center, last_entity, last_dp1,
- star_candidates_dp1,
- next_entity, next_dp1);
+ result = star_next_entity(star_center, last_entity, last_dp2,
+ &tmp_candidates_dp2,
+ next_entity, next_dp2);
if (MB_SUCCESS != result) return result;
-
+
// special case: if starting_star_entity isn't connected to any entities of next
// higher dimension, it's the only entity in the star; put it on the list and return
- if (star_entities.empty() && next_entity == 0 && next_dp1 == 0 &&
- (star_candidates_dp1 == NULL ||
- star_candidates_dp1->find(last_entity) != star_candidates_dp1->end())) {
+ if (star_entities.empty() && next_entity == 0 && next_dp2 == 0) {
star_entities.push_back(last_entity);
bdy_entity = true;
return MB_SUCCESS;
@@ -130,41 +141,48 @@
// if we're at a bdy and bdy_entity hasn't been set yet, we're at the
// first bdy; reverse the lists and start traversing in the other direction; but,
// pop the last star entity off the list and find it again, so that we properly
- // check for next_dp1
- if (0 == next_dp1 && !bdy_entity) {
+ // check for next_dp2
+ if (0 == next_dp2 && !bdy_entity) {
star_entities.push_back(next_entity);
bdy_entity = true;
std::reverse(star_entities.begin(), star_entities.end());
star_entities.pop_back();
last_entity = star_entities.back();
- if (!star_dp1.empty()) {
- std::reverse(star_dp1.begin(), star_dp1.end());
- last_dp1 = star_dp1.back();
+ if (!star_dp2.empty()) {
+ std::reverse(star_dp2.begin(), star_dp2.end());
+ last_dp2 = star_dp2.back();
}
}
// else if we're not on the bdy and next_entity is already in star, that means
// we've come all the way around; don't put next_entity on list again, and
- // zero out last_dp1 to terminate while loop
+ // zero out last_dp2 to terminate while loop
else if (!bdy_entity &&
std::find(star_entities.begin(), star_entities.end(), next_entity) !=
- star_entities.end())
+ star_entities.end() &&
+ (std::find(star_dp2.begin(), star_dp2.end(), next_dp2) !=
+ star_dp2.end() || !next_dp2))
{
- last_dp1 = 0;
+ last_dp2 = 0;
}
// else, just assign last entities seen and go on to next iteration
else {
- star_entities.push_back(next_entity);
- if (0 != next_dp1) star_dp1.push_back(next_dp1);
+ if (std::find(star_entities.begin(), star_entities.end(), next_entity) ==
+ star_entities.end())
+ star_entities.push_back(next_entity);
+ if (0 != next_dp2) {
+ star_dp2.push_back(next_dp2);
+ tmp_candidates_dp2.erase(next_dp2);
+ }
last_entity = next_entity;
- last_dp1 = next_dp1;
+ last_dp2 = next_dp2;
}
}
- while (0 != last_dp1);
+ while (0 != last_dp2);
- // copy over the star_dp1 list, if requested
- if (NULL != star_entities_dp1)
- (*star_entities_dp1).swap(star_dp1);
+ // copy over the star_dp2 list, if requested
+ if (NULL != star_entities_dp2)
+ (*star_entities_dp2).swap(star_dp2);
return MB_SUCCESS;
}
@@ -183,6 +201,7 @@
MBRange from_ents, to_ents;
from_ents.insert(star_center);
if (0 != last_dp1) from_ents.insert(last_dp1);
+
int dim = mbImpl->dimension_from_handle(star_center);
MBErrorCode result = mbImpl->get_adjacencies(from_ents, dim+1, false, to_ents);
@@ -200,6 +219,16 @@
}
to_ents = tmp_to_ents;
}
+
+ if (0 == last_dp1 && to_ents.size() > 1 && NULL != star_candidates_dp1 &&
+ !star_candidates_dp1->empty()) {
+ // if we have a choice of to_ents and no previous dp1 and dp1 candidates,
+ // the one we choose needs to be adjacent to one of the candidates
+ result = mbImpl->get_adjacencies(*star_candidates_dp1, dim+1, false,
+ from_ents, MBInterface::UNION);
+ if (MB_SUCCESS != result) return result;
+ to_ents = to_ents.intersect(from_ents);
+ }
if (!to_ents.empty()) next_entity = *to_ents.begin();
else {
@@ -239,8 +268,8 @@
// Algorithm:
// get the (d+2)-manifold entities; for d=1 / d+2=3, just assume all connected elements, since
// we don't do 4d yet
- // get intersection of (d+1)-entities adjacent to star and union of (d+1)-entities
- // adjacent to (d+2)-manifold entities
+ // get intersection of (d+1)-entities adjacent to star entity and union of (d+1)-entities
+ // adjacent to (d+2)-manifold entities; these will be the entities in the star
// while (d+1)-entities
// remove (d+1)-entity from (d+1)-entities
// get the (d+1)-star and (d+2)-star around that (d+1)-entity (using star_entities)
@@ -319,6 +348,13 @@
// (end while)
}
+ // check for leftover dp2 manifold entities, these should be in one of the
+ // stars
+ if (!dp2_manifold.empty()) {
+ for (MBRange::iterator rit = dp2_manifold.begin(); rit != dp2_manifold.end(); rit++) {
+ }
+ }
+
return MB_SUCCESS;
}
@@ -439,6 +475,38 @@
else return *tmp_range2.begin();
}
+ //! return the opposite side entity given a parent and bounding entity.
+ //! This function is only defined for certain types of parent/child types;
+ //! See MBCN.hpp::OppositeSide for details.
+ //!
+ //! \param parent The parent element
+ //! \param child The child element
+ //! \param opposite_element The index of the opposite element
+MBErrorCode MeshTopoUtil::opposite_entity(const MBEntityHandle parent,
+ const MBEntityHandle child,
+ MBEntityHandle &opposite_element)
+{
+ // get the side no.
+ int side_no, offset, sense;
+ MBErrorCode result = mbImpl->side_number(parent, child, side_no,
+ offset, sense);
+ if (MB_SUCCESS != result) return result;
+
+ // get the child index from MBCN
+ int opposite_index, opposite_dim;
+ int status = MBCN::OppositeSide(mbImpl->type_from_handle(parent),
+ side_no, mbImpl->dimension_from_handle(child),
+ opposite_index, opposite_dim);
+ if (0 != status) return MB_FAILURE;
+
+ // now get the side element from MOAB
+ result = mbImpl->side_element(parent, opposite_dim, opposite_index,
+ opposite_element);
+ if (MB_SUCCESS != result) return result;
+
+ return MB_SUCCESS;
+}
+
MBErrorCode MeshTopoUtil::split_entities_manifold(MBRange &entities,
MBRange &new_entities,
MBRange *fill_entities)
@@ -575,93 +643,50 @@
}
MBErrorCode MeshTopoUtil::split_entity_nonmanifold(MBEntityHandle split_ent,
- MBRange &new_ents)
+ MBRange &old_adjs,
+ MBRange &new_adjs,
+ MBEntityHandle &new_entity)
{
+ // split an entity into two entities; new entity gets explicit adj to new_adjs,
+ // old to old_adjs
- // split an entity into multiple entities, one per (d+2)-connected region
- // in the (d+1)-star around the entity
- std::vector<std::vector<MBEntityHandle> > star_regions;
- std::vector<bool> bdy_flags;
- MBErrorCode result = star_entities_nonmanifold(split_ent, star_regions);
- if (MB_SUCCESS != result) return result;
-
- // should be at least 2 regions
- if (star_regions.size() < 2) return MB_FAILURE;
+ // make new entities and add adjacencies
+ // create the new entity
+ MBEntityType split_type = mbImpl->type_from_handle(split_ent);
- // ok, have the regions; make new entities and add adjacencies to regions
- std::vector<std::vector<MBEntityHandle> >::iterator vvit = star_regions.begin();
- const MBEntityHandle *connect;
- int num_connect;
- MBEntityType split_type = mbImpl->type_from_handle(split_ent);
- if (split_type != MBVERTEX) {
- result = mbImpl->get_connectivity(split_ent, connect, num_connect);
- if (MB_SUCCESS != result) return result;
+ MBErrorCode result;
+ if (MBVERTEX == split_type) {
+ double coords[3];
+ result = mbImpl->get_coords(&split_ent, 1, coords); RR;
+ result = mbImpl->create_vertex(coords, new_entity); RR;
}
-
- for (; vvit != star_regions.end(); vvit++) {
- // create the new entity
- MBEntityHandle new_entity;
- if (vvit != star_regions.begin()) {
- if (MBVERTEX == split_type) {
- double coords[3];
- result = mbImpl->get_coords(&split_ent, 1, coords);
- if (MB_SUCCESS != result) return result;
- result = mbImpl->create_vertex(coords, new_entity);
- if (MB_SUCCESS != result) return result;
- }
- else {
- result = mbImpl->create_element(split_type, connect, num_connect, new_entity);
- if (MB_SUCCESS != result) return result;
+ else {
+ const MBEntityHandle *connect;
+ int num_connect;
+ result = mbImpl->get_connectivity(split_ent, connect, num_connect); RR;
+ result = mbImpl->create_element(split_type, connect, num_connect, new_entity); RR;
- // remove any explicit adjacencies with split entity
- result = mbImpl->remove_adjacencies(split_ent, &(*vvit)[0], vvit->size());
- if (MB_SUCCESS != result) return result;
- }
+ // remove any explicit adjacencies between new_adjs and split entity
+ for (MBRange::iterator rit = new_adjs.begin(); rit != new_adjs.end(); rit++)
+ mbImpl->remove_adjacencies(split_ent, &(*rit), 1);
+ }
- new_ents.insert(new_entity);
+ if (MBVERTEX != split_type) {
+ // add adj's between new_adjs & new entity, old_adjs & split_entity
+ for (MBRange::iterator rit = new_adjs.begin(); rit != new_adjs.end(); rit++)
+ mbImpl->add_adjacencies(new_entity, &(*rit), 1, true);
+ for (MBRange::iterator rit = old_adjs.begin(); rit != old_adjs.end(); rit++)
+ mbImpl->add_adjacencies(split_ent, &(*rit), 1, true);
+ }
+ else if (split_ent != new_entity) {
+ // instead of adjs replace in connectivity
+ std::vector<MBEntityHandle> connect;
+ for (MBRange::iterator rit = new_adjs.begin(); rit != new_adjs.end(); rit++) {
+ connect.clear();
+ result = mbImpl->get_connectivity(&(*rit), 1, connect); RR;
+ std::replace(connect.begin(), connect.end(), split_ent, new_entity);
+ result = mbImpl->set_connectivity(*rit, &connect[0], connect.size()); RR;
}
- else {
- new_entity = split_ent;
- }
-
- if (MBVERTEX != split_type) {
- // add adjacency with new entity
- result = mbImpl->add_adjacencies(new_entity, &(*vvit)[0], vvit->size(), false);
- if (MB_SUCCESS != result) return result;
- }
- else if (split_ent != new_entity) {
- // need to get all entities adjacent to edges in this star, and replace one
- // vertex with another
- MBRange star_ents;
- result = mbImpl->get_adjacencies(&(*vvit)[0], vvit->size(), 2, false, star_ents,
- MBInterface::UNION);
- if (MB_SUCCESS != result) return result;
-
- // add edges adjacent to these faces which are also adjacent to split_ent
- MBRange dum_range, dum_range_2;
- result = mbImpl->get_adjacencies(&split_ent, 1, 1, false, dum_range);
- if (MB_SUCCESS != result) return result;
- result = mbImpl->get_adjacencies(star_ents, 1, false, dum_range_2, MBInterface::UNION);
- if (MB_SUCCESS != result) return result;
- dum_range = dum_range.intersect(dum_range_2);
- star_ents.merge(dum_range);
-
- result = mbImpl->get_adjacencies(&(*vvit)[0], vvit->size(), 3, false, star_ents,
- MBInterface::UNION);
- if (MB_SUCCESS != result) return result;
- std::copy(vvit->begin(), vvit->end(), mb_range_inserter(star_ents));
-
- // shouldn't matter which order we do this...
- std::vector<MBEntityHandle> connect;
- for (MBRange::iterator rit = star_ents.begin(); rit != star_ents.end(); rit++) {
- connect.clear();
- result = mbImpl->get_connectivity(&(*rit), 1, connect);
- if (MB_SUCCESS != result) return result;
- std::replace(connect.begin(), connect.end(), split_ent, new_entity);
-
- result = mbImpl->set_connectivity(*rit, &connect[0], connect.size());
- }
- }
}
return result;
Modified: MOAB/trunk/MeshTopoUtil.hpp
===================================================================
--- MOAB/trunk/MeshTopoUtil.hpp 2007-11-16 15:18:33 UTC (rev 1399)
+++ MOAB/trunk/MeshTopoUtil.hpp 2007-11-16 15:29:36 UTC (rev 1400)
@@ -99,12 +99,25 @@
const MBEntityHandle ent2,
const int dim);
+ //! return the opposite side entity given a parent and bounding entity.
+ //! This function is only defined for certain types of parent/child types;
+ //! See MBCN.hpp::OppositeSide for details.
+ //!
+ //! \param parent The parent element
+ //! \param child The child element
+ //! \param opposite_element The index of the opposite element
+ MBErrorCode opposite_entity(const MBEntityHandle parent,
+ const MBEntityHandle child,
+ MBEntityHandle &opposite_element);
+
//! split entity which is non-manifold, that is, which has > 2 connected entities
//! of next higher dimension; assumes that there are >= 2 connected regions of
//! (d+2)-dimensional entities; a new d-entity is created for each region after the
//! first, and it's made explicitly-adjacent to the region to which it corresponds
MBErrorCode split_entity_nonmanifold(MBEntityHandle split_ent,
- MBRange &new_ents);
+ MBRange &old_adjs,
+ MBRange &new_adjs,
+ MBEntityHandle &new_entity);
//! split entities that are manifold (shared by two or less entities of each higher dimension),
//! optionally creating an entity of next higher dimension to fill the gap
Modified: MOAB/trunk/tools/qvdual/DrawDual.hpp
===================================================================
--- MOAB/trunk/tools/qvdual/DrawDual.hpp 2007-11-16 15:18:33 UTC (rev 1399)
+++ MOAB/trunk/tools/qvdual/DrawDual.hpp 2007-11-16 15:29:36 UTC (rev 1400)
@@ -46,6 +46,8 @@
MBErrorCode reset_drawn_sheets(MBRange *drawn_sheets = NULL);
+ void print_picked_ents(MBRange &picked_ents);
+
private:
static DrawDual *gDrawDual;
@@ -230,8 +232,6 @@
MBErrorCode fixup_degen_bchords(MBEntityHandle dual_surf);
- void print_picked_ents(MBRange &picked_ents);
-
//! given some entities, get the corresponding gviz points on the sheet
void get_points(const MBEntityHandle *ents, const int num_ents,
const bool extra,
Modified: MOAB/trunk/tools/qvdual/uiQVDual.h
===================================================================
--- MOAB/trunk/tools/qvdual/uiQVDual.h 2007-11-16 15:18:33 UTC (rev 1399)
+++ MOAB/trunk/tools/qvdual/uiQVDual.h 2007-11-16 15:29:36 UTC (rev 1400)
@@ -1,7 +1,7 @@
/****************************************************************************
** Form interface generated from reading ui file 'uiQVDual.ui'
**
-** Created: Mon Sep 10 16:49:13 2007
+** Created: Mon Nov 5 08:55:16 2007
** by: The User Interface Compiler ($Id: qt/main.cpp 3.3.7 edited Aug 31 2005 $)
**
** WARNING! All changes made in this file will be lost!
@@ -124,6 +124,7 @@
virtual void fileSaveAs();
virtual void resetDisplay();
virtual void redrawDisplay();
+ virtual void pickline1_returnPressed();
signals:
void toggled();
Modified: MOAB/trunk/tools/qvdual/uiQVDual.ui
===================================================================
--- MOAB/trunk/tools/qvdual/uiQVDual.ui 2007-11-16 15:18:33 UTC (rev 1399)
+++ MOAB/trunk/tools/qvdual/uiQVDual.ui 2007-11-16 15:29:36 UTC (rev 1400)
@@ -922,6 +922,12 @@
<receiver>uiQVDual</receiver>
<slot>negFCbutton_clicked()</slot>
</connection>
+ <connection>
+ <sender>pickline1</sender>
+ <signal>returnPressed()</signal>
+ <receiver>uiQVDual</receiver>
+ <slot>pickline1_returnPressed()</slot>
+ </connection>
</connections>
<includes>
<include location="local" impldecl="in declaration">MBInterface.hpp</include>
@@ -1000,6 +1006,7 @@
<slot>fileSaveAs()</slot>
<slot>resetDisplay()</slot>
<slot>redrawDisplay()</slot>
+ <slot>pickline1_returnPressed()</slot>
</slots>
<functions>
<function access="private" specifier="non virtual">init()</function>
Modified: MOAB/trunk/tools/qvdual/uiQVDual.ui.h
===================================================================
--- MOAB/trunk/tools/qvdual/uiQVDual.ui.h 2007-11-16 15:18:33 UTC (rev 1399)
+++ MOAB/trunk/tools/qvdual/uiQVDual.ui.h 2007-11-16 15:29:36 UTC (rev 1400)
@@ -1055,3 +1055,52 @@
this->updateMesh();
}
+
+
+void uiQVDual::pickline1_returnPressed()
+{
+ // get the currently picked entity
+ QString line = pickline1->text();
+
+ MBRange cell_ents, picked_ents;
+ int last_match = 0, next_match = 0;
+ MBHandleUtils hu(vtkMOABUtils::mbImpl->proc_rank(),
+ vtkMOABUtils::mbImpl->proc_size());
+ while (true) {
+ last_match = next_match;
+ if (-1 == last_match) break;
+ if (0 != last_match) last_match++;
+ next_match = line.find("-", last_match);
+ int ent_no = -1;
+ MBEntityType etype = MBMAXTYPE;
+ if (line.ascii()[last_match] == 'h') etype = MBHEX;
+ else if (line.ascii()[last_match] == 'f') etype = MBQUAD;
+ sscanf(line.ascii()+last_match+1, "%d", &ent_no);
+ if (-1 != ent_no && MBMAXTYPE != etype)
+ cell_ents.insert(hu.create_handle(etype, ent_no, 0));
+ }
+#define PR(a) {pickline1->setText(QString(a));return;}
+
+ if (cell_ents.size() < 2) PR("(not a dual entity!)");
+
+ MBErrorCode result;
+ DualTool dt(vtkMOABUtils::mbImpl);
+ if (cell_ents.size() > 2) {
+ // assume it's a dual 2-cell
+ result = vtkMOABUtils::mbImpl->get_adjacencies(cell_ents, 1, false,
+ picked_ents);
+ if (picked_ents.empty()) PR("(not a dual 2-cell!)");
+ }
+ else {
+ result = vtkMOABUtils::mbImpl->get_adjacencies(cell_ents, 2, false,
+ picked_ents);
+ if (picked_ents.empty()) PR("(not a dual 1-cell!)");
+ }
+
+ MBEntityHandle dual_ent = dt.get_dual_entity(*picked_ents.begin());
+ if (0 == dual_ent) PR("(no dual entity!)");
+ picked_ents.clear();
+ picked_ents.insert(dual_ent);
+
+ vtkMOABUtils::drawDual->print_picked_ents(picked_ents);
+}
More information about the moab-dev
mailing list