Example #1
0
///	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);
}
Example #4
0
////////////////////////////////////////////////////////////////////////
//	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;
}