예제 #1
0
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);
}
예제 #2
0
////////////////////////////////////////////////////////////////////////
//	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);
    }
}
예제 #3
0
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();
}