Ejemplo n.º 1
0
TopoDS_Shape BlockFix_UnionEdges::Perform(const TopoDS_Shape& Shape,
                                          const Standard_Real Tol)
{
  myContext = new ShapeBuild_ReShape;
  myTolerance = Tol;
  TopoDS_Shape aResult = myContext->Apply(Shape);

  // processing each solid
  TopAbs_ShapeEnum aType = TopAbs_SOLID;
  TopExp_Explorer exps (Shape, aType);
  if (!exps.More()) {
    aType = TopAbs_SHELL;
    exps.Init(Shape, aType);
  }
  for (; exps.More(); exps.Next()) {
    //TopoDS_Solid aSolid = TopoDS::Solid(exps.Current());
    TopoDS_Shape aSolid = exps.Current();

    TopTools_IndexedMapOfShape ChangedFaces;

    // creating map of edge faces
    TopTools_IndexedDataMapOfShapeListOfShape aMapEdgeFaces;
    TopExp::MapShapesAndAncestors(aSolid, TopAbs_EDGE, TopAbs_FACE, aMapEdgeFaces);

    Handle(ShapeBuild_ReShape) aContext = new ShapeBuild_ReShape;
    TopoDS_Shape aRes = aSolid;
    aRes = aContext->Apply(aSolid);

    // processing each face
    TopExp_Explorer exp;
    for (exp.Init(aRes, TopAbs_FACE); exp.More(); exp.Next()) {
      TopoDS_Face aFace =
        TopoDS::Face(aContext->Apply(exp.Current().Oriented(TopAbs_FORWARD)));
      TopTools_IndexedDataMapOfShapeListOfShape aMapFacesEdges;

      for (TopExp_Explorer expe(aFace,TopAbs_EDGE); expe.More(); expe.Next()) {
        TopoDS_Edge edge = TopoDS::Edge(expe.Current());
        if (!aMapEdgeFaces.Contains(edge)) continue;
        const TopTools_ListOfShape& aList = aMapEdgeFaces.FindFromKey(edge);
        TopTools_ListIteratorOfListOfShape anIter(aList);
        for ( ; anIter.More(); anIter.Next()) {
          TopoDS_Face face = TopoDS::Face(anIter.Value());
          TopoDS_Face face1 = TopoDS::Face(aContext->Apply(anIter.Value()));
          if (face1.IsSame(aFace)) continue;
          if (aMapFacesEdges.Contains(face)) {
            aMapFacesEdges.ChangeFromKey(face).Append(edge);
          }
          else {
            TopTools_ListOfShape ListEdges;
            ListEdges.Append(edge);
            aMapFacesEdges.Add(face,ListEdges);
          }
        }
      }

      for (Standard_Integer i=1; i<=aMapFacesEdges.Extent(); i++) {
        const TopTools_ListOfShape& ListEdges = aMapFacesEdges.FindFromIndex(i);
        TopTools_SequenceOfShape SeqEdges;
        TopTools_ListIteratorOfListOfShape anIter(ListEdges);
        for ( ; anIter.More(); anIter.Next()) {
          SeqEdges.Append(anIter.Value());
        }
        if (SeqEdges.Length()==1) continue;
        TopoDS_Edge E;
        if ( MergeEdges(SeqEdges,aFace,Tol,E) ) {
          // now we have only one edge - aChain.Value(1)
          // we have to replace old ListEdges with this new edge
          aContext->Replace(SeqEdges(1),E);
          for (Standard_Integer j=2; j<=SeqEdges.Length(); j++) {
            aContext->Remove(SeqEdges(j));
          }
          TopoDS_Face tmpF = TopoDS::Face(exp.Current());
          if ( !ChangedFaces.Contains(tmpF) )
            ChangedFaces.Add(tmpF);
          tmpF = TopoDS::Face(aMapFacesEdges.FindKey(i));
          if ( !ChangedFaces.Contains(tmpF) )
            ChangedFaces.Add(tmpF);
        }
      }

    } // end processing each face

    // fix changed faces and replace them in the local context
    for (Standard_Integer i=1; i<=ChangedFaces.Extent(); i++) {
      TopoDS_Face aFace = TopoDS::Face(aContext->Apply(ChangedFaces.FindKey(i)));
      Handle(ShapeFix_Face) sff = new ShapeFix_Face(aFace);
      sff->SetContext(myContext);
      sff->SetPrecision(myTolerance);
      sff->SetMinTolerance(myTolerance);
      sff->SetMaxTolerance(Max(1.,myTolerance*1000.));
      sff->Perform();
      aContext->Replace(aFace,sff->Face());
    }

    if (ChangedFaces.Extent() > 0) {
      // fix changed shell and replace it in the local context
      TopoDS_Shape aRes1 = aContext->Apply(aRes);
      TopExp_Explorer expsh;
      for (expsh.Init(aRes1, TopAbs_SHELL); expsh.More(); expsh.Next()) {
        TopoDS_Shell aShell = TopoDS::Shell(expsh.Current());
        Handle(ShapeFix_Shell) sfsh = new ShapeFix_Shell;
        sfsh->FixFaceOrientation(aShell);
        aContext->Replace(aShell,sfsh->Shell());
      }
      TopoDS_Shape aRes2 = aContext->Apply(aRes1);
      // put new solid into global context
      myContext->Replace(aSolid,aRes2);
    }

  } // end processing each solid

  aResult = myContext->Apply(Shape);
  return aResult;
}
Ejemplo n.º 2
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;
}