コード例 #1
0
ファイル: vertex_util.cpp プロジェクト: stephanmg/ugcore
Vertex* FindVertexByCoordiante(vector3& coord, VertexIterator iterBegin, VertexIterator iterEnd,
                               Grid::VertexAttachmentAccessor<APosition>& aaPos)
{
    if(iterBegin == iterEnd)
        return NULL;

    Vertex* bestVrt = *iterBegin;
    number bestDistSq = VecDistanceSq(coord, aaPos[bestVrt]);

    VertexIterator iter = iterBegin;
    iter++;
    while(iter != iterEnd)
    {
        number distSq = VecDistanceSq(coord, aaPos[*iter]);
        if(distSq < bestDistSq)
        {
            bestDistSq = distSq;
            bestVrt = *iter;
        }

        ++iter;
    }

    return bestVrt;
}
コード例 #2
0
ファイル: misc_util_impl.hpp プロジェクト: stephanmg/ugcore
TElem* FindClosestByCoordinate(const typename TVertexPositionAttachmentAccessor::ValueType& coord,
						typename geometry_traits<TElem>::iterator iterBegin,
						typename geometry_traits<TElem>::iterator iterEnd,
						TVertexPositionAttachmentAccessor& aaPosVRT)
{
	if(iterBegin == iterEnd)
		return NULL;

	typename geometry_traits<TElem>::iterator iter = iterBegin;
	TElem* bestElem = *iter;
	number bestDistSq = VecDistanceSq(coord, CalculateCenter(bestElem, aaPosVRT));
	iter++;

	while(iter != iterEnd)
	{
		number distSq = VecDistanceSq(coord, CalculateCenter(*iter, aaPosVRT));
		if(distSq < bestDistSq)
		{
			bestDistSq = distSq;
			bestElem = *iter;
		}

		++iter;
	}

	return bestElem;
}
コード例 #3
0
ファイル: misc_util_impl.hpp プロジェクト: stephanmg/ugcore
number ElementDiameterSq(Grid& grid,
                         TAAPos& aaPos,
					     TElem* elem)
{
	PointerConstArray<Vertex*> vVert;
	grid.associated_elements(vVert, elem);

	number max = 0.0;
	for(size_t i = 0; i < vVert.size(); ++i)
		for(size_t j = i+1; j < vVert.size(); ++j)
			max = std::max(max, VecDistanceSq(aaPos[vVert[i]], aaPos[vVert[j]]));

	return max;
}
コード例 #4
0
ファイル: vertex_util_impl.hpp プロジェクト: bsumirak/ugcore
int FindVertexByCoordinate(const MathVector<dim>& coord, size_t ncoords, const MathVector<dim> vCoords[])
{

	if (ncoords <= 0) return -1;

	size_t bestVrt = 0;
	number bestDistSq = VecDistanceSq(coord, vCoords[0]);

	for (size_t i=1; i<ncoords; ++i)
	{
		number distSq = VecDistance(coord, vCoords[i]);
		if(distSq < bestDistSq)
		{
			bestDistSq = distSq;
			bestVrt = i;
		}
	}
	return bestVrt;
}
コード例 #5
0
ファイル: vertex_util_impl.hpp プロジェクト: bsumirak/ugcore
number VertexDistanceSq(Vertex* v0, Vertex* v1, TAAPos& aaPos)
{
	return VecDistanceSq(aaPos[v0], aaPos[v1]);
}
コード例 #6
0
ファイル: vertex_util_impl.hpp プロジェクト: bsumirak/ugcore
void RemoveDoubles(Grid& grid, const TVrtIterator& iterBegin,
					const TVrtIterator& iterEnd,
					TAAPos aaPos,
					number threshold)
{
	typedef Attachment<MathVector<dim> > attachment_type;
	KDTreeStatic<attachment_type, dim, MathVector<dim> > kdTree;
	kdTree.create_from_grid(grid, iterBegin, iterEnd, aaPos, 20, 10, KDSD_LARGEST);

//	we need temporary attachments:
//	a vector<Vertex*> attachment, that stores for each vertex all other vertices
//	closer than threshold, which have higher attachment data index.
	typedef Attachment<std::list<Vertex*> >	AVertexList;
	AVertexList aVertexList;
	grid.attach_to_vertices(aVertexList);
	Grid::VertexAttachmentAccessor<AVertexList> aaVL(grid, aVertexList);

//	we'll store in this attachment whether a vertex will be merged or not.
	AInt aInt;
	grid.attach_to_vertices(aInt);
	Grid::VertexAttachmentAccessor<AInt> aaInt(grid, aInt);
	{
		for(TVrtIterator iter = iterBegin; iter != iterEnd; ++iter)
			aaInt[*iter] = 0;
	}

//	compare squares.
	threshold *= threshold;
	std::vector<Vertex*> neighbours;
//	iterate over all vertices and collect all that have aInt == 0 and are within range.
	for(TVrtIterator iter = iterBegin; iter != iterEnd; ++iter)
	{
		Vertex* v = *iter;
		if(aaInt[v] == 0)
		{//	the vertex will not be removed during merge
		//	find all vertices closer than threshold
			uint numClosest = 3;
			while(numClosest < grid.num_vertices())
			{
				neighbours.clear();
				kdTree.get_neighbourhood(neighbours, aaPos[v], numClosest);

				if(VecDistanceSq(aaPos[neighbours.back()], aaPos[v]) < threshold)
					numClosest *= 2;
				else
					break;
			}

		//	store them in the vertexVec attachment
			if(!neighbours.empty())
			{
				for(std::vector<Vertex*>::iterator nIter = neighbours.begin();
					nIter != neighbours.end(); ++nIter)
				{
					Vertex* nv = *nIter;
					if(aaInt[nv] == 0)
					{
						if(nv != v)
						{
							if(VecDistanceSq(aaPos[v], aaPos[nv]) < threshold)
							{
								aaVL[v].push_back(nv);
								aaInt[nv] = 1;
							}
							else
								break;
						}
					}
				}
			}
		}
	}

//	iterate over all vertices again and merge collected ones
//	This iteration only works, if the iterators stem from a class
//	like Selector or SubsetHandler or Grid etc, which automatically
//	handle removed elements.
//TODO:	This should be improved somehow!
	{
		TVrtIterator iter = iterBegin;
		while(iter != iterEnd)
		{
			Vertex* v = *iter;
			if(!aaVL[v].empty())
			{
				std::list<Vertex*>::iterator nIter = aaVL[v].begin();
				while(nIter != aaVL[v].end())
				{
					Vertex* delVrt = *nIter;
					nIter++;
					MergeVertices(grid, v, delVrt);
				}
			}

			++iter;
		}
	}

	grid.detach_from_vertices(aVertexList);
	grid.detach_from_vertices(aInt);
}
コード例 #7
0
ファイル: tetrahedron_rules.cpp プロジェクト: UG4/ugcore
int Refine(int* newIndsOut, int* newEdgeVrts, bool& newCenterOut,
		   vector3* corners, bool*)
{
	newCenterOut = false;
//	If a refinement rule is not implemented, fillCount will stay at 0.
//	Before returning, we'll check, whether fillCount is at 0 and will
//	perform refinement with an additional vertex in this case.

//	corner status is used to mark vertices, which are connected to refined edges
//	the value tells, how many associated edges are refined.
	int cornerStatus[4] = {0, 0, 0, 0};

//	here we'll store the index of each edge, which will be refined.
//	Size of the valid sub-array is numNewVrts, which is calculated below.
	int refEdgeInds[NUM_EDGES];

//	count the number of new vertices and fill newVrtEdgeInds
	int numNewVrts = 0;
	for(int i = 0; i < NUM_EDGES; ++i){
		if(newEdgeVrts[i]){
			refEdgeInds[numNewVrts] = i;
			++numNewVrts;

		//	adjust corner status of associated vertices
			const int* evi = EDGE_VRT_INDS[i];
			++cornerStatus[evi[0]];
			++cornerStatus[evi[1]];
		}
	}

//	the fillCount tells how much data has already been written to newIndsOut.
	int fillCount = 0;

//	depending on the number of new vertices, we will now apply different
//	refinement rules. Further distinction may have to be done.
	switch(numNewVrts){
		case 0:
		{
		//	simply put the default tetrahedron back to newIndsOut
			newIndsOut[fillCount++] = GOID_TETRAHEDRON;
			newIndsOut[fillCount++] = 0;
			newIndsOut[fillCount++] = 1;
			newIndsOut[fillCount++] = 2;
			newIndsOut[fillCount++] = 3;
		}break;

		case 1:
		{
			int refEdgeInd = refEdgeInds[0];
		//	the two faces which are not connected to the refined edge
		//	serve as bottom for the new tetrahedrons.
			for(int i_face = 0; i_face < NUM_FACES; ++i_face){
				if(!FACE_CONTAINS_EDGE[i_face][refEdgeInd]){
					const int* fvi = FACE_VRT_INDS[i_face];

					newIndsOut[fillCount++] = GOID_TETRAHEDRON;
					newIndsOut[fillCount++] = fvi[0];
					newIndsOut[fillCount++] = fvi[1];
					newIndsOut[fillCount++] = fvi[2];
					newIndsOut[fillCount++] = NUM_VERTICES + refEdgeInd;
				}
			}
		}break;

		case 2:
		{
		//	two types exist: The two refined edges share a vertex or not.
			if(OPPOSED_EDGE[refEdgeInds[0]] == refEdgeInds[1]){
			//	they do not share an edge
			//	we create a local order from refEdgeInds[0], which
			//	always has to be an edge in the base-triangle and
			//	refEdgeInds[1], which always connects a base-corner with
			//	the top.
				const int v0 = EDGE_VRT_INDS[refEdgeInds[0]][0];
				const int v1 = EDGE_VRT_INDS[refEdgeInds[0]][1];
				const int v2 = EDGE_VRT_INDS[refEdgeInds[1]][0];
				const int v3 = EDGE_VRT_INDS[refEdgeInds[1]][1];
				const int n0 = refEdgeInds[0] + NUM_VERTICES;
				const int n1 = refEdgeInds[1] + NUM_VERTICES;

			//	from this local order we can now construct the 4 new tetrahedrons.
				int& fi = fillCount;
				int* inds = newIndsOut;
				inds[fi++] = GOID_TETRAHEDRON;
				inds[fi++] = v0;	inds[fi++] = n0;
				inds[fi++] = v2; 	inds[fi++] = n1;

				inds[fi++] = GOID_TETRAHEDRON;
				inds[fi++] = v0;	inds[fi++] = n0;
				inds[fi++] = n1; 	inds[fi++] = v3;

				inds[fi++] = GOID_TETRAHEDRON;
				inds[fi++] = n0;	inds[fi++] = v1;
				inds[fi++] = v2; 	inds[fi++] = n1;

				inds[fi++] = GOID_TETRAHEDRON;
				inds[fi++] = n0;	inds[fi++] = v1;
				inds[fi++] = n1; 	inds[fi++] = v3;
			}
			else{
			//	they share an edge
			//	We have to create a pyramid and a tetrahedron.
			//	get the triangle, which contains both refEdges
				int refTriInd = FACE_FROM_EDGES[refEdgeInds[0]][refEdgeInds[1]];
				const int* f = FACE_VRT_INDS[refTriInd];

			//	find the edge (v0, v1) in refTri, which won't be refined
				int v0 = -1; int v1 = -1; int v2 = -1;
				for(int i = 0; i < 3; ++i){
					v0 = f[i];
					v1 = f[(i+1)%3];
					v2 = f[(i+2)%3];
					if(cornerStatus[v0] == 1 && cornerStatus[v1] == 1)
						break;
				}

			//	make sure that v2 is connected to two refined edges
				assert(cornerStatus[v2] == 2);

			//	get the new vertex on edge v1v2 and on v2v0
				int v1v2 = EDGE_FROM_VRTS[v1][v2] + NUM_VERTICES;
				int v2v0 = EDGE_FROM_VRTS[v2][v0] + NUM_VERTICES;

			//	get the top (vertex with cornerState 0)
				int vtop = -1;
				for(int i = 0; i < NUM_VERTICES; ++i){
					if(cornerStatus[i] == 0){
						vtop = i;
						break;
					}
				}

			//	now lets build the pyramid
				int& fi = fillCount;
				int* inds = newIndsOut;
				inds[fi++] = GOID_PYRAMID;
				inds[fi++] = v0;	inds[fi++] = v1;
				inds[fi++] = v1v2; 	inds[fi++] = v2v0;
				inds[fi++] = vtop;

			//	and now the terahedron
				inds[fi++] = GOID_TETRAHEDRON;
				inds[fi++] = v2;	inds[fi++] = vtop;
				inds[fi++] = v2v0;	inds[fi++] = v1v2;
			}
		}break;

		case 3:
		{
		//	different possibilities exist. First we'll treat the one,
		//	where all new vertices lie on the edges of one triangle.
		//	Note that refTriInd could be -1 after the call.
			int refTriInd = FACE_FROM_EDGES[refEdgeInds[0]][refEdgeInds[1]];
			if(refTriInd == FACE_FROM_EDGES[refEdgeInds[1]][refEdgeInds[2]])
			{
			//	all three lie in one plane (refTriInd has to be != -1 to get here)
			//	get the top (vertex with cornerState 0)
				int vtop = -1;
				for(int i = 0; i < NUM_VERTICES; ++i){
					if(cornerStatus[i] == 0){
						vtop = i;
						break;
					}
				}

				const int* f = FACE_VRT_INDS[refTriInd];

			//	create four new tetrahedrons
				const int v0 = f[0]; const int v1 = f[1]; const int v2 = f[2];
				const int v0v1 = EDGE_FROM_VRTS[v0][v1] + NUM_VERTICES;
				const int v1v2 = EDGE_FROM_VRTS[v1][v2] + NUM_VERTICES;
				const int v2v0 = EDGE_FROM_VRTS[v2][v0] + NUM_VERTICES;

				int& fi = fillCount;
				int* inds = newIndsOut;
				inds[fi++] = GOID_TETRAHEDRON;
				inds[fi++] = v0;	inds[fi++] = vtop;
				inds[fi++] = v0v1;	inds[fi++] = v2v0;
				inds[fi++] = GOID_TETRAHEDRON;
				inds[fi++] = v1;	inds[fi++] = vtop;
				inds[fi++] = v1v2;	inds[fi++] = v0v1;
				inds[fi++] = GOID_TETRAHEDRON;
				inds[fi++] = v2;	inds[fi++] = vtop;
				inds[fi++] = v2v0;	inds[fi++] = v1v2;
				inds[fi++] = GOID_TETRAHEDRON;
				inds[fi++] = v0v1;	inds[fi++] = vtop;
				inds[fi++] = v1v2;	inds[fi++] = v2v0;
			}
			else{
			//	we have to further distinguish.
			//	gather the corners with corner-state 3 and corner state 1
				int corner3 = -1;
				int freeCorner[NUM_VERTICES];
				int freeCount = 0;
				for(int i = 0; i < NUM_VERTICES; ++i){
					if(cornerStatus[i] == 3)
						corner3 = i;
					else
						freeCorner[freeCount++] = i;
				}

				if(corner3 != -1){
				//	a corner with corner state 3 exists.
					assert(freeCount == 3);

				// get the face which won't be refined (required for correct orientation)
					int freeTriInd = FACE_FROM_VRTS[freeCorner[0]][freeCorner[1]]
												   [freeCorner[2]];

				//	the free tri is the new base, corner3 the top
					const int* f = FACE_VRT_INDS[freeTriInd];
					int v2v3 = EDGE_FROM_VRTS[f[2]][corner3] + NUM_VERTICES;
					int v1v3 = EDGE_FROM_VRTS[f[1]][corner3] + NUM_VERTICES;
					int v0v3 = EDGE_FROM_VRTS[f[0]][corner3] + NUM_VERTICES;

				//	add a prism and a tetrahedron
					int& fi = fillCount;
					int* inds = newIndsOut;
					inds[fi++] = GOID_PRISM;
					inds[fi++] = f[0]; inds[fi++] = f[1]; inds[fi++] = f[2];
					inds[fi++] = v0v3; inds[fi++] = v1v3; inds[fi++] = v2v3;

					inds[fi++] = GOID_TETRAHEDRON;
					inds[fi++] = v2v3; inds[fi++] = corner3; inds[fi++] = v0v3;
					inds[fi++] = v1v3;
				}
			}
		}break;

		case 4:
		{
		//	multiple settings with 4 refined edges exist.
		//	Either two opposing edges are not marked (case all2 == true)
		//	or the two unmarked edges are contained in 1 triangle

		//	check whether all vertices have corner state 2
			bool all2 = true;
			for(int i = 0; i < NUM_VERTICES; ++i){
				if(cornerStatus[i] !=2){
					all2 = false;
					break;
				}
			}

			if(all2){
			//	we've got a straight cut.
			//	we'll rotate the tetrahedron around the tip so, that edge 2 won't be refined.
				int steps = 0;
				if(!newEdgeVrts[EDGE_FROM_VRTS[0][1]])
					steps = 2;
				else if(!newEdgeVrts[EDGE_FROM_VRTS[1][2]])
					steps = 1;

				int t[NUM_VERTICES] = {0, 1, 2, 3};
				TetRotation(t, 3, steps);

				const int v0v1 = EDGE_FROM_VRTS[t[0]][t[1]] + NUM_VERTICES;
				const int v1v2 = EDGE_FROM_VRTS[t[1]][t[2]] + NUM_VERTICES;
				const int v0v3 = EDGE_FROM_VRTS[t[0]][t[3]] + NUM_VERTICES;
				const int v2v3 = EDGE_FROM_VRTS[t[2]][t[3]] + NUM_VERTICES;

				assert(newEdgeVrts[v0v1 - NUM_VERTICES]);
				assert(newEdgeVrts[v1v2 - NUM_VERTICES]);
				assert(newEdgeVrts[v0v3 - NUM_VERTICES]);
				assert(newEdgeVrts[v2v3 - NUM_VERTICES]);

			//	now build two prisms
				int& fi = fillCount;
				int* inds = newIndsOut;

				inds[fi++] = GOID_PRISM;
				inds[fi++] = t[0];	inds[fi++] = v0v3;	inds[fi++] = v0v1;
				inds[fi++] = t[2];	inds[fi++] = v2v3;	inds[fi++] = v1v2;

				inds[fi++] = GOID_PRISM;
				inds[fi++] = t[1];	inds[fi++] = v1v2;	inds[fi++] = v0v1;
				inds[fi++] = t[3];	inds[fi++] = v2v3;	inds[fi++] = v0v3;
			}
			else{
			//	one corner has state 1, one has state 3 and two have state 2.
			//	Rotate the tet so that 1 is at the top and 4 is at the origin
				int I[NUM_VERTICES] = {0, 1, 2, 3};

				int s1 = -1;
				for(int i = 0; i < 4; ++i){
					if(cornerStatus[i] == 1){
						s1 = i;
						break;
					}
				}

				if(s1 != 3){
					const int fixedPoint = (s1 + 2) % 3;
					TetRotation(I, fixedPoint, 1);
				}

				if(cornerStatus[I[1]] == 3)
					TetRotation(I, 3, 2);
				else if(cornerStatus[I[2]] == 3)
					TetRotation(I, 3, 1);

			//	indices of edge-center vertices
				const int v01 = EDGE_FROM_VRTS[I[0]][I[1]] + NUM_VERTICES;
				const int v02 = EDGE_FROM_VRTS[I[0]][I[2]] + NUM_VERTICES;
				const int v03 = EDGE_FROM_VRTS[I[0]][I[3]] + NUM_VERTICES;
				const int v12 = EDGE_FROM_VRTS[I[1]][I[2]] + NUM_VERTICES;

				int& fi = fillCount;
				int* inds = newIndsOut;

				inds[fi++] = GOID_TETRAHEDRON;
				inds[fi++] = I[0];	inds[fi++] = v01;
				inds[fi++] = v02;	inds[fi++] = v03;

				inds[fi++] = GOID_TETRAHEDRON;
				inds[fi++] = v01;	inds[fi++] = v12;
				inds[fi++] = v02;	inds[fi++] = v03;

				inds[fi++] = GOID_PYRAMID;
				inds[fi++] = I[3];	inds[fi++] = I[1];
				inds[fi++] = v01;	inds[fi++] = v03;
				inds[fi++] = v12;

				inds[fi++] = GOID_PYRAMID;
				inds[fi++] = I[2];	inds[fi++] = I[3];
				inds[fi++] = v03;	inds[fi++] = v02;
				inds[fi++] = v12;
			}
		}break;

		case 5:{
		//	only one edge is not marked for refinement
			int unmarkedEdge = 0;
			for(int i = 0; i < NUM_EDGES; ++i){
				if(!newEdgeVrts[i]){
					unmarkedEdge = i;
					break;
				}
			}

			int uei0 = EDGE_VRT_INDS[unmarkedEdge][0];
			int uei1 = EDGE_VRT_INDS[unmarkedEdge][1];

		//	orientate the tetrahedron so that the unmarked edge connects
		//	vertices 2 and 3
			int I[NUM_VERTICES] = {0, 1, 2, 3};
		//	if the unmarked edge lies in the base triangle, we'll first have to
		//	rotate so that it connects a base-vertex with the top
			if(unmarkedEdge < 3){
				const int fixedPoint = (uei1 + 1) % 3;
				TetRotation(I, fixedPoint, 1);
				int IInv[4];
				InverseTetTransform(IInv, I);

				uei0 = IInv[uei0];
				uei1 = IInv[uei1];
				unmarkedEdge = EDGE_FROM_VRTS[uei0][uei1];
			}

		//	now rotate the tet to its final place
			if(unmarkedEdge == 3)
				TetRotation(I, 3, 2);
			else if(unmarkedEdge == 4)
				TetRotation(I, 3, 1);

		//	We obtained the final permutation I. Now create new elements
		//	indices of edge-center vertices
			const int v01 = EDGE_FROM_VRTS[I[0]][I[1]] + NUM_VERTICES;
			const int v02 = EDGE_FROM_VRTS[I[0]][I[2]] + NUM_VERTICES;
			const int v03 = EDGE_FROM_VRTS[I[0]][I[3]] + NUM_VERTICES;
			const int v12 = EDGE_FROM_VRTS[I[1]][I[2]] + NUM_VERTICES;
			const int v13 = EDGE_FROM_VRTS[I[1]][I[3]] + NUM_VERTICES;

			int& fi = fillCount;
			int* inds = newIndsOut;

			inds[fi++] = GOID_TETRAHEDRON;
			inds[fi++] = I[0];	inds[fi++] = v01;
			inds[fi++] = v02;	inds[fi++] = v03;

			inds[fi++] = GOID_TETRAHEDRON;
			inds[fi++] = I[1];	inds[fi++] = v12;
			inds[fi++] = v01;	inds[fi++] = v13;

			inds[fi++] = GOID_PYRAMID;
			inds[fi++] = v02;	inds[fi++] = v12;
			inds[fi++] = v13;	inds[fi++] = v03;
			inds[fi++] = v01;

			inds[fi++] = GOID_PRISM;
			inds[fi++] = v02;	inds[fi++] = v12;	inds[fi++] = I[2];
			inds[fi++] = v03;	inds[fi++] = v13;	inds[fi++] = I[3];


		}break;

	//	REGULAR REFINEMENT
		case 6:
		{
		//	depending on the user specified global refinement rule, we will now apply different
		//	refinement rules.
			switch(g_refinementRule){
				case STANDARD:
				{
					int& fi = fillCount;
					int* inds = newIndsOut;

					inds[fi++] = GOID_TETRAHEDRON;
					inds[fi++] = 0;					inds[fi++] = NUM_VERTICES + 0;
					inds[fi++] = NUM_VERTICES + 2;	inds[fi++] = NUM_VERTICES + 3;

					inds[fi++] = GOID_TETRAHEDRON;
					inds[fi++] = 1;					inds[fi++] = NUM_VERTICES + 1;
					inds[fi++] = NUM_VERTICES + 0;	inds[fi++] = NUM_VERTICES + 4;

					inds[fi++] = GOID_TETRAHEDRON;
					inds[fi++] = 2;					inds[fi++] = NUM_VERTICES + 2;
					inds[fi++] = NUM_VERTICES + 1;	inds[fi++] = NUM_VERTICES + 5;

					inds[fi++] = GOID_TETRAHEDRON;
					inds[fi++] = NUM_VERTICES + 3;	inds[fi++] = NUM_VERTICES + 4;
					inds[fi++] = NUM_VERTICES + 5;	inds[fi++] = 3;

				//	for the remaining four tetrahedrons, we'll choose the shortest diagonal
					int bestDiag = 2;
					if(corners){
					//	there are three diagonals between the following edge-centers:
					//	0-5, 1-3, 2-4
						vector3 c1, c2;

					//	0-5
						VecAdd(c1, corners[0], corners[1]);
						VecScale(c1, c1, 0.5);
						VecAdd(c2, corners[2], corners[3]);
						VecScale(c2, c2, 0.5);
						number d05 = VecDistanceSq(c1, c2);

					//	1-3
						VecAdd(c1, corners[1], corners[2]);
						VecScale(c1, c1, 0.5);
						VecAdd(c2, corners[0], corners[3]);
						VecScale(c2, c2, 0.5);
						number d13 = VecDistanceSq(c1, c2);

					//	2-4
						VecAdd(c1, corners[0], corners[2]);
						VecScale(c1, c1, 0.5);
						VecAdd(c2, corners[1], corners[3]);
						VecScale(c2, c2, 0.5);
						number d = VecDistanceSq(c1, c2);

						if(d13 < d){
							bestDiag = 1;
							d = d13;
						}
						if(d05 < d){
							bestDiag = 0;
						}
					}

					switch(bestDiag){
					case 0:// diag: 0-5
						inds[fi++] = GOID_TETRAHEDRON;
						inds[fi++] = NUM_VERTICES + 0;	inds[fi++] = NUM_VERTICES + 1;
						inds[fi++] = NUM_VERTICES + 2;	inds[fi++] = NUM_VERTICES + 5;

						inds[fi++] = GOID_TETRAHEDRON;
						inds[fi++] = NUM_VERTICES + 1;	inds[fi++] = NUM_VERTICES + 4;
						inds[fi++] = NUM_VERTICES + 5;	inds[fi++] = NUM_VERTICES + 0;

						inds[fi++] = GOID_TETRAHEDRON;
						inds[fi++] = NUM_VERTICES + 2;	inds[fi++] = NUM_VERTICES + 5;
						inds[fi++] = NUM_VERTICES + 3;	inds[fi++] = NUM_VERTICES + 0;

						inds[fi++] = GOID_TETRAHEDRON;
						inds[fi++] = NUM_VERTICES + 0;	inds[fi++] = NUM_VERTICES + 3;
						inds[fi++] = NUM_VERTICES + 4;	inds[fi++] = NUM_VERTICES + 5;

						break;

					case 1:// diag: 1-3
						inds[fi++] = GOID_TETRAHEDRON;
						inds[fi++] = NUM_VERTICES + 0;	inds[fi++] = NUM_VERTICES + 1;
						inds[fi++] = NUM_VERTICES + 2;	inds[fi++] = NUM_VERTICES + 3;

						inds[fi++] = GOID_TETRAHEDRON;
						inds[fi++] = NUM_VERTICES + 1;	inds[fi++] = NUM_VERTICES + 4;
						inds[fi++] = NUM_VERTICES + 5;	inds[fi++] = NUM_VERTICES + 3;

						inds[fi++] = GOID_TETRAHEDRON;
						inds[fi++] = NUM_VERTICES + 2;	inds[fi++] = NUM_VERTICES + 5;
						inds[fi++] = NUM_VERTICES + 3;	inds[fi++] = NUM_VERTICES + 1;

						inds[fi++] = GOID_TETRAHEDRON;
						inds[fi++] = NUM_VERTICES + 0;	inds[fi++] = NUM_VERTICES + 3;
						inds[fi++] = NUM_VERTICES + 4;	inds[fi++] = NUM_VERTICES + 1;

						break;

					case 2:// diag 2-4
						inds[fi++] = GOID_TETRAHEDRON;
						inds[fi++] = NUM_VERTICES + 0;	inds[fi++] = NUM_VERTICES + 2;
						inds[fi++] = NUM_VERTICES + 3;	inds[fi++] = NUM_VERTICES + 4;

						inds[fi++] = GOID_TETRAHEDRON;
						inds[fi++] = NUM_VERTICES + 1;	inds[fi++] = NUM_VERTICES + 2;
						inds[fi++] = NUM_VERTICES + 0;	inds[fi++] = NUM_VERTICES + 4;

						inds[fi++] = GOID_TETRAHEDRON;
						inds[fi++] = NUM_VERTICES + 2;	inds[fi++] = NUM_VERTICES + 3;
						inds[fi++] = NUM_VERTICES + 4;	inds[fi++] = NUM_VERTICES + 5;

						inds[fi++] = GOID_TETRAHEDRON;
						inds[fi++] = NUM_VERTICES + 4;	inds[fi++] = NUM_VERTICES + 1;
						inds[fi++] = NUM_VERTICES + 2;	inds[fi++] = NUM_VERTICES + 5;

						break;
					}
				}break;
				
				case HYBRID_TET_OCT:
				{
				//	REGULAR REFINEMENT
					int& fi = fillCount;
					int* inds = newIndsOut;

				//	outer tetrahedrons analogously defined to STANDARD case
					inds[fi++] = GOID_TETRAHEDRON;
					inds[fi++] = 0;					inds[fi++] = NUM_VERTICES + 0;
					inds[fi++] = NUM_VERTICES + 2;	inds[fi++] = NUM_VERTICES + 3;

					inds[fi++] = GOID_TETRAHEDRON;
					inds[fi++] = 1;					inds[fi++] = NUM_VERTICES + 1;
					inds[fi++] = NUM_VERTICES + 0;	inds[fi++] = NUM_VERTICES + 4;

					inds[fi++] = GOID_TETRAHEDRON;
					inds[fi++] = 2;					inds[fi++] = NUM_VERTICES + 2;
					inds[fi++] = NUM_VERTICES + 1;	inds[fi++] = NUM_VERTICES + 5;

					inds[fi++] = GOID_TETRAHEDRON;
					inds[fi++] = NUM_VERTICES + 3;	inds[fi++] = NUM_VERTICES + 4;
					inds[fi++] = NUM_VERTICES + 5;	inds[fi++] = 3;

				//	inner octahedron:
				//	For the remaining inner cavity we'll choose the shortest diagonal
				//	and order the octahedral nodes, so that, the implicit
				//	subdivision of the octahedron into tetrahedrons during
				//	discretization happens alongside exactly this shortest diagonal.
					int bestDiag = 2;
					if(corners){
					//	there are three diagonals between the following edge-centers:
					//	0-5, 1-3, 2-4
						vector3 c1, c2;

					//	0-5
						VecAdd(c1, corners[0], corners[1]);
						VecScale(c1, c1, 0.5);
						VecAdd(c2, corners[2], corners[3]);
						VecScale(c2, c2, 0.5);
						number d05 = VecDistanceSq(c1, c2);

					//	1-3
						VecAdd(c1, corners[1], corners[2]);
						VecScale(c1, c1, 0.5);
						VecAdd(c2, corners[0], corners[3]);
						VecScale(c2, c2, 0.5);
						number d13 = VecDistanceSq(c1, c2);

					//	2-4
						VecAdd(c1, corners[0], corners[2]);
						VecScale(c1, c1, 0.5);
						VecAdd(c2, corners[1], corners[3]);
						VecScale(c2, c2, 0.5);
						number d = VecDistanceSq(c1, c2);

						if(d13 < d){
							bestDiag = 1;
							d = d13;
						}
						if(d05 < d){
							bestDiag = 0;
						}
					}

					switch(bestDiag){
						case 0:// diag: 0-5
							inds[fi++] = GOID_OCTAHEDRON;
							inds[fi++] = NUM_VERTICES + 1;		inds[fi++] = NUM_VERTICES + 0;
							inds[fi++] = NUM_VERTICES + 4;		inds[fi++] = NUM_VERTICES + 5;
							inds[fi++] = NUM_VERTICES + 2;		inds[fi++] = NUM_VERTICES + 3;
						break;

						case 1:// diag: 1-3
							inds[fi++] = GOID_OCTAHEDRON;
							inds[fi++] = NUM_VERTICES + 0;		inds[fi++] = NUM_VERTICES + 3;
							inds[fi++] = NUM_VERTICES + 4;		inds[fi++] = NUM_VERTICES + 1;
							inds[fi++] = NUM_VERTICES + 2;		inds[fi++] = NUM_VERTICES + 5;
						break;

						case 2:// diag 2-4
							inds[fi++] = GOID_OCTAHEDRON;
							inds[fi++] = NUM_VERTICES + 1;		inds[fi++] = NUM_VERTICES + 2;
							inds[fi++] = NUM_VERTICES + 0;		inds[fi++] = NUM_VERTICES + 4;
							inds[fi++] = NUM_VERTICES + 5;		inds[fi++] = NUM_VERTICES + 3;
						break;
					}break;

				}break;
			}
		}break;
	}

	if(fillCount == 0){
	//	call recursive refine
		fillCount = shared_rules::RecursiveRefine(newIndsOut, newEdgeVrts,
									FACE_VRT_INDS, FACE_EDGE_INDS, NUM_VERTICES,
									NUM_EDGES, NUM_FACES);

	//	the rule requires a new center vertex
		newCenterOut = true;
	}

	return fillCount;
}
コード例 #8
0
ファイル: grid_adaption.cpp プロジェクト: UG4/ugcore
bool AdaptSurfaceGridToCylinder(Selector& selOut, Grid& grid,
                                Vertex* vrtCenter, const vector3& normal,
                                number radius, number rimSnapThreshold,  AInt& aInt,
                                APosition& aPos)
{
    if(!grid.has_vertex_attachment(aPos)) {
        UG_THROW("Position attachment required!");
    }

    Grid::VertexAttachmentAccessor<APosition> aaPos(grid, aPos);

    if(rimSnapThreshold < 0)
        rimSnapThreshold = 0;

    if(rimSnapThreshold > (radius - SMALL))
        rimSnapThreshold = radius - SMALL;

    const number smallRadius = radius - rimSnapThreshold;
    const number smallRadiusSq = smallRadius * smallRadius;
    const number largeRadius = radius + rimSnapThreshold;
    const number largeRadiusSq = largeRadius * largeRadius;

//	the cylinder geometry
    vector3 axis;
    VecNormalize(axis, normal);
    vector3 center = aaPos[vrtCenter];

//	recursively select all vertices in the cylinder which can be reached from a
//	selected vertex by following an edge. Start with the given one.
//	We'll also select edges which connect inner with outer vertices. Note that
//	some vertices are considered rim-vertices (those with a distance between
//	smallRadius and largeRadius). Those are neither considered inner nor outer.
    Selector& sel = selOut;
    sel.clear();
    sel.select(vrtCenter);

    stack<Vertex*> vrtStack;
    vrtStack.push(vrtCenter);

    Grid::edge_traits::secure_container edges;
    Grid::face_traits::secure_container faces;
    vector<Quadrilateral*> quads;

    while(!vrtStack.empty()) {
        Vertex* curVrt = vrtStack.top();
        vrtStack.pop();

        //	we have to convert associated quadrilaterals to triangles.
        //	Be careful not to alter the array of associated elements while we iterate
        //	over it...
        quads.clear();
        grid.associated_elements(faces, curVrt);
        for(size_t i = 0; i < faces.size(); ++i) {
            if(faces[i]->num_vertices() == 4) {
                Quadrilateral* q = dynamic_cast<Quadrilateral*>(faces[i]);
                if(q)
                    quads.push_back(q);
            }
        }

        for(size_t i = 0; i < quads.size(); ++i) {
            Triangulate(grid, quads[i], &aaPos);
        }

        //	now check whether edges leave the cylinder and mark them accordingly.
        //	Perform projection of vertices to the cylinder rim for vertices which
        //	lie in the threshold area.
        grid.associated_elements(edges, curVrt);

        for(size_t i_edge = 0; i_edge < edges.size(); ++i_edge) {
            Edge* e = edges[i_edge];
            Vertex* vrt = GetConnectedVertex(e, curVrt);

            if(sel.is_selected(vrt))
                continue;

            vector3 p = aaPos[vrt];
            vector3 proj;
            ProjectPointToRay(proj, p, center, axis);
            number distSq = VecDistanceSq(p, proj);

            if(distSq < smallRadiusSq) {
                sel.select(vrt);
                vrtStack.push(vrt);
            }
            else if(distSq < largeRadiusSq) {
                sel.select(vrt);
                //	cut the ray from center through p with the cylinder hull to calculate
                //	the new position of vrt.
                vector3 dir;
                VecSubtract(dir, p, center);
                number t0, t1;
                if(RayCylinderIntersection(t0, t1, center, dir, center, axis, radius))
                    VecScaleAdd(aaPos[vrt], 1., center, t1, dir);
            }
            else {
                //	the edge will be refined later on
                sel.select(e);
            }
        }
    }

//	refine selected edges and use a special refinement callback, which places
//	new vertices on edges which intersect a cylinder on the cylinders hull.
    CylinderCutProjector refCallback(MakeGeometry3d(grid, aPos),
                                     center, axis, radius);
    Refine(grid, sel, aInt, &refCallback);

//	finally select all triangles which lie in the cylinder
    sel.clear();
    vrtStack.push(vrtCenter);
    sel.select(vrtCenter);

    while(!vrtStack.empty()) {
        Vertex* curVrt = vrtStack.top();
        vrtStack.pop();
        grid.associated_elements(faces, curVrt);

        for(size_t i_face = 0; i_face < faces.size(); ++i_face) {
            Face* f = faces[i_face];
            if(sel.is_selected(f))
                continue;

            sel.select(f);

            for(size_t i = 0; i < f->num_vertices(); ++i) {
                Vertex* vrt = f->vertex(i);
                if(!sel.is_selected(vrt)) {
                    number dist = DistancePointToRay(aaPos[vrt], center, axis);
                    if(dist < (radius - SMALL)) {
                        sel.select(vrt);
                        vrtStack.push(vrt);
                    }
                }
            }
        }
    }

    sel.clear<Vertex>();

    return true;
}