Пример #1
0
////////////////////////////////////////////////////////////////////////
//	CollectSurfaceNeighborsSorted
bool CollectSurfaceNeighborsSorted(std::vector<Vertex*>& vNeighborsOut,
                                   Grid& grid, Vertex* v)
{
    vNeighborsOut.clear();

//	the algorithm won't work if volumes are connected
    if(grid.num_volumes() > 0) {
        if(grid.associated_volumes_begin(v) != grid.associated_volumes_end(v))
            return false;
    }

//	the algorithm won't work if no faces are connected
    if(grid.associated_faces_begin(v) == grid.associated_faces_end(v))
        return false;

    grid.begin_marking();

    if(grid.option_is_enabled(FACEOPT_AUTOGENERATE_EDGES)
            && grid.option_is_enabled(EDGEOPT_STORE_ASSOCIATED_FACES)) {
        //	collect edges in this vector
        vector<Edge*> edges;
        //	start with an arbitrary edge
        Edge* curEdge = *grid.associated_edges_begin(v);

        while(curEdge) {
            vNeighborsOut.push_back(GetConnectedVertex(curEdge, v));
            grid.mark(curEdge);

            //	get associated faces
            Face* f[2];
            if(GetAssociatedFaces(f, grid, curEdge, 2) != 2)
                return false;

            curEdge = NULL;
            for(int i = 0; i < 2; ++i) {
                if(!grid.is_marked(f[i])) {
                    CollectEdges(edges, grid, f[i]);
                    for(size_t j = 0; j < edges.size(); ++j) {
                        if(!grid.is_marked(edges[j])) {
                            if(EdgeContains(edges[j], v)) {
                                curEdge = edges[j];
                                break;
                            }
                        }
                    }
                }
            }
        }
    }
    else {
        //	we can't use GetAssociatedFaces here, since it uses Grid::mark itself if
        //	EDGEOPT_STORE_ASSOCIATED_FACES is not enabled.
        //	Start with an arbitrary face
        Face* f = *grid.associated_faces_begin(v);
        grid.mark(v);

        while(f) {
            grid.mark(f);

            //	mark one of the edges that is connected to v by marking
            //	the edges endpoints. Make sure that it was not already marked.
            size_t numVrts = f->num_vertices();
            int vind = GetVertexIndex(f, v);
            Vertex* tvrt = f->vertex((vind + 1)%numVrts);
            if(grid.is_marked(tvrt))
                tvrt = f->vertex((vind + numVrts - 1)%numVrts);
            if(grid.is_marked(tvrt))
                throw(UGError("CollectSurfaceNeighborsSorted: unexpected exit."));

            vNeighborsOut.push_back(tvrt);
            grid.mark(tvrt);

            //	iterate through the faces associated with v and find an unmarked one that
            //	contains two marked vertices
            f = NULL;
            Grid::AssociatedFaceIterator iterEnd = grid.associated_faces_end(v);
            for(Grid::AssociatedFaceIterator iter = grid.associated_faces_begin(v);
                    iter != iterEnd; ++iter)
            {
                if(!grid.is_marked(*iter)) {
                    f = *iter;
                    size_t numMarked = 0;
                    for(size_t i = 0; i < f->num_vertices(); ++i) {
                        if(grid.is_marked(f->vertex(i)))
                            ++numMarked;
                    }
                    if(numMarked == 2)
                        break;
                    else
                        f = NULL;
                }
            }
        }
    }

    grid.end_marking();
    return true;
}
Пример #2
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;
}