/// Creates an Icosahedron void GenerateIcosahedron(Grid& grid, const vector3& center, number radius, AVector3& aPos) { const number A = 0.85065080835204; const number B = 0.525731112119134; // create the vertices const number coords[12][3] = { {-B, A, 0}, {0, B, A}, {B, A, 0}, {0, B, -A}, {-A, 0, B}, {A, 0, B}, {A, 0, -B}, {-A, 0, -B}, {-B, -A, 0}, {0, -B, A}, {B, -A, 0}, {0, -B, -A}}; const int inds[20][3] = { {0, 1, 2}, {0, 2, 3}, {3, 7, 0}, {7, 4, 0}, {0, 4, 1}, {1, 5, 2}, {5, 6, 2}, {2, 6, 3}, {4, 9, 1}, {1, 9, 5}, {7, 3, 11}, {3, 6, 11}, {11, 8, 7}, {7, 8, 4}, {8, 9, 4}, {9, 10, 5}, {10, 6, 5}, {10, 11, 6}, {8, 10, 9}, {8, 11, 10}}; Vertex* vrts[12]; if(!grid.has_vertex_attachment(aPos)) grid.attach_to_vertices(aPos); Grid::AttachmentAccessor<Vertex, AVector3> aaPos(grid, aPos); for(size_t i = 0; i < 12; ++i){ vrts[i] = *grid.create<RegularVertex>(); aaPos[vrts[i]] = vector3(coords[i][0], coords[i][1], coords[i][2]); VecScaleAdd(aaPos[vrts[i]], 1.0, center, radius, aaPos[vrts[i]]); } // construct triangles for(size_t i = 0; i < 20; ++i){ grid.create<Triangle>(TriangleDescriptor(vrts[inds[i][0]], vrts[inds[i][1]], vrts[inds[i][2]])); } }
bool TriangleFill_SweepLine(Grid& grid, TIterator edgesBegin, TIterator edgesEnd, APosition& aPosVRT, AInt& aIntVRT, SubsetHandler* pSH, int newSubsetIndex) { if(!grid.has_vertex_attachment(aPosVRT)){ UG_LOG("position attachment missing in TriangleFill_SweepLine"); return false; } if(!grid.has_vertex_attachment(aIntVRT)){ UG_LOG("int attachment missing in TriangleFill_SweepLine"); return false; } Grid::VertexAttachmentAccessor<APosition> aaPos(grid, aPosVRT); Grid::VertexAttachmentAccessor<AInt> aaInt(grid, aIntVRT); // set up the vertex and edge arrays and build some additional // information that is required when it comes to building the triangles. std::vector<Vertex*> vrtPtrs; std::vector<vector3> vrts; std::vector<int> edges; grid.begin_marking(); for(TIterator iter = edgesBegin; iter != edgesEnd; ++iter) { Edge* e = *iter; for(size_t i = 0; i < 2; ++i){ Vertex* vrt = e->vertex(i); if(!grid.is_marked(vrt)){ aaInt[vrt] = (int)vrts.size(); vrts.push_back(aaPos[vrt]); //vrts.push_back(vector2(aaPos[vrt].x(), aaPos[vrt].y())); vrtPtrs.push_back(vrt); grid.mark(vrt); } edges.push_back(aaInt[vrt]); } } grid.end_marking(); // now call the original implementation size_t numInitialEdges = edges.size(); std::vector<int> faces; if(TriangleFill_SweepLine(faces, vrts, edges)){ // now create the triangles for(size_t i = 0; i < faces.size(); i+=3){ Triangle* tri = *grid.create<Triangle>(TriangleDescriptor(vrtPtrs[faces[i]], vrtPtrs[faces[i + 1]], vrtPtrs[faces[i + 2]])); if(pSH){ pSH->assign_subset(tri, newSubsetIndex); } } return true; } else{ //DEBUG ONLY // create edges for(size_t i = numInitialEdges; i < edges.size(); i+=2){ Edge* e = *grid.create<RegularEdge>(EdgeDescriptor(vrtPtrs[edges[i]], vrtPtrs[edges[i+1]])); if(pSH){ pSH->assign_subset(e, newSubsetIndex); } } } return false; }
void AdaptiveRegularRefiner_MultiGrid:: create_closure_elements_3d() { //todo: This method currently only works for one type of elements. No manifolds // are currently supported. // for each surface element (faces in 2d, volumes in 3d) adjacent to a constraining // element, we generate closure elements in the level above. if(!multi_grid()){ UG_THROW("AdaptiveRegularRefiner_MultiGrid has to be associated with a grid!"); } // remove all closure elements. This is currently required, since the selector // m_closureElems is currently also used to store non-closer elements, which are // to be refined. remove_closure_elements(); MultiGrid& mg = *multi_grid(); // iterate over all constraining edges and collect associated surface faces / volumes. // Those then have to be refined to generate a closure. Grid::volume_traits::secure_container assElems; Grid::edge_traits::secure_container assEdges; Grid::face_traits::secure_container assFaces; Volume::ConstVertexArray vrts; std::vector<Vertex*> newVolVrtVrts; std::vector<Vertex*> newVolEdgeVrts; std::vector<Vertex*> newVolFaceVrts; std::vector<Volume*> newVols; EdgeDescriptor ed; FaceDescriptor fd; // when refining the associated faces, we need some structs, too Grid::edge_traits::secure_container assFaceEdges; std::vector<Vertex*> newFaceVrtVrts; std::vector<Vertex*> newFaceEdgeVrts; std::vector<Face*> newFaces; // we'll select all new elements on the fly m_closureElems.enable_autoselection(true); for(Grid::traits<ConstrainingEdge>::iterator i_edge = mg.begin<ConstrainingEdge>(); i_edge != mg.end<ConstrainingEdge>(); ++i_edge) { // check all associated elements of i_edge, whether one is a surface element. // If so, select it into m_closureElems. This is only temporary, since it // isn't a real closure element. mg.associated_elements(assElems, *i_edge); for(size_t i_elem = 0; i_elem < assElems.size(); ++i_elem){ Volume* elem = assElems[i_elem]; if(mg.has_children(elem)) continue; newVolVrtVrts.clear(); newVolEdgeVrts.clear(); newVolFaceVrts.clear(); // copy associated vertices and edges to the next level vrts = elem->vertices(); size_t numVrts = elem->num_vertices(); for(size_t i_vrt = 0; i_vrt < numVrts; ++i_vrt){ Vertex* vrt = vrts[i_vrt]; if(!mg.has_children(vrt)){ newVolVrtVrts.push_back(*mg.create<RegularVertex>(vrt)); if(m_refCallback) m_refCallback->new_vertex(newVolVrtVrts.back(), vrt); } else newVolVrtVrts.push_back(mg.get_child_vertex(vrt)); } mg.associated_elements_sorted(assEdges, elem); for(size_t i = 0; i < assEdges.size(); ++i){ Edge* e = assEdges[i]; if(!mg.has_children(e)){ ed.set_vertices(mg.get_child_vertex(e->vertex(0)), mg.get_child_vertex(e->vertex(1))); mg.create<RegularEdge>(ed, e); newVolEdgeVrts.push_back(NULL); } else newVolEdgeVrts.push_back(mg.get_child_vertex(e)); } // we have to either refine or copy associated faces mg.associated_elements_sorted(assFaces, elem); for(size_t i_face = 0; i_face < assFaces.size(); ++i_face){ Face* f = assFaces[i_face]; if(mg.has_children(f)){ newVolFaceVrts.push_back(mg.get_child_vertex(f)); continue; } // collect child vertices of associated edges mg.associated_elements_sorted(assFaceEdges, f); newFaceEdgeVrts.clear(); bool faceRefinement = false; for(size_t i = 0; i < assFaceEdges.size(); ++i){ Vertex* child = mg.get_child_vertex(assFaceEdges[i]); newFaceEdgeVrts.push_back(child); faceRefinement |= (child != NULL); } if(faceRefinement){ newFaceVrtVrts.clear(); for(size_t i = 0; i < f->num_vertices(); ++i) newFaceVrtVrts.push_back(mg.get_child_vertex(f->vertex(i))); Vertex* newFaceVrt = NULL; if(f->refine(newFaces, &newFaceVrt, &newFaceEdgeVrts.front(), NULL, &newFaceVrtVrts.front())) { if(newFaceVrt){ mg.register_element(newFaceVrt, f); if(m_refCallback) m_refCallback->new_vertex(newFaceVrt, f); } for(size_t i = 0; i < newFaces.size(); ++i) mg.register_element(newFaces[i], f); } newVolFaceVrts.push_back(newFaceVrt); } else{ Face::ConstVertexArray fvrts = f->vertices(); if(f->num_vertices() == 3) mg.create<Triangle>(TriangleDescriptor( mg.get_child_vertex(fvrts[0]), mg.get_child_vertex(fvrts[1]), mg.get_child_vertex(fvrts[2])), f); else if(f->num_vertices() == 4) mg.create<Quadrilateral>(QuadrilateralDescriptor( mg.get_child_vertex(fvrts[0]), mg.get_child_vertex(fvrts[1]), mg.get_child_vertex(fvrts[2]), mg.get_child_vertex(fvrts[3])), f); newVolFaceVrts.push_back(NULL); } } // refine the element // if we're performing tetrahedral refinement, we have to collect // the corner coordinates, so that the refinement algorithm may choose // the best interior diagonal. vector3 corners[4]; vector3* pCorners = NULL; if((elem->num_vertices() == 4) && m_refCallback){ for(size_t i = 0; i < 4; ++i){ m_refCallback->current_pos(&corners[i].x(), vrts[i], 3); } pCorners = corners; } Vertex* newVolVrt; if(elem->refine(newVols, &newVolVrt, &newVolEdgeVrts.front(), &newVolFaceVrts.front(), NULL, RegularVertex(), &newVolVrtVrts.front(), pCorners)) { if(newVolVrt){ mg.register_element(newVolVrt, elem); if(m_refCallback) m_refCallback->new_vertex(newVolVrt, elem); } for(size_t i = 0; i < newVols.size(); ++i) mg.register_element(newVols[i], elem); } } } // stop selecting new elements m_closureElems.enable_autoselection(false); }
//////////////////////////////////////////////////////////////////////// // ImportGridFromLGM bool ImportGridFromLGM(Grid& grid, const char* filename, AVector3& aPos, ISubsetHandler* pSurfaceHandler) { // we'll read the lgm in two steps: // first we'll try to load a 3d lgm. If that fails we'll try to // load a 2d on. If that fails too, we'll give up. // create lgm object lgm* l = lgm_new(); // read lgm file lgm_info* linfo = lgm_info_new(); // load 3d if(lgm_read(filename, l, linfo)) {/* LOG("WARNING in ImportGridFromLGM: " << linfo->err_msg << endl); lgm_delete(l); lgm_info_delete(linfo); return false;*/ // 3d could not be loaded. Try 2d. //TODO: add full 2d support to lgm_parser. There are problems // with line left and line right (They are not yet parsed). // This leads to an error in the current implementation. lgm_info_delete(linfo); lgm_delete(l); l = lgm_new(); l->dim = 2; linfo = lgm_info_new(); if(lgm_read(filename, l, linfo)){ LOG("WARNING in ImportGridFromLGM: " << linfo->err_msg << endl); lgm_info_delete(linfo); lgm_delete(l); return false; } } lgm_info_delete(linfo); // make sure lgm has dimension of 2 or 3 if(l->dim != 2 && l->dim != 3) { LOG("WARNING in ImportGridFromLGM: " << "LGM is does not have dimension of 2 or 3!" << endl); lgm_delete(l); return false; } // set up vertex attachment if(!grid.has_vertex_attachment(aPos)) grid.attach_to_vertices(aPos); // set up vertex attachment accessor Grid::VertexAttachmentAccessor<AVector3> aaPosition(grid, aPos); // read points and store them in an array for index access vector<RegularVertex*> vVertices; vVertices.reserve(l->num_points); // read points for(int i = 0; i < l->num_points; ++i) { // get point double* point = l->points[i]; // create and store vertex RegularVertex* vert = *grid.create<RegularVertex>(); vVertices.push_back(vert); // set vertex coordinates aaPosition[vert] = vector3( (number)point[0], (number)point[1], (l->dim == 3) ? (number)point[2] : (number)0. ); } // read lines and store them in an array for index access vector<RegularEdge*> vEdges; vEdges.reserve(l->num_lines); // read lines for(int i = 0; i < l->num_lines; ++i) { // get line lgm_line* li = &l->lines[i]; // scan through line nodes for(int j = 1; j < li->num_points; ++j) { // vertex indices int v1 = li->points[j-1]; int v2 = li->points[j]; // create edge RegularEdge* e = *grid.create<RegularEdge>(EdgeDescriptor( vVertices[v1], vVertices[v2] )); // add line to line subset if(pSurfaceHandler) pSurfaceHandler->assign_subset(e, i); // store edge vEdges.push_back(e); } } // read surfaces for(int i = 0; i < l->num_surfaces; ++i) { // get surface lgm_surface* s = &l->surfaces[i]; /* // read points for(int j = 0; j < s->num_points; ++j) { // vertex index int v = s->points[j]; // add vertex to surface subset if(pSurfaceHandler) pSurfaceHandler->assign_subset(vVertices[v], i); } // read lines for(int j = 0; j < s->num_lines; ++j) { // edge index int e = s->lines[j]; // add edge to surface subset if(pSurfaceHandler) pSurfaceHandler->assign_subset(vEdges[e], i); }*/ // read triangles for(int j = 0; j < s->num_triangles; ++j) { // vertex indices int v1 = s->triangles[j][0]; int v2 = s->triangles[j][1]; int v3 = s->triangles[j][2]; // create triangle Triangle* t = *grid.create<Triangle>(TriangleDescriptor( vVertices[v1], vVertices[v2], vVertices[v3] )); // add triangle to surface subset if(pSurfaceHandler) pSurfaceHandler->assign_subset(t, i); } } // done importing! // delete lgm object lgm_delete(l); return true; }