Exemplo n.º 1
0
Vertex* MergeMultipleVertices(Grid& grid, TVrtIterator vrtsBegin,
						  	  	  TVrtIterator vrtsEnd)
{
	if(vrtsBegin == vrtsEnd)
		return NULL;

	Vertex* v = *vrtsBegin;
	++vrtsBegin;
	while(vrtsBegin != vrtsEnd){
		Vertex* v2 = *vrtsBegin;
		++vrtsBegin;
		MergeVertices(grid, v, v2);
	}
	return v;
}
Exemplo n.º 2
0
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);
}
Exemplo n.º 3
0
void OCC_Connect::Intersect(BRep_Builder &BB, TopoDS_Shape &target,
    TopoDS_Shape &shape, TopoDS_Shape &tool)
{
    /***************************************************************************
        We start by splitting edges at all the edge-edge intersections.
        This may generate new vertices and edges.
    ***************************************************************************/
    MergeVertices(shape,tool);
    LocOpe_SplitShape splitter1(shape);
    LocOpe_SplitShape splitter2(tool);
    TopOpeBRep_ShapeIntersector intersector;
    for(intersector.InitIntersection(shape,tool);
        intersector.MoreIntersection();
        intersector.NextIntersection()
    ) {
        if(verbose&Cutting) {
            cout << "++++++++++++++++++++++++++++++++++++++++"
                "++++++++++++++++++++++++++++++++++++++++\n";
            intersector.DumpCurrent(1); cout << " --> ";
            intersector.DumpCurrent(2); cout << '\n';
        }

        TopOpeBRep_EdgesIntersector &ee=intersector.ChangeEdgesIntersector();
        if( intersector.CurrentGeomShape(1).ShapeType()==TopAbs_EDGE &&
            intersector.CurrentGeomShape(2).ShapeType()==TopAbs_EDGE
        ) {
            for(ee.InitPoint(); ee.MorePoint(); ee.NextPoint()) {
                TopOpeBRep_Point2d const &p=ee.Point();
                if(verbose&Cutting)
                    cout << "point loop " << p.Parameter(1) << '\n';
                TopoDS_Vertex vertex;
                if(p.IsVertex(1))
                    vertex=p.Vertex(1);
                else if(p.IsVertex(2))
                    vertex=p.Vertex(2);
                else
                    vertex=BRepBuilderAPI_MakeVertex(p.Value());
                if(!p.IsVertex(1)) {
                    TopoDS_Edge edge=TopoDS::Edge(ee.Edge(1));
                    if(!splitter1.CanSplit(edge)) {
                        if(verbose&Cutting)
                            cout << "Cannot split 1\n";;
                    } else {
                        if(verbose&Cutting)
                            cout << "splitting model 1\n";
                        try { splitter1.Add(vertex,p.Parameter(1),edge); }
                        catch(Standard_ConstructionError c) {
                            if(verbose&Cutting)
                                cout << "Ooops \n";
                        }
                    }
                }
                if(!p.IsVertex(2)) {
                    TopoDS_Edge edge=TopoDS::Edge(ee.Edge(2));
                    if(!splitter2.CanSplit(edge)) {
                        if(verbose&Cutting)
                            cout << "Cannot split 2\n";;
                    } else {
                        if(verbose&Cutting)
                            cout << "splitting model 2\n";
                        try { splitter2.Add(vertex,p.Parameter(2),edge); }
                        catch(Standard_ConstructionError c) {
                            if(verbose&Cutting)
                                cout << "Ooops \n";
                        }
                    }
                }
            }
        }
    }

    /***************************************************************************
        Not all intersections seem to be caught, this is an attempt to catch
        some missing intersections. FIXME, this is almost certainly incomplete.
    ***************************************************************************/
    TopTools_IndexedMapOfShape edges, faces, vertices;
    vertices.Clear();
    TopExp::MapShapes(shape,TopAbs_VERTEX,vertices);
    TopExp::MapShapes(tool,TopAbs_VERTEX,vertices);

    edges.Clear();
    TopExp::MapShapes(shape,TopAbs_EDGE,edges);
    for(int e=1; e<=edges.Extent(); e++) {
        TopoDS_Edge edge=TopoDS::Edge(edges(e));
        TopoDS_Vertex o1, o2;
        TopExp::Vertices(edge,o1,o2);
        int skip1=vertices.FindIndex(o1);
        int skip2=vertices.FindIndex(o2);
        for(int v=1; v<=vertices.Extent(); v++) {
            if(v==skip1 || v==skip2)
                continue;
            TopoDS_Vertex vertex=TopoDS::Vertex(vertices(v));
            BRepExtrema_ExtPC distance(vertex,edge);
            if(!distance.IsDone())
                continue;
            double tolerance=std::max(BRep_Tool::Tolerance(edge),
                                      BRep_Tool::Tolerance(vertex));
            for(int i=1;i<=distance.NbExt();i++) {
#if (OCC_VERSION_MAJOR == 6) && (OCC_VERSION_MINOR < 5)
              double value = distance.Value(i);
#else
              double value = distance.SquareDistance(i);
#endif
              if(value<tolerance) {
                    try {
                        // No idea why this can fail
                        splitter1.Add(vertex,distance.Parameter(i),edge);
                    }
                    catch(Standard_ConstructionError c) {
                        if(verbose&Cutting) {
                            cout << "Adding vertex to edge failed\n";
                            TopoDS_Vertex v1, v2;
                            TopExp::Vertices(edge,v1,v2);
                            if(BRepTools::Compare(v1,vertex))
                                cout << "Merge v1\n";
                            if(BRepTools::Compare(v2,vertex))
                                cout << "Merge v2\n";
                            double d1=BRep_Tool::Pnt(v1).Distance(
                                BRep_Tool::Pnt(vertex));
                            double d2=BRep_Tool::Pnt(v2).Distance(
                                BRep_Tool::Pnt(vertex));
                            cout << "Adding " << i << " to edge " << e
                                << " distance=" << value
                                << " parameter=" << distance.Parameter(i)
                                << " point=" << distance.Point(i)
                                << " dv1=" << d1
                                << " dv2=" << d2
                                << endl;
                            BRepTools::Dump(vertex,cout);
                            BRepTools::Dump(edge,cout);
                        }
                    }
                }
            }
        }
    }

    edges.Clear();
    TopExp::MapShapes(tool,TopAbs_EDGE,edges);
    for(int e=1; e<=edges.Extent(); e++) {
        TopoDS_Edge edge=TopoDS::Edge(edges(e));
        TopoDS_Vertex o1, o2;
        TopExp::Vertices(edge,o1,o2);
        int skip1=vertices.FindIndex(o1);
        int skip2=vertices.FindIndex(o2);
        for(int v=1; v<=vertices.Extent(); v++) {
            if(v==skip1 || v==skip2)
                continue;
            TopoDS_Vertex vertex=TopoDS::Vertex(vertices(v));
            BRepExtrema_ExtPC distance(vertex,edge);
            if(!distance.IsDone())
                continue;
            double tolerance=std::max(BRep_Tool::Tolerance(edge),
                                      BRep_Tool::Tolerance(vertex));
            for(int i=1;i<=distance.NbExt();i++) {
#if (OCC_VERSION_MAJOR == 6) && (OCC_VERSION_MINOR < 5)
              double value = distance.Value(i);
#else
              double value = distance.SquareDistance(i);
#endif
              if(value<tolerance) {
                    try {
                        splitter2.Add(vertex,distance.Parameter(i),edge);
                    }
                    catch(Standard_ConstructionError c) {
                        if(verbose&Cutting) {
                            cout << "Adding vertex to edge failed\n";
                            TopoDS_Vertex v1, v2;
                            TopExp::Vertices(edge,v1,v2);
                            if(BRepTools::Compare(v1,vertex))
                                cout << "Merge v1\n";
                            if(BRepTools::Compare(v2,vertex))
                                cout << "Merge v2\n";
                            double d1=BRep_Tool::Pnt(v1).Distance(
                                BRep_Tool::Pnt(vertex));
                            double d2=BRep_Tool::Pnt(v2).Distance(
                                BRep_Tool::Pnt(vertex));
                            cout << "Adding " << i << " to edge " << e
                                << " distance=" << value
                                << " parameter=" << distance.Parameter(i)
                                << " point=" << distance.Point(i)
                                << " dv1=" << d1
                                << " dv2=" << d2
                                << endl;
                            BRepTools::Dump(vertex,cout);
                            BRepTools::Dump(edge,cout);
                        }
                    }
                }
            }
        }
    }

    /***************************************************************************
        We need the shapes with all the edge-edge intersections to split
        all the faces. All vertices and edges which can be merged, will
        be merged.
    ***************************************************************************/
    TopoDS_Compound intermediate1;
    BB.MakeCompound(intermediate1);
    for(TopTools_ListIteratorOfListOfShape p(splitter1.DescendantShapes(shape));
        p.More();
        p.Next()
    ) {
        BB.Add(intermediate1,p.Value());
    }
    TopoDS_Compound intermediate2;
    BB.MakeCompound(intermediate2);
    for(TopTools_ListIteratorOfListOfShape p(splitter2.DescendantShapes(tool));
        p.More();
        p.Next()
    ) {
        BB.Add(intermediate2,p.Value());
    }
    if(verbose&Cutting) {
        cout << "Before merging vertices and edges\n";
        TopoDS_Compound t;
        BB.MakeCompound(t);
        BB.Add(t,intermediate1);
        BB.Add(t,intermediate2);
        PrintItemCount(t);
    }
    MergeVertices(intermediate1,intermediate2);
    MergeEdges(intermediate1,intermediate2);
    if(verbose&Cutting) {
        cout << "After merging vertices and edges\n";
        TopoDS_Compound t;
        BB.MakeCompound(t);
        BB.Add(t,intermediate1);
        BB.Add(t,intermediate2);
        PrintItemCount(t);
    }

    // Create the result
    TopoDS_Compound result;
    BB.MakeCompound(result);
    BB.Add(result,intermediate1);
    BB.Add(result,intermediate2);

    // Add any missing PCurves
    for(TopExp_Explorer face(result,TopAbs_FACE); face.More(); face.Next()) {
        for(TopExp_Explorer edge(face.Current(),TopAbs_EDGE);
            edge.More();
            edge.Next()
        ) {
            Standard_Real s, e;
            TopoDS_Edge c_edge=TopoDS::Edge(edge.Current());
            TopoDS_Face c_face=TopoDS::Face(face.Current());
            Handle_Geom2d_Curve c=BRep_Tool::CurveOnSurface(c_edge,c_face,s,e);
            if(c.IsNull()) {
                if(verbose&Cutting)
                    cout << "Adding missing PCurve\n";
                ShapeFix_Edge().FixAddPCurve(c_edge,c_face,false,1e-7);
            }
        }
    }

    /***************************************************************************
        We determine which edges/wires are going to cut a face. To do this
        we create a map of FaceCutters which is indexed by the face number
        in the faces map. The FaceCutters generate the correct cutting wires.
    ***************************************************************************/
    int retry;
do {
    if(verbose&Cutting)
        std::cout << "STARTED CUTTING\n";
    retry=0;
    edges.Clear(); TopExp::MapShapes(result,TopAbs_EDGE,edges);
    faces.Clear(); TopExp::MapShapes(result,TopAbs_FACE,faces);
    cutmap_t cutters=SelectCuttingEdges(edges,faces);

    /***************************************************************************
        Apply all face splits stored in the map.
    ***************************************************************************/
    int cut_count=0;
    LocOpe_SplitShape splitter(result);
    for(cutmap_t::iterator f=cutters.begin(); f!=cutters.end(); f++) {
        TopoDS_Face const &face=TopoDS::Face(faces(f->first));
        FaceCutters &cutter=f->second;
        cut_count+=cutter.size();
        if(verbose&Cutting) {
            cout << "Cutting face " << f->first << " *************************\n";
            BRepTools::Dump(face,cout);
        }
        cutter.Build(face,result,verbose);
        for(FaceCutters::iterator p=cutter.begin(); p!=cutter.end(); p++) {
            TopTools_IndexedMapOfShape edges;
            TopExp::MapShapes(*p,TopAbs_EDGE,edges);
            if(edges.Extent()<3 && BRep_Tool::IsClosed(*p)) {
                // FIXME This doesn't work.
                cout << "IGNORED Closed wire with less than three edges\n";
                continue;
            }
            //BRepTools::Dump(*p,cout);
            try {
                splitter.Add(*p,face);
            }
            catch(Standard_ConstructionError c) {
                cout << "splitting the face failed\n";
                retry=1;
            }
        }
    }
    if(verbose&Cutting)
        cout << cut_count << " cuts in " << cutters.size() << " faces\n";

    // Create the final shape with the cutted faces.
    TopoDS_Compound cutted;
    BB.MakeCompound(cutted);
    int count=0;
    for(TopTools_ListIteratorOfListOfShape p(splitter.DescendantShapes(result));
        p.More();
        p.Next()
    ) {
        if(++count==1) {
            if(verbose&Cutting) {
                cout << "--------- " << count << " ---------------------------\n";
                BRepTools::Dump(p.Value(),cout);
            }
            BB.Add(cutted,p.Value());
        }
    }
    MergeFaces(cutted);
    result=cutted;
} while(0 && retry);
    target=result;
}