Beispiel #1
0
int NumAssociatedEdges(Grid& grid, Vertex* v)
{
    Grid::edge_traits::secure_container edges;
    grid.associated_elements(edges, v);
    return (int)edges.size();
}
void SelectShortPolychains(ISelector& sel, number maxLength, bool closedChainsOnly,
						   TAAPos aaPos)
{
	if(!sel.grid())
		return;
	Grid& grid = *sel.grid();

//	we'll collect all contained short polychains in this vector before deciding
//	to select them or not. If a polychain is already longer than maxLength
//	we won't add its edges to the vector
	std::vector<Edge*> curChain;
	std::queue<Edge*> nextEdges;
	Grid::edge_traits::secure_container edges;

	std::vector<Vertex*> junctionPoints;

	grid.begin_marking();

	for(EdgeIterator eiter = grid.begin<Edge>(); eiter != grid.end<Edge>(); ++eiter){
		if(grid.is_marked(*eiter))
			continue;

		bool curChainIsClosed = true;
		number curChainLength = 0;

		curChain.clear();
		junctionPoints.clear();
		
		nextEdges.push(*eiter);
		grid.mark(*eiter);

		while(!nextEdges.empty()){
			Edge* e = nextEdges.front();
			nextEdges.pop();
			
			curChainLength += EdgeLength(e, aaPos);
			if(curChainLength <= maxLength)
				curChain.push_back(e);

			for(size_t ivrt = 0; ivrt < 2; ++ivrt){
				Vertex* vrt = e->vertex(ivrt);
				grid.associated_elements(edges, vrt);
				if(edges.size() < 2)
					curChainIsClosed = false;
				else if(edges.size() == 2){
					for(size_t iedge = 0; iedge < 2; ++iedge){
						Edge* nextEdge = edges[iedge];
						if(!grid.is_marked(nextEdge)){
							grid.mark(nextEdge);
							nextEdges.push(nextEdge);
						}
					}
				}
				else{
					junctionPoints.push_back(vrt);
				}
			}
		}

		if((curChainLength <= maxLength)){
			if(closedChainsOnly && curChainIsClosed && !junctionPoints.empty()){
			//	count the number of associated edges of each junction-point
			//	in curChain. If one is associated with != 2 vertices the chain
			//	is considered as not closed 
				for(size_t ivrt = 0; ivrt < junctionPoints.size(); ++ivrt){
					Vertex* vrt = junctionPoints[ivrt];
					size_t numConnectedEdges = 0;
					for(size_t iedge = 0; iedge < curChain.size(); ++iedge){
						if(EdgeContains(curChain[iedge], vrt))
							++numConnectedEdges;
					}

					if(numConnectedEdges != 2){
						curChainIsClosed = false;
						break;
					}
				}

		 	}

		 	if(curChainIsClosed || !closedChainsOnly)
				sel.select(curChain.begin(), curChain.end());
		}
	}

	grid.end_marking();
}
void AdaptiveRegularRefiner_MultiGrid::
create_closure_elements_2d()
{
//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
//	Those then have to be refined to generate a closure.

	Grid::face_traits::secure_container	assElems;
	Grid::edge_traits::secure_container assEdges;
	Face::ConstVertexArray vrts;
	std::vector<Vertex*> newVrtVrts;
	std::vector<Vertex*> newEdgeVrts;
	std::vector<Face*>	newFaces;
	EdgeDescriptor ed;

//	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, create the closure.
		mg.associated_elements(assElems, *i_edge);

		for(size_t i_elem = 0; i_elem < assElems.size(); ++i_elem){
			Face* elem = assElems[i_elem];
			if(mg.has_children(elem))
				continue;

			newVrtVrts.clear();
			newEdgeVrts.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)){
					newVrtVrts.push_back(*mg.create<RegularVertex>(vrt));
					if(m_refCallback)
						m_refCallback->new_vertex(newVrtVrts.back(), vrt);
				}
				else
					newVrtVrts.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);
					newEdgeVrts.push_back(NULL);
				}
				else
					newEdgeVrts.push_back(mg.get_child_vertex(e));
			}

		//	refine the element
			Vertex* newFaceVrt;
			if(elem->refine(newFaces, &newFaceVrt, &newEdgeVrts.front(),
							NULL, &newVrtVrts.front()))
			{
				if(newFaceVrt){
					mg.register_element(newFaceVrt, elem);
					if(m_refCallback)
						m_refCallback->new_vertex(newFaceVrt, elem);
				}
				for(size_t i = 0; i < newFaces.size(); ++i)
					mg.register_element(newFaces[i], elem);
			}
		}
	}

//	stop selecting new elements
	m_closureElems.enable_autoselection(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);
}
Beispiel #5
0
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;
}