// Created on: 2003-10-21 // Created by: Mikhail KLOKOV // Copyright (c) 2003-2014 OPEN CASCADE SAS // // This file is part of Open CASCADE Technology software library. // // This library is free software; you can redistribute it and/or modify it under // the terms of the GNU Lesser General Public License version 2.1 as published // by the Free Software Foundation, with special exception defined in the file // OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT // distribution for complete text of the license and disclaimer of any warranty. // // Alternatively, this file may be used under the terms of Open CASCADE // commercial license or contractual agreement. #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include static TopoDS_Edge FindEdgeCloseToBisectorPlane(const TopoDS_Vertex& theVertex, TopoDS_Compound& theComp, const gp_Ax1& theAxis); static Standard_Boolean FindMiddleEdges(const TopoDS_Vertex& theVertex1, const TopoDS_Vertex& theVertex2, const gp_Ax1& theAxis, TopoDS_Compound& theComp, TopTools_ListOfShape& theElist); static Standard_Boolean FindCommonVertex(const TopoDS_Edge& theFirstEdge, const TopoDS_Edge& theLastEdge, const TopoDS_Vertex& theFirstVertex, const TopoDS_Vertex& theLastVertex, TopoDS_Vertex& theCommonVertex); static Standard_Boolean FindCommonVertex(const BOPDS_PDS& theDS, const Standard_Integer theEIndex1, const Standard_Integer theEIndex2, const gp_Vec& theCrossDirection, TopoDS_Vertex& theCommonVertex, Standard_Real& theParamOnE1, Standard_Real& theParamOnE2); static Standard_Boolean SplitUEdges(const Handle(TopTools_HArray2OfShape)& theUEdges, const BOPDS_PDS& theDS, const gp_Vec& theCrossDirection, TopTools_DataMapOfShapeListOfShape& theHistMap); static void StoreVedgeInHistMap(const Handle(TopTools_HArray1OfShape)& theVEdges, const Standard_Integer theIndex, const TopoDS_Shape& theNewVedge, TopTools_DataMapOfShapeListOfShape& theHistMap); static void FindFreeVertices(const TopoDS_Shape& theShape, const TopTools_MapOfShape& theVerticesToAvoid, TopTools_ListOfShape& theListOfVertex); static Standard_Boolean CheckAndOrientEdges(const TopTools_ListOfShape& theOrderedList, const gp_Pnt2d& theFirstPoint, const gp_Pnt2d& theLastPoint, const TopoDS_Face& theFace, TopTools_ListOfShape& theOrientedList); static Standard_Boolean FillGap(const TopoDS_Vertex& theFirstVertex, const TopoDS_Vertex& theLastVertex, const gp_Pnt2d& theFirstPoint, const gp_Pnt2d& theLastPoint, const TopoDS_Face& theFace, const TopoDS_Compound& theSectionEdges, TopTools_ListOfShape& theOrderedList); static Standard_Boolean FindNextEdge(const TopoDS_Vertex& theFirstVertex, const TopoDS_Vertex& theLastVertex, const TopTools_IndexedDataMapOfShapeListOfShape& theMapVE, const TopTools_MapOfShape& theMapToAvoid, TopTools_ListOfShape& theOrderedList); static Standard_Boolean FindVertex(const TopoDS_Edge& theEdge, const Standard_Integer theRank, const BOPDS_PDS& theDS, const TopTools_DataMapOfShapeListOfShape& theHistMap, TopoDS_Vertex& theVertex, BOPDS_Pave& thePave); static Standard_Boolean FindNextVertex(const Standard_Integer theEdgeIndex, const BOPDS_Pave& thePrevPave, const BOPDS_PDS& theDS, TopoDS_Vertex& theNextVertex, BOPDS_Pave& thePave); static Standard_Boolean GetPave(const Standard_Integer theEdgeIndex, const Standard_Boolean isFirst, const BOPDS_PDS& theDS, BOPDS_Pave& thePave); static Standard_Boolean FindFromUEdge(const TopoDS_Edge& theUE1Old, const TopoDS_Edge& theUE2Old, const TopoDS_Edge& theUE1New, const TopoDS_Edge& theUE2New, const TopoDS_Face& theFace, const TopoDS_Compound& theSecEdges, const Standard_Integer theRank, const TopoDS_Edge& theBoundEdge, const Standard_Integer theBoundEdgeIndex, const BOPDS_PDS& theDS, const TopTools_DataMapOfShapeListOfShape& theHistMap, TopoDS_Compound& theSecEdgesNew, TopTools_ListOfShape& theListOfWireEdges, BOPDS_Pave& theFoundPave, Standard_Boolean& isOnUEdge); static Standard_Boolean FindFromVEdge(const BOPDS_Pave& thePrevPave, const Standard_Boolean& isOnUEdge, const TopoDS_Edge& theUE1Old, const TopoDS_Edge& theUE2Old, const TopoDS_Face& theFace, const TopoDS_Compound& theSecEdges, const Standard_Integer theRank, const TopoDS_Edge& theBoundEdge, const Standard_Integer theBoundEdgeIndex, const BOPDS_PDS& theDS, const TopTools_DataMapOfShapeListOfShape& theHistMap, TopTools_ListOfShape& theListOfWireEdges, Standard_Boolean& isSectionFound); static void RemoveEdges(const TopoDS_Compound& theSourceComp, const TopTools_ListOfShape& theListToRemove, TopoDS_Compound& theResultComp); static Standard_Boolean FilterSectionEdges(const BOPDS_VectorOfCurve& theBCurves, const TopoDS_Face& theSecPlane, const BOPDS_PDS& theDS, TopoDS_Compound& theResult); static Standard_Boolean GetUEdges(const Standard_Integer theIndex, const Standard_Integer theRank, const Handle(TopTools_HArray2OfShape)& theUEdges, const TopoDS_Edge& theBoundEdge, const TopoDS_Face& theFace, TopoDS_Edge& theFirstUEdge, TopoDS_Edge& theSecondUEdge); static Standard_Real ComputeAveragePlaneAndMaxDeviation(const TopoDS_Shape& aWire, gp_Pln& thePlane, Standard_Boolean& IsSingular); static void UpdateSectionEdge(TopoDS_Edge& theEdge, const TopoDS_Vertex& theConstVertex, TopoDS_Vertex& theVertex, const Standard_Real theParam); //================================================================================================= BRepFill_TrimShellCorner::BRepFill_TrimShellCorner(const Handle(TopTools_HArray2OfShape)& theFaces, const BRepFill_TransitionStyle theTransition, const gp_Ax2& theAxeOfBisPlane, const gp_Vec& theIntPointCrossDir) : myTransition(theTransition), myAxeOfBisPlane(theAxeOfBisPlane), myIntPointCrossDir(theIntPointCrossDir), myDone(Standard_False), myHasSection(Standard_False) { myFaces = new TopTools_HArray2OfShape(theFaces->LowerRow(), theFaces->UpperRow(), theFaces->LowerCol(), theFaces->UpperCol()); myFaces->ChangeArray2() = theFaces->Array2(); } //================================================================================================= void BRepFill_TrimShellCorner::AddBounds(const Handle(TopTools_HArray2OfShape)& theBounds) { myBounds = new TopTools_HArray2OfShape(theBounds->LowerRow(), theBounds->UpperRow(), theBounds->LowerCol(), theBounds->UpperCol()); myBounds->ChangeArray2() = theBounds->Array2(); } //================================================================================================= void BRepFill_TrimShellCorner::AddUEdges(const Handle(TopTools_HArray2OfShape)& theUEdges) { myUEdges = new TopTools_HArray2OfShape(theUEdges->LowerRow(), theUEdges->UpperRow(), theUEdges->LowerCol(), theUEdges->UpperCol()); myUEdges->ChangeArray2() = theUEdges->Array2(); } //================================================================================================= void BRepFill_TrimShellCorner::AddVEdges(const Handle(TopTools_HArray2OfShape)& theVEdges, const Standard_Integer theIndex) { myVEdges = new TopTools_HArray1OfShape(theVEdges->LowerRow(), theVEdges->UpperRow()); for (Standard_Integer i = theVEdges->LowerRow(); i <= theVEdges->UpperRow(); i++) myVEdges->SetValue(i, theVEdges->Value(i, theIndex)); } //================================================================================================= void BRepFill_TrimShellCorner::Perform() { Standard_Integer anIndex1, anIndex2, nF1, nF2, i, j, aNbP, aNbC; Standard_Boolean bhassec; myDone = Standard_False; myHistMap.Clear(); if (myFaces->RowLength() != 2) return; Standard_Integer ii = 0, jj = 0; BRep_Builder aBB; for (jj = myFaces->LowerCol(); jj <= myFaces->UpperCol(); jj++) { TopoDS_Shell aShell; aBB.MakeShell(aShell); for (ii = myFaces->LowerRow(); ii <= myFaces->UpperRow(); ii++) { aBB.Add(aShell, myFaces->Value(ii, jj)); } aShell.Closed(BRep_Tool::IsClosed(aShell)); if (jj == myFaces->LowerCol()) { myShape1 = aShell; } else { myShape2 = aShell; } } Standard_Real aMaxTol = 0.; TopExp_Explorer anExp(myShape1, TopAbs_VERTEX); for (; anExp.More(); anExp.Next()) { aMaxTol = Max(aMaxTol, BRep_Tool::Tolerance(TopoDS::Vertex(anExp.Current()))); } anExp.Init(myShape2, TopAbs_VERTEX); for (; anExp.More(); anExp.Next()) { aMaxTol = Max(aMaxTol, BRep_Tool::Tolerance(TopoDS::Vertex(anExp.Current()))); } Standard_Real aFuzzy = 4. * Precision::Confusion(); BOPAlgo_PaveFiller aPF; TopTools_ListOfShape aLS; aLS.Append(myShape1); aLS.Append(myShape2); aPF.SetArguments(aLS); if (aMaxTol < 1.005 * Precision::Confusion()) { aFuzzy = Max(aPF.FuzzyValue(), aFuzzy); aPF.SetFuzzyValue(aFuzzy); } // aPF.Perform(); if (aPF.HasErrors()) { return; } // const BOPDS_PDS& theDS = aPF.PDS(); // BOPDS_VectorOfInterfFF& aFFs = theDS->InterfFF(); Standard_Integer aNbFFs = aFFs.Length(); if (!SplitUEdges(myUEdges, theDS, myIntPointCrossDir, myHistMap)) { return; } for (ii = myFaces->LowerRow(); ii <= myFaces->UpperRow(); ii++) { TopoDS_Shape aF1 = myFaces->Value(ii, myFaces->LowerCol()); TopoDS_Shape aF2 = myFaces->Value(ii, myFaces->UpperCol()); // anIndex1 = theDS->Index(aF1); anIndex2 = theDS->Index(aF2); if ((anIndex1 == -1) || (anIndex2 == -1)) continue; for (i = 0; i < aNbFFs; ++i) { BOPDS_InterfFF& aFFi = aFFs(i); aFFi.Indices(nF1, nF2); // BOPDS_VectorOfPoint& aVP = aFFi.ChangePoints(); aNbP = aVP.Length(); const BOPDS_VectorOfCurve& aVC = aFFi.Curves(); aNbC = aVC.Length(); if (!aNbP && !aNbC) { if (!theDS->HasInterfSubShapes(nF1, nF2)) { continue; } } // if ((nF1 == anIndex1) && (nF2 == anIndex2)) { bhassec = Standard_False; // for (j = 0; j < aNbC; ++j) { const BOPDS_Curve& aBCurve = aVC(j); const BOPDS_ListOfPaveBlock& aSectEdges = aBCurve.PaveBlocks(); // if (aSectEdges.Extent()) { bhassec = Standard_True; break; } } if (!bhassec) { if (!MakeFacesNonSec(ii, theDS, anIndex1, anIndex2)) { myHistMap.Clear(); return; } } else { if (!MakeFacesSec(ii, theDS, anIndex1, anIndex2, i)) { myHistMap.Clear(); return; } } break; } } } myDone = Standard_True; } //================================================================================================= Standard_Boolean BRepFill_TrimShellCorner::IsDone() const { return myDone; } //================================================================================================= Standard_Boolean BRepFill_TrimShellCorner::HasSection() const { return myHasSection; } //================================================================================================= void BRepFill_TrimShellCorner::Modified(const TopoDS_Shape& theShape, TopTools_ListOfShape& theModified) { theModified.Clear(); if (myHistMap.IsBound(theShape)) { theModified = myHistMap.Find(theShape); } } // ---------------------------------------------------------------------------------------------------- // function: MakeFacesNonSec // purpose: Updates by new faces in the case when old faces do not intersect // ---------------------------------------------------------------------------------------------------- Standard_Boolean BRepFill_TrimShellCorner::MakeFacesNonSec(const Standard_Integer theIndex, const BOPDS_PDS& theDS, const Standard_Integer theFaceIndex1, const Standard_Integer theFaceIndex2) { Standard_Boolean bHasNewEdge = Standard_False; TopoDS_Edge aNewEdge; BRep_Builder aBB; const TopoDS_Shape& aE1 = myBounds->Value(theIndex, 1); const TopoDS_Shape& aE2 = myBounds->Value(theIndex, 2); // search common vertex between bounds. begin TopoDS_Vertex aCommonVertex; Standard_Integer anIndex1 = theDS->Index(aE1); Standard_Integer anIndex2 = theDS->Index(aE2); Standard_Real apar1 = 0., apar2 = 0.; Standard_Boolean bvertexfound = FindCommonVertex(theDS, anIndex1, anIndex2, myIntPointCrossDir, aCommonVertex, apar1, apar2); // search common vertex between bounds. end Handle(BRepTools_ReShape) aSubstitutor = new BRepTools_ReShape(); // search common vertices between uedges. begin TopTools_ListOfShape aCommonVertices; Standard_Integer acommonflag = 0; // 0 - no, 1 - first pair, 2 - second pair, 3 - both Standard_Integer ueit = 0, eindex = 0; for (ueit = 1, eindex = theIndex; ueit <= 2; ueit++, eindex++) { const TopoDS_Shape& aShape1 = myUEdges->Value(eindex, myUEdges->LowerCol()); const TopoDS_Shape& aShape2 = myUEdges->Value(eindex, myUEdges->UpperCol()); TopoDS_Edge aUE1 = TopoDS::Edge(aShape1); TopoDS_Edge aUE2 = TopoDS::Edge(aShape2); if (myHistMap.IsBound(aShape1)) { const TopTools_ListOfShape& lst = myHistMap.Find(aShape1); if (!lst.IsEmpty()) aUE1 = TopoDS::Edge(lst.First()); } if (myHistMap.IsBound(aShape2)) { const TopTools_ListOfShape& lst = myHistMap.Find(aShape2); if (!lst.IsEmpty()) aUE2 = TopoDS::Edge(lst.First()); } if (!aShape1.IsSame(aUE1)) aSubstitutor->Replace(aShape1.Oriented(TopAbs_FORWARD), aUE1.Oriented(TopAbs_FORWARD)); if (!aShape2.IsSame(aUE2)) aSubstitutor->Replace(aShape2.Oriented(TopAbs_FORWARD), aUE2.Oriented(TopAbs_FORWARD)); TopoDS_Vertex V1 = TopExp::LastVertex(aUE1); TopoDS_Vertex V2 = TopExp::FirstVertex(aUE2); if (V1.IsSame(V2)) { acommonflag = (acommonflag == 0) ? ueit : 3; aCommonVertices.Append(V1); } } // search common vertices between uedges. end if (bvertexfound) { if (aCommonVertices.Extent() != 1) return Standard_False; if (acommonflag == 1) aNewEdge = BRepLib_MakeEdge(TopoDS::Vertex(aCommonVertices.First()), aCommonVertex); else aNewEdge = BRepLib_MakeEdge(aCommonVertex, TopoDS::Vertex(aCommonVertices.First())); bHasNewEdge = Standard_True; } if (aCommonVertices.Extent() == 2) { aNewEdge = BRepLib_MakeEdge(TopoDS::Vertex(aCommonVertices.First()), TopoDS::Vertex(aCommonVertices.Last())); bHasNewEdge = Standard_True; } Standard_Integer fit = 0; for (fit = 1; fit <= 2; fit++) { TopoDS_Compound aComp; TopTools_MapOfShape aMapV; aBB.MakeCompound(aComp); for (ueit = 1, eindex = theIndex; ueit <= 2; ueit++, eindex++) { const TopoDS_Shape& aShape = myUEdges->Value(eindex, myUEdges->LowerCol() + fit - 1); TopoDS_Shape aUE = aShape; if (myHistMap.IsBound(aShape)) { const TopTools_ListOfShape& lst = myHistMap.Find(aShape); if (!lst.IsEmpty()) aUE = TopoDS::Edge(lst.First()); } const TopoDS_Shape& aV = (fit == 1) ? TopExp::FirstVertex(TopoDS::Edge(aUE)) : TopExp::LastVertex(TopoDS::Edge(aUE)); aMapV.Add(aV); aBB.Add(aComp, aUE); } if (bHasNewEdge) { aBB.Add(aComp, aNewEdge); StoreVedgeInHistMap(myVEdges, theIndex, aNewEdge, myHistMap); } TopTools_ListOfShape alonevertices; FindFreeVertices(aComp, aMapV, alonevertices); if (!alonevertices.IsEmpty() && (alonevertices.Extent() != 2)) return Standard_False; Standard_Integer aFaceIndex = (fit == 1) ? theFaceIndex1 : theFaceIndex2; TopoDS_Shape aFace = theDS->Shape(aFaceIndex); TopAbs_Orientation aFaceOri = aFace.Orientation(); aFace.Orientation(TopAbs_FORWARD); TopExp_Explorer anExpE(aFace, TopAbs_EDGE); if (bHasNewEdge) { aNewEdge.Orientation(TopAbs_FORWARD); // Refer to BrepFill_Sweep.cxx BuildEdge Construct an edge via an iso gp_Pnt P1, P2; Standard_Real p11, p12, p21, p22; P1 = BRep_Tool::Pnt(TopExp::FirstVertex(TopoDS::Edge(aNewEdge))); P2 = BRep_Tool::Pnt(TopExp::LastVertex(TopoDS::Edge(aNewEdge))); TopoDS_Edge aERef = TopoDS::Edge(fit == 1 ? aE1 : aE2); p11 = P1.Distance(BRep_Tool::Pnt(TopExp::FirstVertex(aERef))); p22 = P2.Distance(BRep_Tool::Pnt(TopExp::LastVertex(aERef))); p12 = P1.Distance(BRep_Tool::Pnt(TopExp::LastVertex(aERef))); p21 = P2.Distance(BRep_Tool::Pnt(TopExp::FirstVertex(aERef))); if (p11 > p12 && p22 > p21) { aNewEdge.Reverse(); } // for nonPlane surface, we should add pCurve Handle(ShapeFix_Edge) sfe = new ShapeFix_Edge(); sfe->FixAddPCurve(aNewEdge, TopoDS::Face(aFace), Standard_False); } TopTools_ListOfShape aOrderedList; if (!alonevertices.IsEmpty()) { Standard_Integer anEIndex = (fit == 1) ? anIndex1 : anIndex2; Standard_Boolean bfound1 = Standard_False; Standard_Boolean bfound2 = Standard_False; Standard_Real aparam1 = 0., aparam2 = 0.; BOPDS_ListOfPave aLP; theDS->Paves(anEIndex, aLP); BOPDS_ListIteratorOfListOfPave aIt; aIt.Initialize(aLP); for (; aIt.More(); aIt.Next()) { const BOPDS_Pave& aPave = aIt.Value(); const TopoDS_Shape& aV = theDS->Shape(aPave.Index()); if (aV.IsSame(alonevertices.First())) { if (!bfound1) { aparam1 = aPave.Parameter(); bfound1 = Standard_True; } } if (aV.IsSame(alonevertices.Last())) { if (!bfound2) { aparam2 = aPave.Parameter(); bfound2 = Standard_True; } } } if (bfound1 && bfound2) { TopoDS_Edge aNewBoundE; if (fit == 1) { aNewBoundE = TopoDS::Edge(aE1.EmptyCopied()); } else { aNewBoundE = TopoDS::Edge(aE2.EmptyCopied()); } TopoDS_Vertex aV1, aV2; if (aparam1 < aparam2) { aV1 = TopoDS::Vertex(alonevertices.First()); aV2 = TopoDS::Vertex(alonevertices.Last()); } else { aV1 = TopoDS::Vertex(alonevertices.Last()); aV2 = TopoDS::Vertex(alonevertices.First()); Standard_Real tmp = aparam1; aparam1 = aparam2; aparam2 = tmp; } aV1.Orientation(TopAbs_FORWARD); aV2.Orientation(TopAbs_REVERSED); aBB.Add(aNewBoundE, aV1); aBB.Add(aNewBoundE, aV2); aBB.Range(aNewBoundE, aparam1, aparam2); aNewBoundE.Orientation(TopAbs_FORWARD); aOrderedList.Append(aNewBoundE); if (bHasNewEdge) { TopExp_Explorer anExpV(aNewEdge, TopAbs_VERTEX); Standard_Boolean bfoundv = Standard_False; for (; !bfoundv && anExpV.More(); anExpV.Next()) { if (aV2.IsSame(anExpV.Current())) bfoundv = Standard_True; } if (bfoundv) aOrderedList.Append(aNewEdge); else aOrderedList.Prepend(aNewEdge); } } else { return Standard_False; } } else { if (bHasNewEdge) { aOrderedList.Append(aNewEdge); } } if (!aOrderedList.IsEmpty()) { TopoDS_Wire aW; aBB.MakeWire(aW); TopTools_ListIteratorOfListOfShape anItE(aOrderedList); for (; anItE.More(); anItE.Next()) { aBB.Add(aW, anItE.Value()); } if (fit == 1) aSubstitutor->Replace(aE1.Oriented(TopAbs_FORWARD), aW); else aSubstitutor->Replace(aE2.Oriented(TopAbs_FORWARD), aW); } aSubstitutor->Apply(aFace); TopoDS_Shape aNewFace = aSubstitutor->Value(aFace); aNewFace.Orientation(aFaceOri); TopTools_ListOfShape atmpList; atmpList.Append(aNewFace); myHistMap.Bind(aFace, atmpList); anExpE.Init(aFace, TopAbs_EDGE); for (; anExpE.More(); anExpE.Next()) { TopoDS_Shape aNewValue = aSubstitutor->Value(anExpE.Current()); if (aNewValue.IsNull() || aNewValue.IsSame(anExpE.Current())) continue; if (myHistMap.IsBound(anExpE.Current())) continue; TopTools_ListOfShape aListOfNewEdge; TopExp_Explorer anExpE2(aNewValue, TopAbs_EDGE); for (; anExpE2.More(); anExpE2.Next()) { aListOfNewEdge.Append(anExpE2.Current()); } myHistMap.Bind(anExpE.Current(), aListOfNewEdge); } } return Standard_True; } // ---------------------------------------------------------------------------------------------------- // function: MakeFacesSec // purpose: Updates by new faces in the case when old faces intersect each other // ---------------------------------------------------------------------------------------------------- Standard_Boolean BRepFill_TrimShellCorner::MakeFacesSec(const Standard_Integer theIndex, const BOPDS_PDS& theDS, const Standard_Integer theFaceIndex1, const Standard_Integer theFaceIndex2, const Standard_Integer theSSInterfIndex) { const BOPDS_VectorOfInterfFF& aFFs = theDS->InterfFF(); const BOPDS_InterfFF& aFFi = aFFs(theSSInterfIndex); const BOPDS_VectorOfCurve& aBCurves = aFFi.Curves(); TopoDS_Compound aSecEdges; TopoDS_Face aSecPlane; if (!FilterSectionEdges(aBCurves, aSecPlane, theDS, aSecEdges)) return Standard_False; // Extract vertices on the intersection of correspondent U-edges const TopoDS_Shape& LeftE1 = myUEdges->Value(theIndex, 1); const TopoDS_Shape& LeftE2 = myUEdges->Value(theIndex, 2); const TopoDS_Shape& RightE1 = myUEdges->Value(theIndex + 1, 1); const TopoDS_Shape& RightE2 = myUEdges->Value(theIndex + 1, 2); Standard_Integer IndexOfLeftE1 = theDS->Index(LeftE1); Standard_Integer IndexOfLeftE2 = theDS->Index(LeftE2); Standard_Integer IndexOfRightE1 = theDS->Index(RightE1); Standard_Integer IndexOfRightE2 = theDS->Index(RightE2); TopoDS_Vertex FirstVertex, LastVertex; Standard_Real ParamOnLeftE1, ParamOnLeftE2, ParamOnRightE1, ParamOnRightE2; FindCommonVertex(theDS, IndexOfLeftE1, IndexOfLeftE2, myIntPointCrossDir, FirstVertex, ParamOnLeftE1, ParamOnLeftE2); FindCommonVertex(theDS, IndexOfRightE1, IndexOfRightE2, myIntPointCrossDir, LastVertex, ParamOnRightE1, ParamOnRightE2); TopoDS_Shape SecWire; gp_Pln SecPlane; Standard_Boolean IsSingular; Standard_Boolean WireFound = ChooseSection(aSecEdges, FirstVertex, LastVertex, SecWire, SecPlane, IsSingular); if (WireFound) { // aSecEdges = SecWire; TopoDS_Compound aComp; BRep_Builder BB; BB.MakeCompound(aComp); TopExp_Explorer explo(SecWire, TopAbs_EDGE); for (; explo.More(); explo.Next()) BB.Add(aComp, explo.Current()); aSecEdges = aComp; StoreVedgeInHistMap(myVEdges, theIndex, SecWire, myHistMap); } TopTools_ListOfShape aCommonVertices; // Standard_Integer acommonflag = 0; // 0 - no, 1 - first pair, 2 - second pair, 3 - both Standard_Integer fit = 0; //, ueit = 0, eindex = 0, i = 0; Handle(BRepTools_ReShape) aSubstitutor = new BRepTools_ReShape(); for (fit = 0; fit < 2; fit++) { Standard_Integer aFaceIndex = (fit == 0) ? theFaceIndex1 : theFaceIndex2; TopoDS_Face aFace = TopoDS::Face(theDS->Shape(aFaceIndex)); TopAbs_Orientation aFaceOri = aFace.Orientation(); TopoDS_Face aFaceF = aFace; aFaceF.Orientation(TopAbs_FORWARD); TopoDS_Edge aBoundEdge = TopoDS::Edge(myBounds->Value(theIndex, myBounds->LowerCol() + fit)); Standard_Integer aBoundEdgeIndex = theDS->Index(aBoundEdge); TopoDS_Edge aUE1; TopoDS_Edge aUE2; if (!GetUEdges(theIndex, fit, myUEdges, aBoundEdge, aFaceF, aUE1, aUE2)) return Standard_False; TopoDS_Edge aUE1old = aUE1; TopoDS_Edge aUE2old = aUE2; if (myHistMap.IsBound(aUE1)) { const TopTools_ListOfShape& lst = myHistMap.Find(aUE1); if (!lst.IsEmpty()) { const TopoDS_Shape& anEdge = lst.First().Oriented(aUE1.Orientation()); if (!aUE1.IsSame(anEdge)) aSubstitutor->Replace(aUE1.Oriented(TopAbs_FORWARD), anEdge.Oriented(TopAbs_FORWARD)); aUE1 = TopoDS::Edge(anEdge); } } if (myHistMap.IsBound(aUE2)) { const TopTools_ListOfShape& lst = myHistMap.Find(aUE2); if (!lst.IsEmpty()) { const TopoDS_Shape& anEdge = lst.First().Oriented(aUE2.Orientation()); if (!aUE2.IsSame(anEdge)) aSubstitutor->Replace(aUE2.Oriented(TopAbs_FORWARD), anEdge.Oriented(TopAbs_FORWARD)); aUE2 = TopoDS::Edge(anEdge); } } TopoDS_Vertex aPrevVertex, aNextVertex; TopoDS_Compound aCompOfSecEdges = aSecEdges; TopTools_ListOfShape aListOfWireEdges; BRep_Builder aBB; BOPDS_Pave aPave1; Standard_Boolean isPave1OnUEdge = Standard_True; if (FindFromUEdge(aUE1old, aUE2old, aUE1, aUE2, aFace, aSecEdges, fit, aBoundEdge, aBoundEdgeIndex, theDS, myHistMap, aCompOfSecEdges, aListOfWireEdges, aPave1, isPave1OnUEdge)) { TopTools_ListOfShape aSecondListOfEdges; Standard_Boolean bisSectionFound = Standard_False; if (!FindFromVEdge(aPave1, isPave1OnUEdge, aUE1old, aUE2old, aFace, aCompOfSecEdges, fit, aBoundEdge, aBoundEdgeIndex, theDS, myHistMap, aSecondListOfEdges, bisSectionFound)) { return Standard_False; } if (!bisSectionFound && aListOfWireEdges.IsEmpty()) { return Standard_False; } aListOfWireEdges.Append(aSecondListOfEdges); } else { return Standard_False; } if (!aListOfWireEdges.IsEmpty()) { TopoDS_Wire aW; aBB.MakeWire(aW); TopTools_ListIteratorOfListOfShape aEIt(aListOfWireEdges); for (; aEIt.More(); aEIt.Next()) { if (!aBoundEdge.IsSame(aEIt.Value())) aBB.Add(aW, aEIt.Value()); } aSubstitutor->Replace(aBoundEdge.Oriented(TopAbs_FORWARD), aW); } aSubstitutor->Apply(aFace); TopoDS_Shape aNewFace = aSubstitutor->Value(aFace); aNewFace.Orientation(aFaceOri); TopTools_ListOfShape atmpList; atmpList.Append(aNewFace); myHistMap.Bind(aFace, atmpList); TopExp_Explorer anExpE(aFace, TopAbs_EDGE); for (; anExpE.More(); anExpE.Next()) { TopoDS_Shape aNewValue = aSubstitutor->Value(anExpE.Current()); if (aNewValue.IsNull() || aNewValue.IsSame(anExpE.Current())) continue; if (myHistMap.IsBound(anExpE.Current())) continue; TopTools_ListOfShape aListOfNewEdge; TopExp_Explorer anExpE2(aNewValue, TopAbs_EDGE); for (; anExpE2.More(); anExpE2.Next()) { aListOfNewEdge.Append(anExpE2.Current()); } myHistMap.Bind(anExpE.Current(), aListOfNewEdge); } } return Standard_True; } //================================================================================================= Standard_Boolean BRepFill_TrimShellCorner::ChooseSection(const TopoDS_Shape& Comp, const TopoDS_Vertex& theFirstVertex, const TopoDS_Vertex& theLastVertex, TopoDS_Shape& resWire, gp_Pln& resPlane, Standard_Boolean& IsSingular) { IsSingular = Standard_False; Standard_Integer ind, i, j; BRep_Builder BB; if (myTransition == BRepFill_Right && !theFirstVertex.IsNull() && !theLastVertex.IsNull()) // the case where section wire goes from // its known first vertex to its known last vertex { TopoDS_Wire NewWire; BB.MakeWire(NewWire); TopoDS_Compound OldComp; BB.MakeCompound(OldComp); TopoDS_Iterator iter(Comp); for (; iter.More(); iter.Next()) BB.Add(OldComp, iter.Value()); TopoDS_Edge FirstEdge = FindEdgeCloseToBisectorPlane(theFirstVertex, OldComp, myAxeOfBisPlane.Axis()); if (FirstEdge.IsNull()) return Standard_False; iter.Initialize(OldComp); if (!iter.More()) { iter.Initialize(Comp); BB.Add(OldComp, iter.Value()); } TopoDS_Edge LastEdge = FindEdgeCloseToBisectorPlane(theLastVertex, OldComp, myAxeOfBisPlane.Axis()); if (LastEdge.IsNull()) return Standard_False; if (FirstEdge.IsNull() || LastEdge.IsNull()) { return Standard_False; } BB.Add(NewWire, FirstEdge); if (!FirstEdge.IsSame(LastEdge)) { TopoDS_Vertex aCommonVertex; Standard_Boolean CommonVertexExists = FindCommonVertex(FirstEdge, LastEdge, theFirstVertex, theLastVertex, aCommonVertex); if (CommonVertexExists) BB.Add(NewWire, LastEdge); else { TopoDS_Vertex Vertex1, Vertex2, V1, V2; TopExp::Vertices(FirstEdge, V1, V2); Vertex1 = (theFirstVertex.IsSame(V1)) ? V2 : V1; TopExp::Vertices(LastEdge, V1, V2); Vertex2 = (theLastVertex.IsSame(V1)) ? V2 : V1; TopTools_ListOfShape MiddleEdges; if (FindMiddleEdges(Vertex1, Vertex2, myAxeOfBisPlane.Axis(), OldComp, MiddleEdges)) { TopTools_ListIteratorOfListOfShape itl(MiddleEdges); for (; itl.More(); itl.Next()) BB.Add(NewWire, itl.Value()); BB.Add(NewWire, LastEdge); } else { // trim and in the points of extrema // these points become new vertex with centre between them BRepExtrema_ExtCC Extrema(FirstEdge, LastEdge); if (Extrema.IsDone() && Extrema.NbExt() > 0) { Standard_Integer imin = 1; for (i = 2; i <= Extrema.NbExt(); i++) if (Extrema.SquareDistance(i) < Extrema.SquareDistance(imin)) imin = i; Standard_Real aMinDist = sqrt(Extrema.SquareDistance(imin)); Standard_Real ParamOnFirstEdge = Extrema.ParameterOnE1(imin); Standard_Real ParamOnLastEdge = Extrema.ParameterOnE2(imin); gp_Pnt PointOnFirstEdge = Extrema.PointOnE1(imin); gp_Pnt PointOnLastEdge = Extrema.PointOnE2(imin); gp_Pnt MidPnt((PointOnFirstEdge.XYZ() + PointOnLastEdge.XYZ()) / 2); aCommonVertex = BRepLib_MakeVertex(MidPnt); BB.UpdateVertex(aCommonVertex, 1.001 * aMinDist / 2); UpdateSectionEdge(FirstEdge, theFirstVertex, aCommonVertex, ParamOnFirstEdge); UpdateSectionEdge(LastEdge, theLastVertex, aCommonVertex, ParamOnLastEdge); BB.Add(NewWire, LastEdge); } } } } resWire = NewWire; resPlane = gp_Pln(myAxeOfBisPlane); return Standard_True; } // General case: try to find continuous section closest to bisector plane TopoDS_Compound OldComp; BRep_Builder B; B.MakeCompound(OldComp); TopoDS_Iterator iter(Comp); for (; iter.More(); iter.Next()) B.Add(OldComp, iter.Value()); Standard_Boolean anError = Standard_False; // TopoDS_Wire NewWire [2]; TopTools_SequenceOfShape Wseq; for (;;) { TopExp_Explorer explo(OldComp, TopAbs_EDGE); if (!explo.More()) break; TopoDS_Edge FirstEdge = TopoDS::Edge(explo.Current()); TopoDS_Wire NewWire = BRepLib_MakeWire(FirstEdge); B.Remove(OldComp, FirstEdge); if (NewWire.Closed()) { Wseq.Append(NewWire); continue; } for (;;) { TopoDS_Vertex Extremity[2]; TopExp::Vertices(NewWire, Extremity[0], Extremity[1]); if (Extremity[0].IsNull() || Extremity[1].IsNull()) { anError = Standard_True; break; } TopTools_IndexedDataMapOfShapeListOfShape VEmap; TopExp::MapShapesAndAncestors(OldComp, TopAbs_VERTEX, TopAbs_EDGE, VEmap); TopTools_ListOfShape Vedges[2]; for (j = 0; j < 2; j++) if (VEmap.Contains(Extremity[j])) Vedges[j] = VEmap.FindFromKey(Extremity[j]); if (Vedges[0].IsEmpty() && Vedges[1].IsEmpty()) // no more edges in OldComp to continue NewWire break; Standard_Boolean Modified = Standard_False; for (j = 0; j < 2; j++) { if (Vedges[j].Extent() == 1) { const TopoDS_Edge& anEdge = TopoDS::Edge(Vedges[j].First()); NewWire = BRepLib_MakeWire(NewWire, anEdge); B.Remove(OldComp, anEdge); Modified = Standard_True; } } if (!Modified) // only multiple connections { ind = (Vedges[0].IsEmpty()) ? 1 : 0; TopTools_SequenceOfShape Edges; TopTools_ListIteratorOfListOfShape itl(Vedges[ind]); for (; itl.More(); itl.Next()) Edges.Append(itl.Value()); Standard_Integer theind = 0; Standard_Real MinDeviation = RealLast(); for (j = 1; j <= Edges.Length(); j++) { TopoDS_Wire aWire = BRepLib_MakeWire(NewWire, TopoDS::Edge(Edges(j))); gp_Pln aPlane; Standard_Boolean issing; Standard_Real Deviation = ComputeAveragePlaneAndMaxDeviation(aWire, aPlane, issing); if (Deviation < MinDeviation) { MinDeviation = Deviation; theind = j; } } NewWire = BRepLib_MakeWire(NewWire, TopoDS::Edge(Edges(theind))); B.Remove(OldComp, Edges(theind)); } if (NewWire.Closed()) break; } Wseq.Append(NewWire); if (anError) break; } Standard_Real MinAngle = RealLast(); TopExp_Explorer Explo(OldComp, TopAbs_EDGE); if (!anError && !Explo.More()) // wires are built successfully and compound is empty { if (Wseq.Length() == 1) // only one wire => it becomes result { resWire = Wseq.First(); ComputeAveragePlaneAndMaxDeviation(resWire, resPlane, IsSingular); return Standard_True; } else // we must choose the wire which average plane is closest to bisector plane { //(check angle between axes) for (i = 1; i <= Wseq.Length(); i++) { TopoDS_Wire aWire = TopoDS::Wire(Wseq(i)); gp_Pln aPln; Standard_Boolean issing; ComputeAveragePlaneAndMaxDeviation(aWire, aPln, issing); if (issing) continue; Standard_Real Angle = aPln.Axis().Angle(myAxeOfBisPlane.Axis()); if (Angle > M_PI / 2) Angle = M_PI - Angle; if (Angle < MinAngle) { MinAngle = Angle; resWire = aWire; resPlane = aPln; } } return Standard_True; } } return Standard_False; } // ------------------------------------------------------------------------------------------ // static function: SplitUEdges // purpose: // ------------------------------------------------------------------------------------------ Standard_Boolean SplitUEdges(const Handle(TopTools_HArray2OfShape)& theUEdges, const BOPDS_PDS& theDS, const gp_Vec& theCrossDirection, TopTools_DataMapOfShapeListOfShape& theHistMap) { const BOPDS_VectorOfInterfVV& aVVs = theDS->InterfVV(); BRep_Builder aBB; Standard_Integer ueit = 0, upRow, lowCol, upCol; TopTools_Array2OfShape aNewVertices(1, 2, 1, 2); // upRow = theUEdges->UpperRow(); lowCol = theUEdges->LowerCol(); upCol = theUEdges->UpperCol(); // for (ueit = theUEdges->LowerRow(); ueit <= upRow; ueit++) { const TopoDS_Shape& aE1 = theUEdges->Value(ueit, lowCol); const TopoDS_Shape& aE2 = theUEdges->Value(ueit, upCol); if (theHistMap.IsBound(aE1) || theHistMap.IsBound(aE2)) continue; Standard_Integer anEIndex1 = theDS->Index(aE1); Standard_Integer anEIndex2 = theDS->Index(aE2); TopoDS_Vertex aCommonVertex; Standard_Real apar1 = 0., apar2 = 0.; Standard_Boolean bvertexfound = FindCommonVertex(theDS, anEIndex1, anEIndex2, theCrossDirection, aCommonVertex, apar1, apar2); // if (!bvertexfound) { TopoDS_Vertex V1 = TopExp::LastVertex(TopoDS::Edge(aE1)); TopoDS_Vertex V2 = TopExp::FirstVertex(TopoDS::Edge(aE2)); Standard_Integer vindex1 = theDS->Index(V1); Standard_Integer vindex2 = theDS->Index(V2); Standard_Integer vvit = 0; Standard_Integer aNbVVs = aVVs.Length(); for (vvit = 0; !bvertexfound && (vvit < aNbVVs); vvit++) { // const BOPTools_VVInterference& aVV = aVVs(vvit); const BOPDS_InterfVV& aVV = aVVs(vvit); if (((vindex1 == aVV.Index1()) && (vindex2 == aVV.Index2())) || ((vindex1 == aVV.Index2()) && (vindex2 == aVV.Index1()))) { if (!aVV.HasIndexNew()) { continue; } aCommonVertex = TopoDS::Vertex(theDS->Shape(aVV.IndexNew())); bvertexfound = Standard_True; apar1 = BRep_Tool::Parameter(V1, TopoDS::Edge(aE1)); apar2 = BRep_Tool::Parameter(V2, TopoDS::Edge(aE2)); } } } if (bvertexfound) { TopoDS_Vertex aV1, aV2; Standard_Real f = 0., l = 0.; // TopoDS_Edge aNewE1 = TopoDS::Edge(aE1.EmptyCopied()); TopExp::Vertices(TopoDS::Edge(aE1), aV1, aV2); aNewE1.Orientation(TopAbs_FORWARD); aV1.Orientation(TopAbs_FORWARD); aBB.Add(aNewE1, aV1); aCommonVertex.Orientation(TopAbs_REVERSED); aBB.Add(aNewE1, aCommonVertex); BRep_Tool::Range(TopoDS::Edge(aE1), f, l); aBB.Range(aNewE1, f, apar1); // TopoDS_Edge aNewE2 = TopoDS::Edge(aE2.EmptyCopied()); TopExp::Vertices(TopoDS::Edge(aE2), aV1, aV2); aNewE2.Orientation(TopAbs_FORWARD); aCommonVertex.Orientation(TopAbs_FORWARD); aBB.Add(aNewE2, aCommonVertex); aBB.Add(aNewE2, aV2); BRep_Tool::Range(TopoDS::Edge(aE2), f, l); aBB.Range(aNewE2, apar2, l); TopTools_ListOfShape lst; lst.Append(aNewE1); theHistMap.Bind(aE1, lst); lst.Clear(); lst.Append(aNewE2); theHistMap.Bind(aE2, lst); } } return Standard_True; } // ------------------------------------------------------------------------------------------ // static function: StoreVedgeInHistMap // purpose: // ------------------------------------------------------------------------------------------ void StoreVedgeInHistMap(const Handle(TopTools_HArray1OfShape)& theVEdges, const Standard_Integer theIndex, const TopoDS_Shape& theNewVshape, TopTools_DataMapOfShapeListOfShape& theHistMap) { // Replace default value in the map (v-iso edge of face) // by intersection of two consecutive faces const TopoDS_Shape& aVEdge = theVEdges->Value(theIndex); theHistMap.Bound(aVEdge, TopTools_ListOfShape())->Append(theNewVshape); } // ------------------------------------------------------------------------------------------ // static function: FindFreeVertices // purpose: // ------------------------------------------------------------------------------------------ void FindFreeVertices(const TopoDS_Shape& theShape, const TopTools_MapOfShape& theVerticesToAvoid, TopTools_ListOfShape& theListOfVertex) { theListOfVertex.Clear(); TopTools_IndexedDataMapOfShapeListOfShape aMap; TopExp::MapShapesAndAncestors(theShape, TopAbs_VERTEX, TopAbs_EDGE, aMap); Standard_Integer i = 0; for (i = 1; i <= aMap.Extent(); i++) { const TopoDS_Shape& aKey = aMap.FindKey(i); if (theVerticesToAvoid.Contains(aKey)) continue; const TopTools_ListOfShape& aList = aMap.FindFromIndex(i); if (aList.Extent() < 2) { theListOfVertex.Append(aKey); } } } // ------------------------------------------------------------------------------------------ // static function: FindCommonVertex // purpose: // ------------------------------------------------------------------------------------------ Standard_Boolean FindCommonVertex(const BOPDS_PDS& theDS, const Standard_Integer theEIndex1, const Standard_Integer theEIndex2, const gp_Vec& theCrossDirection, TopoDS_Vertex& theCommonVertex, Standard_Real& theParamOnE1, Standard_Real& theParamOnE2) { const BOPDS_VectorOfInterfEE& aEEs = theDS->InterfEE(); Standard_Boolean bvertexfound = Standard_False; TopoDS_Vertex aCommonVertex; Standard_Integer eeit = 0; TopoDS_Edge theE1 = TopoDS::Edge(theDS->Shape(theEIndex1)); TopoDS_Edge theE2 = TopoDS::Edge(theDS->Shape(theEIndex2)); BRepAdaptor_Curve aBC1(theE1), aBC2(theE2); Standard_Integer aNbEEs; aNbEEs = aEEs.Length(); for (eeit = 0; eeit < aNbEEs; ++eeit) { const BOPDS_InterfEE& aEE = aEEs(eeit); if ((theEIndex1 == aEE.Index1() && theEIndex2 == aEE.Index2()) || (theEIndex1 == aEE.Index2() && theEIndex2 == aEE.Index1())) { if (!aEE.HasIndexNew()) continue; IntTools_CommonPrt aCP = aEE.CommonPart(); if (aCP.Type() == TopAbs_VERTEX) { theCommonVertex = *(TopoDS_Vertex*)&theDS->Shape(aEE.IndexNew()); if (theEIndex1 == aEE.Index1()) IntTools_Tools::VertexParameters(aCP, theParamOnE1, theParamOnE2); else IntTools_Tools::VertexParameters(aCP, theParamOnE2, theParamOnE1); gp_Pnt aPt; gp_Vec aDirOnE1, aDirOnE2; gp_Dir aIntersectPointCrossDir; // intersect point aDirOnE1.cross(aDirOnE2) should same direction with path // theCrossDirection aBC1.D1(theParamOnE1, aPt, aDirOnE1); aBC2.D1(theParamOnE2, aPt, aDirOnE2); aIntersectPointCrossDir = aDirOnE1.Crossed(aDirOnE2); if (aIntersectPointCrossDir.Dot(theCrossDirection) > Precision::SquareConfusion()) { bvertexfound = Standard_True; break; } } } } return bvertexfound; } // ---------------------------------------------------------------------------------------------------- // static function: GetUEdges // purpose: // ---------------------------------------------------------------------------------------------------- Standard_Boolean GetUEdges(const Standard_Integer theIndex, const Standard_Integer theRank, const Handle(TopTools_HArray2OfShape)& theUEdges, const TopoDS_Edge& theBoundEdge, const TopoDS_Face& theFace, TopoDS_Edge& theFirstUEdge, TopoDS_Edge& theSecondUEdge) { const TopoDS_Shape& aUE1 = theUEdges->Value(theIndex, theUEdges->LowerCol() + theRank); const TopoDS_Shape& aUE2 = theUEdges->Value(theIndex + 1, theUEdges->LowerCol() + theRank); TopoDS_Face aFace = theFace; aFace.Orientation(TopAbs_FORWARD); TopoDS_Edge E1, E2; TopExp_Explorer anExp(aFace, TopAbs_EDGE); for (; anExp.More(); anExp.Next()) { if (E1.IsNull() && aUE1.IsSame(anExp.Current())) { E1 = TopoDS::Edge(anExp.Current()); } else if (E2.IsNull() && aUE2.IsSame(anExp.Current())) { E2 = TopoDS::Edge(anExp.Current()); } } if (E1.IsNull() || E2.IsNull()) return Standard_False; Standard_Real f, l; Handle(Geom2d_Curve) C1 = BRep_Tool::CurveOnSurface(E1, aFace, f, l); if (C1.IsNull()) return Standard_False; gp_Pnt2d PU1 = (theRank == 0) ? C1->Value(l) : C1->Value(f); Handle(Geom2d_Curve) C2 = BRep_Tool::CurveOnSurface(theBoundEdge, aFace, f, l); if (C2.IsNull()) return Standard_False; BRep_Tool::Range(theBoundEdge, f, l); gp_Pnt2d pf = C2->Value(f); TopoDS_Vertex aV = (theRank == 0) ? TopExp::LastVertex(E1) : TopExp::FirstVertex(E1); Standard_Real aTolerance = BRep_Tool::Tolerance(aV); BRepAdaptor_Surface aBAS(aFace, Standard_False); if (pf.Distance(PU1) > aBAS.UResolution(aTolerance)) { TopoDS_Edge atmpE = E1; E1 = E2; E2 = atmpE; } theFirstUEdge = E1; theSecondUEdge = E2; return Standard_True; } // ---------------------------------------------------------------------------------------------------- // static function: FillGap // purpose: // ---------------------------------------------------------------------------------------------------- Standard_Boolean FillGap(const TopoDS_Vertex& theFirstVertex, const TopoDS_Vertex& theLastVertex, const gp_Pnt2d& theFirstPoint, const gp_Pnt2d& theLastPoint, const TopoDS_Face& theFace, const TopoDS_Compound& theSectionEdges, TopTools_ListOfShape& theOrderedList) { TopTools_IndexedDataMapOfShapeListOfShape aMap; TopExp::MapShapesAndAncestors(theSectionEdges, TopAbs_VERTEX, TopAbs_EDGE, aMap); if (aMap.IsEmpty()) { return Standard_False; } if (!aMap.Contains(theFirstVertex) || !aMap.Contains(theLastVertex)) { return Standard_False; } TopTools_ListOfShape aListOfEdge; // Standard_Integer i = 0; // TopoDS_Vertex aCurVertex = theFirstVertex; TopTools_MapOfShape aMapToAvoid; if (FindNextEdge(theFirstVertex, theLastVertex, aMap, aMapToAvoid, aListOfEdge)) { if (!aListOfEdge.IsEmpty()) { return CheckAndOrientEdges(aListOfEdge, theFirstPoint, theLastPoint, theFace, theOrderedList); } } return Standard_False; } // ---------------------------------------------------------------------------------------------------- // static function: FindNextEdge // purpose: // ---------------------------------------------------------------------------------------------------- Standard_Boolean FindNextEdge(const TopoDS_Vertex& theFirstVertex, const TopoDS_Vertex& theLastVertex, const TopTools_IndexedDataMapOfShapeListOfShape& theMapVE, const TopTools_MapOfShape& theMapToAvoid, TopTools_ListOfShape& theOrderedList) { TopoDS_Vertex aCurVertex = theFirstVertex; TopTools_MapOfShape aMapToAvoid; aMapToAvoid = theMapToAvoid; TopTools_ListOfShape aListOfEdge; Standard_Integer i = 0; for (i = 1; i <= theMapVE.Extent(); i++) { if (!theMapVE.Contains(aCurVertex)) break; const TopTools_ListOfShape& lste = theMapVE.FindFromKey(aCurVertex); Standard_Boolean befound = Standard_False; TopTools_ListIteratorOfListOfShape anIt(lste); for (; anIt.More(); anIt.Next()) { TopoDS_Shape anEdge = anIt.Value(); TopoDS_Vertex aSaveCurVertex = aCurVertex; if (!aMapToAvoid.Contains(anEdge)) { TopoDS_Vertex V1, V2; TopExp::Vertices(TopoDS::Edge(anEdge), V1, V2); if (!aCurVertex.IsSame(V1)) { aCurVertex = V1; } else if (!aCurVertex.IsSame(V2)) { aCurVertex = V2; } aMapToAvoid.Add(anEdge); befound = Standard_True; aListOfEdge.Append(anEdge); if (!aCurVertex.IsSame(theLastVertex)) { TopTools_ListOfShape aListtmp; if (!FindNextEdge(aCurVertex, theLastVertex, theMapVE, aMapToAvoid, aListtmp)) { aListOfEdge.Clear(); aCurVertex = aSaveCurVertex; continue; } else { aListOfEdge.Append(aListtmp); theOrderedList.Append(aListOfEdge); return Standard_True; } } break; } } if (aCurVertex.IsSame(theLastVertex)) break; if (!befound) { return Standard_False; } } if (aCurVertex.IsSame(theLastVertex)) { theOrderedList.Append(aListOfEdge); return Standard_True; } return Standard_False; } // ---------------------------------------------------------------------------------------------------- // static function: CheckAndOrientEdges // purpose: // ---------------------------------------------------------------------------------------------------- Standard_Boolean CheckAndOrientEdges(const TopTools_ListOfShape& theOrderedList, const gp_Pnt2d& theFirstPoint, const gp_Pnt2d& theLastPoint, const TopoDS_Face& theFace, TopTools_ListOfShape& theOrientedList) { TopTools_ListIteratorOfListOfShape anIt(theOrderedList); if (!anIt.More()) return Standard_True; Standard_Real f, l; TopoDS_Edge aEPrev = TopoDS::Edge(anIt.Value()); anIt.Next(); Handle(Geom2d_Curve) aCurve = BRep_Tool::CurveOnSurface(aEPrev, theFace, f, l); TopoDS_Vertex Vf, Vl; TopExp::Vertices(aEPrev, Vf, Vl); BRepAdaptor_Surface aBAS(theFace, Standard_False); Standard_Real aTolerance1 = (Vf.IsNull()) ? Precision::Confusion() : BRep_Tool::Tolerance(Vf); Standard_Real aTolerance2 = (Vl.IsNull()) ? Precision::Confusion() : BRep_Tool::Tolerance(Vl); Standard_Real utol = aBAS.UResolution(aTolerance1); Standard_Real vtol = aBAS.VResolution(aTolerance1); aTolerance1 = (utol > vtol) ? utol : vtol; utol = aBAS.UResolution(aTolerance2); vtol = aBAS.VResolution(aTolerance2); aTolerance2 = (utol > vtol) ? utol : vtol; gp_Pnt2d ap = aCurve->Value(f); Standard_Boolean bFirstFound = Standard_False; Standard_Boolean bLastFound = Standard_False; if (ap.Distance(theFirstPoint) < aTolerance1) { if (theOrientedList.IsEmpty()) theOrientedList.Append(aEPrev.Oriented(TopAbs_FORWARD)); bFirstFound = Standard_True; } else if (ap.Distance(theLastPoint) < aTolerance1) { if (theOrientedList.IsEmpty()) theOrientedList.Append(aEPrev.Oriented(TopAbs_REVERSED)); bLastFound = Standard_True; } ap = aCurve->Value(l); if (ap.Distance(theLastPoint) < aTolerance2) { if (theOrientedList.IsEmpty()) theOrientedList.Append(aEPrev.Oriented(TopAbs_FORWARD)); bLastFound = Standard_True; } else if (ap.Distance(theFirstPoint) < aTolerance2) { if (theOrientedList.IsEmpty()) theOrientedList.Append(aEPrev.Oriented(TopAbs_REVERSED)); bFirstFound = Standard_True; } if (!theOrientedList.IsEmpty()) aEPrev = TopoDS::Edge(theOrientedList.Last()); for (; anIt.More(); anIt.Next()) { const TopoDS_Edge& aE = TopoDS::Edge(anIt.Value()); TopoDS_Vertex aV11, aV12; TopExp::Vertices(aEPrev, aV11, aV12, Standard_True); TopoDS_Vertex aV21, aV22; TopExp::Vertices(aE, aV21, aV22, Standard_False); TopAbs_Orientation anOri = (aV12.IsSame(aV21) || aV11.IsSame(aV22)) ? TopAbs_FORWARD : TopAbs_REVERSED; theOrientedList.Append(aE.Oriented(anOri)); aEPrev = TopoDS::Edge(theOrientedList.Last()); aTolerance1 = (aV21.IsNull()) ? Precision::Confusion() : BRep_Tool::Tolerance(aV21); aTolerance2 = (aV22.IsNull()) ? Precision::Confusion() : BRep_Tool::Tolerance(aV22); utol = aBAS.UResolution(aTolerance1); vtol = aBAS.VResolution(aTolerance1); aTolerance1 = (utol > vtol) ? utol : vtol; utol = aBAS.UResolution(aTolerance2); vtol = aBAS.VResolution(aTolerance2); aTolerance2 = (utol > vtol) ? utol : vtol; aCurve = BRep_Tool::CurveOnSurface(aE, theFace, f, l); ap = aCurve->Value(f); if (ap.Distance(theFirstPoint) < aTolerance1) { bFirstFound = Standard_True; } else if (ap.Distance(theLastPoint) < aTolerance1) { bLastFound = Standard_True; } ap = aCurve->Value(l); if (ap.Distance(theFirstPoint) < aTolerance2) { bFirstFound = Standard_True; } else if (ap.Distance(theLastPoint) < aTolerance2) { bLastFound = Standard_True; } } return bFirstFound && bLastFound; } // ---------------------------------------------------------------------------------------------------- // static function: FindVertex // purpose: // ---------------------------------------------------------------------------------------------------- Standard_Boolean FindVertex(const TopoDS_Edge& theEdge, const Standard_Integer theRank, const BOPDS_PDS& theDS, const TopTools_DataMapOfShapeListOfShape& theHistMap, TopoDS_Vertex& theVertex, BOPDS_Pave& thePave) { if (!theHistMap.IsBound(theEdge)) return Standard_False; const TopTools_ListOfShape& lst = theHistMap.Find(theEdge); if (lst.IsEmpty()) return Standard_False; TopoDS_Edge aNewEdge = TopoDS::Edge(lst.First()); Standard_Real f, l; BRep_Tool::Range(aNewEdge, f, l); if (theRank == 0) { thePave.SetParameter(l); theVertex = TopExp::LastVertex(aNewEdge); } else { thePave.SetParameter(f); theVertex = TopExp::FirstVertex(aNewEdge); } Standard_Integer anIndex = theDS->Index(theVertex); if (anIndex == -1) { Standard_Integer i, i1, i2; i1 = theDS->NbSourceShapes(); i2 = theDS->NbShapes(); for (i = i1; i < i2; ++i) { const TopoDS_Shape& aSx = theDS->Shape(i); if (aSx.IsSame(theVertex)) { anIndex = i; break; } } } thePave.SetIndex(anIndex); return Standard_True; } // ---------------------------------------------------------------------------------------------------- // static function: FindNextVertex // purpose: // ---------------------------------------------------------------------------------------------------- Standard_Boolean FindNextVertex(const Standard_Integer theEdgeIndex, const BOPDS_Pave& thePrevPave, const BOPDS_PDS& theDS, TopoDS_Vertex& theNextVertex, BOPDS_Pave& thePave) { Standard_Boolean bTakePave, bFound; BOPDS_Pave aTmpPave; BOPDS_ListIteratorOfListOfPave aItP; // BOPDS_Pave anullpave; bFound = Standard_False; bTakePave = thePrevPave.IsEqual(anullpave); BOPDS_ListOfPave aLP; theDS->Paves(theEdgeIndex, aLP); aItP.Initialize(aLP); for (; aItP.More(); aItP.Next()) { aTmpPave = aItP.Value(); // if (bTakePave) { if (theDS->IsNewShape(aTmpPave.Index())) { theNextVertex = *(TopoDS_Vertex*)&theDS->Shape(aTmpPave.Index()); thePave = aTmpPave; bFound = Standard_True; break; } } // else if (aTmpPave.IsEqual(thePrevPave)) { bTakePave = Standard_True; } } return bFound; } // ---------------------------------------------------------------------------------------------------- // static function: GetPave // purpose: // ---------------------------------------------------------------------------------------------------- Standard_Boolean GetPave(const Standard_Integer theEdgeIndex, const Standard_Boolean isFirst, const BOPDS_PDS& theDS, BOPDS_Pave& thePave) { Handle(BOPDS_PaveBlock) aPB; BOPDS_ListOfPave aLP; theDS->Paves(theEdgeIndex, aLP); if (!aLP.Extent()) { return Standard_False; } // if (isFirst) { thePave = aLP.First(); } else { thePave = aLP.Last(); } return Standard_True; } // ---------------------------------------------------------------------------------------------------- // static function: FindFromUEdge // purpose: // ---------------------------------------------------------------------------------------------------- Standard_Boolean FindFromUEdge(const TopoDS_Edge& theUE1Old, const TopoDS_Edge& theUE2Old, const TopoDS_Edge& theUE1New, const TopoDS_Edge& theUE2New, const TopoDS_Face& theFace, const TopoDS_Compound& theSecEdges, const Standard_Integer theRank, const TopoDS_Edge& theBoundEdge, const Standard_Integer theBoundEdgeIndex, const BOPDS_PDS& theDS, const TopTools_DataMapOfShapeListOfShape& theHistMap, TopoDS_Compound& theSecEdgesNew, TopTools_ListOfShape& theListOfWireEdges, BOPDS_Pave& theFoundPave, Standard_Boolean& isOnUEdge) { theFoundPave.SetIndex(0); theFoundPave.SetParameter(0.); isOnUEdge = Standard_True; TopoDS_Face aFaceF = theFace; aFaceF.Orientation(TopAbs_FORWARD); TopoDS_Vertex aPrevVertex, aNextVertex; TopoDS_Compound aCompOfSecEdges = theSecEdges; TopTools_ListOfShape aListOfWireEdges; // BRep_Builder aBB; BOPDS_Pave aPave1, aPave2; Standard_Real f = 0., l = 0.; gp_Pnt2d p1, p2; TopoDS_Vertex aFirstV, aLastV; BOPDS_Pave atmpPave; if (!FindVertex(theUE1Old, theRank, theDS, theHistMap, aPrevVertex, atmpPave)) { return Standard_True; } if (aPrevVertex.IsNull()) { return Standard_False; } aFirstV = aPrevVertex; Standard_Boolean bSecFound = Standard_False; Handle(Geom2d_Curve) aC1 = BRep_Tool::CurveOnSurface(theUE1New, aFaceF, f, l); p1 = (theRank == 0) ? aC1->Value(l) : aC1->Value(f); BOPDS_Pave afoundpave; BOPDS_ListOfPave aLP; theDS->Paves(theBoundEdgeIndex, aLP); Standard_Integer nbpave = aLP.Extent(); Standard_Integer pit = 0; while (FindNextVertex(theBoundEdgeIndex, aPave1, theDS, aNextVertex, aPave2) && (pit < nbpave)) { aLastV = aNextVertex; Handle(Geom2d_Curve) aC2 = BRep_Tool::CurveOnSurface(theBoundEdge, aFaceF, f, l); p2 = aC2->Value(aPave2.Parameter()); TopTools_ListOfShape aOrderedList; if (FillGap(aFirstV, aLastV, p1, p2, aFaceF, aCompOfSecEdges, aOrderedList)) { // remove found edges... TopoDS_Compound aComp; RemoveEdges(aCompOfSecEdges, aOrderedList, aComp); aCompOfSecEdges = aComp; aListOfWireEdges.Append(aOrderedList); afoundpave = aPave2; isOnUEdge = Standard_False; bSecFound = Standard_True; break; } aPrevVertex = aNextVertex; aPave1 = aPave2; pit++; } if (!bSecFound && FindVertex(theUE2Old, theRank, theDS, theHistMap, aNextVertex, aPave2)) { aLastV = aNextVertex; Handle(Geom2d_Curve) aC2 = BRep_Tool::CurveOnSurface(theUE2New, aFaceF, f, l); p2 = aC2->Value(aPave2.Parameter()); TopTools_ListOfShape aOrderedList; if (FillGap(aFirstV, aLastV, p1, p2, aFaceF, aCompOfSecEdges, aOrderedList)) { // remove found edges... TopoDS_Compound aComp; RemoveEdges(aCompOfSecEdges, aOrderedList, aComp); aCompOfSecEdges = aComp; aListOfWireEdges.Append(aOrderedList); afoundpave = aPave2; bSecFound = Standard_True; isOnUEdge = Standard_True; } } if (bSecFound) { theFoundPave = afoundpave; theListOfWireEdges = aListOfWireEdges; theSecEdgesNew = aCompOfSecEdges; } return Standard_True; } // ---------------------------------------------------------------------------------------------------- // static function: FindFromVEdge // purpose: // ---------------------------------------------------------------------------------------------------- Standard_Boolean FindFromVEdge(const BOPDS_Pave& thePrevPave, const Standard_Boolean& isOnUEdge, const TopoDS_Edge& theUE1Old, const TopoDS_Edge& theUE2Old, const TopoDS_Face& theFace, const TopoDS_Compound& theSecEdges, const Standard_Integer theRank, const TopoDS_Edge& theBoundEdge, const Standard_Integer theBoundEdgeIndex, const BOPDS_PDS& theDS, const TopTools_DataMapOfShapeListOfShape& theHistMap, TopTools_ListOfShape& theListOfWireEdges, Standard_Boolean& isSectionFound) { theListOfWireEdges.Clear(); isSectionFound = Standard_False; // TopoDS_Face aFaceF = theFace; aFaceF.Orientation(TopAbs_FORWARD); TopoDS_Vertex aPrevVertex, aNextVertex; TopoDS_Compound aCompOfSecEdges = theSecEdges; TopTools_ListOfShape aListOfWireEdges; // BRep_Builder aBB; BOPDS_Pave aPave1, aPave2; if (isOnUEdge) { TopoDS_Vertex atmpVertex; BOPDS_Pave aPaveOfE2; if (FindVertex(theUE2Old, theRank, theDS, theHistMap, atmpVertex, aPaveOfE2)) { if (thePrevPave.IsEqual(aPaveOfE2)) return Standard_True; } } Standard_Real f = 0., l = 0.; gp_Pnt2d p1(0., 0.), p2(0., 0.); TopoDS_Vertex aFirstV, aLastV; Handle(Geom2d_Curve) aC1 = BRep_Tool::CurveOnSurface(theUE1Old, aFaceF, f, l); Handle(Geom2d_Curve) aC2 = BRep_Tool::CurveOnSurface(theBoundEdge, aFaceF, f, l); Standard_Boolean bSecFound = Standard_False; aPave1 = thePrevPave; if (isOnUEdge) { BOPDS_Pave atmpPave; if (!GetPave(theBoundEdgeIndex, Standard_True, theDS, atmpPave)) { return Standard_False; } aPave1 = atmpPave; } p1 = aC2->Value(aPave1.Parameter()); aPrevVertex = TopoDS::Vertex(theDS->Shape(aPave1.Index())); BOPDS_ListOfPave aLP; theDS->Paves(theBoundEdgeIndex, aLP); Standard_Integer nbpave = aLP.Extent(); Standard_Integer pit = 0; TopTools_Array1OfListOfShape anArrayOfListOfSec(1, nbpave); // by pairs non continuously. begin Standard_Integer k = 0; BOPDS_Pave aFirstPave = aPave1; TopoDS_Vertex aFirstVertex = aPrevVertex; gp_Pnt2d apfirst = p1; BOPDS_ListOfPave aFirstPaves, aLastPaves; TColStd_ListOfInteger aListOfFlags; Standard_Integer apaircounter = 1; for (k = 0; k < nbpave; k++) { aPave1 = aFirstPave; p1 = apfirst; aPrevVertex = aFirstVertex; Standard_Boolean bfound = Standard_False; pit = 0; while (FindNextVertex(theBoundEdgeIndex, aPave1, theDS, aNextVertex, aPave2) && (pit < nbpave)) { aFirstV = aPrevVertex; aLastV = aNextVertex; p2 = aC2->Value(aPave2.Parameter()); TopTools_ListOfShape aOrderedList; if (FillGap(aFirstV, aLastV, p1, p2, aFaceF, aCompOfSecEdges, aOrderedList)) { TopoDS_Compound aComp; RemoveEdges(aCompOfSecEdges, aOrderedList, aComp); aCompOfSecEdges = aComp; anArrayOfListOfSec(apaircounter++).Append(aOrderedList); aFirstPaves.Append(aFirstPave); aLastPaves.Append(aPave2); aListOfFlags.Append(1); aFirstPave = aPave2; aFirstVertex = aNextVertex; apfirst = p2; aPrevVertex = aNextVertex; bSecFound = Standard_True; bfound = Standard_True; } aPave1 = aPave2; pit++; } if (FindVertex(theUE2Old, theRank, theDS, theHistMap, aNextVertex, aPave2)) { aFirstV = aPrevVertex; aLastV = aNextVertex; Handle(Geom2d_Curve) aC3 = BRep_Tool::CurveOnSurface(theUE2Old, aFaceF, f, l); p2 = aC3->Value(aPave2.Parameter()); TopTools_ListOfShape aOrderedList; if (FillGap(aFirstV, aLastV, p1, p2, aFaceF, aCompOfSecEdges, aOrderedList)) { TopoDS_Compound aComp; RemoveEdges(aCompOfSecEdges, aOrderedList, aComp); aCompOfSecEdges = aComp; anArrayOfListOfSec(apaircounter++).Append(aOrderedList); aFirstPaves.Append(aFirstPave); aLastPaves.Append(aPave2); aListOfFlags.Append(0); bSecFound = Standard_True; break; } } if (!bfound) { if (!FindNextVertex(theBoundEdgeIndex, aFirstPave, theDS, aNextVertex, aPave2)) { break; } aFirstPave = aPave2; apfirst = aC2->Value(aPave2.Parameter()); aFirstVertex = aNextVertex; } } // by pairs non continuously. end // by pairs continuously. begin aPave1 = thePrevPave; if (isOnUEdge) { BOPDS_Pave atmpPave; if (!GetPave(theBoundEdgeIndex, Standard_True, theDS, atmpPave)) { return Standard_False; } aPave1 = atmpPave; } p1 = aC2->Value(aPave1.Parameter()); aPrevVertex = TopoDS::Vertex(theDS->Shape(aPave1.Index())); pit = 0; while (FindNextVertex(theBoundEdgeIndex, aPave1, theDS, aNextVertex, aPave2) && (pit < nbpave)) { aFirstV = aPrevVertex; aLastV = aNextVertex; p2 = aC2->Value(aPave2.Parameter()); Standard_Boolean bisinside = Standard_False; Standard_Integer apbindex = 0; Standard_Integer apbcounter = 1; BOPDS_ListIteratorOfListOfPaveBlock aPBIt; BOPDS_ListIteratorOfListOfPave aPIt1, aPIt2; TColStd_ListIteratorOfListOfInteger aFlagIt; for (aPIt1.Initialize(aFirstPaves), aPIt2.Initialize(aLastPaves), aFlagIt.Initialize(aListOfFlags); aPIt1.More() && aPIt2.More() && aFlagIt.More(); aPIt1.Next(), aPIt2.Next(), aFlagIt.Next(), apbcounter++) { Standard_Boolean bfin = Standard_False; Standard_Boolean blin = Standard_False; if (aPave1.IsEqual(aPIt1.Value())) { bfin = Standard_True; } else { bfin = (aPave1.Parameter() > aPIt1.Value().Parameter()); } if (aFlagIt.Value()) { if (aPave2.IsEqual(aPIt2.Value())) { blin = Standard_True; } else { blin = (aPave2.Parameter() < aPIt2.Value().Parameter()); } } else { if ((aPave2.Index() == aPIt2.Value().Index()) && (aPave2.Index() > 0)) { Handle(Geom2d_Curve) pc = BRep_Tool::CurveOnSurface(theUE2Old, aFaceF, f, l); gp_Pnt2d p3 = pc->Value(aPIt2.Value().Parameter()); TopoDS_Vertex aV = TopoDS::Vertex(theDS->Shape(aPave2.Index())); BRepAdaptor_Surface aBAS(aFaceF, Standard_False); Standard_Real aTolerance = BRep_Tool::Tolerance(aV); Standard_Real utol = aBAS.UResolution(aTolerance); Standard_Real vtol = aBAS.VResolution(aTolerance); aTolerance = (utol > vtol) ? utol : vtol; if (p2.Distance(p3) < aTolerance) blin = Standard_True; } } if (bfin && blin) { apbindex = apbcounter; bisinside = Standard_True; break; } } if (!bisinside) { TopTools_ListOfShape aOrderedList; if (FillGap(aFirstV, aLastV, p1, p2, aFaceF, aCompOfSecEdges, aOrderedList)) { TopoDS_Compound aComp; RemoveEdges(aCompOfSecEdges, aOrderedList, aComp); aCompOfSecEdges = aComp; aListOfWireEdges.Append(aOrderedList); bSecFound = Standard_True; } else { TopoDS_Edge aESplit; // get split aPBIt.Initialize(theDS->PaveBlocks(theBoundEdgeIndex)); for (; aPBIt.More(); aPBIt.Next()) { const Handle(BOPDS_PaveBlock)& aPB1 = aPBIt.Value(); if (aPB1->OriginalEdge() == theBoundEdgeIndex && aPB1->Pave1().IsEqual(aPave1) && aPB1->Pave2().IsEqual(aPave2)) { if (aPB1->Edge() > 0) { aESplit = *(TopoDS_Edge*)&theDS->Shape(aPB1->Edge()); break; } } } if (!aESplit.IsNull()) { aListOfWireEdges.Append(aESplit); } } } else { if (apbindex > 0) { TopTools_ListOfShape& aListOfSec = anArrayOfListOfSec(apbindex); aListOfWireEdges.Append(aListOfSec); } } aPave1 = aPave2; aPrevVertex = aNextVertex; p1 = p2; pit++; } if (FindVertex(theUE2Old, theRank, theDS, theHistMap, aNextVertex, aPave2)) { aFirstV = aPrevVertex; aLastV = aNextVertex; Handle(Geom2d_Curve) aC3 = BRep_Tool::CurveOnSurface(theUE2Old, aFaceF, f, l); p2 = aC3->Value(aPave2.Parameter()); Standard_Boolean bisinside = Standard_False; Standard_Integer apbindex = 0; Standard_Integer apbcounter = 1; BOPDS_ListIteratorOfListOfPaveBlock aPBIt; BOPDS_ListIteratorOfListOfPave aPIt1, aPIt2; TColStd_ListIteratorOfListOfInteger aFlagIt; for (aPIt1.Initialize(aFirstPaves), aPIt2.Initialize(aLastPaves), aFlagIt.Initialize(aListOfFlags); aPIt1.More() && aPIt2.More() && aFlagIt.More(); aPIt1.Next(), aPIt2.Next(), aFlagIt.Next(), apbcounter++) { Standard_Boolean bfin = Standard_False; Standard_Boolean blin = Standard_False; if (aPave1.IsEqual(aPIt1.Value())) { bfin = Standard_True; } else { bfin = (aPave1.Parameter() > aPIt1.Value().Parameter()); } if (aFlagIt.Value()) { if (aPave2.IsEqual(aPIt2.Value())) { blin = Standard_True; } else { blin = (aPave2.Parameter() < aPIt2.Value().Parameter()); } } else { blin = Standard_True; } if (bfin && blin) { apbindex = apbcounter; bisinside = Standard_True; break; } } if (!bisinside) { TopTools_ListOfShape aOrderedList; if (FillGap(aFirstV, aLastV, p1, p2, aFaceF, aCompOfSecEdges, aOrderedList)) { TopoDS_Compound aComp; RemoveEdges(aCompOfSecEdges, aOrderedList, aComp); aCompOfSecEdges = aComp; aListOfWireEdges.Append(aOrderedList); bSecFound = Standard_True; } else { // add split TopoDS_Edge aESplit; // get split if (!GetPave(theBoundEdgeIndex, Standard_False, theDS, aPave2)) return Standard_False; // aPBIt.Initialize(theDS->PaveBlocks(theBoundEdgeIndex)); for (; aPBIt.More(); aPBIt.Next()) { const Handle(BOPDS_PaveBlock)& aPB1 = aPBIt.Value(); if (aPB1->OriginalEdge() == theBoundEdgeIndex && aPB1->Pave1().IsEqual(aPave1) && aPB1->Pave2().IsEqual(aPave2)) { if (aPB1->Edge() > 0) { aESplit = *(TopoDS_Edge*)&theDS->Shape(aPB1->Edge()); break; } } } if (!aESplit.IsNull()) { aListOfWireEdges.Append(aESplit); } } } else { if (apbindex > 0) { TopTools_ListOfShape& aListOfSec = anArrayOfListOfSec(apbindex); aListOfWireEdges.Append(aListOfSec); } } } else { // add split TopoDS_Edge aESplit; // get split if (!GetPave(theBoundEdgeIndex, Standard_False, theDS, aPave2)) return Standard_False; BOPDS_ListIteratorOfListOfPaveBlock aPBIt; aPBIt.Initialize(theDS->PaveBlocks(theBoundEdgeIndex)); for (; aPBIt.More(); aPBIt.Next()) { const Handle(BOPDS_PaveBlock)& aPB1 = aPBIt.Value(); if (aPB1->OriginalEdge() == theBoundEdgeIndex && aPB1->Pave1().IsEqual(aPave1) && aPB1->Pave2().IsEqual(aPave2)) { if (aPB1->Edge() > 0) { aESplit = *(TopoDS_Edge*)&theDS->Shape(aPB1->Edge()); break; } } } if (!aESplit.IsNull()) { aListOfWireEdges.Append(aESplit); } } // by pairs continuously. end theListOfWireEdges = aListOfWireEdges; isSectionFound = bSecFound; return Standard_True; } // ---------------------------------------------------------------------------------------------------- // static function: RemoveEdges // purpose: // ---------------------------------------------------------------------------------------------------- void RemoveEdges(const TopoDS_Compound& theSourceComp, const TopTools_ListOfShape& theListToRemove, TopoDS_Compound& theResultComp) { BRep_Builder aBB; TopoDS_Compound aComp; aBB.MakeCompound(aComp); TopExp_Explorer anExp(theSourceComp, TopAbs_EDGE); for (; anExp.More(); anExp.Next()) { Standard_Boolean bfound = Standard_False; TopTools_ListIteratorOfListOfShape anIt(theListToRemove); for (; !bfound && anIt.More(); anIt.Next()) { bfound = anExp.Current().IsSame(anIt.Value()); } if (!bfound) { aBB.Add(aComp, anExp.Current()); } } theResultComp = aComp; } // ---------------------------------------------------------------------------------------------------- // static function: FilterSectionEdges // purpose: // ---------------------------------------------------------------------------------------------------- Standard_Boolean FilterSectionEdges(const BOPDS_VectorOfCurve& theBCurves, const TopoDS_Face& theSecPlane, const BOPDS_PDS& theDS, TopoDS_Compound& theResult) { theResult.Nullify(); BRep_Builder aBB; aBB.MakeCompound(theResult); Standard_Integer aNbCurves = theBCurves.Length(); Standard_Integer cit = 0; BOPDS_ListIteratorOfListOfPaveBlock aPBIt; for (cit = 0; cit < aNbCurves; ++cit) { const BOPDS_Curve& aBCurve = theBCurves(cit); const BOPDS_ListOfPaveBlock& aSectEdges = aBCurve.PaveBlocks(); aPBIt.Initialize(aSectEdges); for (; aPBIt.More(); aPBIt.Next()) { const Handle(BOPDS_PaveBlock)& aPB = aPBIt.Value(); Standard_Integer nSect = aPB->Edge(); const TopoDS_Shape& aS = theDS->Shape(nSect); TopoDS_Edge anEdge = TopoDS::Edge(aS); Standard_Boolean bAddEdge = Standard_True; if (!theSecPlane.IsNull()) { IntTools_BeanFaceIntersector anIntersector(anEdge, theSecPlane); Standard_Real f = 0., l = 0.; BRep_Tool::Range(anEdge, f, l); anIntersector.SetBeanParameters(f, l); // Handle(IntTools_Context) aContext = new IntTools_Context; anIntersector.SetContext(aContext); // anIntersector.Perform(); if (anIntersector.IsDone()) { bAddEdge = Standard_False; Standard_Integer r = 0; for (r = 1; r <= anIntersector.Result().Length(); r++) { const IntTools_Range& aRange = anIntersector.Result().Value(r); if (((aRange.First() - f) < Precision::PConfusion()) && ((l - aRange.Last()) < Precision::PConfusion())) { bAddEdge = Standard_True; break; } // if(((aRange.First() - f) < Precision::PConfusion()) && } // for(r = 1; r <= anIntersector.Result().Length(); r++) { } // if(anIntersector.IsDone()) { } // if(!theSecPlane.IsNull()) { if (bAddEdge) { aBB.Add(theResult, aS); } } // for (; aPBIt.More(); aPBIt.Next()) { } // for(cit = 0; cit < aNbCurves; ++cit) { return Standard_True; } //================================================================================================= static Standard_Real ComputeAveragePlaneAndMaxDeviation(const TopoDS_Shape& aWire, gp_Pln& thePlane, Standard_Boolean& IsSingular) { Standard_Integer N = 40; Standard_Integer nedges = aWire.NbChildren(); TColgp_Array1OfPnt Pnts(1, nedges * N); Standard_Integer ind = 1, i; for (TopoDS_Iterator iter(aWire); iter.More(); iter.Next()) { const TopoDS_Edge& anEdge = TopoDS::Edge(iter.Value()); BRepAdaptor_Curve aCurve(anEdge); GCPnts_UniformAbscissa Distribution(aCurve, N + 1); for (i = 1; i <= N; i++) { Standard_Real par = Distribution.Parameter(i); Pnts(ind++) = aCurve.Value(par); } } gp_Ax2 Axe; GeomLib::AxeOfInertia(Pnts, Axe, IsSingular); if (IsSingular) return -1; thePlane = gp_Pln(Axe); Standard_Real MaxDeviation = 0; for (i = 1; i <= Pnts.Length(); i++) { Standard_Real dist = thePlane.Distance(Pnts(i)); if (dist > MaxDeviation) MaxDeviation = dist; } return MaxDeviation; } static void UpdateSectionEdge(TopoDS_Edge& theEdge, const TopoDS_Vertex& theConstVertex, TopoDS_Vertex& theVertex, const Standard_Real theParam) { TopoDS_Edge F_Edge = theEdge; F_Edge.Orientation(TopAbs_FORWARD); TopAbs_Orientation OrOfVertex; TopoDS_Vertex V1, V2, AnotherVertex; TopExp::Vertices(F_Edge, V1, V2); if (theConstVertex.IsSame(V1)) { // OrOfConst = TopAbs_FORWARD; OrOfVertex = TopAbs_REVERSED; AnotherVertex = V2; } else { // OrOfConst = TopAbs_REVERSED; OrOfVertex = TopAbs_FORWARD; AnotherVertex = V1; } BRep_Builder BB; Standard_Real fpar, lpar; BRep_Tool::Range(F_Edge, fpar, lpar); if (OrOfVertex == TopAbs_FORWARD) fpar = theParam; else lpar = theParam; BB.Range(F_Edge, fpar, lpar); F_Edge.Free(Standard_True); BB.Remove(F_Edge, AnotherVertex); theVertex.Orientation(OrOfVertex); BB.Add(F_Edge, theVertex); } // Finds the edge connected to in the compound // that is closest to bisector plane angularly. // Removes found edge from // is the axis of bisector plane static TopoDS_Edge FindEdgeCloseToBisectorPlane(const TopoDS_Vertex& theVertex, TopoDS_Compound& theComp, const gp_Ax1& theAxis) { TopTools_IndexedDataMapOfShapeListOfShape VEmap; TopExp::MapShapesAndAncestors(theComp, TopAbs_VERTEX, TopAbs_EDGE, VEmap); TopoDS_Edge MinEdge; if (!VEmap.Contains(theVertex)) return MinEdge; BRep_Builder BB; const TopTools_ListOfShape& Edges = VEmap.FindFromKey(theVertex); if (Edges.Extent() == 1) MinEdge = TopoDS::Edge(Edges.First()); else { TopTools_ListIteratorOfListOfShape itl(Edges); Standard_Real MinAngle = RealLast(); for (; itl.More(); itl.Next()) { const TopoDS_Edge& anEdge = TopoDS::Edge(itl.Value()); TopoDS_Wire aWire; BB.MakeWire(aWire); BB.Add(aWire, anEdge); gp_Pln aPln; Standard_Boolean issing; ComputeAveragePlaneAndMaxDeviation(aWire, aPln, issing); Standard_Real anAngle; if (issing) // edge is a segment of line { // is angle between and its projection on bisector plane BRepAdaptor_Curve BAcurve(anEdge); gp_Pnt FirstPnt = BAcurve.Value(BAcurve.FirstParameter()); gp_Pnt LastPnt = BAcurve.Value(BAcurve.LastParameter()); gp_Vec EdgeVec(FirstPnt, LastPnt); gp_Ax1 EdgeAxis(FirstPnt, EdgeVec); anAngle = EdgeAxis.Direction().Angle(theAxis.Direction()); if (anAngle > M_PI / 2) anAngle = M_PI - anAngle; anAngle = M_PI / 2 - anAngle; } else { anAngle = aPln.Axis().Angle(theAxis); if (anAngle > M_PI / 2) anAngle = M_PI - anAngle; } if (anAngle < MinAngle) { MinAngle = anAngle; MinEdge = anEdge; } } } // else (more than one edge) BB.Remove(theComp, MinEdge); return MinEdge; } static Standard_Boolean FindMiddleEdges(const TopoDS_Vertex& theVertex1, const TopoDS_Vertex& theVertex2, const gp_Ax1& theAxis, TopoDS_Compound& theComp, TopTools_ListOfShape& theElist) { TopTools_IndexedDataMapOfShapeListOfShape VEmap; TopExp::MapShapesAndAncestors(theComp, TopAbs_VERTEX, TopAbs_EDGE, VEmap); if (VEmap.IsEmpty()) return Standard_False; if (!VEmap.Contains(theVertex1) || !VEmap.Contains(theVertex2)) return Standard_False; TopoDS_Vertex CurVertex = theVertex1; for (;;) { TopoDS_Edge CurEdge; CurEdge = FindEdgeCloseToBisectorPlane(CurVertex, theComp, theAxis); if (CurEdge.IsNull()) return Standard_False; TopoDS_Vertex V1, V2; TopExp::Vertices(CurEdge, V1, V2); CurVertex = (V1.IsSame(CurVertex)) ? V2 : V1; theElist.Append(CurEdge); if (CurVertex.IsSame(theVertex2)) return Standard_True; } } static Standard_Boolean FindCommonVertex(const TopoDS_Edge& theFirstEdge, const TopoDS_Edge& theLastEdge, const TopoDS_Vertex& theFirstVertex, const TopoDS_Vertex& theLastVertex, TopoDS_Vertex& theCommonVertex) { if (!theFirstVertex.IsSame(theLastVertex)) { Standard_Boolean CommonVertexExists = TopExp::CommonVertex(theFirstEdge, theLastEdge, theCommonVertex); return CommonVertexExists; } TopoDS_Vertex V1, V2, V3, V4; TopExp::Vertices(theFirstEdge, V1, V2); TopExp::Vertices(theLastEdge, V3, V4); if (V1.IsSame(theFirstVertex)) { if (V2.IsSame(V3) || V2.IsSame(V4)) { theCommonVertex = V2; return Standard_True; } } else { if (V1.IsSame(V3) || V1.IsSame(V4)) { theCommonVertex = V1; return Standard_True; } } return Standard_False; }