bool ContainsPoint(Volume* vol, const vector3& p, TAAPos aaPos) { // iterate over face descriptors of the sides and check whether the point // lies inside or outside FaceDescriptor fd; vector3 n, dir; // to minimize rounding errors we'll compare against a small-constant which is // relative to the first edge of the examined volume. EdgeDescriptor ed; vol->edge_desc(0, ed); number len = EdgeLength(&ed, aaPos); // the constant should be relative to the same geometric measure as what it is // compared against later on, i.e. length*area, since otherwise problems arise // with geometries scaled to very small extensions; // which is why I changed sqrt(lenSq) to lenSq^1.5 (mbreit, 2015-05-11) const number locSmall = len * len * len * SMALL; for(size_t i = 0; i < vol->num_faces(); ++i){ vol->face_desc(i, fd); CalculateNormalNoNormalize(n, &fd, aaPos); VecSubtract(dir, aaPos[fd.vertex(0)], p); if(VecDot(dir, n) < -locSmall) return false; } return true; }
//////////////////////////////////////////////////////////////////////// // GetNeighbours - sreiter void GetNeighbours(std::vector<Volume*>& vVolsOut, Grid& grid, Volume* v, int side, bool clearContainer) { if(clearContainer) vVolsOut.clear(); // if VOLOPT_AUTOGENERATE_FACES and FACEOPT_STORE_ASSOCIATED_VOLUMES are // activated, we may use them to find the connected volume quite fast. if(grid.option_is_enabled(VOLOPT_AUTOGENERATE_FACES | FACEOPT_STORE_ASSOCIATED_VOLUMES)) { Face* f = grid.get_face(v, side); Grid::AssociatedVolumeIterator iterEnd = grid.associated_volumes_end(f); for(Grid::AssociatedVolumeIterator iter = grid.associated_volumes_begin(f); iter != iterEnd; ++iter) { if(*iter != v) vVolsOut.push_back(*iter); } return; } // we can't assume that associated faces exist. // we have to find the neighbour by hand. // mark all vertices of the side grid.begin_marking(); FaceDescriptor fd; v->face_desc(side, fd); uint numFaceVrts = fd.num_vertices(); for(uint i = 0; i < numFaceVrts; ++ i) grid.mark(fd.vertex(i)); // iterate over associated volumes of the first vertex and count // the number of marked vertices it contains. Vertex* vrt = fd.vertex(0); Grid::AssociatedVolumeIterator iterEnd = grid.associated_volumes_end(vrt); for(Grid::AssociatedVolumeIterator iter = grid.associated_volumes_begin(vrt); iter != iterEnd; ++iter) { Volume* vol = *iter; if(vol != v){ size_t count = 0; uint numVrts = vol->num_vertices(); for(uint i = 0; i < numVrts; ++i){ if(grid.is_marked(vol->vertex(i))) ++count; } // if the number of marked vertices in vol matches the // number of vertices of the specified side, we consider // the volume to be a neighbout of that side. if(count == numFaceVrts) vVolsOut.push_back(vol); } } grid.end_marking(); }
UG_API bool OrientationMatches(FaceVertices* fv, Volume* v) { // find the matching face desc and compare FaceDescriptor fd; for(size_t iface = 0; iface < v->num_faces(); ++iface){ v->face_desc(iface, fd); if(CompareVertices(fv, &fd)){ // check if their orientation matches // find the first vertex of fv in f size_t i; for(i = 0; i < fd.num_vertices(); ++i) { if(fd.vertex(i) == fv->vertex(0)) break; } if(i < fd.num_vertices()) { // the first one has been found. // check whether the second vertex of ed is the // same as the next vertex of f if(fv->vertex(1) == fd.vertex((i+1) % fd.num_vertices())) return true;// the orientation is the same } // the orientation is not the same. return false; } } // the orientation is not the same. return false; }
//////////////////////////////////////////////////////////////////////// // MergeVertices /// merges two vertices and restructures the adjacent elements. void MergeVertices(Grid& grid, Vertex* v1, Vertex* v2) { // make sure that GRIDOPT_VERTEXCENTRIC_INTERCONNECTION is enabled if(grid.num_edges() && (!grid.option_is_enabled(VRTOPT_STORE_ASSOCIATED_EDGES))) { LOG(" WARNING in MergeVertices: autoenabling VRTOPT_STORE_ASSOCIATED_EDGES\n"); grid.enable_options(VRTOPT_STORE_ASSOCIATED_EDGES); } if(grid.num_faces() && (!grid.option_is_enabled(VRTOPT_STORE_ASSOCIATED_FACES))) { LOG(" WARNING in MergeVertices: autoenabling VRTOPT_STORE_ASSOCIATED_FACES\n"); grid.enable_options(VRTOPT_STORE_ASSOCIATED_FACES); } if(grid.num_volumes() && (!grid.option_is_enabled(VRTOPT_STORE_ASSOCIATED_VOLUMES))) { LOG(" WARNING in MergeVertices: autoenabling VRTOPT_STORE_ASSOCIATED_VOLUMES\n"); grid.enable_options(VRTOPT_STORE_ASSOCIATED_VOLUMES); } Edge* conEdge = grid.get_edge(v1, v2); if(conEdge) { // perform an edge-collapse on conEdge CollapseEdge(grid, conEdge, v1); } else { // notify the grid, that the two vertices will be merged grid.objects_will_be_merged(v1, v1, v2); // we have to check if there are elements that connect the vertices. // We have to delete those. EraseConnectingElements(grid, v1, v2); // create new edges for each edge that is connected with v2. // avoid double edges if(grid.num_edges() > 0) { EdgeDescriptor ed; Grid::AssociatedEdgeIterator iterEnd = grid.associated_edges_end(v2); for(Grid::AssociatedEdgeIterator iter = grid.associated_edges_begin(v2); iter != iterEnd; ++iter) { Edge* e = *iter; if(e->vertex(0) == v2) ed.set_vertices(v1, e->vertex(1)); else ed.set_vertices(e->vertex(0), v1); Edge* existingEdge = grid.get_edge(ed); if(!existingEdge) grid.create_by_cloning(e, ed, e); else grid.objects_will_be_merged(existingEdge, existingEdge, e); } } // create new faces for each face that is connected to v2 // avoid double faces. if(grid.num_faces() > 0) { FaceDescriptor fd; Grid::AssociatedFaceIterator iterEnd = grid.associated_faces_end(v2); for(Grid::AssociatedFaceIterator iter = grid.associated_faces_begin(v2); iter != iterEnd; ++iter) { Face* f = *iter; uint numVrts = f->num_vertices(); fd.set_num_vertices(numVrts); for(uint i = 0; i < numVrts; ++i) { if(f->vertex(i) == v2) fd.set_vertex(i, v1); else fd.set_vertex(i, f->vertex(i)); } Face* existingFace = grid.get_face(fd); if(!existingFace) grid.create_by_cloning(f, fd, f); else grid.objects_will_be_merged(existingFace, existingFace, f); } } // create new volumes for each volume that is connected to v2 if(grid.num_volumes() > 0) { VolumeDescriptor vd; Grid::AssociatedVolumeIterator iterEnd = grid.associated_volumes_end(v2); for(Grid::AssociatedVolumeIterator iter = grid.associated_volumes_begin(v2); iter != iterEnd; ++iter) { Volume* v = *iter; uint numVrts = v->num_vertices(); vd.set_num_vertices(numVrts); for(uint i = 0; i < numVrts; ++i) { if(v->vertex(i) == v2) vd.set_vertex(i, v1); else vd.set_vertex(i, v->vertex(i)); } //assert(!"avoid double volumes! implement FindVolume and use it here."); grid.create_by_cloning(v, vd, v); } } // new elements have been created. remove the old ones. // it is sufficient to simply erase v2. grid.erase(v2); } }
void MinimizeEdgeLength_SwapsOnly(Grid& grid, EdgeIterator edgesBegin, EdgeIterator edgesEnd, TAAPos& aaPos) { using namespace std; // helper to collect neighbors Face* nbrFaces[2]; vector<Edge*> edges; // flipCandidates queue<Edge*> candidates; // sadly we can't use marking. Thats why we attach a simple byte to the edges, // which will tell whether an edge is already a candidate. AByte aIsCandidate; grid.attach_to_edges_dv(aIsCandidate, 0, false); Grid::AttachmentAccessor<Edge, AByte> aaIsCandidate(grid, aIsCandidate); // set up candidate array for(EdgeIterator iter = edgesBegin; iter != edgesEnd; ++iter){ aaIsCandidate[*iter] = 1; candidates.push(*iter); } while(!candidates.empty()){ Edge* e = candidates.front(); candidates.pop(); aaIsCandidate[e] = 0; // we only perform swaps on regular manifolds. if(GetAssociatedFaces(nbrFaces, grid, e, 2) == 2){ // make sure that both neighbors are triangles if(nbrFaces[0]->num_vertices() != 3 || nbrFaces[1]->num_vertices() != 3) continue; // check whether a swap would make the edge shorter. Vertex* conVrt0 = GetConnectedVertex(e, nbrFaces[0]); Vertex* conVrt1 = GetConnectedVertex(e, nbrFaces[1]); if(VertexDistanceSq(conVrt0, conVrt1, aaPos) < EdgeLengthSq(e, aaPos)) { // it'll be shorter // now make sure that associated triangles won't flip //todo: add support for 2d position attachments vector3 n0, n1; CalculateNormal(n0, nbrFaces[0], aaPos); CalculateNormal(n1, nbrFaces[1], aaPos); number oldDot = VecDot(n0, n1); FaceDescriptor ntri; ntri.set_num_vertices(3); ntri.set_vertex(0, e->vertex(0)); ntri.set_vertex(1, conVrt1); ntri.set_vertex(2, conVrt0); CalculateNormal(n0, &ntri, aaPos); ntri.set_vertex(0, e->vertex(1)); ntri.set_vertex(1, conVrt0); ntri.set_vertex(2, conVrt1); CalculateNormal(n1, &ntri, aaPos); number newDot = VecDot(n0, n1); // if both have the same sign, we're fine! if(oldDot * newDot < 0){ continue;// not fine! } // ok - everything is fine. Now swap the edge e = SwapEdge(grid, e); UG_ASSERT(e, "SwapEdge did not produce a new edge."); // all edges of associated triangles are candidates again (except e) GetAssociatedFaces(nbrFaces, grid, e, 2); for(size_t i = 0; i < 2; ++i){ CollectAssociated(edges, grid, nbrFaces[i]); for(size_t j = 0; j < edges.size(); ++j){ if(edges[j] != e && (!aaIsCandidate[edges[j]])){ candidates.push(edges[j]); aaIsCandidate[edges[j]] = 1; } } } } } } grid.detach_from_edges(aIsCandidate); }
HPREF_ELEMENT_TYPE ClassifyTrig(HPRefElement & el, INDEX_2_HASHTABLE<int> & edges, INDEX_2_HASHTABLE<int> & edgepoint_dom, BitArray & cornerpoint, BitArray & edgepoint, INDEX_3_HASHTABLE<int> & faces, INDEX_2_HASHTABLE<int> & face_edges, INDEX_2_HASHTABLE<int> & surf_edges, Array<int, PointIndex::BASE> & facepoint, int dim, const FaceDescriptor & fd) { HPREF_ELEMENT_TYPE type = HP_NONE; int pnums[3]; INDEX_3 i3 (el.pnums[0], el.pnums[1], el.pnums[2]); i3.Sort(); bool sing_face = faces.Used (i3); for (int j = 1; j <= 3; j++) { int ep1 = edgepoint.Test (el.PNumMod (j)); int ep2 = edgepoint.Test (el.PNumMod (j+1)); int ep3 = edgepoint.Test (el.PNumMod (j+2)); if (dim == 2) { // JS, Dec 11 ep1 = edgepoint_dom.Used (INDEX_2 (fd.SurfNr(), el.PNumMod(j))) || edgepoint_dom.Used (INDEX_2 (-1, el.PNumMod(j))); ep2 = edgepoint_dom.Used (INDEX_2 (fd.SurfNr(), el.PNumMod(j+1))) || edgepoint_dom.Used (INDEX_2 (-1, el.PNumMod(j+1))); ep3 = edgepoint_dom.Used (INDEX_2 (fd.SurfNr(), el.PNumMod(j+2))) || edgepoint_dom.Used (INDEX_2 (-1, el.PNumMod(j+2))); /* ep1 = edgepoint_dom.Used (INDEX_2 (el.index, el.PNumMod(j))); ep2 = edgepoint_dom.Used (INDEX_2 (el.index, el.PNumMod(j+1))); ep3 = edgepoint_dom.Used (INDEX_2 (el.index, el.PNumMod(j+2))); */ // ep3 = edgepoint_dom.Used (INDEX_2 (mesh.SurfaceElement(i).GetIndex(), el.PNumMod(j+2))); } int cp1 = cornerpoint.Test (el.PNumMod (j)); int cp2 = cornerpoint.Test (el.PNumMod (j+1)); int cp3 = cornerpoint.Test (el.PNumMod (j+2)); ep1 |= cp1; ep2 |= cp2; ep3 |= cp3; // (*testout) << "cp = " << cp1 << cp2 << cp3 << ", ep = " << ep1 << ep2 << ep3 << endl; int p[3] = { el.PNumMod (j), el.PNumMod (j+1), el.PNumMod (j+2)}; if(ep1) { INDEX_2 i2a=INDEX_2::Sort(p[0], p[1]); INDEX_2 i2b=INDEX_2::Sort(p[0], p[2]); if(!edges.Used(i2a) && !edges.Used(i2b)) cp1 = 1; } if(ep2) { INDEX_2 i2a=INDEX_2::Sort(p[1], p[0]); INDEX_2 i2b=INDEX_2::Sort(p[1], p[2]); if(!edges.Used(i2a) && !edges.Used(i2b)) cp2 = 1; } if(ep3) { INDEX_2 i2a=INDEX_2::Sort(p[2], p[0]); INDEX_2 i2b=INDEX_2::Sort(p[2], p[1]); if(!edges.Used(i2a) && !edges.Used(i2b)) cp3= 1; } int isedge1=0, isedge2=0, isedge3=0; if(dim == 3 ) { INDEX_2 i2; i2 = INDEX_2(el.PNumMod (j), el.PNumMod (j+1)); isedge1 = edges.Used (i2); i2.Sort(); if(surf_edges.Used(i2) && surf_edges.Get(i2) != fd.SurfNr()+1 && (face_edges.Get(i2) == -1 || face_edges.Get(i2) == fd.DomainIn() || face_edges.Get(i2) == fd.DomainOut()) ) { isedge1=1; ep1 = 1; ep2=1; } i2 = INDEX_2(el.PNumMod (j+1), el.PNumMod (j+2)); isedge2 = edges.Used (i2); i2.Sort(); if(surf_edges.Used(i2) && surf_edges.Get(i2) != fd.SurfNr()+1 && (face_edges.Get(i2) == -1 || face_edges.Get(i2) == fd.DomainIn() || face_edges.Get(i2) == fd.DomainOut()) ) { isedge2=1; ep2 = 1; ep3=1; } i2 = INDEX_2(el.PNumMod (j+2), el.PNumMod (j+3)); isedge3 = edges.Used (i2); i2.Sort(); if(surf_edges.Used(i2) && surf_edges.Get(i2) != fd.SurfNr()+1 && (face_edges.Get(i2) == -1 || face_edges.Get(i2) == fd.DomainIn() || face_edges.Get(i2) == fd.DomainOut()) ) { isedge3=1; ep1 = 1; ep3=1; } // cout << " isedge " << isedge1 << " \t " << isedge2 << " \t " << isedge3 << endl; if (!sing_face) { /* if (!isedge1) { cp1 |= ep1; cp2 |= ep2; } if (!isedge2) { cp2 |= ep2; cp3 |= ep3; } if (!isedge3) { cp3 |= ep3; cp1 |= ep1; } */ ep1 |= facepoint [el.PNumMod(j)] != 0; ep2 |= facepoint [el.PNumMod(j+1)] != 0; ep3 |= facepoint [el.PNumMod(j+2)] != 0; isedge1 |= face_edges.Used (INDEX_2::Sort (el.PNumMod(j), el.PNumMod(j+1))); isedge2 |= face_edges.Used (INDEX_2::Sort (el.PNumMod(j+1), el.PNumMod(j+2))); isedge3 |= face_edges.Used (INDEX_2::Sort (el.PNumMod(j+2), el.PNumMod(j+3))); } } if(dim ==2) { INDEX_2 i2; i2 = INDEX_2(el.PNumMod (j), el.PNumMod (j+1)); i2.Sort(); isedge1 = edges.Used (i2); if(isedge1) { ep1 = 1; ep2=1; } i2 = INDEX_2(el.PNumMod (j+1), el.PNumMod (j+2)); i2.Sort(); isedge2 = edges.Used (i2); if(isedge2) { ep2 = 1; ep3=1; } i2 = INDEX_2(el.PNumMod (j+2), el.PNumMod (j+3)); i2.Sort(); isedge3 = edges.Used (i2); if(isedge3) { ep1 = 1; ep3=1; } } /* cout << " used " << face_edges.Used (INDEX_2::Sort (el.PNumMod(j), el.PNumMod(j+1))) << endl; cout << " isedge " << isedge1 << " \t " << isedge2 << " \t " << isedge3 << endl; cout << " ep " << ep1 << "\t" << ep2 << " \t " << ep3 << endl; cout << " cp " << cp1 << "\t" << cp2 << " \t " << cp3 << endl; */ if (isedge1 + isedge2 + isedge3 == 0) { if (!ep1 && !ep2 && !ep3) type = HP_TRIG; if (ep1 && !ep2 && !ep3) type = HP_TRIG_SINGCORNER; if (ep1 && ep2 && !ep3) type = HP_TRIG_SINGCORNER12; if (ep1 && ep2 && ep3) { if (dim == 2) type = HP_TRIG_SINGCORNER123_2D; else type = HP_TRIG_SINGCORNER123; } if (type != HP_NONE) { pnums[0] = el.PNumMod (j); pnums[1] = el.PNumMod (j+1); pnums[2] = el.PNumMod (j+2); break; } } if (isedge1 && !isedge2 && !isedge3) { int code = 0; if (cp1) code += 1; if (cp2) code += 2; if (ep3) code += 4; HPREF_ELEMENT_TYPE types[] = { HP_TRIG_SINGEDGE, HP_TRIG_SINGEDGECORNER1, HP_TRIG_SINGEDGECORNER2, HP_TRIG_SINGEDGECORNER12, HP_TRIG_SINGEDGECORNER3, HP_TRIG_SINGEDGECORNER13, HP_TRIG_SINGEDGECORNER23, HP_TRIG_SINGEDGECORNER123, }; type = types[code]; pnums[0] = el.PNumMod (j); pnums[1] = el.PNumMod (j+1); pnums[2] = el.PNumMod (j+2); break; } if (isedge1 && !isedge2 && isedge3) { if (!cp3) { if (!cp2) type = HP_TRIG_SINGEDGES; else type = HP_TRIG_SINGEDGES2; } else { if (!cp2) type = HP_TRIG_SINGEDGES3; else type = HP_TRIG_SINGEDGES23; } pnums[0] = el.PNumMod (j); pnums[1] = el.PNumMod (j+1); pnums[2] = el.PNumMod (j+2); break; } if (isedge1 && isedge2 && isedge3) { type = HP_TRIG_3SINGEDGES; pnums[0] = el.PNumMod (j); pnums[1] = el.PNumMod (j+1); pnums[2] = el.PNumMod (j+2); break; } } for(int k=0;k<3;k++) el[k] = pnums[k]; /*if(type != HP_NONE) { cout << " TRIG with pnums " << pnums[0] << "\t" << pnums[1] << "\t" << pnums[2] << endl; cout << " type " << type << endl; } */ return(type); }
// #ifdef SABINE HPREF_ELEMENT_TYPE ClassifyTrig(HPRefElement & el, INDEX_2_HASHTABLE<int> & edges, INDEX_2_HASHTABLE<int> & edgepoint_dom, BitArray & cornerpoint, BitArray & edgepoint, INDEX_3_HASHTABLE<int> & faces, INDEX_2_HASHTABLE<int> & face_edges, INDEX_2_HASHTABLE<int> & surf_edges, Array<int, PointIndex::BASE> & facepoint, int dim, const FaceDescriptor & fd) { HPREF_ELEMENT_TYPE type = HP_NONE; int pnums[3]; int p[3]; INDEX_3 i3 (el.pnums[0], el.pnums[1], el.pnums[2]); i3.Sort(); bool sing_face = faces.Used (i3); // *testout << " facepoint " << facepoint << endl; // Try all rotations of the trig for (int j=0;j<3;j++) { int point_sing[3] = {0,0,0}; int edge_sing[3] = {0,0,0}; // *testout << " actual rotation of trig points " ; for(int m=0;m<3;m++) { p[m] = (j+m)%3 +1; // local vertex number pnums[m] = el.PNum(p[m]); // global vertex number // *testout << pnums[m] << " \t "; } // *testout << endl ; if(dim == 3) { // face point for(int k=0;k<3;k++) if(!sing_face) { // *testout << " fp [" << k << "] = " << facepoint[pnums[k]] << endl; // *testout << " fd.DomainIn()" << fd.DomainIn() << endl; // *testout << " fd.DomainOut()" << fd.DomainOut() << endl; if( facepoint[pnums[k]] && (facepoint[pnums[k]] ==-1 || facepoint[pnums[k]] == fd.DomainIn() || facepoint[pnums[k]] == fd.DomainOut())) point_sing[p[k]-1] = 1; } // if point is on face_edge in next step sing = 2 /* *testout << " pointsing NACH FACEPOints ... FALLS EDGEPOINT UMSETZEN" ; for (int k=0;k<3;k++) *testout << "\t" << point_sing[p[k]-1] ; *testout << endl; */ } const ELEMENT_EDGE * eledges = MeshTopology::GetEdges(TRIG); if(dim==3) { for(int k=0;k<3;k++) { int ep1=p[eledges[k][0]-1]; int ep2=p[eledges[k][1]-1]; INDEX_2 i2(el.PNum(ep1),el.PNum(ep2)); if(edges.Used(i2)) { edge_sing[k]=2; point_sing[ep1-1] = 2; point_sing[ep2-1] = 2; } else // face_edge? { i2.Sort(); if(surf_edges.Used(i2) && surf_edges.Get(i2) != fd.SurfNr()+1) // edge not face_edge acc. to surface in which trig lies if(face_edges.Get(i2)==-1 ||face_edges.Get(i2) == fd.DomainIn() || face_edges.Get(i2) == fd.DomainOut() ) { edge_sing[k]=1; } else { point_sing[ep1-1] = 0; // set to edge_point point_sing[ep2-1] = 0; // set to edge_point } } /* *testout << " pointsing NACH edges UND FACEEDGES UMSETZEN ... " ; for (int k=0;k<3;k++) *testout << "\t" << point_sing[p[k]-1] ; *testout << endl; */ } } /* *testout << " dim " << dim << endl; *testout << " edgepoint_dom " << edgepoint_dom << endl; */ if(dim==2) { for(int k=0;k<3;k++) { int ep1=p[eledges[k][0]-1]; int ep2=p[eledges[k][1]-1]; INDEX_2 i2(el.PNum(ep1),el.PNum(ep2)); if(edges.Used(i2)) { if(edgepoint_dom.Used(INDEX_2(fd.SurfNr(),pnums[ep1-1])) || edgepoint_dom.Used(INDEX_2(-1,pnums[ep1-1])) || edgepoint_dom.Used(INDEX_2(fd.SurfNr(),pnums[ep2-1])) || edgepoint_dom.Used(INDEX_2(-1,pnums[ep2-1]))) { edge_sing[k]=2; point_sing[ep1-1] = 2; point_sing[ep2-1] = 2; } } } } for(int k=0;k<3;k++) if(edgepoint.Test(pnums[k])) //edgepoint, but not member of sing_edge on trig -> cp { INDEX_2 i2a=INDEX_2::Sort(el.PNum(p[k]), el.PNum(p[(k+1)%3])); INDEX_2 i2b=INDEX_2::Sort(el.PNum(p[k]), el.PNum(p[(k+2)%3])); if(!edges.Used(i2a) && !edges.Used(i2b)) point_sing[p[k]-1] = 3; } for(int k=0;k<3;k++) if(cornerpoint.Test(el.PNum(p[k]))) point_sing[p[k]-1] = 3; *testout << "point_sing = " << point_sing[0] << point_sing[1] << point_sing[2] << endl; if(edge_sing[0] + edge_sing[1] + edge_sing[2] == 0) { int ps = point_sing[0] + point_sing[1] + point_sing[2]; if(ps==0) type = HP_TRIG; else if(point_sing[p[0]-1] && !point_sing[p[1]-1] && !point_sing[p[2]-1]) type = HP_TRIG_SINGCORNER; else if(point_sing[p[0]-1] && point_sing[p[1]-1] && !point_sing[p[2]-1]) type = HP_TRIG_SINGCORNER12; else if(point_sing[p[0]-1] && point_sing[p[1]-1] && point_sing[p[2]-1]) { if(dim==2) type = HP_TRIG_SINGCORNER123_2D; else type = HP_TRIG_SINGCORNER123; } } else if (edge_sing[2] && !edge_sing[0] && !edge_sing[1]) //E[2]=(1,2) { int code = 0; if(point_sing[p[0]-1] > edge_sing[2]) code+=1; if(point_sing[p[1]-1] > edge_sing[2]) code+=2; if(point_sing[p[2]-1]) code+=4; HPREF_ELEMENT_TYPE types[] = { HP_TRIG_SINGEDGE, HP_TRIG_SINGEDGECORNER1, HP_TRIG_SINGEDGECORNER2, HP_TRIG_SINGEDGECORNER12, HP_TRIG_SINGEDGECORNER3, HP_TRIG_SINGEDGECORNER13, HP_TRIG_SINGEDGECORNER23, HP_TRIG_SINGEDGECORNER123, }; type = types[code]; } // E[0] = [0,2], E[1] =[1,2], E[2] = [0,1] else if(edge_sing[2] && !edge_sing[1] && edge_sing[0]) { if(point_sing[p[2]-1] <= edge_sing[0] ) { if(point_sing[p[1]-1]<= edge_sing[2]) type = HP_TRIG_SINGEDGES; else type = HP_TRIG_SINGEDGES2; } else { if(point_sing[p[1]-1]<= edge_sing[2]) type = HP_TRIG_SINGEDGES3; else type = HP_TRIG_SINGEDGES23; } } else if (edge_sing[2] && edge_sing[1] && edge_sing[0]) type = HP_TRIG_3SINGEDGES; // cout << " run for " << j << " gives type " << type << endl; //*testout << " run for " << j << " gives type " << type << endl; if(type!=HP_NONE) break; } *testout << "type = " << type << endl; for(int k=0;k<3;k++) el[k] = pnums[k]; /*if(type != HP_NONE) { cout << " TRIG with pnums " << pnums[0] << "\t" << pnums[1] << "\t" << pnums[2] << endl; cout << " type " << type << endl; } */ return(type); }
HPREF_ELEMENT_TYPE ClassifyQuad(HPRefElement & el, INDEX_2_HASHTABLE<int> & edges, INDEX_2_HASHTABLE<int> & edgepoint_dom, BitArray & cornerpoint, BitArray & edgepoint, INDEX_3_HASHTABLE<int> & faces, INDEX_2_HASHTABLE<int> & face_edges, INDEX_2_HASHTABLE<int> & surf_edges, Array<int, PointIndex::BASE> & facepoint, int dim, const FaceDescriptor & fd) { HPREF_ELEMENT_TYPE type = HP_NONE; int ep1(-1), ep2(-1), ep3(-1), ep4(-1), cp1(-1), cp2(-1), cp3(-1), cp4(-1); int isedge1, isedge2, isedge3, isedge4; *testout << "edges = " << edges << endl; for (int j = 1; j <= 4; j++) { ep1 = edgepoint.Test (el.PNumMod (j)); ep2 = edgepoint.Test (el.PNumMod (j+1)); ep3 = edgepoint.Test (el.PNumMod (j+2)); ep4 = edgepoint.Test (el.PNumMod (j+3)); if (dim == 2) { ep1 = edgepoint_dom.Used (INDEX_2 (el.GetIndex(), el.PNumMod(j))); ep2 = edgepoint_dom.Used (INDEX_2 (el.GetIndex(), el.PNumMod(j+1))); ep3 = edgepoint_dom.Used (INDEX_2 (el.GetIndex(), el.PNumMod(j+2))); ep4 = edgepoint_dom.Used (INDEX_2 (el.GetIndex(), el.PNumMod(j+3))); } cp1 = cornerpoint.Test (el.PNumMod (j)); cp2 = cornerpoint.Test (el.PNumMod (j+1)); cp3 = cornerpoint.Test (el.PNumMod (j+2)); cp4 = cornerpoint.Test (el.PNumMod (j+3)); ep1 |= cp1; ep2 |= cp2; ep3 |= cp3; ep4 |= cp4; int p[4] = { el.PNumMod (j), el.PNumMod (j+1), el.PNumMod (j+2), el.PNumMod(j+4)}; //int epp[4] = { ep1, ep2, ep3, ep4}; int cpp[4] = { cp1, cp2, cp3, cp4}; for(int k=0;k<0;k++) { INDEX_2 i2a=INDEX_2::Sort(p[k], p[(k+1)%4]); INDEX_2 i2b=INDEX_2::Sort(p[k], p[(k-1)%4]); if(!edges.Used(i2a) && !edges.Used(i2b)) cpp[k] = 1; } cp1= cpp[0]; cp2=cpp[1]; cp3=cpp[2]; cp4=cpp[3]; if(dim ==3) { INDEX_2 i2; i2 = INDEX_2(el.PNumMod (j), el.PNumMod (j+1)); // i2.Sort(); isedge1 = edges.Used (i2); i2.Sort(); if(surf_edges.Used(i2) && surf_edges.Get(i2) != fd.SurfNr()+1 && (face_edges.Get(i2) == -1 || face_edges.Get(i2) == fd.DomainIn() || face_edges.Get(i2) == fd.DomainOut()) ) { isedge1=1; ep1 = 1; ep2=1; } i2 = INDEX_2(el.PNumMod (j+1), el.PNumMod (j+2)); // i2.Sort(); isedge2 = edges.Used (i2); i2.Sort(); if(surf_edges.Used(i2) && surf_edges.Get(i2) != fd.SurfNr()+1 && (face_edges.Get(i2) == -1 || face_edges.Get(i2) == fd.DomainIn() || face_edges.Get(i2) == fd.DomainOut()) ) { isedge2=1; ep2=1; ep3=1; } i2 = INDEX_2(el.PNumMod (j+2), el.PNumMod (j+3)); // i2.Sort(); isedge3 = edges.Used (i2); i2.Sort(); if(surf_edges.Used(i2) && surf_edges.Get(i2) != fd.SurfNr()+1 && (face_edges.Get(i2) == -1 || face_edges.Get(i2) == fd.DomainIn() || face_edges.Get(i2) == fd.DomainOut()) ) { isedge3=1; ep3=1; ep4=1; } i2 = INDEX_2(el.PNumMod (j+3), el.PNumMod (j+4)); // i2.Sort(); isedge4 = edges.Used (i2); i2.Sort(); if(surf_edges.Used(i2) && surf_edges.Get(i2) != fd.SurfNr()+1 && (face_edges.Get(i2) == -1 || face_edges.Get(i2) == fd.DomainIn() || face_edges.Get(i2) == fd.DomainOut()) ) { isedge4=1; ep4=1; ep1=1; } //MH*********************************************************************************************************** if(ep1) if(edgepoint.Test(p[0])) { INDEX_2 i2a=INDEX_2::Sort(p[0], p[1]); INDEX_2 i2b=INDEX_2::Sort(p[0], p[3]); if(!edges.Used(i2a) && !edges.Used(i2b)) cp1 = 1; } if(ep2) if(edgepoint.Test(p[1])) { INDEX_2 i2a=INDEX_2::Sort(p[0], p[1]); INDEX_2 i2b=INDEX_2::Sort(p[1], p[2]); if(!edges.Used(i2a) && !edges.Used(i2b)) cp2 = 1; } if(ep3) if(edgepoint.Test(p[2])) { INDEX_2 i2a=INDEX_2::Sort(p[2], p[1]); INDEX_2 i2b=INDEX_2::Sort(p[3], p[2]); if(!edges.Used(i2a) && !edges.Used(i2b)) cp3 = 1; } if(ep4) if(edgepoint.Test(p[3])) { INDEX_2 i2a=INDEX_2::Sort(p[0], p[3]); INDEX_2 i2b=INDEX_2::Sort(p[3], p[2]); if(!edges.Used(i2a) && !edges.Used(i2b)) cp4 = 1; } //MH***************************************************************************************************************************** } else { INDEX_2 i2; i2 = INDEX_2(el.PNumMod (j), el.PNumMod (j+1)); i2.Sort(); isedge1 = edges.Used (i2); if(isedge1) { ep1 = 1; ep2=1; } i2 = INDEX_2(el.PNumMod (j+1), el.PNumMod (j+2)); i2.Sort(); isedge2 = edges.Used (i2); if(isedge2) { ep2=1; ep3=1; } i2 = INDEX_2(el.PNumMod (j+2), el.PNumMod (j+3)); i2.Sort(); isedge3 = edges.Used (i2); if(isedge3) { ep3=1; ep4=1; } i2 = INDEX_2(el.PNumMod (j+3), el.PNumMod (j+4)); i2.Sort(); isedge4 = edges.Used (i2); if(isedge4) { ep4=1; ep1=1; } } int sumcp = cp1 + cp2 + cp3 + cp4; int sumep = ep1 + ep2 + ep3 + ep4; int sumedge = isedge1 + isedge2 + isedge3 + isedge4; *testout << "isedge = " << isedge1 << isedge2 << isedge3 << isedge4 << endl; *testout << "iscp = " << cp1 << cp2 << cp3 << cp4 << endl; *testout << "isep = " << ep1 << ep2 << ep3 << ep4 << endl; switch (sumedge) { case 0: { switch (sumep) { case 0: type = HP_QUAD; break; case 1: if (ep1) type = HP_QUAD_SINGCORNER; break; case 2: { if (ep1 && ep2) type = HP_QUAD_0E_2VA; if (ep1 && ep3) type = HP_QUAD_0E_2VB; break; } case 3: if (!ep4) type = HP_QUAD_0E_3V; break; case 4: type = HP_QUAD_0E_4V; break; } break; } case 1: { if (isedge1) { switch (cp1+cp2+ep3+ep4) { case 0: type = HP_QUAD_SINGEDGE; break; case 1: { if (cp1) type = HP_QUAD_1E_1VA; if (cp2) type = HP_QUAD_1E_1VB; if (ep3) type = HP_QUAD_1E_1VC; if (ep4) type = HP_QUAD_1E_1VD; break; } case 2: { if (cp1 && cp2) type = HP_QUAD_1E_2VA; if (cp1 && ep3) type = HP_QUAD_1E_2VB; if (cp1 && ep4) type = HP_QUAD_1E_2VC; if (cp2 && ep3) type = HP_QUAD_1E_2VD; if (cp2 && ep4) type = HP_QUAD_1E_2VE; if (ep3 && ep4) type = HP_QUAD_1E_2VF; break; } case 3: { if (cp1 && cp2 && ep3) type = HP_QUAD_1E_3VA; if (cp1 && cp2 && ep4) type = HP_QUAD_1E_3VB; if (cp1 && ep3 && ep4) type = HP_QUAD_1E_3VC; if (cp2 && ep3 && ep4) type = HP_QUAD_1E_3VD; break; } case 4: { type = HP_QUAD_1E_4V; break; } } } break; } case 2: { if (isedge1 && isedge4) { if (!cp2 && !ep3 && !cp4) type = HP_QUAD_2E; if (cp2 && !ep3 && !cp4) type = HP_QUAD_2E_1VA; if (!cp2 && ep3 && !cp4) type = HP_QUAD_2E_1VB; if (!cp2 && !ep3 && cp4) type = HP_QUAD_2E_1VC; if (cp2 && ep3 && !cp4) type = HP_QUAD_2E_2VA; if (cp2 && !ep3 && cp4) type = HP_QUAD_2E_2VB; if (!cp2 && ep3 && cp4) type = HP_QUAD_2E_2VC; if (cp2 && ep3 && cp4) type = HP_QUAD_2E_3V; } if (isedge1 && isedge3) { switch (sumcp) { case 0: type = HP_QUAD_2EB_0V; break; case 1: { if (cp1) type = HP_QUAD_2EB_1VA; if (cp2) type = HP_QUAD_2EB_1VB; break; } case 2: { if (cp1 && cp2) { type = HP_QUAD_2EB_2VA; } if (cp1 && cp3) { type = HP_QUAD_2EB_2VB; } if (cp1 && cp4) { type = HP_QUAD_2EB_2VC; } if (cp2 && cp4) { type = HP_QUAD_2EB_2VD; } break; } case 3: { if (cp1 && cp2 && cp3) { type = HP_QUAD_2EB_3VA; } if (cp1 && cp2 && cp4) { type = HP_QUAD_2EB_3VB; } break; } case 4: { type = HP_QUAD_2EB_4V; break; } } } break; } case 3: { if (isedge1 && isedge2 && isedge4) { if (!cp3 && !cp4) type = HP_QUAD_3E; if (cp3 && !cp4) type = HP_QUAD_3E_3VA; if (!cp3 && cp4) type = HP_QUAD_3E_3VB; if (cp3 && cp4) type = HP_QUAD_3E_4V; } break; } case 4: { type = HP_QUAD_4E; break; } } if (type != HP_NONE) { int pnums[4]; pnums[0] = el.PNumMod (j); pnums[1] = el.PNumMod (j+1); pnums[2] = el.PNumMod (j+2); pnums[3] = el.PNumMod (j+3); for (int k=0;k<4;k++) el[k] = pnums[k]; /* cout << " QUAD with pnums " << pnums[0] << "\t" << pnums[1] << "\t" << pnums[2] << "\t" << pnums[3] << endl << " of type " << type << endl; */ break; } } if (type == HP_NONE) { (*testout) << "undefined element" << endl << "cp = " << cp1 << cp2 << cp3 << cp4 << endl << "ep = " << ep1 << ep2 << ep3 << ep4 << endl << "isedge = " << isedge1 << isedge2 << isedge3 << isedge4 << endl; } *testout << "quad type = " << type << endl; return type; }
void MultiGridRefiner::refine() { assert(m_pMG && "refiner not has to be assigned to a multi-grid!"); if(!m_pMG) return; // the multi-grid MultiGrid& mg = *m_pMG; // make sure that the required options are enabled. if(!mg.option_is_enabled(GRIDOPT_FULL_INTERCONNECTION)) { LOG("WARNING in MultiGridRefiner::refine(): auto-enabling GRIDOPT_FULL_INTERCONNECTION.\n"); mg.enable_options(GRIDOPT_FULL_INTERCONNECTION); } // access position attachments Grid::VertexAttachmentAccessor<APosition> aaPos; if(mg.has_vertex_attachment(aPosition)) aaPos.access(mg, aPosition); // collect objects for refine collect_objects_for_refine(); // notify derivates that refinement begins refinement_step_begins(); // cout << "num marked edges: " << m_selMarks.num<Edge>() << endl; // cout << "num marked faces: " << m_selMarks.num<Face>() << endl; // we want to add new elements in a new layer. bool bHierarchicalInsertionWasEnabled = mg.hierarchical_insertion_enabled(); if(!bHierarchicalInsertionWasEnabled) mg.enable_hierarchical_insertion(true); // some buffers vector<Vertex*> vVrts; vector<Vertex*> vEdgeVrts; vector<Edge*> vEdges; vector<Face*> vFaces; // some repeatedly used objects EdgeDescriptor ed; FaceDescriptor fd; VolumeDescriptor vd; //LOG("creating new vertices\n"); // create new vertices from marked vertices for(VertexIterator iter = m_selMarks.begin<Vertex>(); iter != m_selMarks.end<Vertex>(); ++iter) { Vertex* v = *iter; if(!mg.get_child_vertex(v)) { // create a new vertex in the next layer. Vertex* nVrt = *mg.create_by_cloning(v, v); if(aaPos.valid()) { aaPos[nVrt] = aaPos[v]; // change z-coord to visualise the hierarchy //aaPos[nVrt].z() += 0.01; } } } //LOG("creating new edges\n"); // create new vertices and edges from marked edges for(EdgeIterator iter = m_selMarks.begin<Edge>(); iter != m_selMarks.end<Edge>(); ++iter) { // collect_objects_for_refine removed all edges that already were // refined. No need to check that again. Edge* e = *iter; int rule = get_rule(e); switch(rule) { case RM_COPY: { // clone the edge. ed.set_vertices(mg.get_child_vertex(e->vertex(0)), mg.get_child_vertex(e->vertex(1))); Edge* newEdge = *mg.create_by_cloning(e, ed, e); set_status(newEdge, SM_COPY); }break; default: { // create two new edges by edge-split RegularVertex* nVrt = *mg.create<RegularVertex>(e); Vertex* substituteVrts[2]; substituteVrts[0] = mg.get_child_vertex(e->vertex(0)); substituteVrts[1] = mg.get_child_vertex(e->vertex(1)); if(aaPos.valid()) { VecScaleAdd(aaPos[nVrt], 0.5, aaPos[e->vertex(0)], 0.5, aaPos[e->vertex(1)]); // change z-coord to visualise the hierarchy //aaPos[nVrt].z() += 0.01; } // split the edge e->refine(vEdges, nVrt, substituteVrts); assert((vEdges.size() == 2) && "RegularEdge refine produced wrong number of edges."); mg.register_element(vEdges[0], e); mg.register_element(vEdges[1], e); set_status(vEdges[0], SM_REGULAR); set_status(vEdges[1], SM_REGULAR); }break; } } //LOG("creating new faces\n"); // create new vertices and faces from marked faces for(FaceIterator iter = m_selMarks.begin<Face>(); iter != m_selMarks.end<Face>(); ++iter) { Face* f = *iter; int rule = get_rule(f); switch(rule) { case RM_COPY: { // clone the face. if(fd.num_vertices() != f->num_vertices()) fd.set_num_vertices(f->num_vertices()); for(size_t i = 0; i < fd.num_vertices(); ++i) fd.set_vertex(i, mg.get_child_vertex(f->vertex(i))); Face* nf = *mg.create_by_cloning(f, fd, f); set_status(nf, SM_COPY); }break; default: { // collect child-vertices vVrts.clear(); for(uint j = 0; j < f->num_vertices(); ++j){ vVrts.push_back(mg.get_child_vertex(f->vertex(j))); } // collect the associated edges vEdgeVrts.clear(); //bool bIrregular = false; for(uint j = 0; j < f->num_edges(); ++j){ Vertex* vrt = mg.get_child_vertex(mg.get_edge(f, j)); vEdgeVrts.push_back(vrt); //if(!vrt) // bIrregular = true; } /* if(bIrregular){ assert((get_rule(f) != RM_REFINE) && "Bad refinement-rule set during collect_objects_for_refine!"); //TODO: care about anisotropy set_rule(f, RM_IRREGULAR); } */ Vertex* newVrt; if(f->refine(vFaces, &newVrt, &vEdgeVrts.front(), NULL, &vVrts.front())){ // if a new vertex was generated, we have to register it if(newVrt){ mg.register_element(newVrt, f); if(aaPos.valid()){ aaPos[newVrt] = CalculateCenter(f, aaPos); // change z-coord to visualise the hierarchy //aaPos[newVrt].z() += 0.01; } } int oldRule = get_rule(f); // register the new faces and assign status for(size_t j = 0; j < vFaces.size(); ++j){ mg.register_element(vFaces[j], f); switch(oldRule) { case RM_REFINE: set_status(vFaces[j], SM_REGULAR); break; case RM_IRREGULAR: set_status(vFaces[j], SM_IRREGULAR); break; default: assert((oldRule == RM_REFINE) && "rule not yet handled.");//always fails. break; } } } else{ LOG(" WARNING in Refine: could not refine face.\n"); } } } } // done - clean up if(!bHierarchicalInsertionWasEnabled) mg.enable_hierarchical_insertion(false); m_selMarks.clear(); // notify derivates that refinement ends refinement_step_ends(); }
void InsertCenterVertex(Grid& g, Volume* vol, Vertex* vrt, bool eraseOldVol) { // get the sides of the volume and create new elements FaceDescriptor fd; for(size_t i = 0; i < vol->num_faces(); ++i){ vol->face_desc(i, fd); if(fd.num_vertices() == 3){ // create a tetrahedron g.create<Tetrahedron>(TetrahedronDescriptor(fd.vertex(2), fd.vertex(1), fd.vertex(0), vrt), vol); } else if(fd.num_vertices() == 4){ // create a pyramid g.create<Pyramid>(PyramidDescriptor(fd.vertex(3), fd.vertex(2), fd.vertex(1), fd.vertex(0), vrt), vol); } else{ UG_THROW("Unsupported face type in InsertCenterVertex (#Corners " << fd.num_vertices() << ")"); } } if(eraseOldVol) g.erase(vol); }