// Created on: 1995-03-24 // Created by: Jing Cheng MEI // Copyright (c) 1995-1999 Matra Datavision // Copyright (c) 1999-2012 OPEN CASCADE SAS // // The content of this file is subject to the Open CASCADE Technology Public // License Version 6.5 (the "License"). You may not use the content of this file // except in compliance with the License. Please obtain a copy of the License // at http://www.opencascade.org and read it completely before using this file. // // The Initial Developer of the Original Code is Open CASCADE S.A.S., having its // main offices at: 1, place des Freres Montgolfier, 78280 Guyancourt, France. // // The Original Code and all software distributed under the License is // distributed on an "AS IS" basis, without warranty of any kind, and the // Initial Developer hereby disclaims all such warranties, including without // limitation, any warranties of merchantability, fitness for a particular // purpose or non-infringement. Please see the License for the specific terms // and conditions governing the rights and limitations under the License. // dcl CCI60011 : Correction of degeneratedSection // Improvement of SameParameter Edge to treat case of failure in BRepLib::SameParameter // dcl Thu Aug 20 09:24:49 1998 // Suppression of little faces. // dcl Fri Aug 7 15:27:46 1998 // Refection of function SameParameter Edge. // Merge on the edge which has the less of poles. // Suppression of the Connected Edge function. // dcl Tue Jun 9 14:21:53 1998 // Do not merge edge if they belong the same face // Tolerance management in VerticesAssembling // Tolerance management in Cutting // dcl Thu May 14 15:51:46 1998 // optimization of cutting // dcl Thu May 7 15:51:46 1998 // Add of cutting option // Add of SameParameter call //-- lbr April 1 97 //-- dpf December 10 1997 Processing of pcurve collections //rln 02.02.99 BUC60449 Making compilable on NT in DEB mode //rln 02.02.99 BUC60449 Protection against exception on NT #define TEST 1 #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 #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 void SortBox (const Handle(Bnd_HArray1OfBox) hSetBoxes, const Bnd_Box& aBox, TColStd_ListOfInteger& listIndex) { Standard_Integer i, nbBoxes = hSetBoxes->Length(); for (i = 1; i <= nbBoxes; i++) if (!aBox.IsOut(hSetBoxes->Value(i))) listIndex.Append(i); } //======================================================================= //function : SameRange //purpose : //======================================================================= Handle(Geom2d_Curve) BRepBuilderAPI_Sewing::SameRange(const Handle(Geom2d_Curve)& CurvePtr, const Standard_Real FirstOnCurve, const Standard_Real LastOnCurve, const Standard_Real RequestedFirst, const Standard_Real RequestedLast) const { Handle(Geom2d_Curve) NewCurvePtr; try { GeomLib::SameRange(Precision::PConfusion(),CurvePtr,FirstOnCurve,LastOnCurve, RequestedFirst,RequestedLast,NewCurvePtr); } catch (Standard_Failure) { #ifdef DEB cout << "Exception in BRepBuilderAPI_Sewing::SameRange: "; Standard_Failure::Caught()->Print(cout); cout << endl; #endif } return NewCurvePtr; } //======================================================================= //function : WhichFace //purpose : Give the face whose edge is the border //======================================================================= TopoDS_Face BRepBuilderAPI_Sewing::WhichFace(const TopoDS_Edge& theEdg, const Standard_Integer index) const { TopoDS_Shape bound = theEdg; if (mySectionBound.IsBound(bound)) bound = mySectionBound(bound); if (myBoundFaces.Contains(bound)) { Standard_Integer i = 1; TopTools_ListIteratorOfListOfShape itf(myBoundFaces.FindFromKey(bound)); for (; itf.More(); itf.Next(), i++) if (i == index) return TopoDS::Face(itf.Value()); } return TopoDS_Face(); } //======================================================================= //function : IsClosedShape //purpose : //======================================================================= static Standard_Boolean IsClosedShape(const TopoDS_Shape& theshape, const TopoDS_Shape& v1, const TopoDS_Shape& v2) { Standard_Real TotLength = 0.0; TopExp_Explorer aexp; for (aexp.Init(theshape,TopAbs_EDGE); aexp.More(); aexp.Next()) { TopoDS_Edge aedge = TopoDS::Edge(aexp.Current()); if (aedge.IsNull()) continue; TopoDS_Vertex ve1,ve2; TopExp::Vertices(aedge,ve1,ve2); if (!ve1.IsSame(v1) && !ve1.IsSame(v2)) continue; if (BRep_Tool::Degenerated(aedge)) continue; Standard_Real first,last; Handle(Geom_Curve) c3d = BRep_Tool::Curve(TopoDS::Edge(aedge), first, last); if (!c3d.IsNull()) { GeomAdaptor_Curve cAdapt(c3d); Standard_Real length = GCPnts_AbscissaPoint::Length(cAdapt, first, last); TotLength += length; if (ve2.IsSame(v1) || ve2.IsSame(v2)) break; } } if (TotLength > 0.0) { gp_Pnt p1 = BRep_Tool::Pnt(TopoDS::Vertex(v1)); gp_Pnt p2 = BRep_Tool::Pnt(TopoDS::Vertex(v2)); return (p1.Distance(p2) < TotLength/(1.2 * M_PI)); } return Standard_False; } //======================================================================= //function : IsClosedByIsos //purpose : //======================================================================= static Standard_Boolean IsClosedByIsos(const Handle(Geom_Surface)& thesurf, const Handle(Geom2d_Curve)& acrv2d, const Standard_Real f2d, const Standard_Real l2d, const Standard_Boolean isUIsos) { Standard_Boolean isClosed = Standard_False; gp_Pnt2d psurf1 = (acrv2d->IsPeriodic() ? acrv2d->Value(f2d) : acrv2d->Value(Max(f2d,acrv2d->FirstParameter()))); gp_Pnt2d psurf2 = (acrv2d->IsPeriodic() ? acrv2d->Value(l2d) : acrv2d->Value(Min(l2d,acrv2d->LastParameter()))); Handle(Geom_Curve) aCrv1; Handle(Geom_Curve) aCrv2; if(isUIsos) { aCrv1 = thesurf->UIso(psurf1.X()); aCrv2 = thesurf->UIso(psurf2.X()); } else { aCrv1 = thesurf->VIso(psurf1.Y()); aCrv2 = thesurf->VIso(psurf2.Y()); } gp_Pnt p11,p1m,p12,p21,p2m,p22; Standard_Real af1 = aCrv1->FirstParameter(); Standard_Real al1 = aCrv1->LastParameter(); Standard_Real af2 = aCrv2->FirstParameter(); Standard_Real al2 = aCrv2->LastParameter(); aCrv1->D0(af1,p11); aCrv1->D0((af1+al1)*0.5,p1m); aCrv1->D0(al1,p12); aCrv2->D0(af2,p21); aCrv2->D0((af2+al2)*0.5,p2m); aCrv2->D0(al2,p22); isClosed = (((p11.XYZ() - p12.XYZ()).Modulus() < (p11.XYZ() - p1m.XYZ()).Modulus() - Precision::Confusion()) && ((p21.XYZ() - p22.XYZ()).Modulus() < (p21.XYZ() - p2m.XYZ()).Modulus() - Precision::Confusion())) ; return isClosed; } //======================================================================= //function : IsUClosedSurface //purpose : //======================================================================= Standard_Boolean BRepBuilderAPI_Sewing::IsUClosedSurface(const Handle(Geom_Surface)& surf, const TopoDS_Shape& theEdge, const TopLoc_Location& theloc) const { Handle(Geom_Surface) tmpsurf = surf; if(tmpsurf->IsKind(STANDARD_TYPE(Geom_RectangularTrimmedSurface))) tmpsurf = Handle(Geom_RectangularTrimmedSurface)::DownCast(surf)->BasisSurface(); else if(tmpsurf->IsKind(STANDARD_TYPE(Geom_OffsetSurface))) tmpsurf = Handle(Geom_OffsetSurface)::DownCast(surf)->BasisSurface(); else { Standard_Boolean isClosed = tmpsurf->IsUClosed(); if(!isClosed) { Standard_Real f2d, l2d; Handle(Geom2d_Curve) acrv2d = BRep_Tool::CurveOnSurface(TopoDS::Edge(theEdge), surf,theloc, f2d, l2d); if(!acrv2d.IsNull()) isClosed = IsClosedByIsos(tmpsurf,acrv2d,f2d, l2d,Standard_False ); } return isClosed; } return IsUClosedSurface(tmpsurf,theEdge,theloc); //return surf->IsUClosed(); } //======================================================================= //function : IsVClosedSurface //purpose : //======================================================================= Standard_Boolean BRepBuilderAPI_Sewing::IsVClosedSurface(const Handle(Geom_Surface)& surf, const TopoDS_Shape& theEdge, const TopLoc_Location& theloc) const { Handle(Geom_Surface) tmpsurf = surf; if(tmpsurf->IsKind(STANDARD_TYPE(Geom_RectangularTrimmedSurface))) tmpsurf = Handle(Geom_RectangularTrimmedSurface)::DownCast(surf)->BasisSurface(); else if(tmpsurf->IsKind(STANDARD_TYPE(Geom_OffsetSurface))) tmpsurf = Handle(Geom_OffsetSurface)::DownCast(surf)->BasisSurface(); else { Standard_Boolean isClosed = tmpsurf->IsVClosed(); if(!isClosed) { Standard_Real f2d, l2d; Handle(Geom2d_Curve) acrv2d = BRep_Tool::CurveOnSurface(TopoDS::Edge(theEdge), surf,theloc, f2d, l2d); if(!acrv2d.IsNull()) isClosed = IsClosedByIsos(tmpsurf,acrv2d,f2d, l2d,Standard_True ); } return isClosed; } return IsVClosedSurface(tmpsurf,theEdge,theloc); //return surf->IsVClosed(); } //======================================================================= //function : SameParameter //purpose : internal use //======================================================================= void BRepBuilderAPI_Sewing::SameParameter(const TopoDS_Edge& edge) const { try { BRepLib::SameParameter(edge); } catch (Standard_Failure) { #ifdef DEB cout << "Exception in BRepBuilderAPI_Sewing::SameParameter: "; Standard_Failure::Caught()->Print(cout); cout << endl; #endif } } //======================================================================= //function : SameParameterEdge //purpose : internal use // Merge the Sequence Of Section on one edge. // This function keep the curve3d,curve2d,range and parametrization // from the first section, and report and made sameparameter the // pcurves of the other function. // This function works when the are not more than two Pcurves // on a same face. //======================================================================= TopoDS_Edge BRepBuilderAPI_Sewing::SameParameterEdge(const TopoDS_Shape& edge, const TopTools_SequenceOfShape& seqEdges, const TColStd_SequenceOfInteger& seqForward, TopTools_MapOfShape& mapMerged, const Handle(BRepTools_ReShape)& locReShape) { // Retrieve reference section TopoDS_Shape aTmpShape = myReShape->Apply(edge); //for porting TopoDS_Edge Edge1 = TopoDS::Edge(aTmpShape); aTmpShape = locReShape->Apply(Edge1); if (locReShape != myReShape) Edge1 = TopoDS::Edge(aTmpShape); Standard_Boolean isDone = Standard_False; // Create data structures for temporary merged edges TopTools_ListOfShape listFaces1; TopTools_MapOfShape MergedFaces; if (mySewing) { // Fill MergedFaces with faces of Edge1 TopoDS_Shape bnd1 = edge; if (mySectionBound.IsBound(bnd1)) bnd1 = mySectionBound(bnd1); if (myBoundFaces.Contains(bnd1)) { TopTools_ListIteratorOfListOfShape itf(myBoundFaces.FindFromKey(bnd1)); for (; itf.More(); itf.Next()) if (MergedFaces.Add(itf.Value())) listFaces1.Append(itf.Value()); } } else { // Create presentation edge TopoDS_Vertex V1, V2; TopExp::Vertices(Edge1,V1,V2); if (myVertexNode.Contains(V1)) V1 = TopoDS::Vertex(myVertexNode.FindFromKey(V1)); if (myVertexNode.Contains(V2)) V2 = TopoDS::Vertex(myVertexNode.FindFromKey(V2)); TopoDS_Edge NewEdge = Edge1; NewEdge.EmptyCopy(); // Add the vertices BRep_Builder aBuilder; TopoDS_Shape anEdge = NewEdge.Oriented(TopAbs_FORWARD); aBuilder.Add(anEdge,V1.Oriented(TopAbs_FORWARD)); aBuilder.Add(anEdge,V2.Oriented(TopAbs_REVERSED)); Edge1 = NewEdge; } Standard_Boolean isForward = Standard_True; // Merge candidate sections for (Standard_Integer i = 1; i <= seqEdges.Length(); i++) { // Retrieve candidate section TopoDS_Shape oedge2 = seqEdges(i); if (mySewing) { aTmpShape = myReShape->Apply(oedge2); //for porting TopoDS_Edge Edge2 = TopoDS::Edge(aTmpShape); aTmpShape = locReShape->Apply(Edge2); if (locReShape != myReShape) Edge2 = TopoDS::Edge(aTmpShape); // Calculate relative orientation Standard_Integer Orientation = seqForward(i); if (!isForward) Orientation = (Orientation? 0 : 1); // Retrieve faces information for the second edge TopoDS_Shape bnd2 = oedge2; if (mySectionBound.IsBound(bnd2)) bnd2 = mySectionBound(bnd2); if (!myBoundFaces.Contains(bnd2)) continue; // Skip floating edge const TopTools_ListOfShape& listFaces2 = myBoundFaces.FindFromKey(bnd2); Standard_Integer whichSec = 1; // Indicates on which edge the pCurve has been reported TopoDS_Edge NewEdge = SameParameterEdge(Edge1,Edge2,listFaces1,listFaces2,Orientation,whichSec); if (NewEdge.IsNull()) continue; // Record faces information for the temporary merged edge TopTools_ListIteratorOfListOfShape itf(listFaces2); for (; itf.More(); itf.Next()) if (MergedFaces.Add(itf.Value())) listFaces1.Append(itf.Value()); // Record merged section orientation if (!Orientation && whichSec != 1) isForward = isForward? Standard_False : Standard_True; Edge1 = NewEdge; } // Append actually merged edge mapMerged.Add(oedge2); isDone = Standard_True; if (!myNonmanifold) break; } if (isDone) { // Change result orientation Edge1.Orientation(isForward? TopAbs_FORWARD : TopAbs_REVERSED); } else Edge1.Nullify(); return Edge1; } //======================================================================= //function : SameParameterEdge //purpose : internal use //======================================================================= static Standard_Boolean findNMVertices(const TopoDS_Edge& theEdge, TopTools_SequenceOfShape& theSeqNMVert, TColStd_SequenceOfReal& theSeqPars) { TopoDS_Iterator aItV(theEdge,Standard_False); for( ; aItV.More(); aItV.Next()) { if(aItV.Value().Orientation() == TopAbs_INTERNAL || aItV.Value().Orientation() == TopAbs_EXTERNAL) theSeqNMVert.Append(aItV.Value()); } Standard_Integer nbV = theSeqNMVert.Length(); if(!nbV) return Standard_False; Standard_Real first, last; Handle(Geom_Curve) c3d = BRep_Tool::Curve(theEdge,first, last); GeomAdaptor_Curve GAC(c3d); Extrema_ExtPC locProj; locProj.Initialize(GAC, first, last); gp_Pnt pfirst = GAC.Value(first), plast = GAC.Value(last); for (Standard_Integer i = 1; i <= nbV; i++) { TopoDS_Vertex aV = TopoDS::Vertex(theSeqNMVert.Value(i)); gp_Pnt pt = BRep_Tool::Pnt(aV); Standard_Real distF2 = pfirst.SquareDistance(pt); Standard_Real distL2 = plast.SquareDistance(pt); Standard_Real apar = (distF2 > distL2 ? last : first); // Project current point on curve locProj.Perform(pt); if (locProj.IsDone() && locProj.NbExt() > 0) { Standard_Real dist2Min = Min(distF2,distL2); Standard_Integer ind, indMin = 0; for (ind = 1; ind <= locProj.NbExt(); ind++) { Standard_Real dProj2 = locProj.SquareDistance(ind); if (dProj2 < dist2Min) { indMin = ind; dist2Min = dProj2; } } if(indMin) apar = locProj.Point(indMin).Parameter(); theSeqPars.Append(apar); } } return Standard_True; } static inline Standard_Real ComputeToleranceVertex(const Standard_Real dist, const Standard_Real Tol1, const Standard_Real Tol2) { return (dist * 0.5 + Tol1 + Tol2); } TopoDS_Edge BRepBuilderAPI_Sewing::SameParameterEdge(const TopoDS_Edge& edgeFirst, const TopoDS_Edge& edgeLast, const TopTools_ListOfShape& listFacesFirst, const TopTools_ListOfShape& listFacesLast, const Standard_Boolean secForward, Standard_Integer& whichSec, const Standard_Boolean firstCall) { // Do not process floating edges if (!listFacesFirst.Extent() || !listFacesLast.Extent()) return TopoDS_Edge(); // Sort input edges TopoDS_Edge edge1, edge2; if (firstCall) { // Take the longest edge as first Standard_Real f, l; Handle(Geom_Curve) c3d1 = BRep_Tool::Curve(TopoDS::Edge(edgeFirst), f, l); GeomAdaptor_Curve cAdapt1(c3d1); Standard_Real len1 = GCPnts_AbscissaPoint::Length(cAdapt1, f, l); Handle(Geom_Curve) c3d2 = BRep_Tool::Curve(TopoDS::Edge(edgeLast), f, l); GeomAdaptor_Curve cAdapt2(c3d2); Standard_Real len2 = GCPnts_AbscissaPoint::Length(cAdapt2, f, l); if (len1 < len2) { edge1 = edgeLast; edge2 = edgeFirst; whichSec = 2; } else { edge1 = edgeFirst; edge2 = edgeLast; whichSec = 1; } } else { if (whichSec == 1) { edge1 = edgeLast; edge2 = edgeFirst; whichSec = 2; } else { edge1 = edgeFirst; edge2 = edgeLast; whichSec = 1; } } Standard_Real first, last; BRep_Tool::Range(edge1, first, last); BRep_Builder aBuilder; //To keep NM vertices on edge TopTools_SequenceOfShape aSeqNMVert; TColStd_SequenceOfReal aSeqNMPars; findNMVertices(edge1,aSeqNMVert,aSeqNMPars); findNMVertices(edge2,aSeqNMVert,aSeqNMPars); // Create new edge TopoDS_Edge edge; aBuilder.MakeEdge(edge); edge.Orientation( edge1.Orientation()); // Retrieve edge curve TopLoc_Location loc3d; Standard_Real first3d, last3d; Handle(Geom_Curve) c3d = BRep_Tool::Curve(edge1, loc3d, first3d, last3d); if (!loc3d.IsIdentity()) { c3d = Handle(Geom_Curve)::DownCast(c3d->Copy()); c3d->Transform(loc3d.Transformation()); } aBuilder.UpdateEdge(edge,c3d,BRep_Tool::Tolerance(edge1)); aBuilder.Range(edge, first, last); aBuilder.SameRange(edge, Standard_False); //Standard_True aBuilder.SameParameter(edge, Standard_False); // Create and add new vertices { TopoDS_Vertex V1New, V2New; // Retrieve original vertices from edges TopoDS_Vertex V11,V12,V21,V22; TopExp::Vertices(edge1,V11,V12); TopExp::Vertices(edge2,V21,V22); //check that edges merged valid way (for edges having length less than specified //tolerance // Check if edges are closed Standard_Boolean isClosed1 = V11.IsSame(V12); Standard_Boolean isClosed2 = V21.IsSame(V22); if(!isClosed1 && !isClosed2) { if(secForward ) { if( V11.IsSame(V22) || V12.IsSame(V21) ) return TopoDS_Edge(); } else { if( V11.IsSame(V21) || V12.IsSame(V22) ) return TopoDS_Edge(); } } //szv: do not reshape here!!! //V11 = TopoDS::Vertex(myReShape->Apply(V11)); //V12 = TopoDS::Vertex(myReShape->Apply(V12)); //V21 = TopoDS::Vertex(myReShape->Apply(V21)); //V22 = TopoDS::Vertex(myReShape->Apply(V22)); gp_Pnt p11 = BRep_Tool::Pnt(V11); gp_Pnt p12 = BRep_Tool::Pnt(V12); gp_Pnt p21 = BRep_Tool::Pnt(V21); gp_Pnt p22 = BRep_Tool::Pnt(V22); //Standard_Boolean isRev = Standard_False; gp_Pnt pfirst; Standard_Real Tol1 = 0.; if (isClosed1 || isClosed2) { // at least one of the edges is closed if (isClosed1 && isClosed2) { // both edges are closed pfirst.SetXYZ(0.5*(p11.XYZ() + p21.XYZ())); gp_Vec v1 = p21.XYZ() - p11.XYZ(); Standard_Real d1 = v1.Magnitude(); Tol1 = ComputeToleranceVertex(d1,BRep_Tool::Tolerance(V11),BRep_Tool::Tolerance(V21)); //Tol1 = Max(pfirst.Distance(p11),pfirst.Distance(p21)); } else if (isClosed1) { // only first edge is closed gp_XYZ pt =0.5*(p21.XYZ()+ p22.XYZ()); pfirst.SetXYZ(0.5*(p11.XYZ() + pt)); gp_Vec v1 = p22.XYZ() - p21.XYZ(); Standard_Real d1 = v1.Magnitude(); Tol1= ComputeToleranceVertex(d1,BRep_Tool::Tolerance(V22),BRep_Tool::Tolerance(V21)); gp_Vec v2 = p11.XYZ() - pt; Standard_Real d2 = v2.Magnitude(); Tol1= ComputeToleranceVertex(d2,Tol1,BRep_Tool::Tolerance(V11)); //Tol1 = Max(pfirst.Distance(p21),pfirst.Distance(p22)); //Tol1 = Max(pfirst.Distance(p11),Tol1); } else { // only second edge is closed gp_XYZ pt = 0.5*(p11.XYZ()+ p12.XYZ()); pfirst.SetXYZ(0.5*(p21.XYZ() + pt)); gp_Vec v1 = p11.XYZ() - p12.XYZ(); Standard_Real d1 = v1.Magnitude(); Tol1 = ComputeToleranceVertex(d1,BRep_Tool::Tolerance(V11),BRep_Tool::Tolerance(V12)); gp_Vec v2 = p21.XYZ() - pt; Standard_Real d2 = v2.Magnitude(); Tol1 = ComputeToleranceVertex(d2,Tol1,BRep_Tool::Tolerance(V21)); //Tol1 = Max(pfirst.Distance(p11),pfirst.Distance(p12)); //Tol1 = Max(pfirst.Distance(p21),Tol1); } aBuilder.MakeVertex(V1New,pfirst,Tol1); V2New = V1New; } else { // both edges are open gp_Pnt plast; Standard_Real Tol2 = 0.; Standard_Boolean isOldFirst = ( secForward ? V11.IsSame(V21) : V11.IsSame(V22) ); Standard_Boolean isOldLast = ( secForward ? V12.IsSame(V22) : V12.IsSame(V21)) ; if (secForward) { //case if vertices already sewed if(!isOldFirst) { pfirst.SetXYZ(0.5*(p11.XYZ() + p21.XYZ())); gp_Vec v1 = p21.XYZ() - p11.XYZ(); Standard_Real d1 = v1.Magnitude(); Tol1 = ComputeToleranceVertex(d1,BRep_Tool::Tolerance(V11),BRep_Tool::Tolerance(V21)); } if(!isOldLast) { plast.SetXYZ(0.5*(p12.XYZ() + p22.XYZ())); gp_Vec v2 = p22.XYZ() - p12.XYZ(); Standard_Real d2 = v2.Magnitude(); Tol2 = ComputeToleranceVertex(d2,BRep_Tool::Tolerance(V12),BRep_Tool::Tolerance(V22)); } } else { if(!isOldFirst) { pfirst.SetXYZ(0.5*(p11.XYZ() + p22.XYZ())); gp_Vec v1 = p22.XYZ() - p11.XYZ(); Standard_Real d1 = v1.Magnitude(); Tol1 = ComputeToleranceVertex(d1,BRep_Tool::Tolerance(V11),BRep_Tool::Tolerance(V22)); } if(!isOldLast) { plast.SetXYZ(0.5*(p12.XYZ() + p21.XYZ())); gp_Vec v2 = p21.XYZ() - p12.XYZ(); Standard_Real d2 = v2.Magnitude(); Tol2 = ComputeToleranceVertex(d2,BRep_Tool::Tolerance(V12),BRep_Tool::Tolerance(V21)); } } if(!isOldFirst) aBuilder.MakeVertex(V1New,pfirst,Tol1); else V1New = V11; if(!isOldLast) aBuilder.MakeVertex(V2New,plast,Tol2); else V2New = V12; } // Add the vertices in the good sense TopoDS_Shape anEdge = edge.Oriented(TopAbs_FORWARD); TopoDS_Shape aLocalEdge = V1New.Oriented(TopAbs_FORWARD); //(listNode.First()).Oriented(TopAbs_FORWARD); aBuilder.Add(anEdge,aLocalEdge); aLocalEdge = V2New.Oriented(TopAbs_REVERSED); //(listNode.Last()).Oriented(TopAbs_REVERSED); aBuilder.Add(anEdge,aLocalEdge); Standard_Integer k =1; for( ; k <= aSeqNMVert.Length(); k++) aBuilder.Add(anEdge,aSeqNMVert.Value(k)); } // Retrieve second PCurves TopLoc_Location loc2; Handle(Geom_Surface) surf2; //Handle(Geom2d_Curve) c2d2, c2d21; // Standard_Real firstOld, lastOld; TopTools_ListIteratorOfListOfShape itf2; if (whichSec == 1) itf2.Initialize(listFacesLast); else itf2.Initialize(listFacesFirst); Standard_Boolean isResEdge = Standard_False; for (; itf2.More(); itf2.Next()) { Handle(Geom2d_Curve) c2d2, c2d21; Standard_Real firstOld, lastOld; const TopoDS_Face& fac2 = TopoDS::Face(itf2.Value()); surf2 = BRep_Tool::Surface(fac2, loc2); Standard_Boolean isSeam2 = ((IsUClosedSurface(surf2,edge2,loc2) || IsVClosedSurface(surf2,edge2,loc2)) && BRep_Tool::IsClosed(TopoDS::Edge(edge2),fac2)); if (isSeam2) { if (!myNonmanifold) return TopoDS_Edge(); TopoDS_Shape aTmpShape = edge2.Reversed(); //for porting c2d21 = BRep_Tool::CurveOnSurface(TopoDS::Edge(aTmpShape), fac2, firstOld, lastOld); } c2d2 = BRep_Tool::CurveOnSurface(edge2, fac2, firstOld, lastOld); if (c2d2.IsNull() && c2d21.IsNull()) continue; if (!c2d21.IsNull()) { c2d21 = Handle(Geom2d_Curve)::DownCast(c2d21->Copy()); if (!secForward) { if (c2d21->IsKind(STANDARD_TYPE(Geom2d_Line))) c2d21 = new Geom2d_TrimmedCurve(c2d21, firstOld, lastOld); Standard_Real first2d = firstOld; //c2dTmp->FirstParameter(); BUG USA60321 Standard_Real last2d = lastOld; //c2dTmp->LastParameter(); firstOld = c2d21->ReversedParameter(last2d); lastOld = c2d21->ReversedParameter(first2d); c2d21->Reverse(); } c2d21 = SameRange(c2d21,firstOld,lastOld,first,last); } // Make second PCurve sameRange with the 3d curve c2d2 = Handle(Geom2d_Curve)::DownCast(c2d2->Copy()); if (!secForward) { if (c2d2->IsKind(STANDARD_TYPE(Geom2d_Line))) c2d2 = new Geom2d_TrimmedCurve(c2d2, firstOld, lastOld); Standard_Real first2d = firstOld; Standard_Real last2d = lastOld; firstOld = c2d2->ReversedParameter(last2d); lastOld = c2d2->ReversedParameter(first2d); c2d2->Reverse(); } c2d2 = SameRange(c2d2,firstOld,lastOld,first,last); if (c2d2.IsNull()) continue; // Add second PCurve Standard_Boolean isSeam = Standard_False; TopAbs_Orientation Ori = TopAbs_FORWARD; //Handle(Geom2d_Curve) c2d1, c2d11; TopTools_ListIteratorOfListOfShape itf1; if (whichSec == 1) itf1.Initialize(listFacesFirst); else itf1.Initialize(listFacesLast); for (; itf1.More() && !isSeam; itf1.Next()) { Handle(Geom2d_Curve) c2d1, c2d11; const TopoDS_Face& fac1 = TopoDS::Face(itf1.Value()); TopLoc_Location loc1; Handle(Geom_Surface) surf1 = BRep_Tool::Surface(fac1, loc1); Standard_Real first2d, last2d; Standard_Boolean isSeam1 = ((IsUClosedSurface(surf1,edge1,loc1) || IsVClosedSurface(surf1,edge1,loc1)) && BRep_Tool::IsClosed(TopoDS::Edge(edge1),fac1)); c2d1 = BRep_Tool::CurveOnSurface(edge1, fac1, first2d, last2d); Ori = edge1.Orientation(); if (fac1.Orientation() == TopAbs_REVERSED) Ori = TopAbs::Reverse(Ori); if (isSeam1) { if (!myNonmanifold) return TopoDS_Edge(); TopoDS_Shape aTmpShape = edge1.Reversed(); //for porting c2d11 = BRep_Tool::CurveOnSurface(TopoDS::Edge(aTmpShape), fac1, first2d, last2d); //if(fac1.Orientation() == TopAbs_REVERSED) // if(Ori == TopAbs_FORWARD) aBuilder.UpdateEdge(edge,c2d1,c2d11,fac1,0); else aBuilder.UpdateEdge(edge,c2d11,c2d1,fac1,0); } else aBuilder.UpdateEdge(edge,c2d1,fac1,0); if (c2d1.IsNull() && c2d11.IsNull()) continue; if (surf2 == surf1) { // Merge sections which are on the same face if (!loc2.IsDifferent(loc1)) { Standard_Boolean uclosed = IsUClosedSurface(surf2,edge2,loc2); Standard_Boolean vclosed = IsVClosedSurface(surf2,edge2,loc2); if (uclosed || vclosed) { Standard_Real pf = c2d1->FirstParameter(); // Standard_Real pl = c2d1->LastParameter(); gp_Pnt2d p1n = c2d1->Value(Max(first,pf)); // gp_Pnt2d p2n = c2d1->Value(Min(pl,last)); gp_Pnt2d p21n = c2d2->Value(Max(first,c2d2->FirstParameter())); gp_Pnt2d p22n = c2d2->Value(Min(last,c2d2->LastParameter())); Standard_Real aDist = Min(p1n.Distance(p21n), p1n.Distance(p22n)); Standard_Real U1, U2, V1, V2; surf2->Bounds(U1, U2, V1, V2); isSeam = ((uclosed && aDist > 0.75*(fabs(U2-U1))) || (vclosed && aDist > 0.75*(fabs(V2-V1)))); if( !isSeam && BRep_Tool::IsClosed(TopoDS::Edge(edge),fac1)) continue; } } } isResEdge = Standard_True; if (isSeam) { if (Ori == TopAbs_FORWARD) aBuilder.UpdateEdge(edge, c2d1, c2d2, surf2, loc2, Precision::Confusion()); else aBuilder.UpdateEdge(edge, c2d2, c2d1, surf2, loc2, Precision::Confusion()); } else if (isSeam2) { TopAbs_Orientation InitOri = edge2.Orientation(); TopAbs_Orientation SecOri = edge.Orientation(); if (fac2.Orientation() == TopAbs_REVERSED) { InitOri = TopAbs::Reverse(InitOri); SecOri = TopAbs::Reverse(SecOri); } if(!secForward) InitOri = TopAbs::Reverse(InitOri); if (InitOri == TopAbs_FORWARD) aBuilder.UpdateEdge(edge, c2d2,c2d21, surf2, loc2, Precision::Confusion()); else aBuilder.UpdateEdge(edge, c2d21,c2d2, surf2, loc2, Precision::Confusion()); } else { aBuilder.UpdateEdge(edge, c2d2, surf2, loc2, Precision::Confusion()); } } } if(isResEdge) // Try to make the edge sameparameter SameParameter(edge); // Standard_Real tolReached = BRep_Tool::Tolerance(edge); //if (!BRep_Tool::SameParameter(edge)) return edge; //gka ???????? if (firstCall && (!BRep_Tool::SameParameter(edge) || !isResEdge)) { Standard_Integer whichSecn = whichSec; // Try to merge on the second section Standard_Boolean second_ok = Standard_True; TopoDS_Edge s_edge = SameParameterEdge(edgeFirst,edgeLast,listFacesFirst,listFacesLast, secForward,whichSecn,Standard_False); //if (s_edge.IsNull()) return s_edge; // gka version for free edges if (s_edge.IsNull()) second_ok = Standard_False; else if (!BRep_Tool::SameParameter(s_edge)) second_ok = Standard_False; else { edge = s_edge; whichSec = whichSecn; } if (!second_ok) { GeomAdaptor_Curve c3dAdapt(c3d); // Discretize edge curve Standard_Integer i, j, nbp = 15; Standard_Real deltaT = (last3d - first3d) / (nbp + 1); TColgp_Array1OfPnt c3dpnt(1,nbp); for (i = 1; i <= nbp; i++) c3dpnt(i) = c3dAdapt.Value(first3d + i*deltaT); Standard_Real u, v, dist, maxTol = -1.0; Standard_Boolean more = Standard_True; for (j = 1; more; j++) { Handle(Geom2d_Curve) c2d2; BRep_Tool::CurveOnSurface(edge, c2d2, surf2, loc2, first, last, j); more = !c2d2.IsNull(); if (more) { deltaT = (last - first) / (nbp + 1); for (i = 1; i <= nbp; i++) { c2d2->Value(first + i*deltaT).Coord(u,v); dist = surf2->Value(u,v).Distance(c3dpnt(i)); if (dist > maxTol) maxTol = dist; } } } if (maxTol >= 0.) aBuilder.UpdateEdge(edge, maxTol); aBuilder.SameParameter(edge,Standard_True); } } BRepLib::EncodeRegularity(edge,0.01); Standard_Real tolEdge1 = BRep_Tool::Tolerance(edge); if (tolEdge1 > MaxTolerance()) edge.Nullify(); return edge; } //======================================================================= // function : EvaluateAngulars // purpose : internal use //======================================================================= void BRepBuilderAPI_Sewing::EvaluateAngulars(TopTools_SequenceOfShape& sequenceSec, TColStd_Array1OfBoolean& secForward, TColStd_Array1OfReal& tabAng, const Standard_Integer indRef) const { tabAng.Init(-1.0); Standard_Integer i, j, npt = 4, lengSec = sequenceSec.Length(); TopoDS_Edge edge; TopoDS_Face face; TopLoc_Location loc; Standard_Real first, last; Handle(Geom_Curve) c3d; Handle(Geom2d_Curve) c2d; Handle(Geom_Surface) surf; TColgp_Array1OfVec normRef(1,npt); for (i = indRef; i <= lengSec; i++) { edge = TopoDS::Edge(sequenceSec(i)); TopoDS_Shape bnd = edge; if (mySectionBound.IsBound(bnd)) bnd = mySectionBound(bnd); if (myBoundFaces.Contains(bnd)) { face = TopoDS::Face(myBoundFaces.FindFromKey(bnd).First()); surf = BRep_Tool::Surface(face,loc); if (!loc.IsIdentity()) { surf = Handle(Geom_Surface)::DownCast(surf->Copy()); surf->Transform(loc.Transformation()); } c2d = BRep_Tool::CurveOnSurface(edge, face, first, last); } else if (i == indRef) return; else continue; c3d = BRep_Tool::Curve(edge, loc, first, last); if (!loc.IsIdentity()) { c3d = Handle(Geom_Curve)::DownCast(c3d->Copy()); c3d->Transform(loc.Transformation()); } GeomAdaptor_Curve adapt(c3d); GCPnts_UniformAbscissa uniAbs(adapt, npt, first, last); Standard_Real cumulateAngular = 0.0; Standard_Integer nbComputedAngle = 0; for (j = 1; j <= npt; j++) { gp_Pnt2d P; c2d->D0(uniAbs.Parameter((secForward(i) || i == indRef)? j : npt-j+1),P); gp_Vec w1, w2; gp_Pnt unused; surf->D1(P.X(), P.Y(), unused, w1, w2); gp_Vec n = w1^w2; // Compute the normal vector if (i == indRef) normRef(j) = n; else if ((n.Magnitude()>gp::Resolution()) && (normRef(j).Magnitude()>gp::Resolution())) { nbComputedAngle++; Standard_Real angular = n.Angle(normRef(j)); if (angular > M_PI/2.) angular = M_PI - angular; cumulateAngular += angular; } } if (nbComputedAngle) tabAng(i) = cumulateAngular/((Standard_Real)nbComputedAngle); } } //======================================================================= // function : EvaluateDistances // purpose : internal use // Evaluate distance beetween edges with indice indRef and the following edges in the list // Remarks (lengSec - indRef) must be >= 1 //======================================================================= void BRepBuilderAPI_Sewing::EvaluateDistances(TopTools_SequenceOfShape& sequenceSec, TColStd_Array1OfBoolean& secForward, TColStd_Array1OfReal& tabDst, TColStd_Array1OfReal& arrLen, TColStd_Array1OfReal& tabMinDist, const Standard_Integer indRef) const { secForward.Init(Standard_True); tabDst.Init(-1.0); arrLen.Init(0.); tabMinDist.Init(Precision::Infinite()); const Standard_Integer npt = 8; // Number of points for curve discretization TColgp_Array1OfPnt ptsRef(1, npt), ptsSec(1, npt); Standard_Integer i, j, lengSec = sequenceSec.Length(); TColgp_SequenceOfPnt seqSec; Handle(Geom_Curve) c3dRef; Standard_Real firstRef=0., lastRef=0.; for (i = indRef; i <= lengSec; i++) { // reading of the edge (attention for the first one: reference) const TopoDS_Edge& sec = TopoDS::Edge(sequenceSec(i)); TopLoc_Location loc; Standard_Real first, last; Handle(Geom_Curve) c3d = BRep_Tool::Curve(sec, loc, first, last); if (!loc.IsIdentity()) { c3d = Handle(Geom_Curve)::DownCast(c3d->Copy()); c3d->Transform(loc.Transformation()); } if (i == indRef) { c3dRef = c3d; firstRef = first; lastRef = last; } Standard_Real dist = Precision::Infinite(), distFor = -1.0, distRev = -1.0; Standard_Real aMinDist = Precision::Infinite(); Standard_Real T, deltaT = (last - first) / (npt - 1); Standard_Real aLenSec2 = 0.; Standard_Integer nbFound = 0; for (j = 1; j <= npt; j++) { // Uniform parameter on curve if (j == 1) T = first; else if (j == npt) T = last; else T = first + (j - 1) * deltaT; // Take point on curve gp_Pnt pt = c3d->Value(T); if (i == indRef) { ptsRef(j) = pt; if(j > 1) aLenSec2 += pt.SquareDistance(ptsRef(j-1)); } else { ptsSec(j) = pt; //protection to avoid merging with small sections if(j > 1) aLenSec2 += pt.SquareDistance(ptsSec(j-1)); // To evaluate mutual orientation and distance dist = pt.Distance(ptsRef(j)); if(aMinDist > dist) aMinDist = dist; if (distFor < dist) distFor = dist; dist = pt.Distance(ptsRef(npt-j+1)); if(aMinDist > dist) aMinDist = dist; if (distRev < dist) distRev = dist; // Check that point lays between vertices of reference curve const gp_Pnt &p11 = ptsRef(1); const gp_Pnt &p12 = ptsRef(npt); const gp_Vec aVec1(pt,p11); const gp_Vec aVec2(pt,p12); const gp_Vec aVecRef(p11,p12); if((aVecRef * aVec1) * (aVecRef * aVec2) < 0.) nbFound++; } } Standard_Real aLenSec = sqrt(aLenSec2); //if(aLenSec < myMinTolerance ) // continue; arrLen.SetValue(i,aLenSec); // Record mutual orientation Standard_Boolean isForward = (distFor < distRev); //szv debug: <= secForward(i) = isForward; dist = (isForward? distFor : distRev); if(i == indRef || (dist < myTolerance && nbFound >= npt * 0.5) ) { tabDst(i) = dist; tabMinDist(i) = aMinDist; } else { nbFound = 0, aMinDist = Precision::Infinite(), dist = -1; TColgp_Array1OfPnt arrProj(1, npt); TColStd_Array1OfReal arrDist(1, npt), arrPara(1, npt); if( arrLen(indRef) >= arrLen(i)) ProjectPointsOnCurve(ptsSec,c3dRef,firstRef,lastRef,arrDist,arrPara,arrProj,Standard_False); else ProjectPointsOnCurve(ptsRef,c3d,first,last,arrDist,arrPara,arrProj,Standard_False); for( j = 1; j <= npt; j++ ) { if(arrDist(j) < 0.) continue; if(dist < arrDist(j)) dist = arrDist(j); if( aMinDist > arrDist(j)) aMinDist = arrDist(j); nbFound++; } if(nbFound > 1) { tabDst(i) = dist; tabMinDist(i) = aMinDist; } } } /* // Project distant points Standard_Integer nbFailed = seqSec.Length(); if (!nbFailed) return; TColgp_Array1OfPnt arrPnt(1, nbFailed), arrProj(1, nbFailed); for (i = 1; i <= nbFailed; i++) arrPnt(i) = seqSec(i); seqSec.Clear(); TColStd_Array1OfReal arrDist(1, nbFailed), arrPara(1, nbFailed); ProjectPointsOnCurve(arrPnt,c3dRef,firstRef,lastRef,arrDist,arrPara,arrProj,Standard_False); // Process distant sections Standard_Integer idx1 = 1; for (i = indRef + 1; i <= lengSec; i++) { // Skip section if already evaluated if (tabDst(i) >= 0.0) continue; Standard_Real dist, distMax = -1.0, aMinDist = Precision::Infinite(); Standard_Integer idx2 = (idx1 - 1)*npt; for (j = 1; j <= npt; j++) { dist = arrDist(idx2 + j); // If point is not projected - stop evaluation if (dist < 0.0) { distMax = -1.0; break; } if (distMax < dist) distMax = dist; if(aMinDist > dist) aMinDist = dist; } // If section is close - record distance if (distMax >= 0.0) { if (secForward(i)) { dist = arrPnt(idx2+1).Distance(ptsRef(1)); if (distMax < dist) distMax = dist; if(aMinDist > dist) aMinDist = dist; dist = arrPnt(idx2+npt).Distance(ptsRef(npt)); if (distMax < dist) distMax = dist; if(aMinDist > dist) aMinDist = dist; } else { dist = arrPnt(idx2+1).Distance(ptsRef(npt)); if (distMax < dist) distMax = dist; if(aMinDist > dist) aMinDist = dist; dist = arrPnt(idx2+npt).Distance(ptsRef(1)); if (distMax < dist) distMax = dist; if(aMinDist > dist) aMinDist = dist; } if (distMax < myTolerance) { tabDst(i) = distMax; tabMinDist(i) = aMinDist; } } idx1++; // To the next distant curve }*/ } //======================================================================= //function : IsMergedClosed //purpose : internal use //======================================================================= Standard_Boolean BRepBuilderAPI_Sewing::IsMergedClosed(const TopoDS_Edge& Edge1, const TopoDS_Edge& Edge2, const TopoDS_Face& face) const { // Check for closed surface TopLoc_Location loc; Handle(Geom_Surface) surf = BRep_Tool::Surface(face,loc); Standard_Boolean isUClosed = IsUClosedSurface(surf,Edge1,loc); Standard_Boolean isVClosed = IsVClosedSurface(surf,Edge1,loc); if (!isUClosed && !isVClosed) return Standard_False; // Check condition on closed surface /* Standard_Real first1,last1,first2,last2; Handle(Geom_Curve) C3d1 = BRep_Tool::Curve(Edge1,first1,last1); Handle(Geom_Curve) C3d2 = BRep_Tool::Curve(Edge2,first2,last2); if (C3d1.IsNull() || C3d2.IsNull()) return Standard_False; */ Standard_Real first2d1,last2d1,first2d2,last2d2; Handle(Geom2d_Curve) C2d1 = BRep_Tool::CurveOnSurface(Edge1,face,first2d1,last2d1); Handle(Geom2d_Curve) C2d2 = BRep_Tool::CurveOnSurface(Edge2,face,first2d2,last2d2); if (C2d1.IsNull() || C2d2.IsNull()) return Standard_False; /* gp_Pnt p1 = C3d1->Value(0.5*(first1 + last1)); gp_Pnt p2 = C3d1->Value(0.5*(first2 + last2)); Standard_Real dist = p1.Distance(p2); gp_Pnt2d p12d = C2d1->Value(0.5*(first2d1 + last2d1)); gp_Pnt2d p22d = C2d1->Value(0.5*(first2d2 + last2d2)); Standard_Real dist2d = p12d.Distance(p22d); GeomAdaptor_Surface Ads(BRep_Tool::Surface(face)); Standard_Real distSurf = Max(Ads.UResolution(dist), Ads.VResolution(dist)); return (dist2d*0.2 >= distSurf); */ Standard_Integer isULongC1, isULongC2, isVLongC1, isVLongC2; Standard_Real SUmin, SUmax, SVmin, SVmax; Standard_Real C1Umin, C1Vmin, C1Umax, C1Vmax; Standard_Real C2Umin, C2Vmin, C2Umax, C2Vmax; { //szv: Use brackets to destroy local variables Bnd_Box2d B1, B2; Geom2dAdaptor_Curve aC2d1(C2d1), aC2d2(C2d2); BndLib_Add2dCurve::Add(aC2d1,first2d1,last2d1,Precision::PConfusion(),B1); BndLib_Add2dCurve::Add(aC2d2,first2d2,last2d2,Precision::PConfusion(),B2); B1.Get(C1Umin,C1Vmin,C1Umax,C1Vmax); B2.Get(C2Umin,C2Vmin,C2Umax,C2Vmax); Standard_Real du, dv; du = (C1Umax - C1Umin); dv = (C1Vmax - C1Vmin); isULongC1 = (dv <= du); isVLongC1 = (du <= dv); du = (C2Umax - C2Umin); dv = (C2Vmax - C2Vmin); isULongC2 = (dv <= du); isVLongC2 = (du <= dv); surf->Bounds(SUmin,SUmax,SVmin,SVmax); } if (isUClosed && isVLongC1 && isVLongC2) { // Do not merge if not overlapped by V Standard_Real dist = Max((C2Vmin - C1Vmax),(C1Vmin - C2Vmax)); if (dist < 0.0) { Standard_Real distInner = Max((C2Umin - C1Umax),(C1Umin - C2Umax)); Standard_Real distOuter = (SUmax - SUmin) - Max((C2Umax - C1Umin),(C1Umax - C2Umin)); if (distOuter <= distInner) return Standard_True; } } if (isVClosed && isULongC1 && isULongC2) { // Do not merge if not overlapped by U Standard_Real dist = Max((C2Umin - C1Umax),(C1Umin - C2Umax)); if (dist < 0.0) { Standard_Real distInner = Max((C2Vmin - C1Vmax),(C1Vmin - C2Vmax)); Standard_Real distOuter = (SVmax - SVmin) - Max((C2Vmax - C1Vmin),(C1Vmax - C2Vmin)); if (distOuter <= distInner) return Standard_True; } } return Standard_False; } //======================================================================= //function : AnalysisNearestEdges //purpose : //======================================================================= void BRepBuilderAPI_Sewing::AnalysisNearestEdges(const TopTools_SequenceOfShape& sequenceSec, TColStd_SequenceOfInteger& seqIndCandidate, TColStd_SequenceOfInteger& seqOrientations, const Standard_Boolean evalDist) { Standard_Integer workIndex = seqIndCandidate.First(); TopoDS_Shape workedge = sequenceSec.Value(workIndex); TopoDS_Shape bnd = workedge; TopTools_ListOfShape workfaces; if (mySectionBound.IsBound(bnd)) bnd = mySectionBound(bnd); if (myBoundFaces.Contains(bnd)) workfaces = myBoundFaces.FindFromKey(bnd); if(workfaces.IsEmpty()) return; TopTools_MapOfShape mapFaces; TopTools_ListIteratorOfListOfShape lIt; for (lIt.Initialize(workfaces); lIt.More(); lIt.Next()) mapFaces.Add(lIt.Value()); TColStd_SequenceOfInteger seqNotCandidate; TColStd_SequenceOfInteger seqNewForward; // Separates edges belonging the same face as work edge // for exception of edges belonging closed faces seqNotCandidate.Append(workIndex); for(Standard_Integer i = 1; i<= seqIndCandidate.Length(); ) { Standard_Integer index = seqIndCandidate.Value(i); Standard_Boolean isRemove = Standard_False; if(index == workIndex) { seqIndCandidate.Remove(i); seqOrientations.Remove(i); isRemove = Standard_True; } if(!isRemove) { TopoDS_Shape bnd2 = sequenceSec.Value(index); if (mySectionBound.IsBound(bnd2)) bnd2 = mySectionBound(bnd2); if(myBoundFaces.Contains(bnd2)) { const TopTools_ListOfShape& listfaces = myBoundFaces.FindFromKey(bnd2); Standard_Boolean isMerged = Standard_True; for (lIt.Initialize(listfaces); lIt.More() && isMerged; lIt.Next()) { if(mapFaces.Contains(lIt.Value())) { TopLoc_Location loc; Handle(Geom_Surface) surf = BRep_Tool::Surface(TopoDS::Face(lIt.Value()),loc); isMerged = ((IsUClosedSurface(surf,bnd2,loc) || IsVClosedSurface(surf,bnd2,loc)) && IsMergedClosed(TopoDS::Edge(sequenceSec.Value(index)),TopoDS::Edge(workedge),TopoDS::Face(lIt.Value()))); } } if(!isMerged) { seqNotCandidate.Append(index); seqIndCandidate.Remove(i); seqOrientations.Remove(i); isRemove = Standard_True; } } else { seqIndCandidate.Remove(i); seqOrientations.Remove(i); isRemove = Standard_True; } } if(!isRemove) i++; } if(seqIndCandidate.Length() == 0 || seqNotCandidate.Length() == 1) return; if(!evalDist) return; TColStd_Array2OfReal TotTabDist(1,seqNotCandidate.Length(),1,seqIndCandidate.Length()); TColStd_MapOfInteger MapIndex; TColStd_SequenceOfInteger seqForward; // Definition and removing edges wich are not candidate for work edge // ( they have other nearest edges belonging to the work face) for(Standard_Integer k = 1; k<= seqNotCandidate.Length(); k++) { Standard_Integer index1 = seqNotCandidate.Value(k); TopoDS_Shape edge = sequenceSec.Value(index1); TopTools_SequenceOfShape tmpSeq; tmpSeq.Append(edge); for(Standard_Integer kk = 1; kk <= seqIndCandidate.Length();kk++) tmpSeq.Append(sequenceSec.Value(seqIndCandidate.Value(kk))); Standard_Integer lengSec = tmpSeq.Length(); TColStd_Array1OfBoolean tabForward(1,lengSec); TColStd_Array1OfReal tabDist(1,lengSec); TColStd_Array1OfReal arrLen(1,lengSec); TColStd_Array1OfReal tabMinDist(1,lengSec); for (Standard_Integer i1 = 1 ; i1 <= lengSec; i1++) tabDist(i1) =-1; EvaluateDistances(tmpSeq,tabForward, tabDist,arrLen,tabMinDist,1 ); if(k == 1) { for(Standard_Integer n = 1; n < lengSec; n++) { if(tabDist(n+1) == -1 || tabDist(n+1) > myTolerance) { MapIndex.Add(n); continue; } TotTabDist(k,n) = tabDist(n+1 ); seqForward.Append(tabForward(n+1) ? 1:0); } } else { for(Standard_Integer n = 1; n < lengSec; n++) { if(tabDist(n) == -1 || tabDist(n) > myTolerance) continue; if(tabDist(n+1) < TotTabDist(1,n)) { MapIndex.Add(n); } } } } Standard_Integer i2 = seqIndCandidate.Length(); for( ; i2 >=1 ; i2--) { if(MapIndex.Contains(i2)) { seqIndCandidate.Remove(i2); seqOrientations.Remove(i2); } } //for(TColStd_MapIteratorOfMapOfInteger IMap(MapIndex); IMap.More(); IMap.Next()) { // seqIndCandidate.Remove(IMap.Key()); // seqOrientations.Remove(IMap.Key()); //} } //======================================================================= //function : FindCandidates //purpose : internal use //======================================================================= Standard_Boolean BRepBuilderAPI_Sewing::FindCandidates(TopTools_SequenceOfShape& seqSections, TColStd_IndexedMapOfInteger& mapReference, TColStd_SequenceOfInteger& seqCandidates, TColStd_SequenceOfInteger& seqOrientations) { Standard_Integer i, nbSections = seqSections.Length(); if(nbSections <= 1) return Standard_False; // Retrieve last reference index Standard_Integer indReference = mapReference(mapReference.Extent()); Standard_Integer nbCandidates = 0; TopTools_MapOfShape Faces1; //if (nbSections > 1) { TopoDS_Edge Edge1 = TopoDS::Edge(seqSections(indReference)); // Retrieve faces for reference section { //szv: Use brackets to destroy local variables TopoDS_Shape bnd = Edge1; if (mySectionBound.IsBound(bnd)) bnd = mySectionBound(bnd); if (myBoundFaces.Contains(bnd)) { TopTools_ListIteratorOfListOfShape itf1(myBoundFaces.FindFromKey(bnd)); for (; itf1.More(); itf1.Next()) Faces1.Add(itf1.Value()); } } // Check merging conditions for candidates and remove unsatisfactory TopTools_SequenceOfShape seqSectionsNew; TColStd_SequenceOfInteger seqCandidatesNew; for (i = 1; i <= nbSections; i++) { if (i == indReference) { seqSectionsNew.Prepend(Edge1); seqCandidatesNew.Prepend(i); } else { const TopoDS_Edge& Edge2 = TopoDS::Edge(seqSections(i)); //gka seqSectionsNew.Append(Edge2); seqCandidatesNew.Append(i); /*TopoDS_Shape bnd = Edge2; if (mySectionBound.IsBound(bnd)) bnd = mySectionBound(bnd); //gka if (myBoundFaces.Contains(bnd)) { Standard_Boolean isOK = Standard_True; TopTools_ListIteratorOfListOfShape itf2(myBoundFaces.FindFromKey(bnd)); for (; itf2.More() && isOK; itf2.Next()) { const TopoDS_Face& Face2 = TopoDS::Face(itf2.Value()); // Check whether condition is satisfied isOK = !Faces1.Contains(Face2); if (!isOK) isOK = IsMergedClosed(Edge1,Edge2,Face2); } if (isOK) { seqSectionsNew.Append(Edge2); seqCandidatesNew.Append(i); } }*/ } } Standard_Integer nbSectionsNew = seqSectionsNew.Length(); if (nbSectionsNew > 1) { // Evaluate distances between reference and other sections TColStd_Array1OfBoolean arrForward(1,nbSectionsNew); TColStd_Array1OfReal arrDistance(1,nbSectionsNew); TColStd_Array1OfReal arrLen(1,nbSectionsNew); TColStd_Array1OfReal arrMinDist(1,nbSectionsNew); EvaluateDistances(seqSectionsNew,arrForward,arrDistance,arrLen,arrMinDist,1); // Fill sequence of candidate indices sorted by distance for (i = 2; i <= nbSectionsNew; i++) { if (arrDistance(i) >= 0.0 && arrLen(i) > myMinTolerance) { // Reference section is connected to section #i Standard_Boolean isInserted = Standard_False; Standard_Integer j, ori = (arrForward(i)? 1 : 0); for (j = 1; (j <= seqCandidates.Length()) && !isInserted; j++) { Standard_Real aDelta = arrDistance(i) - arrDistance(seqCandidates.Value(j)); //if (arrDistance(i) <= arrDistance(seqCandidates.Value(j))) { if( aDelta < Precision::Confusion()) { if(fabs(aDelta) > RealSmall() || arrMinDist(i) < arrMinDist(seqCandidates.Value(j))) { seqCandidates.InsertBefore(j,i); seqOrientations.InsertBefore(j,ori); isInserted = Standard_True; } } } if (!isInserted) { seqCandidates.Append(i); seqOrientations.Append(ori); } } } // Replace candidate indices nbCandidates = seqCandidates.Length(); for (i = 1; i <= nbCandidates; i++) seqCandidates(i) = seqCandidatesNew(seqCandidates(i)); } //} if (!nbCandidates) return Standard_False; // Section has no candidates to merge if (myNonmanifold && nbCandidates >1) { TColStd_SequenceOfInteger seqNewCandidates; TColStd_SequenceOfInteger seqOrientationsNew; seqCandidates.Prepend(1); seqOrientations.Prepend(1); for(Standard_Integer k = 1; k <= seqSections.Length() && seqCandidates.Length() > 1 ; k++) { AnalysisNearestEdges(seqSections,seqCandidates,seqOrientations,(k==1)); if(k == 1 && !seqCandidates.Length()) return Standard_False; if(seqCandidates.Length()) { seqNewCandidates.Append(seqCandidates.First()); seqOrientationsNew.Append(seqOrientations.First()); } } seqCandidates.Prepend(seqNewCandidates); seqOrientations.Prepend(seqOrientationsNew); return Standard_True; } else { // For manifold case leave only one candidate from equidistant candidates /*Standard_Integer minIndex = seqCandidateIndex.First(); Standard_Real minDistance = arrDistance(minIndex); // Find equidistant candidates TColStd_SequenceOfInteger seqEqDistantIndex; seqEqDistantIndex.Append(1); for (i = 2; i <= nbCandidates; i++) { Standard_Integer index = seqCandidateIndex(i); if (Abs(minDistance - arrDistance(index)) <= Precision::Confusion()) seqEqDistantIndex.Append(index); } Standard_Integer eqLen = seqEqDistantIndex.Length(); if (eqLen > 2) { // Fill map of faces which equidistant sections belong to TopTools_MapOfShape mapFace; for (i = 1; i <= eqLen; i++) { Standard_Integer index = seqEqDistantIndex.Value(i); if (isCandidate(index)) { mapFace.Add(arrFace(index)); } } // Non Manifold case // Edges are merged by pair among a face continuity C1 criterion if (mapFace.Extent() == eqLen) { tabDist.Init(-1); tabMinInd.Init(-1); min=10000000.; //indMin = -1; Standard_Integer indMin = -1;// To check if the edge can be merged. // Computation of distances between the edges. TopTools_SequenceOfShape seqSh; Standard_Integer nbInd = EqDistSeq.Length(); TColStd_Array1OfBoolean tmptabForward(1,nbInd); seqSh.Append(sequenceSec.Value(1)); for (j = 2; j <= EqDistSeq.Length(); j++) { Standard_Integer index = EqDistSeq.Value(j); tmptabForward(j) = tabForward(index); seqSh.Append(sequenceSec.Value(index)); } EvaluateAngulars(seqSh, tmptabForward, tabDist,1); for(j=2; j <= seqSh.Length(); j++) { if (tabDist(j) > -1.) { // if edge(j) is connected to edge(i) if (min > tabDist(j)) { min = tabDist(j); indMin = j; } } } // Construct minDist, tabMinInd , tabMinForward(i) = tabForward(j); if (indMin > 0) { seqSh.Remove(indMin); for(j =2; j <= tmpSeq.Length(); ) { TopoDS_Shape sh = tmpSeq.Value(j); Standard_Boolean isRem = Standard_False; for(Standard_Integer k = 1; k<= seqSh.Length();k++) { if(seqSh.Value(k) == sh) { isRem = Standard_True; break; } } if(isRem) { tmpSeq.Remove(j); tabMinForward.Remove(j); // = -1; } else j++; } } } }*/ // Find the best approved candidate while (nbCandidates) { // Retrieve first candidate Standard_Integer indCandidate = seqCandidates.First(); // Candidate is approved if it is in the map if (mapReference.Contains(indCandidate)) break; // Find candidates for candidate #indCandidate mapReference.Add(indCandidate); // Push candidate in the map TColStd_SequenceOfInteger seqCandidates1, seqOrientations1; Standard_Boolean isFound = FindCandidates(seqSections,mapReference,seqCandidates1,seqOrientations1); mapReference.RemoveLast(); // Pop candidate from the map if (isFound) isFound = (seqCandidates1.Length() > 0); if (isFound) { Standard_Integer indCandidate1 = seqCandidates1.First(); // If indReference is the best candidate for indCandidate // then indCandidate is the best candidate for indReference if (indCandidate1 == indReference) break; // If some other reference in the map is the best candidate for indCandidate // then assume that reference is the best candidate for indReference if (mapReference.Contains(indCandidate1)) { seqCandidates.Prepend(indCandidate1); nbCandidates++; break; } isFound = Standard_False; } if (!isFound) { // Remove candidate #1 seqCandidates.Remove(1); seqOrientations.Remove(1); nbCandidates--; } } } //gka if(nbCandidates > 0) { Standard_Integer anInd = seqCandidates.Value(1); TopoDS_Edge Edge2 = TopoDS::Edge(seqSections(anInd)); TopoDS_Shape bnd = Edge2; if (mySectionBound.IsBound(bnd)) bnd = mySectionBound(bnd); //gka if (myBoundFaces.Contains(bnd)) { Standard_Boolean isOK = Standard_True; TopTools_ListIteratorOfListOfShape itf2(myBoundFaces.FindFromKey(bnd)); for (; itf2.More() && isOK; itf2.Next()) { const TopoDS_Face& Face2 = TopoDS::Face(itf2.Value()); // Check whether condition is satisfied isOK = !Faces1.Contains(Face2); if (!isOK) isOK = IsMergedClosed(Edge1,Edge2,Face2); } if(!isOK) return Standard_False; } } return (nbCandidates > 0); } //======================================================================= //function : Constructor //purpose : //======================================================================= BRepBuilderAPI_Sewing::BRepBuilderAPI_Sewing(const Standard_Real tolerance, const Standard_Boolean optionSewing, const Standard_Boolean optionAnalysis, const Standard_Boolean optionCutting, const Standard_Boolean optionNonmanifold) { myReShape = new BRepTools_ReShape; Init(tolerance, optionSewing, optionAnalysis, optionCutting, optionNonmanifold); } //======================================================================= //function : Init //purpose : Initialise Talerance, and options sewing, faceAnalysis and cutting //======================================================================= void BRepBuilderAPI_Sewing::Init(const Standard_Real tolerance, const Standard_Boolean optionSewing, const Standard_Boolean optionAnalysis, const Standard_Boolean optionCutting, const Standard_Boolean optionNonmanifold) { // Set tolerance and Perform options myTolerance = tolerance; mySewing = optionSewing; myAnalysis = optionAnalysis; myCutting = optionCutting; myNonmanifold = optionNonmanifold; // Set min and max tolerances myMinTolerance = tolerance*1e-4; //szv: proposal if (myMinTolerance < Precision::Confusion()) myMinTolerance = Precision::Confusion(); myMaxTolerance = Precision::Infinite(); // Set other modes myFaceMode = Standard_True; myFloatingEdgesMode = Standard_False; //myCuttingFloatingEdgesMode = Standard_False; //gka mySameParameterMode = Standard_True; myLocalToleranceMode = Standard_False; mySewedShape.Nullify(); // Load empty shape Load(TopoDS_Shape()); } //======================================================================= //function : Load //purpose : Loads the context shape //======================================================================= void BRepBuilderAPI_Sewing::Load(const TopoDS_Shape& theShape) { myReShape->Clear(); if (theShape.IsNull()) myShape.Nullify(); else myShape = myReShape->Apply(theShape); mySewedShape.Nullify(); // Nullify flags and counters myNbShapes = myNbEdges = myNbVertices = 0; // Clear all maps myOldShapes.Clear(); //myOldFaces.Clear(); myDegenerated.Clear(); myFreeEdges.Clear(); myMultipleEdges.Clear(); myContigousEdges.Clear(); myContigSecBound.Clear(); myBoundFaces.Clear(); myBoundSections.Clear(); myVertexNode.Clear(); myVertexNodeFree.Clear(); myNodeSections.Clear(); myCuttingNode.Clear(); mySectionBound.Clear(); myLittleFace.Clear(); } //======================================================================= //function : Add //purpose : //======================================================================= void BRepBuilderAPI_Sewing::Add(const TopoDS_Shape& aShape) { if (aShape.IsNull()) return; TopoDS_Shape oShape = myReShape->Apply(aShape); myOldShapes.Add(aShape,oShape); myNbShapes = myOldShapes.Extent(); } //======================================================================= //function : Perform //purpose : //======================================================================= #ifdef DEB #include #endif void BRepBuilderAPI_Sewing::Perform(const Handle(Message_ProgressIndicator)& thePI) { const Standard_Integer aNumberOfStages = myAnalysis + myCutting + mySewing + 2; Message_ProgressSentry aPS (thePI, "Sewing", 0, aNumberOfStages, 1); #ifdef DEB Standard_Real t_total = 0., t_analysis = 0., t_assembling = 0., t_cutting = 0., t_merging = 0.; OSD_Chronometer chr_total, chr_local; chr_total.Reset(); chr_total.Start(); #endif // face analysis if (myAnalysis) { #if DEB cout << "Begin face analysis..." << endl; chr_local.Reset(); chr_local.Start(); #endif FaceAnalysis (thePI); if (!aPS.More()) return; aPS.Next(); #if DEB chr_local.Stop(); chr_local.Show(t_analysis); cout << "Face analysis finished after " << t_analysis << " s" << endl; #endif } if (myNbShapes || !myShape.IsNull()) { FindFreeBoundaries(); if (myBoundFaces.Extent()) { #if DEB cout << "Begin vertices assembling..." << endl; chr_local.Reset(); chr_local.Start(); #endif VerticesAssembling (thePI); if (!aPS.More()) return; aPS.Next(); #if DEB chr_local.Stop(); chr_local.Show(t_assembling); cout << "Vertices assembling finished after " << t_assembling << " s" << endl; #endif if (myCutting) { #if DEB cout << "Begin cutting..." << endl; chr_local.Reset(); chr_local.Start(); #endif Cutting (thePI); if (!aPS.More()) return; aPS.Next(); #if DEB chr_local.Stop(); chr_local.Show(t_cutting); cout << "Cutting finished after " << t_cutting << " s" << endl; #endif } #if DEB cout << "Begin merging..." << endl; chr_local.Reset(); chr_local.Start(); #endif Merging (Standard_True, thePI); if (!aPS.More()) return; aPS.Next(); #if DEB chr_local.Stop(); chr_local.Show(t_merging); cout << "Merging finished after " << t_merging << " s" << endl; #endif } else { aPS.Next( 1, Handle(TCollection_HAsciiString)()); if (myCutting) aPS.Next( 1, Handle(TCollection_HAsciiString)()); aPS.Next( 1, Handle(TCollection_HAsciiString)()); if (!aPS.More()) return; } if (mySewing) { #if DEB cout << "Creating sewed shape..." << endl; #endif // examine the multiple edges if any and process sameparameter for edges if necessary EdgeProcessing (thePI); if (!aPS.More()) return; CreateSewedShape(); if (!aPS.More()) { mySewedShape.Nullify(); return; } if (mySameParameterMode && myFaceMode) SameParameterShape(); if (!aPS.More()) { mySewedShape.Nullify(); return; } #if DEB cout << "Sewed shape created" << endl; #endif } // create edge informations for output CreateOutputInformations(); if (!aPS.More()) { mySewedShape.Nullify(); return; } } #if DEB chr_total.Stop(); chr_total.Show(t_total); cout << "Sewing finished!" << endl; cout << " analysis time : " << t_analysis << " s" << endl; cout << " assembling time : " << t_assembling << " s" << endl; cout << " cutting time : " << t_cutting << " s" << endl; cout << " merging time : " << t_merging << " s" << endl; cout << "Total time : " << t_total << " s" << endl; #endif } //======================================================================= //function : SewedShape //purpose : give the sewed shape // if a null shape, reasons: // -- no useable input shapes : all input shapes are degenerated // -- has multiple edges //======================================================================= const TopoDS_Shape& BRepBuilderAPI_Sewing::SewedShape() const { return mySewedShape; } //======================================================================= //function : NbFreeEdges //purpose : //======================================================================= Standard_Integer BRepBuilderAPI_Sewing::NbFreeEdges() const { return myFreeEdges.Extent(); } //======================================================================= //function : FreeEdge //purpose : //======================================================================= const TopoDS_Edge& BRepBuilderAPI_Sewing::FreeEdge(const Standard_Integer index) const { Standard_OutOfRange_Raise_if(index < 0 || index > NbFreeEdges(), "BRepBuilderAPI_Sewing::FreeEdge"); return TopoDS::Edge(myFreeEdges(index)); } //======================================================================= //function : NbMultipleEdges //purpose : //======================================================================= Standard_Integer BRepBuilderAPI_Sewing::NbMultipleEdges() const { return myMultipleEdges.Extent(); } //======================================================================= //function : MultipleEdge //purpose : //======================================================================= const TopoDS_Edge& BRepBuilderAPI_Sewing::MultipleEdge(const Standard_Integer index) const { Standard_OutOfRange_Raise_if(index < 0 || index > NbMultipleEdges(), "BRepBuilderAPI_Sewing::MultipleEdge"); return TopoDS::Edge(myMultipleEdges(index)); } //======================================================================= //function : NbContigousEdges //purpose : //======================================================================= Standard_Integer BRepBuilderAPI_Sewing::NbContigousEdges() const { return myContigousEdges.Extent(); } //======================================================================= //function : ContigousEdge //purpose : //======================================================================= const TopoDS_Edge& BRepBuilderAPI_Sewing::ContigousEdge(const Standard_Integer index) const { Standard_OutOfRange_Raise_if(index < 0 || index > NbContigousEdges(), "BRepBuilderAPI_Sewing::ContigousEdge"); return TopoDS::Edge(myContigousEdges.FindKey(index)); } //======================================================================= //function : ContigousEdgeCouple //purpose : //======================================================================= const TopTools_ListOfShape& BRepBuilderAPI_Sewing::ContigousEdgeCouple(const Standard_Integer index) const { Standard_OutOfRange_Raise_if(index < 0 || index > NbContigousEdges(), "BRepBuilderAPI_Sewing::ContigousEdgeCouple"); return myContigousEdges(index); } //======================================================================= //function : IsSectionBound //purpose : //======================================================================= Standard_Boolean BRepBuilderAPI_Sewing::IsSectionBound(const TopoDS_Edge& section) const { if(myContigSecBound.IsBound(section)) { return Standard_True; } else { return Standard_False; } } //======================================================================= //function : SectionToBoundary //purpose : //======================================================================= const TopoDS_Edge& BRepBuilderAPI_Sewing::SectionToBoundary(const TopoDS_Edge& section) const { Standard_NoSuchObject_Raise_if(!IsSectionBound(section), "BRepBuilderAPI_Sewing::SectionToBoundary"); return TopoDS::Edge(myContigSecBound(section)); } //======================================================================= //function : NbDeletedFaces //purpose : //======================================================================= Standard_Integer BRepBuilderAPI_Sewing::NbDeletedFaces() const { return myLittleFace.Extent(); } //======================================================================= //function : DeletedFace //purpose : //======================================================================= const TopoDS_Face& BRepBuilderAPI_Sewing::DeletedFace(const Standard_Integer index) const { Standard_OutOfRange_Raise_if(index < 0 || index > NbDeletedFaces(), "BRepBuilderAPI_Sewing::DeletedFace"); return TopoDS::Face(myLittleFace(index)); } //======================================================================= //function : NbDegeneratedShapes //purpose : //======================================================================= Standard_Integer BRepBuilderAPI_Sewing::NbDegeneratedShapes() const { return myDegenerated.Extent(); } //======================================================================= //function : DegeneratedShape //purpose : //======================================================================= const TopoDS_Shape& BRepBuilderAPI_Sewing::DegeneratedShape(const Standard_Integer index) const { Standard_OutOfRange_Raise_if(index < 0 || index > NbDegeneratedShapes(), "BRepBuilderAPI_Sewing::DegereratedShape"); return myDegenerated(index); } //======================================================================= //function : IsDegenerated //purpose : //======================================================================= Standard_Boolean BRepBuilderAPI_Sewing::IsDegenerated(const TopoDS_Shape& aShape) const { TopoDS_Shape NewShape = myReShape->Apply(aShape); // Degenerated face if (aShape.ShapeType() == TopAbs_FACE) return NewShape.IsNull(); if (NewShape.IsNull()) return Standard_False; // Degenerated edge if (NewShape.ShapeType() == TopAbs_EDGE) return BRep_Tool::Degenerated(TopoDS::Edge(NewShape)); // Degenerated wire if (NewShape.ShapeType() == TopAbs_WIRE) { Standard_Boolean isDegenerated = Standard_True; for (TopoDS_Iterator aIt(NewShape); aIt.More() && isDegenerated; aIt.Next()) isDegenerated = BRep_Tool::Degenerated(TopoDS::Edge(aIt.Value())); return isDegenerated; } return Standard_False; } //======================================================================= //function : IsModified //purpose : //======================================================================= Standard_Boolean BRepBuilderAPI_Sewing::IsModified(const TopoDS_Shape& aShape) const { TopoDS_Shape NewShape = aShape; if (myOldShapes.Contains(aShape)) NewShape = myOldShapes.FindFromKey(aShape); if(!NewShape.IsSame(aShape)) return Standard_True; return Standard_False; } //======================================================================= //function : Modified //purpose : //======================================================================= const TopoDS_Shape& BRepBuilderAPI_Sewing::Modified(const TopoDS_Shape& aShape) const { if (myOldShapes.Contains(aShape)) return myOldShapes.FindFromKey(aShape); //if (myOldFaces.Contains(aShape)) return myOldFaces.FindFromKey(aShape); return aShape; } //======================================================================= //function : IsModifiedSubShape //purpose : //======================================================================= Standard_Boolean BRepBuilderAPI_Sewing::IsModifiedSubShape(const TopoDS_Shape& aShape) const { TopoDS_Shape NewShape = myReShape->Apply(aShape); if(!NewShape.IsSame(aShape)) return Standard_True; return Standard_False; } //======================================================================= //function : ModifiedSubShape //purpose : //======================================================================= TopoDS_Shape BRepBuilderAPI_Sewing::ModifiedSubShape(const TopoDS_Shape& aShape) const { return myReShape->Apply(aShape); } //======================================================================= //function : Dump //purpose : //======================================================================= void BRepBuilderAPI_Sewing::Dump() const { Standard_Integer i, NbBounds = myBoundFaces.Extent(), NbSections = 0; TopTools_MapOfShape mapVertices, mapEdges; for (i = 1; i <= NbBounds; i++) { TopoDS_Shape bound = myBoundFaces.FindKey(i); if (myBoundSections.IsBound(bound)) NbSections += myBoundSections(bound).Extent(); else NbSections++; TopExp_Explorer aExp(myReShape->Apply(bound),TopAbs_EDGE); for (; aExp.More(); aExp.Next()) { TopoDS_Edge E = TopoDS::Edge(aExp.Current()); mapEdges.Add(E); TopoDS_Vertex V1, V2; TopExp::Vertices(E,V1,V2); mapVertices.Add(V1); mapVertices.Add(V2); } } cout << " " << endl; cout << " Informations " << endl; cout << " ===========================================================" << endl; cout << " " << endl; cout << " Number of input shapes : " << myOldShapes.Extent() << endl; cout << " Number of actual shapes : " << myNbShapes << endl; cout << " Number of Bounds : " << NbBounds << endl; cout << " Number of Sections : " << NbSections << endl; cout << " Number of Edges : " << mapEdges.Extent() << endl; cout << " Number of Vertices : " << myNbVertices << endl; cout << " Number of Nodes : " << mapVertices.Extent() << endl; cout << " Number of Free Edges : " << myFreeEdges.Extent() << endl; cout << " Number of Contigous Edges : " << myContigousEdges.Extent() << endl; cout << " Number of Multiple Edges : " << myMultipleEdges.Extent() << endl; cout << " Number of Degenerated Edges : " << myDegenerated.Extent() << endl; cout << " ===========================================================" << endl; cout << " " << endl; } //======================================================================= //function : FaceAnalysis //purpose : Remove // Modifies: // myNbShapes // myOldShapes // // Constructs: // myDegenerated //======================================================================= void BRepBuilderAPI_Sewing::FaceAnalysis(const Handle(Message_ProgressIndicator)& thePI) { if (!myShape.IsNull() && myOldShapes.IsEmpty()) { Add(myShape); myShape.Nullify(); } BRep_Builder B; TopTools_MapOfShape SmallEdges; TopTools_DataMapOfShapeListOfShape GluedVertices; Standard_Integer i = 1; Message_ProgressSentry aPS (thePI, "Shape analysis", 0, myOldShapes.Extent(), 1); for (i = 1; i <= myOldShapes.Extent() && aPS.More(); i++, aPS.Next()) { for (TopExp_Explorer fexp(myOldShapes(i),TopAbs_FACE); fexp.More(); fexp.Next()) { // Retrieve current face TopoDS_Shape aTmpShape = fexp.Current(); //for porting TopoDS_Face face = TopoDS::Face(aTmpShape); Standard_Integer nbEdges = 0, nbSmall = 0; // Build replacing face aTmpShape = face.EmptyCopied().Oriented(TopAbs_FORWARD); //for porting TopoDS_Face nface = TopoDS::Face(aTmpShape); Standard_Boolean isFaceChanged = Standard_False; TopoDS_Iterator witer(face.Oriented(TopAbs_FORWARD)); for (; witer.More(); witer.Next()) { // Retrieve current wire aTmpShape = witer.Value(); //for porting if( aTmpShape.ShapeType() != TopAbs_WIRE) continue; TopoDS_Wire wire = TopoDS::Wire(aTmpShape); // Build replacing wire aTmpShape = wire.EmptyCopied().Oriented(TopAbs_FORWARD); TopoDS_Wire nwire = TopoDS::Wire(aTmpShape); Standard_Boolean isWireChanged = Standard_False; TopoDS_Iterator eiter(wire.Oriented(TopAbs_FORWARD)); for (; eiter.More(); eiter.Next()) { // Retrieve current edge aTmpShape = eiter.Value(); //for porting TopoDS_Edge edge = TopoDS::Edge(aTmpShape); nbEdges++; // Process degenerated edge if (BRep_Tool::Degenerated(edge)) { B.Add(nwire,edge); // Old edge kept myDegenerated.Add(edge); nbSmall++; continue; } Standard_Boolean isSmall = SmallEdges.Contains(edge); if (!isSmall) { // Check for small edge Standard_Real first, last; Handle(Geom_Curve) c3d = BRep_Tool::Curve(edge,first,last); if (c3d.IsNull()) { #ifdef DEB cout << "Warning: Possibly small edge can be sewed: No 3D curve" << endl; #endif } else { // Evaluate curve compactness const Standard_Integer npt = 5; gp_Pnt cp((c3d->Value(first).XYZ()+c3d->Value(last).XYZ())*0.5); Standard_Real dist, maxdist = 0.0; Standard_Real delta = (last - first)/(npt - 1); for (Standard_Integer idx = 0; idx < npt; idx++) { dist = cp.Distance(c3d->Value(first + idx*delta)); if (maxdist < dist) maxdist = dist; } isSmall = (2.*maxdist <= MinTolerance()); /*try { GeomAdaptor_Curve cAdapt(c3d); Standard_Real length = GCPnts_AbscissaPoint::Length(cAdapt,first,last); isSmall = (length <= MinTolerance()); } catch (Standard_Failure) { #ifdef DEB cout << "Warning: Possibly small edge can be sewed: "; Standard_Failure::Caught()->Print(cout); cout << endl; #endif }*/ } if (isSmall) { // Store small edge in the map SmallEdges.Add(edge); TopoDS_Vertex v1, v2; TopExp::Vertices(edge,v1,v2); TopoDS_Shape nv1 = myReShape->Apply(v1), nv2 = myReShape->Apply(v2); // Store glued vertices if (!nv1.IsSame(v1)) { TopTools_ListOfShape& vlist1 = GluedVertices(nv1); // First vertex was already glued if (!nv2.IsSame(v2)) { // Merge lists of glued vertices if (!nv1.IsSame(nv2)) { TopTools_ListIteratorOfListOfShape liter(GluedVertices(nv2)); for (; liter.More(); liter.Next()) { TopoDS_Shape v = liter.Value(); myReShape->Replace(v,nv1.Oriented(v.Orientation())); vlist1.Append(v); } GluedVertices.UnBind(nv2); } } else { // Add second vertex to the existing list vlist1.Append(v2); myReShape->Replace(v2,nv1.Oriented(v2.Orientation())); } } else if (!nv2.IsSame(v2)) { // Add first vertex to the existing list GluedVertices(nv2).Append(v1); myReShape->Replace(v1,nv2.Oriented(v1.Orientation())); } else if (!v1.IsSame(v2)) { // Record new glued vertices TopoDS_Vertex nv; B.MakeVertex(nv); TopTools_ListOfShape vlist; vlist.Append(v1); vlist.Append(v2); GluedVertices.Bind(nv,vlist); myReShape->Replace(v1,nv.Oriented(v1.Orientation())); myReShape->Replace(v2,nv.Oriented(v2.Orientation())); } } } // Replace small edge if (isSmall) { #ifdef DEB cout << "Warning: Small edge made degenerated by FaceAnalysis" << endl; #endif nbSmall++; // Create new degenerated edge aTmpShape = edge.Oriented(TopAbs_FORWARD); TopoDS_Edge fedge = TopoDS::Edge(aTmpShape); Standard_Real pfirst, plast; Handle(Geom2d_Curve) c2d = BRep_Tool::CurveOnSurface(fedge,face,pfirst,plast); if (!c2d.IsNull()) { TopoDS_Edge nedge; B.MakeEdge(nedge); B.UpdateEdge(nedge,c2d,face,Precision::Confusion()); B.Range(nedge,pfirst,plast); B.Degenerated(nedge,Standard_True); TopoDS_Vertex v1, v2; TopExp::Vertices(fedge,v1,v2); B.Add(nedge,myReShape->Apply(v1).Oriented(v1.Orientation())); B.Add(nedge,myReShape->Apply(v2).Oriented(v2.Orientation())); B.Add(nwire,nedge.Oriented(edge.Orientation())); myDegenerated.Add(nedge); } isWireChanged = Standard_True; } else B.Add(nwire,edge); // Old edge kept } // Record wire in the new face if (isWireChanged) { B.Add(nface,nwire.Oriented(wire.Orientation())); isFaceChanged = Standard_True; } else B.Add(nface,wire); } // Remove small face if (nbSmall == nbEdges) { #ifdef DEB cout << "Warning: Small face removed by FaceAnalysis" << endl; #endif myLittleFace.Add(face); myReShape->Remove(face); } else if (isFaceChanged) { myReShape->Replace(face,nface.Oriented(face.Orientation())); } } } // Update glued vertices TopTools_DataMapIteratorOfDataMapOfShapeListOfShape miter(GluedVertices); for (; miter.More(); miter.Next()) { TopoDS_Vertex vnew = TopoDS::Vertex(miter.Key()); gp_XYZ coord(0.,0.,0.); Standard_Integer nbPoints = 0; const TopTools_ListOfShape& vlist = miter.Value(); TopTools_ListIteratorOfListOfShape liter1(vlist); for (; liter1.More(); liter1.Next()) { coord += BRep_Tool::Pnt(TopoDS::Vertex(liter1.Value())).XYZ(); nbPoints++; } if (nbPoints) { gp_Pnt vp(coord / nbPoints); Standard_Real tol = 0.0, mtol = 0.0; TopTools_ListIteratorOfListOfShape liter2(vlist); for (; liter2.More(); liter2.Next()) { Standard_Real vtol = BRep_Tool::Tolerance(TopoDS::Vertex(liter2.Value())); if (mtol < vtol) mtol = vtol; vtol = vp.Distance(BRep_Tool::Pnt(TopoDS::Vertex(liter2.Value()))); if (tol < vtol) tol = vtol; } B.UpdateVertex(vnew,vp,tol+mtol); } } // Update input shapes for (i = 1; i <= myOldShapes.Extent(); i++) myOldShapes(i) = myReShape->Apply(myOldShapes(i)); } //======================================================================= //function : FindFreeBoundaries //purpose : Constructs : // myBoundFaces (bound = list of faces) - REFERENCE // myVertexNode (vertex = node) // myVertexNodeFree (floating vertex = node) // //======================================================================= void BRepBuilderAPI_Sewing::FindFreeBoundaries() { // Take into account the context shape if needed TopTools_IndexedMapOfShape NewShapes; if (!myShape.IsNull()) { if (myOldShapes.IsEmpty()) { Add(myShape); myShape.Nullify(); } else { TopoDS_Shape newShape = myReShape->Apply(myShape); if (!newShape.IsNull()) NewShapes.Add(newShape); } } // Create map Edge -> Faces TopTools_IndexedDataMapOfShapeListOfShape EdgeFaces; Standard_Integer i, nbShapes = myOldShapes.Extent(); for (i = 1; i <= nbShapes; i++) { // Retrieve new shape TopoDS_Shape shape = myOldShapes(i); if (shape.IsNull()) continue; NewShapes.Add(shape); // Explore shape to find all boundaries for (TopExp_Explorer eExp(shape,TopAbs_EDGE); eExp.More(); eExp.Next()) { TopoDS_Shape edge = eExp.Current(); if (!EdgeFaces.Contains(edge)) { TopTools_ListOfShape listFaces; EdgeFaces.Add(edge,listFaces); } } } // Fill map Edge -> Faces nbShapes = NewShapes.Extent(); TopTools_MapOfShape mapFaces; for (i = 1; i <= nbShapes; i++) { // Explore shape to find all faces TopExp_Explorer fExp(NewShapes.FindKey(i),TopAbs_FACE); for (; fExp.More(); fExp.Next()) { TopoDS_Shape face = fExp.Current(); if(mapFaces.Contains(face)) continue; else mapFaces.Add(face); // Explore face to find all boundaries for (TopoDS_Iterator aIw(face); aIw.More(); aIw.Next()) { if(aIw.Value().ShapeType() != TopAbs_WIRE) continue; for (TopoDS_Iterator aIIe(aIw.Value()); aIIe.More(); aIIe.Next()) { TopoDS_Shape edge = aIIe.Value(); if (EdgeFaces.Contains(edge)) { EdgeFaces.ChangeFromKey(edge).Append(face); //TopTools_ListOfShape& listFaces = EdgeFaces.ChangeFromKey(edge); //Standard_Boolean isContained = Standard_False; //TopTools_ListIteratorOfListOfShape itf(listFaces); //for (; itf.More() && !isContained; itf.Next()) // isContained = face.IsSame(itf.Value()); //if (!isContained) listFaces.Append(face); } } } } } // Find free boundaries nbShapes = EdgeFaces.Extent(); for (i = 1; i <= nbShapes; i++) { TopTools_ListOfShape& listFaces = EdgeFaces(i); Standard_Integer nbFaces = listFaces.Extent(); TopoDS_Shape edge = EdgeFaces.FindKey(i); if(edge.Orientation() == TopAbs_INTERNAL) continue; Standard_Boolean isSeam = Standard_False; if (nbFaces == 1) { TopoDS_Face face = TopoDS::Face(listFaces.First()); isSeam = BRep_Tool::IsClosed(TopoDS::Edge(edge),face); if (isSeam) { ///Handle(Geom_Surface) surf = BRep_Tool::Surface(face); //isSeam = (IsUClosedSurface(surf) || IsVClosedSurface(surf)); //if(!isSeam) { BRep_Builder aB; TopoDS_Shape anewEdge = edge.EmptyCopied(); TopoDS_Iterator aItV(edge); for( ; aItV.More() ; aItV.Next()) aB.Add(anewEdge,aItV.Value()); Standard_Real first2d,last2d; Handle(Geom2d_Curve) c2dold = BRep_Tool::CurveOnSurface(TopoDS::Edge(edge),TopoDS::Face(listFaces.First()),first2d,last2d); Handle(Geom2d_Curve) c2d; BRep_Builder B; B.UpdateEdge(TopoDS::Edge(anewEdge),c2d,c2d,TopoDS::Face(listFaces.First()),0); B.UpdateEdge(TopoDS::Edge(anewEdge),c2dold,TopoDS::Face(listFaces.First()),0); Standard_Real aFirst, aLast; BRep_Tool::Range(TopoDS::Edge(edge),aFirst, aLast); aB.Range(TopoDS::Edge(anewEdge),aFirst, aLast); aB.Range(TopoDS::Edge(anewEdge),TopoDS::Face(listFaces.First()),first2d,last2d); myReShape->Replace(edge,anewEdge); edge = anewEdge; //} isSeam = Standard_False; } } Standard_Boolean isBoundFloat = (myFloatingEdgesMode && !nbFaces); Standard_Boolean isBound = (myFaceMode && ((myNonmanifold && nbFaces) || (nbFaces == 1 && !isSeam))); if (isBound || isBoundFloat) { // Ignore degenerated edge if (BRep_Tool::Degenerated(TopoDS::Edge(edge))) continue; // Ignore edge with internal vertices // Standard_Integer nbVtx = 0; // for (TopExp_Explorer vExp(edge,TopAbs_VERTEX); vExp.More(); vExp.Next()) nbVtx++; // if (nbVtx != 2) continue; // Add to BoundFaces TopTools_ListOfShape listFacesCopy; listFacesCopy.Append(listFaces); myBoundFaces.Add(edge,listFacesCopy); // Process edge vertices TopoDS_Vertex vFirst, vLast; TopExp::Vertices(TopoDS::Edge(edge), vFirst, vLast); if(vFirst.IsNull() || vLast.IsNull()) continue; if(vFirst.Orientation() == TopAbs_INTERNAL || vLast.Orientation() == TopAbs_INTERNAL) continue; if (isBound) { // Add to VertexNode if (!myVertexNode.Contains(vFirst)) myVertexNode.Add(vFirst,vFirst); if (!myVertexNode.Contains(vLast)) myVertexNode.Add(vLast,vLast); } else { // Add to VertexNodeFree if (!myVertexNodeFree.Contains(vFirst)) myVertexNodeFree.Add(vFirst,vFirst); if (!myVertexNodeFree.Contains(vLast)) myVertexNodeFree.Add(vLast,vLast); } } } } //======================================================================= //function : VerticesAssembling //purpose : Modifies : // myVertexNode (nodes glued) // myVertexNodeFree (nodes glued) // myNodeSections (lists of sections merged for glued nodes) // //======================================================================= static Standard_Boolean CreateNewNodes(const TopTools_IndexedDataMapOfShapeShape& NodeNearestNode, const TopTools_IndexedDataMapOfShapeListOfShape& NodeVertices, TopTools_IndexedDataMapOfShapeShape& aVertexNode, TopTools_DataMapOfShapeListOfShape& aNodeEdges) { Standard_Integer i, nbNearest = NodeNearestNode.Extent(); // Create new nodes BRep_Builder B; TopTools_DataMapOfShapeShape OldNodeNewNode; TopTools_DataMapOfShapeListOfShape NewNodeOldNodes; for (i = 1; i <= nbNearest; i++) { // Retrieve a pair of nodes to merge TopoDS_Shape oldnode1 = NodeNearestNode.FindKey(i); TopoDS_Shape oldnode2 = NodeNearestNode(i); // Second node should also be in the map if (!NodeNearestNode.Contains(oldnode2)) continue; // Get new node for old node #1 if (OldNodeNewNode.IsBound(oldnode1)) { TopoDS_Shape newnode1 = OldNodeNewNode(oldnode1); if (OldNodeNewNode.IsBound(oldnode2)) { TopoDS_Shape newnode2 = OldNodeNewNode(oldnode2); if (!newnode1.IsSame(newnode2)) { // Change data for new node #2 TopTools_ListOfShape& lnode1 = NewNodeOldNodes(newnode1); TopTools_ListIteratorOfListOfShape itn(NewNodeOldNodes(newnode2)); for (; itn.More(); itn.Next()) { TopoDS_Shape node2 = itn.Value(); lnode1.Append(node2); OldNodeNewNode(node2) = newnode1; } NewNodeOldNodes.UnBind(newnode2); } } else { // Old node #2 is not bound - add to old node #1 OldNodeNewNode.Bind(oldnode2,newnode1); NewNodeOldNodes(newnode1).Append(oldnode2); } } else { if (OldNodeNewNode.IsBound(oldnode2)) { // Old node #1 is not bound - add to old node #2 TopoDS_Shape newnode2 = OldNodeNewNode(oldnode2); OldNodeNewNode.Bind(oldnode1,newnode2); NewNodeOldNodes(newnode2).Append(oldnode1); } else { // Nodes are not bound - create new node TopoDS_Vertex newnode; B.MakeVertex(newnode); OldNodeNewNode.Bind(oldnode1,newnode); OldNodeNewNode.Bind(oldnode2,newnode); TopTools_ListOfShape lnodes; lnodes.Append(oldnode1); lnodes.Append(oldnode2); NewNodeOldNodes.Bind(newnode,lnodes); } } } // Stop if no new nodes created if (!NewNodeOldNodes.Extent()) return Standard_False; TopTools_DataMapIteratorOfDataMapOfShapeListOfShape iter1(NewNodeOldNodes); for (; iter1.More(); iter1.Next()) { const TopoDS_Vertex& newnode = TopoDS::Vertex(iter1.Key()); // Calculate new node center point gp_XYZ theCoordinates(0.,0.,0.); TopTools_ListOfShape lvert; // Accumulate node vertices TopTools_MapOfShape medge; TopTools_ListOfShape ledge; // Accumulate node edges // Iterate on old nodes TopTools_ListIteratorOfListOfShape itn(iter1.Value()); for (; itn.More(); itn.Next()) { const TopoDS_Shape& oldnode = itn.Value(); // Iterate on node vertices TopTools_ListIteratorOfListOfShape itv(NodeVertices.FindFromKey(oldnode)); for (; itv.More(); itv.Next()) { TopoDS_Vertex vertex = TopoDS::Vertex(itv.Value()); // Change node for vertex aVertexNode.ChangeFromKey(vertex) = newnode; // Accumulate coordinates theCoordinates += BRep_Tool::Pnt(vertex).XYZ(); lvert.Append(vertex); } // Iterate on node edges const TopTools_ListOfShape& edges = aNodeEdges(oldnode); TopTools_ListIteratorOfListOfShape ite(edges); for (; ite.More(); ite.Next()) { TopoDS_Shape edge = ite.Value(); if (!medge.Contains(edge)) { medge.Add(edge); ledge.Append(edge); } } // Unbind old node edges aNodeEdges.UnBind(oldnode); } // Bind new node edges aNodeEdges.Bind(newnode,ledge); gp_Pnt center(theCoordinates / lvert.Extent()); // Calculate new node tolerance Standard_Real toler = 0.0; TopTools_ListIteratorOfListOfShape itv(lvert); for (; itv.More(); itv.Next()) { const TopoDS_Vertex& vertex = TopoDS::Vertex(itv.Value()); Standard_Real t = center.Distance(BRep_Tool::Pnt(vertex)) + BRep_Tool::Tolerance(vertex); if (toler < t) toler = t; } // Update new node parameters B.UpdateVertex(newnode,center,toler); } return Standard_True; } static Standard_Integer IsMergedVertices(const TopoDS_Shape& face1, const TopoDS_Shape& e1, const TopoDS_Shape& e2, const TopoDS_Shape& vtx1, const TopoDS_Shape& vtx2) { //Case of floating edges if (face1.IsNull()) return (!IsClosedShape(e1,vtx1,vtx2)); // Find wires containing given edges TopoDS_Shape wire1, wire2; TopExp_Explorer itw(face1,TopAbs_WIRE); for (; itw.More() && (wire1.IsNull() || wire2.IsNull()); itw.Next()) { TopoDS_Iterator ite(itw.Current(),Standard_False); for (; ite.More() && (wire1.IsNull() || wire2.IsNull()); ite.Next()) { if (wire1.IsNull() && e1.IsSame(ite.Value())) wire1 = itw.Current(); if (wire2.IsNull() && e2.IsSame(ite.Value())) wire2 = itw.Current(); } } Standard_Integer Status = 0; if (!wire1.IsNull() && !wire2.IsNull()) { if (wire1.IsSame(wire2)) { for (TopoDS_Iterator aIte(wire1,Standard_False); aIte.More(); aIte.Next()) { TopoDS_Vertex ve1,ve2; TopExp::Vertices(TopoDS::Edge(aIte.Value()),ve1,ve2); if ((ve1.IsSame(vtx1) && ve2.IsSame(vtx2)) || (ve2.IsSame(vtx1) && ve1.IsSame(vtx2))) return (IsClosedShape(aIte.Value(),vtx1,vtx2)? 0 : 1); } if (IsClosedShape(wire1,vtx1,vtx2)) { TopoDS_Vertex V1, V2; TopExp::Vertices(TopoDS::Wire(wire1),V1,V2); Standard_Boolean isEndVertex = ((V1.IsSame(vtx1) && V2.IsSame(vtx2)) || (V2.IsSame(vtx1) && V1.IsSame(vtx2))); if (!isEndVertex) Status = 1; } else Status = 1; } else Status = -1; } return Status; } static Standard_Boolean GlueVertices(TopTools_IndexedDataMapOfShapeShape& aVertexNode, TopTools_DataMapOfShapeListOfShape& aNodeEdges, const TopTools_IndexedDataMapOfShapeListOfShape& aBoundFaces, const Standard_Real Tolerance, const Handle(Message_ProgressIndicator)& theProgress) { Standard_Integer i, nbVertices = aVertexNode.Extent(); // Create map of node -> vertices TopTools_IndexedDataMapOfShapeListOfShape NodeVertices; BRepBuilderAPI_CellFilter aFilter (Tolerance); BRepBuilderAPI_VertexInspector anInspector (Tolerance); for (i = 1; i <= nbVertices; i++) { TopoDS_Shape vertex = aVertexNode.FindKey(i); TopoDS_Vertex node = TopoDS::Vertex(aVertexNode(i)); if (NodeVertices.Contains(node)) { NodeVertices.ChangeFromKey(node).Append(vertex); } else { TopTools_ListOfShape vlist; vlist.Append(vertex); NodeVertices.Add(node,vlist); gp_Pnt aPnt = BRep_Tool::Pnt (TopoDS::Vertex (node)); aFilter.Add (NodeVertices.FindIndex (node), aPnt.XYZ()); anInspector.Add (aPnt.XYZ()); } } Standard_Integer nbNodes = NodeVertices.Extent(); #ifdef DEB cout << "Glueing " << nbNodes << " nodes..." << endl; #endif // Merge nearest nodes TopTools_IndexedDataMapOfShapeShape NodeNearestNode; Message_ProgressSentry aPS (theProgress, "Glueing nodes", 0, nbNodes, 1, Standard_True); for (i = 1; i <= nbNodes && aPS.More(); i++, aPS.Next()) { TopoDS_Vertex node1 = TopoDS::Vertex(NodeVertices.FindKey(i)); // Find near nodes gp_Pnt pt1 = BRep_Tool::Pnt (node1); anInspector.SetCurrent (pt1.XYZ()); gp_XYZ aPntMin = anInspector.Shift (pt1.XYZ(), -Tolerance); gp_XYZ aPntMax = anInspector.Shift (pt1.XYZ(), Tolerance); aFilter.Inspect (aPntMin, aPntMax, anInspector); if (anInspector.ResInd().IsEmpty()) continue; // Retrieve list of edges for the first node const TopTools_ListOfShape& ledges1 = aNodeEdges(node1); // Explore list of near nodes and fill the sequence of glued nodes TopTools_SequenceOfShape SeqNodes; TopTools_ListOfShape listNodesSameEdge; //gp_Pnt pt1 = BRep_Tool::Pnt(node1); TColStd_ListIteratorOfListOfInteger iter1(anInspector.ResInd()); for (; iter1.More(); iter1.Next()) { TopoDS_Vertex node2 = TopoDS::Vertex(NodeVertices.FindKey(iter1.Value())); if (node1 == node2) continue; // Retrieve list of edges for the second node const TopTools_ListOfShape& ledges2 = aNodeEdges(node2); // Check merging condition for the pair of nodes Standard_Integer Status = 0, isSameEdge = Standard_False; // Explore edges of the first node TopTools_ListIteratorOfListOfShape Ie1(ledges1); for (; Ie1.More() && !Status && !isSameEdge; Ie1.Next()) { const TopoDS_Shape& e1 = Ie1.Value(); // Obtain real vertex from edge TopoDS_Shape v1 = node1; { //szv: Use brackets to destroy local variables TopoDS_Vertex ov1, ov2; TopExp::Vertices(TopoDS::Edge(e1),ov1,ov2); if (aVertexNode.Contains(ov1)) { if (node1.IsSame(aVertexNode.FindFromKey(ov1))) v1 = ov1; } if (aVertexNode.Contains(ov2)) { if (node1.IsSame(aVertexNode.FindFromKey(ov2))) v1 = ov2; } } // Create map of faces for e1 TopTools_MapOfShape Faces1; const TopTools_ListOfShape& lfac1 = aBoundFaces.FindFromKey(e1); if (lfac1.Extent()) { TopTools_ListIteratorOfListOfShape itf(lfac1); for (; itf.More(); itf.Next()) if (!itf.Value().IsNull()) Faces1.Add(itf.Value()); } // Explore edges of the second node TopTools_ListIteratorOfListOfShape Ie2(ledges2); for (; Ie2.More() && !Status && !isSameEdge; Ie2.Next()) { const TopoDS_Shape& e2 = Ie2.Value(); // Obtain real vertex from edge TopoDS_Shape v2 = node2; { //szv: Use brackets to destroy local variables TopoDS_Vertex ov1, ov2; TopExp::Vertices(TopoDS::Edge(e2),ov1,ov2); if (aVertexNode.Contains(ov1)) { if (node2.IsSame(aVertexNode.FindFromKey(ov1))) v2 = ov1; } if (aVertexNode.Contains(ov2)) { if (node2.IsSame(aVertexNode.FindFromKey(ov2))) v2 = ov2; } } // Explore faces for e2 const TopTools_ListOfShape& lfac2 = aBoundFaces.FindFromKey(e2); if (lfac2.Extent()) { TopTools_ListIteratorOfListOfShape itf(lfac2); for (; itf.More() && !Status && !isSameEdge; itf.Next()) { // Check merging conditions for the same face if (Faces1.Contains(itf.Value())) { Standard_Integer stat = IsMergedVertices(itf.Value(),e1,e2,v1,v2); if (stat == 1) isSameEdge = Standard_True; else Status = stat; } } } else if (Faces1.IsEmpty() && e1 == e2) { Standard_Integer stat = IsMergedVertices(TopoDS_Face(),e1,e1,v1,v2); if (stat == 1) isSameEdge = Standard_True; else Status = stat; break; } } } if (Status) continue; if (isSameEdge) listNodesSameEdge.Append(node2); // Append near node to the sequence gp_Pnt pt2 = BRep_Tool::Pnt(node2); Standard_Real dist = pt1.Distance(pt2); if (dist < Tolerance) { Standard_Boolean isIns = Standard_False; for (Standard_Integer kk = 1; kk <= SeqNodes.Length() && !isIns; kk++) { gp_Pnt pt = BRep_Tool::Pnt(TopoDS::Vertex(SeqNodes.Value(kk))); if (dist < pt1.Distance(pt)) { SeqNodes.InsertBefore(kk,node2); isIns = Standard_True; } } if (!isIns) SeqNodes.Append(node2); } } if (SeqNodes.Length()) { // Remove nodes near to some other from the same edge if (listNodesSameEdge.Extent()) { TopTools_ListIteratorOfListOfShape lInt(listNodesSameEdge); for (; lInt.More(); lInt.Next()) { const TopoDS_Vertex& n2 = TopoDS::Vertex(lInt.Value()); gp_Pnt p2 = BRep_Tool::Pnt(n2); for (Standard_Integer k = 1; k <= SeqNodes.Length(); ) { const TopoDS_Vertex& n1 = TopoDS::Vertex(SeqNodes.Value(k)); if (n1 != n2) { gp_Pnt p1 = BRep_Tool::Pnt(n1); if (p2.Distance(p1) >= pt1.Distance(p1)) { k++; continue; } } SeqNodes.Remove(k); } } } // Bind nearest node if at least one exists if (SeqNodes.Length()) NodeNearestNode.Add(node1,SeqNodes.First()); } anInspector.ClearResList(); } // Create new nodes for chained nearest nodes if (NodeNearestNode.IsEmpty()) return Standard_False; return CreateNewNodes(NodeNearestNode,NodeVertices,aVertexNode,aNodeEdges); } void BRepBuilderAPI_Sewing::VerticesAssembling(const Handle(Message_ProgressIndicator)& thePI) { Standard_Integer nbVert = myVertexNode.Extent(); Standard_Integer nbVertFree = myVertexNodeFree.Extent(); Message_ProgressSentry aPS (thePI, "Vertices assembling", 0, 2, 1); if (nbVert || nbVertFree) { // Fill map node -> sections Standard_Integer i; for (i = 1; i <= myBoundFaces.Extent(); i++) { TopoDS_Shape bound = myBoundFaces.FindKey(i); for (TopoDS_Iterator itv(bound,Standard_False); itv.More(); itv.Next()) { TopoDS_Shape node = itv.Value(); if (myNodeSections.IsBound(node)) myNodeSections(node).Append(bound); else { TopTools_ListOfShape lbnd; lbnd.Append(bound); myNodeSections.Bind(node,lbnd); } } } // Glue vertices if (nbVert) { #ifdef DEB cout << "Assemble " << nbVert << " vertices on faces..." << endl; #endif while (GlueVertices(myVertexNode,myNodeSections,myBoundFaces,myTolerance, thePI)); } if (!aPS.More()) return; aPS.Next(); if (nbVertFree) { #ifdef DEB cout << "Assemble " << nbVertFree << " vertices on floating edges..." << endl; #endif while (GlueVertices(myVertexNodeFree,myNodeSections,myBoundFaces,myTolerance, thePI)); } } } //======================================================================= //function : replaceNMVertices //purpose : internal use (static) //======================================================================= static void replaceNMVertices(const TopoDS_Edge& theEdge, const TopoDS_Vertex& theV1, const TopoDS_Vertex& theV2, const Handle(BRepTools_ReShape)& theReShape) { //To keep NM vertices on edge TopTools_SequenceOfShape aSeqNMVert; TColStd_SequenceOfReal aSeqNMPars; Standard_Boolean hasNMVert = findNMVertices(theEdge,aSeqNMVert,aSeqNMPars); if(!hasNMVert) return; Standard_Real first, last; BRep_Tool::Range(theEdge, first, last); TopLoc_Location aLoc; Handle(Geom_Curve) c3d = BRep_Tool::Curve(theEdge,aLoc,first, last); if(c3d.IsNull()) return; TopTools_SequenceOfShape aEdVert; TColStd_SequenceOfReal aEdParams; Standard_Integer i =1, nb = aSeqNMPars.Length(); for( ; i <= nb;i++) { Standard_Real apar = aSeqNMPars.Value(i); if(fabs(apar - first) <= Precision::PConfusion()) { theReShape->Replace(aSeqNMVert.Value(i),theV1); continue; } if(fabs(apar - last) <= Precision::PConfusion()) { theReShape->Replace(aSeqNMVert.Value(i),theV2); continue; } TopoDS_Shape aV = aSeqNMVert.Value(i); Standard_Integer j =1; for( ; j <= aEdParams.Length();j++) { Standard_Real apar2 = aEdParams.Value(j); if(fabs(apar - apar2) <= Precision::PConfusion()) { theReShape->Replace(aV,aEdVert.Value(j)); break; } else if(apar < apar2) { TopoDS_Shape anewV = aV.EmptyCopied(); aEdVert.InsertBefore(j,anewV); aEdParams.InsertBefore(j,apar); BRep_ListOfPointRepresentation& alistrep = (*((Handle(BRep_TVertex)*)&anewV.TShape()))->ChangePoints(); Handle(BRep_PointOnCurve) aPRep = new BRep_PointOnCurve(apar,c3d,aLoc); alistrep.Append(aPRep); theReShape->Replace(aV,anewV); break; } } if (j > aEdParams.Length()) { TopoDS_Shape anewV = aV.EmptyCopied(); aEdVert.Append(anewV); aEdParams.Append(apar); BRep_ListOfPointRepresentation& alistrep = (*((Handle(BRep_TVertex)*) &anewV.TShape()))->ChangePoints(); Handle(BRep_PointOnCurve) aPRep = new BRep_PointOnCurve(apar,c3d,aLoc); alistrep.Append(aPRep); theReShape->Replace(aV,anewV); } } Standard_Integer newnb = aEdParams.Length(); if(newnb < nb) { TopoDS_Shape anewEdge = theEdge.EmptyCopied(); TopAbs_Orientation anOri = theEdge.Orientation(); anewEdge.Orientation(TopAbs_FORWARD); BRep_Builder aB; aB.Add(anewEdge,theV1); aB.Add(anewEdge,theV2); for( i =1; i <= aEdVert.Length();i++) aB.Add(anewEdge,aEdVert.Value(i)); anewEdge.Orientation(anOri); theReShape->Replace(theEdge,anewEdge); } } //======================================================================= //function : ReplaceEdge //purpose : internal use (static) //======================================================================= static void ReplaceEdge(const TopoDS_Shape& oldEdge, const TopoDS_Shape& theNewShape, const Handle(BRepTools_ReShape)& aReShape) { TopoDS_Shape oldShape = aReShape->Apply(oldEdge); TopoDS_Shape newShape = aReShape->Apply(theNewShape); if (oldShape.IsSame(newShape)|| aReShape->IsRecorded(newShape)) return; aReShape->Replace(oldShape,newShape); TopoDS_Vertex V1old,V2old,V1new,V2new; TopExp::Vertices(TopoDS::Edge(oldShape),V1old,V2old); TopAbs_Orientation Orold = oldShape.Orientation(); TopAbs_Orientation Ornew = Orold; if (newShape.ShapeType() == TopAbs_EDGE) { TopoDS_Edge aEn = TopoDS::Edge(newShape); TopExp::Vertices(aEn,V1new,V2new); Ornew = aEn.Orientation(); replaceNMVertices(aEn,V1new,V2new,aReShape); } else if (newShape.ShapeType() == TopAbs_WIRE) { for (TopExp_Explorer aex(newShape,TopAbs_EDGE); aex.More(); aex.Next()) { TopoDS_Edge ed = TopoDS::Edge(aex.Current()); Ornew = ed.Orientation(); TopoDS_Vertex aV1,aV2; TopExp::Vertices(ed,aV1,aV2); replaceNMVertices(ed,aV1,aV2,aReShape); if (V1new.IsNull()) V1new = aV1; V2new =aV2; } } V1new.Orientation(V1old.Orientation()); V2new.Orientation(V2old.Orientation()); if (V1old.IsSame(V2old) && !V1old.IsSame(V1new)&& !aReShape->IsRecorded(V1new)) { aReShape->Replace(V1old,V1new); return; } if (Orold == Ornew) { V1new.Orientation(V1old.Orientation()); V2new.Orientation(V2old.Orientation()); if (!V1old.IsSame(V1new) && !V1old.IsSame(V2new)&& !aReShape->IsRecorded(V1new)) aReShape->Replace(V1old,V1new); if (!V2old.IsSame(V2new) && !V2old.IsSame(V1new)&& !aReShape->IsRecorded(V2new)) aReShape->Replace(V2old,V2new); } else { V1new.Orientation(V2old.Orientation()); V2new.Orientation(V1old.Orientation()); if (!V1old.IsSame(V2new) && !V1old.IsSame(V1new)&& !aReShape->IsRecorded(V2new)) aReShape->Replace(V1old,V2new); if (!V2old.IsSame(V2new) && !V2old.IsSame(V1new)&& !aReShape->IsRecorded(V1new)) aReShape->Replace(V2old,V1new); } } //======================================================================= //function : Merging //purpose : Modifies : // myHasFreeBound // //======================================================================= void BRepBuilderAPI_Sewing::Merging(const Standard_Boolean /* firstTime */, const Handle(Message_ProgressIndicator)& thePI) { BRep_Builder B; // TopTools_MapOfShape MergedEdges; Message_ProgressSentry aPS (thePI, "Merging bounds", 0, myBoundFaces.Extent(), 1); for (Standard_Integer i = 1; i <= myBoundFaces.Extent() && aPS.More(); i++, aPS.Next()) { TopoDS_Shape bound = myBoundFaces.FindKey(i); // If bound was already merged - continue if (myMergedEdges.Contains(bound)) continue; if (!myBoundFaces(i).Extent()) { // Merge free edge - only vertices TopoDS_Vertex no1, no2; TopExp::Vertices(TopoDS::Edge(bound),no1,no2); TopoDS_Shape nno1 = no1, nno2 = no2; if (myVertexNodeFree.Contains(no1)) nno1 = myVertexNodeFree.FindFromKey(no1); if (myVertexNodeFree.Contains(no2)) nno2 = myVertexNodeFree.FindFromKey(no2); if (!no1.IsSame(nno1)) { nno1.Orientation(no1.Orientation()); myReShape->Replace(no1,nno1); } if (!no2.IsSame(nno2)) { nno2.Orientation(no2.Orientation()); myReShape->Replace(no2,nno2); } myMergedEdges.Add(bound); continue; } // Check for previous splitting, build replacing wire TopoDS_Wire BoundWire; Standard_Boolean isPrevSplit = Standard_False; Standard_Boolean hasCuttingSections = myBoundSections.IsBound(bound); if (hasCuttingSections) { B.MakeWire(BoundWire); BoundWire.Orientation(bound.Orientation()); // Iterate on cutting sections TopTools_ListIteratorOfListOfShape its(myBoundSections(bound)); for (; its.More(); its.Next()) { TopoDS_Shape section = its.Value(); B.Add(BoundWire,section); if (myMergedEdges.Contains(section)) isPrevSplit = Standard_True; } } // Merge with bound TopTools_DataMapOfShapeShape MergedWithBound; if (!isPrevSplit) { // Obtain sequence of edges merged with bound TopTools_SequenceOfShape seqMergedWithBound; TColStd_SequenceOfInteger seqMergedWithBoundOri; if (MergedNearestEdges(bound,seqMergedWithBound,seqMergedWithBoundOri)) { // Store bound in the map MergedWithBound.Bind(bound,bound); // Iterate on edges merged with bound Standard_Integer ii = 1; while (ii <= seqMergedWithBound.Length()) { TopoDS_Shape iedge = seqMergedWithBound.Value(ii); // Remove edge if recorded as merged Standard_Boolean isRejected = (myMergedEdges.Contains(iedge) || MergedWithBound.IsBound(iedge)); if (!isRejected) { if (myBoundSections.IsBound(iedge)) { // Edge is splitted - check sections TopTools_ListIteratorOfListOfShape lit(myBoundSections(iedge)); for (; lit.More() && !isRejected; lit.Next()) { const TopoDS_Shape& sec = lit.Value(); // Remove edge (bound) if at least one of its sections already merged isRejected = (myMergedEdges.Contains(sec) || MergedWithBound.IsBound(sec)); } } if (!isRejected) { if (mySectionBound.IsBound(iedge)) { // Edge is a section - check bound const TopoDS_Shape& bnd = mySectionBound(iedge); // Remove edge (section) if its bound already merged isRejected = (myMergedEdges.Contains(bnd) || MergedWithBound.IsBound(bnd)); } } } // To the next merged edge if (isRejected) { // Remove rejected edge seqMergedWithBound.Remove(ii); seqMergedWithBoundOri.Remove(ii); } else { // Process accepted edge MergedWithBound.Bind(iedge,iedge); ii++; } } Standard_Integer nbMerged = seqMergedWithBound.Length(); if (nbMerged) { // Create same parameter edge TopTools_MapOfShape ActuallyMerged; TopoDS_Edge MergedEdge = SameParameterEdge(bound,seqMergedWithBound, seqMergedWithBoundOri, ActuallyMerged,myReShape); Standard_Boolean isForward = Standard_False; if (!MergedEdge.IsNull()) isForward = (MergedEdge.Orientation() == TopAbs_FORWARD); // Process actually merged edges Standard_Integer nbActuallyMerged = 0; for (ii = 1; ii <= nbMerged; ii++) { TopoDS_Shape iedge = seqMergedWithBound(ii); if (ActuallyMerged.Contains(iedge)) { nbActuallyMerged++; // Record merged edge in the map TopAbs_Orientation orient = iedge.Orientation(); if (!isForward) orient = TopAbs::Reverse(orient); if (!seqMergedWithBoundOri(ii)) orient = TopAbs::Reverse(orient); MergedWithBound.ChangeFind(iedge) = MergedEdge.Oriented(orient); } else MergedWithBound.UnBind(iedge); } if (nbActuallyMerged) { // Record merged bound in the map TopAbs_Orientation orient = bound.Orientation(); if (!isForward) orient = TopAbs::Reverse(orient); MergedWithBound.ChangeFind(bound) = MergedEdge.Oriented(orient); } nbMerged = nbActuallyMerged; } // Remove bound from the map if not finally merged if (!nbMerged) MergedWithBound.UnBind(bound); } } Standard_Boolean isMerged = MergedWithBound.Extent(); // Merge with cutting sections Handle(BRepTools_ReShape) SectionsReShape = new BRepTools_ReShape; TopTools_DataMapOfShapeShape MergedWithSections; if (hasCuttingSections) { // Iterate on cutting sections TopTools_ListIteratorOfListOfShape its(myBoundSections(bound)); for (; its.More(); its.Next()) { // Retrieve cutting section TopoDS_Shape section = its.Value(); // Skip section if already merged if (myMergedEdges.Contains(section)) continue; // Merge cutting section TopTools_SequenceOfShape seqMergedWithSection; TColStd_SequenceOfInteger seqMergedWithSectionOri; if (MergedNearestEdges(section,seqMergedWithSection,seqMergedWithSectionOri)) { // Store section in the map MergedWithSections.Bind(section,section); // Iterate on edges merged with section Standard_Integer ii = 1; while (ii <= seqMergedWithSection.Length()) { TopoDS_Shape iedge = seqMergedWithSection.Value(ii); // Remove edge if recorded as merged Standard_Boolean isRejected = (myMergedEdges.Contains(iedge) || MergedWithSections.IsBound(iedge)); if (!isRejected) { if (myBoundSections.IsBound(iedge)) { // Edge is splitted - check sections TopTools_ListIteratorOfListOfShape lit(myBoundSections(iedge)); for (; lit.More() && !isRejected; lit.Next()) { const TopoDS_Shape& sec = lit.Value(); // Remove edge (bound) if at least one of its sections already merged isRejected = (myMergedEdges.Contains(sec) || MergedWithSections.IsBound(sec)); } } if (!isRejected) { if (mySectionBound.IsBound(iedge)) { // Edge is a section - check bound const TopoDS_Shape& bnd = mySectionBound(iedge); // Remove edge (section) if its bound already merged isRejected = (myMergedEdges.Contains(bnd) || MergedWithSections.IsBound(bnd)); } } } // To the next merged edge if (isRejected) { // Remove rejected edge seqMergedWithSection.Remove(ii); seqMergedWithSectionOri.Remove(ii); } else { // Process accepted edge MergedWithSections.Bind(iedge,iedge); ii++; } } Standard_Integer nbMerged = seqMergedWithSection.Length(); if (nbMerged) { // Create same parameter edge TopTools_MapOfShape ActuallyMerged; TopoDS_Edge MergedEdge = SameParameterEdge(section,seqMergedWithSection, seqMergedWithSectionOri, ActuallyMerged,SectionsReShape); Standard_Boolean isForward = Standard_False; if (!MergedEdge.IsNull()) isForward = (MergedEdge.Orientation() == TopAbs_FORWARD); // Process actually merged edges Standard_Integer nbActuallyMerged = 0; for (ii = 1; ii <= nbMerged; ii++) { TopoDS_Shape iedge = seqMergedWithSection(ii); if (ActuallyMerged.Contains(iedge)) { nbActuallyMerged++; // Record merged edge in the map TopAbs_Orientation orient = iedge.Orientation(); if (!isForward) orient = TopAbs::Reverse(orient); if (!seqMergedWithSectionOri(ii)) orient = TopAbs::Reverse(orient); TopoDS_Shape oedge = MergedEdge.Oriented(orient); MergedWithSections.ChangeFind(iedge) = oedge; ReplaceEdge(myReShape->Apply(iedge),oedge,SectionsReShape); } else MergedWithSections.UnBind(iedge); } if (nbActuallyMerged) { // Record merged section in the map TopAbs_Orientation orient = section.Orientation(); if (!isForward) orient = TopAbs::Reverse(orient); TopoDS_Shape oedge = MergedEdge.Oriented(orient); MergedWithSections.ChangeFind(section) = oedge; ReplaceEdge(myReShape->Apply(section),oedge,SectionsReShape); } nbMerged = nbActuallyMerged; } // Remove section from the map if not finally merged if (!nbMerged) MergedWithSections.UnBind(section); } else if (isMerged) { // Reject merging of sections MergedWithSections.Clear(); break; } } } Standard_Boolean isMergedSplit = MergedWithSections.Extent(); if (!isMerged && !isMergedSplit) { // Nothing was merged in this iteration if (isPrevSplit) { // Replace previously splitted bound myReShape->Replace(myReShape->Apply(bound),myReShape->Apply(BoundWire)); } // else if (hasCuttingSections) { // myBoundSections.UnBind(bound); //szv: are you sure ??? // } continue; } // Set splitting flag Standard_Boolean isSplitted = ((!isMerged && isMergedSplit) || isPrevSplit); // Choose between bound and sections merging if (isMerged && isMergedSplit && !isPrevSplit) { // Fill map of merged cutting sections TopTools_MapOfShape MapSplitEdges; TopTools_DataMapIteratorOfDataMapOfShapeShape itm; for (itm.Initialize(MergedWithSections); itm.More(); itm.Next()) { TopoDS_Shape edge = itm.Key(); MapSplitEdges.Add(edge); } // Iterate on edges merged with bound for (itm.Initialize(MergedWithBound); itm.More(); itm.Next()) { // Retrieve edge merged with bound TopoDS_Shape edge = itm.Key(); // Remove edge from the map if (MapSplitEdges.Contains(edge)) MapSplitEdges.Remove(edge); if (myBoundSections.IsBound(edge)) { // Edge has cutting sections TopTools_ListIteratorOfListOfShape its(myBoundSections(edge)); for (; its.More(); its.Next()) { TopoDS_Shape sec = its.Value(); // Remove section from the map if (MapSplitEdges.Contains(sec)) MapSplitEdges.Remove(sec); } } } // Calculate section merging tolerance Standard_Real MinSplitTol = RealLast(); TopTools_MapIteratorOfMapOfShape im(MapSplitEdges); for (; im.More(); im.Next()) { TopoDS_Edge edge = TopoDS::Edge(MergedWithSections(im.Key())); MinSplitTol = Min(MinSplitTol,BRep_Tool::Tolerance(edge)); } // Calculate bound merging tolerance TopoDS_Edge BoundEdge = TopoDS::Edge(MergedWithBound(bound)); Standard_Real BoundEdgeTol = BRep_Tool::Tolerance(BoundEdge); isSplitted = ((MinSplitTol < BoundEdgeTol+MinTolerance()) || myNonmanifold); isSplitted = (!MapSplitEdges.IsEmpty() && isSplitted); } if (isSplitted) { // Merging of cutting sections //myMergedEdges.Add(bound); myReShape->Replace(myReShape->Apply(bound),myReShape->Apply(BoundWire)); TopTools_DataMapIteratorOfDataMapOfShapeShape itm(MergedWithSections); for (; itm.More(); itm.Next()) { TopoDS_Shape oldedge = itm.Key(); TopoDS_Shape newedge = SectionsReShape->Apply(itm.Value()); ReplaceEdge(myReShape->Apply(oldedge),newedge,myReShape); myMergedEdges.Add(oldedge); if (myBoundSections.IsBound(oldedge)) myBoundSections.UnBind(oldedge); } } else { // Merging of initial bound TopTools_DataMapIteratorOfDataMapOfShapeShape itm(MergedWithBound); //myMergedEdges.Add(bound); for (; itm.More(); itm.Next()) { TopoDS_Shape oldedge = itm.Key(); TopoDS_Shape newedge = itm.Value(); ReplaceEdge(myReShape->Apply(oldedge),newedge,myReShape); myMergedEdges.Add(oldedge); if (myBoundSections.IsBound(oldedge)) myBoundSections.UnBind(oldedge); } if (myBoundSections.IsBound(bound)) myBoundSections.UnBind(bound); if(!myMergedEdges.Contains(bound)) myMergedEdges.Add(bound); } } myNbVertices = myVertexNode.Extent() + myVertexNodeFree.Extent(); myNodeSections.Clear(); myVertexNode.Clear(); myVertexNodeFree.Clear(); myCuttingNode.Clear(); } //======================================================================= //function : MergedNearestEdges //purpose : //======================================================================= Standard_Boolean BRepBuilderAPI_Sewing::MergedNearestEdges(const TopoDS_Shape& edge, TopTools_SequenceOfShape& SeqMergedEdge, TColStd_SequenceOfInteger& SeqMergedOri) { // Retrieve edge nodes TopoDS_Vertex no1, no2; TopExp::Vertices(TopoDS::Edge(edge),no1,no2); TopoDS_Shape nno1 = no1, nno2 = no2; Standard_Boolean isNode1 = myVertexNode.Contains(no1); Standard_Boolean isNode2 = myVertexNode.Contains(no2); if (isNode1) nno1 = myVertexNode.FindFromKey(no1); if (isNode2) nno2 = myVertexNode.FindFromKey(no2); // Fill map of nodes connected to the node #1 TopTools_MapOfShape mapVert1; mapVert1.Add(nno1); if (myCuttingNode.IsBound(nno1)) { TopTools_ListIteratorOfListOfShape ilv(myCuttingNode(nno1)); for (; ilv.More(); ilv.Next()) { TopoDS_Shape v1 = ilv.Value(); mapVert1.Add(v1); if (!isNode1 && myCuttingNode.IsBound(v1)) { TopTools_ListIteratorOfListOfShape ilvn(myCuttingNode(v1)); for (; ilvn.More(); ilvn.Next()) { TopoDS_Shape vn = ilvn.Value(); mapVert1.Add(vn); } } } } // Fill map of nodes connected to the node #2 TopTools_MapOfShape mapVert2; mapVert2.Add(nno2); if (myCuttingNode.IsBound(nno2)) { TopTools_ListIteratorOfListOfShape ilv(myCuttingNode(nno2)); for (; ilv.More(); ilv.Next()) { TopoDS_Shape v1 = ilv.Value(); mapVert2.Add(v1); if (!isNode2 && myCuttingNode.IsBound(v1)) { TopTools_ListIteratorOfListOfShape ilvn(myCuttingNode(v1)); for (; ilvn.More(); ilvn.Next()) { TopoDS_Shape vn = ilvn.Value(); mapVert2.Add(vn); } } } } // Find all possible contigous edges TopTools_SequenceOfShape seqEdges; seqEdges.Append(edge); TopTools_MapOfShape mapEdges; mapEdges.Add(edge); for (TopTools_MapIteratorOfMapOfShape imv1(mapVert1); imv1.More(); imv1.Next()) { TopoDS_Shape node1 = imv1.Key(); if (!myNodeSections.IsBound(node1)) continue; TopTools_ListIteratorOfListOfShape ilsec(myNodeSections(node1)); for (; ilsec.More(); ilsec.Next()) { TopoDS_Shape sec = ilsec.Value(); if (sec.IsSame(edge)) continue; // Retrieve section nodes TopoDS_Vertex vs1, vs2; TopExp::Vertices(TopoDS::Edge(sec),vs1,vs2); TopoDS_Shape vs1n = vs1, vs2n = vs2; if (myVertexNode.Contains(vs1)) vs1n = myVertexNode.FindFromKey(vs1); if (myVertexNode.Contains(vs2)) vs2n = myVertexNode.FindFromKey(vs2); if ((mapVert1.Contains(vs1n) && mapVert2.Contains(vs2n)) || (mapVert1.Contains(vs2n) && mapVert2.Contains(vs1n))) if (mapEdges.Add(sec)) { // Check for rejected cutting Standard_Boolean isRejected = myMergedEdges.Contains(sec); if(!isRejected && myBoundSections.IsBound(sec)) { TopTools_ListIteratorOfListOfShape its(myBoundSections(sec)); for (; its.More() && !isRejected; its.Next()) { TopoDS_Shape section = its.Value(); if (myMergedEdges.Contains(section)) isRejected = Standard_True; } } if( !isRejected && mySectionBound.IsBound(sec)) { const TopoDS_Shape& bnd = mySectionBound(sec); isRejected = (!myBoundSections.IsBound(bnd) || myMergedEdges.Contains(bnd)); } if (!isRejected) seqEdges.Append(sec); } } } mapEdges.Clear(); Standard_Boolean success = Standard_False; Standard_Integer nbSection = seqEdges.Length(); if (nbSection > 1) { // Find the longest edge CCI60011 Standard_Integer i, indRef = 1; if (myNonmanifold) { Standard_Real lenRef = 0.; for (i = 1; i <= nbSection; i++) { Standard_Real f, l; Handle(Geom_Curve) c3d = BRep_Tool::Curve(TopoDS::Edge(seqEdges(i)), f, l); GeomAdaptor_Curve cAdapt(c3d); Standard_Real len = GCPnts_AbscissaPoint::Length(cAdapt, f, l); if (len > lenRef) { indRef = i; lenRef = len; } } if (indRef != 1) { TopoDS_Shape longEdge = seqEdges(indRef); seqEdges(indRef) = seqEdges(1); seqEdges(1) = longEdge; } } // Find merging candidates TColStd_SequenceOfInteger seqForward; TColStd_SequenceOfInteger seqCandidates; TColStd_IndexedMapOfInteger mapReference; mapReference.Add(1); // Add index of reference section if (FindCandidates(seqEdges,mapReference,seqCandidates,seqForward)) { Standard_Integer nbCandidates = seqCandidates.Length(); // Check if reference section is merged reversed Standard_Boolean toReverse = Standard_False; if (indRef != 1) { // Find reference edge in candidates Standard_Boolean isFound = Standard_False; for (i = 1; i <= nbCandidates && !isFound; i++) { isFound = (seqCandidates(i) == indRef); if (isFound) { // Record orientation toReverse = !seqForward(i); // Restore first edge seqCandidates(i) = 1; seqForward(i) = 1; } } // Fail if reference is not in candidates if (!isFound) return Standard_False; } // Record candidate sections for (i = 1; i <= nbCandidates; i++) { // Retrieve merged edge TopoDS_Shape iedge = seqEdges(seqCandidates(i)); Standard_Integer ori = ((seqForward(i) && toReverse) || (!seqForward(i) && !toReverse))? 0 : 1; SeqMergedEdge.Append(iedge); SeqMergedOri.Append(ori); if (!myNonmanifold) break; } success = nbCandidates; } } return success; } //======================================================================= //function : Cutting //purpose : Modifies : // myBoundSections // myNodeSections // myCuttingNode //======================================================================= void BRepBuilderAPI_Sewing::Cutting(const Handle(Message_ProgressIndicator)& thePI) { Standard_Integer i, nbVertices = myVertexNode.Extent(); if (!nbVertices) return; // Create a box tree with vertices Standard_Real eps = myTolerance*0.5; BRepBuilderAPI_BndBoxTree aTree; NCollection_UBTreeFiller aTreeFiller (aTree); BRepBuilderAPI_BndBoxTreeSelector aSelector; for (i = 1; i <= nbVertices; i++) { gp_Pnt pt = BRep_Tool::Pnt(TopoDS::Vertex(myVertexNode.FindKey(i))); Bnd_Box aBox; aBox.Set(pt); aBox.Enlarge(eps); aTreeFiller.Add (i, aBox); } aTreeFiller.Fill(); Handle(Geom_Curve) c3d; TopLoc_Location loc; Standard_Real first, last; // Iterate on all boundaries Standard_Integer nbBounds = myBoundFaces.Extent(); Message_ProgressSentry aPS (thePI, "Cutting bounds", 0, nbBounds, 1); for (i = 1; i <= nbBounds && aPS.More(); i++, aPS.Next()) { const TopoDS_Edge& bound = TopoDS::Edge(myBoundFaces.FindKey(i)); // Do not cut floating edges if (!myBoundFaces(i).Extent()) continue; // Create cutting sections TopTools_ListOfShape listSections; { //szv: Use brackets to destroy local variables // Obtain bound curve c3d = BRep_Tool::Curve(bound, loc, first, last); if (!loc.IsIdentity()) { c3d = Handle(Geom_Curve)::DownCast(c3d->Copy()); c3d->Transform(loc.Transformation()); } // Obtain candidate vertices TopoDS_Vertex V1, V2; TopTools_IndexedMapOfShape CandidateVertices; { //szv: Use brackets to destroy local variables // Create bounding box around curve Bnd_Box aGlobalBox; GeomAdaptor_Curve adptC(c3d,first,last); BndLib_Add3dCurve::Add(adptC,myTolerance,aGlobalBox); // Sort vertices to find candidates aSelector.SetCurrent (aGlobalBox); aTree.Select (aSelector); // Skip bound if no node is in the boundind box if (!aSelector.ResInd().Extent()) continue; // Retrieve bound nodes TopExp::Vertices(bound,V1,V2); const TopoDS_Shape& Node1 = myVertexNode.FindFromKey(V1); const TopoDS_Shape& Node2 = myVertexNode.FindFromKey(V2); // Fill map of candidate vertices TColStd_ListIteratorOfListOfInteger itl(aSelector.ResInd()); for (; itl.More(); itl.Next()) { const Standard_Integer index = itl.Value(); const TopoDS_Shape& Node = myVertexNode.FindFromIndex(index); if (!Node.IsSame(Node1) && !Node.IsSame(Node2)) { TopoDS_Shape vertex = myVertexNode.FindKey(index); CandidateVertices.Add(vertex); } } aSelector.ClearResList(); } Standard_Integer nbCandidates = CandidateVertices.Extent(); if (!nbCandidates) continue; // Project vertices on curve TColStd_Array1OfReal arrPara(1,nbCandidates), arrDist(1,nbCandidates); TColgp_Array1OfPnt arrPnt(1,nbCandidates), arrProj(1,nbCandidates); for (Standard_Integer j = 1; j <= nbCandidates; j++) arrPnt(j) = BRep_Tool::Pnt(TopoDS::Vertex(CandidateVertices(j))); ProjectPointsOnCurve(arrPnt,c3d,first,last,arrDist,arrPara,arrProj,Standard_True); // Create cutting nodes TopTools_SequenceOfShape seqNode; TColStd_SequenceOfReal seqPara; CreateCuttingNodes(CandidateVertices,bound, V1,V2,arrDist,arrPara,arrProj,seqNode,seqPara); if (!seqPara.Length()) continue; // Create cutting sections CreateSections(bound, seqNode, seqPara, listSections); } if (listSections.Extent() > 1) { // modification of maps: // myBoundSections TopTools_ListIteratorOfListOfShape its(listSections); for (; its.More(); its.Next()) { TopoDS_Shape section = its.Value(); // Iterate on section vertices for (TopoDS_Iterator itv(section); itv.More(); itv.Next()) { TopoDS_Shape vertex = itv.Value(); // Convert vertex to node if (myVertexNode.Contains(vertex)) vertex = TopoDS::Vertex(myVertexNode.FindFromKey(vertex)); // Update node sections if (myNodeSections.IsBound(vertex)) myNodeSections.ChangeFind(vertex).Append(section); else { TopTools_ListOfShape lsec; lsec.Append(section); myNodeSections.Bind(vertex,lsec); } } // Store bound for section mySectionBound.Bind(section,bound); } // Store splitted bound myBoundSections.Bind(bound,listSections); } } #ifdef DEB cout << "From " << nbBounds << " bounds " << myBoundSections.Extent() << " were cut into " << mySectionBound.Extent() << " sections" << endl; #endif } //======================================================================= //function : GetSeqEdges //purpose : //======================================================================= static void GetSeqEdges(const TopoDS_Shape& edge, TopTools_SequenceOfShape& seqEdges, TopTools_DataMapOfShapeListOfShape& VertEdge) { Standard_Integer numV = 0; for (TopoDS_Iterator Iv(edge,Standard_False); Iv.More(); Iv.Next()) { TopoDS_Vertex V1 = TopoDS::Vertex(Iv.Value()); numV++; if (VertEdge.IsBound(V1)) { const TopTools_ListOfShape& listEdges = VertEdge.Find(V1); for (TopTools_ListIteratorOfListOfShape lIt(listEdges); lIt.More(); lIt.Next()) { TopoDS_Shape edge1 = lIt.Value(); if (edge1.IsSame(edge)) continue; Standard_Boolean isContained = Standard_False; Standard_Integer i, index = 1; for (i = 1; i <= seqEdges.Length() && !isContained; i++) { isContained = seqEdges.Value(i).IsSame(edge1); if (!isContained && seqEdges.Value(i).IsSame(edge)) index = i; } if (!isContained) { if (numV == 1) seqEdges.InsertBefore(index,edge1); else seqEdges.InsertAfter(index,edge1); GetSeqEdges(edge1,seqEdges,VertEdge); } } } } } //======================================================================= //function : GetFreeWires //purpose : //======================================================================= void BRepBuilderAPI_Sewing::GetFreeWires(TopTools_MapOfShape& MapFreeEdges, TopTools_SequenceOfShape& seqWires) { TopTools_DataMapOfShapeListOfShape VertEdge; TopTools_MapIteratorOfMapOfShape itMap(MapFreeEdges); TopTools_SequenceOfShape seqFreeEdges; for (; itMap.More(); itMap.Next()) { TopoDS_Shape edge = itMap.Key(); seqFreeEdges.Append(edge); for (TopoDS_Iterator Iv(edge,Standard_False); Iv.More(); Iv.Next()) { TopoDS_Vertex V1 = TopoDS::Vertex(Iv.Value()); if (VertEdge.IsBound(V1)) VertEdge.ChangeFind(V1).Append(edge); else { TopTools_ListOfShape ls; ls.Append(edge); VertEdge.Bind(V1,ls); } } } BRep_Builder B; Standard_Integer i, j; for (i = 1; i <= seqFreeEdges.Length(); i++) { TopTools_SequenceOfShape seqEdges; TopoDS_Shape edge = seqFreeEdges.Value(i); if (!MapFreeEdges.Contains(edge)) continue; seqEdges.Append(edge); GetSeqEdges(edge,seqEdges,VertEdge); TopoDS_Wire wire; B.MakeWire(wire); for (j = 1; j <= seqEdges.Length(); j++) { B.Add(wire,seqEdges.Value(j)); MapFreeEdges.Remove(seqEdges.Value(j)); } seqWires.Append(wire); if (MapFreeEdges.IsEmpty()) break; } } //======================================================================= //function : IsDegeneratedWire //purpose : internal use //======================================================================= static Standard_Boolean IsDegeneratedWire(const TopoDS_Shape& wire) { if (wire.ShapeType() != TopAbs_WIRE) return Standard_False; // Get maximal vertices tolerance TopoDS_Vertex V1,V2; //TopExp::Vertices(TopoDS::Wire(wire),V1,V2); //Standard_Real tol = Max(BRep_Tool::Tolerance(V1),BRep_Tool::Tolerance(V2)); Standard_Real wireLength = 0.0; TopLoc_Location loc; Standard_Real first, last; Standard_Integer nume = 0; Standard_Integer isSmall = 0; for (TopoDS_Iterator aIt(wire,Standard_False); aIt.More(); aIt.Next()) { nume++; TopoDS_Shape edge = aIt.Value(); TopoDS_Vertex Ve1,Ve2; TopExp::Vertices(TopoDS::Edge(edge),Ve1,Ve2); if(nume == 1) { V1 = Ve1; V2 = Ve2; } else { if(Ve1.IsSame(V1)) V1 = Ve2; else if(Ve1.IsSame(V2)) V2 = Ve2; if(Ve2.IsSame(V1)) V1 = Ve1; else if(Ve2.IsSame(V2)) V2 = Ve1; } Handle(Geom_Curve) c3d = BRep_Tool::Curve(TopoDS::Edge(aIt.Value()),loc,first,last); if (!c3d.IsNull()) { c3d = Handle(Geom_Curve)::DownCast(c3d->Copy()); if (!loc.IsIdentity()) { //c3d = Handle(Geom_Curve)::DownCast(c3d->Copy()); c3d->Transform(loc.Transformation()); } gp_Pnt pfirst = c3d->Value(first); gp_Pnt plast = c3d->Value(last); gp_Pnt pmid = c3d->Value((first +last)*0.5); Standard_Real length =0; if(pfirst.Distance(plast) > pfirst.Distance(pmid)) { length = pfirst.Distance(plast); } else { GeomAdaptor_Curve cAdapt(c3d); length = GCPnts_AbscissaPoint::Length(cAdapt, first, last); } Standard_Real tole = BRep_Tool::Tolerance(Ve1)+BRep_Tool::Tolerance(Ve2); if(length <= tole) isSmall++; wireLength += length; } } if(isSmall == nume) return Standard_True; Standard_Real tol = BRep_Tool::Tolerance(V1)+BRep_Tool::Tolerance(V2);//Max(BRep_Tool::Tolerance(V1),BRep_Tool::Tolerance(V2)); if (wireLength > tol) return Standard_False; return Standard_True; } //======================================================================= //function : DegeneratedSection //purpose : internal use // create a new degenerated edge if the section is degenerated //======================================================================= static TopoDS_Edge DegeneratedSection(const TopoDS_Shape& section, const TopoDS_Shape& face) { // Return if section is already degenerated if (BRep_Tool::Degenerated(TopoDS::Edge(section))) return TopoDS::Edge(section); // Retrieve edge curve TopLoc_Location loc; Standard_Real first, last; Handle(Geom_Curve) c3d = BRep_Tool::Curve(TopoDS::Edge(section), loc, first, last); if (c3d.IsNull()) { //gka BRep_Builder aB; TopoDS_Edge edge1 = TopoDS::Edge(section); aB.Degenerated(edge1, Standard_True); return edge1; } if (!loc.IsIdentity()) { c3d = Handle(Geom_Curve)::DownCast(c3d->Copy()); c3d->Transform(loc.Transformation()); } // Test if the new edge is degenerated TopoDS_Vertex v1,v2; TopExp::Vertices(TopoDS::Edge(section),v1,v2); //Standard_Real tol = Max(BRep_Tool::Tolerance(v1),BRep_Tool::Tolerance(v2)); //tol = Max(tolerance,tol); gp_Pnt p1, p2, p3; p1 = BRep_Tool::Pnt(v1); p3 = BRep_Tool::Pnt(v2); c3d->D0(0.5*(first + last),p2); //Standard_Boolean isDegenerated = Standard_False; //if (p1.Distance(p3) < tol) { //GeomAdaptor_Curve cAdapt(c3d); //Standard_Real length = GCPnts_AbscissaPoint::Length(cAdapt, first, last); //isDegenerated = Standard_True; //(length < tol); //} TopoDS_Edge edge; //if (!isDegenerated) return edge; // processing BRep_Builder aBuilder; edge = TopoDS::Edge(section); edge.EmptyCopy(); if (v1.IsSame(v2)) { TopoDS_Shape anEdge = edge.Oriented(TopAbs_FORWARD); aBuilder.Add(anEdge, v1.Oriented(TopAbs_FORWARD)); aBuilder.Add(anEdge, v2.Oriented(TopAbs_REVERSED)); } else { TopoDS_Vertex newVertex; if (p1.Distance(p3) < BRep_Tool::Tolerance(v1)) newVertex = v1; else if (p1.Distance(p3) < BRep_Tool::Tolerance(v2)) newVertex = v2; else { Standard_Real d1 = BRep_Tool::Tolerance(v1) + p2.Distance(p1); Standard_Real d2 = BRep_Tool::Tolerance(v2) + p2.Distance(p3); Standard_Real newTolerance = Max(d1,d2); aBuilder.MakeVertex(newVertex, p2, newTolerance); } TopoDS_Shape anEdge = edge.Oriented(TopAbs_FORWARD); aBuilder.Add(anEdge, newVertex.Oriented(TopAbs_FORWARD)); aBuilder.Add(anEdge, newVertex.Oriented(TopAbs_REVERSED)); } BRep_Tool::Range(TopoDS::Edge(section), first, last); TopoDS_Shape anEdge = edge.Oriented(TopAbs_FORWARD); aBuilder.Range(TopoDS::Edge(anEdge), first, last); aBuilder.Degenerated(edge, Standard_True); Handle(Geom_Curve) aC3dNew; if (!face.IsNull()) { Standard_Real af,al; Handle(Geom2d_Curve) aC2dt = BRep_Tool::CurveOnSurface(TopoDS::Edge(section),TopoDS::Face(face),af,al); aBuilder.UpdateEdge(edge,aC3dNew,0); Handle(Geom2d_Curve) aC2dn = BRep_Tool::CurveOnSurface(edge,TopoDS::Face(face),af,al); if (aC2dn.IsNull()) aBuilder.UpdateEdge(edge,aC2dt,TopoDS::Face(face),0); } return edge; } //======================================================================= //function : EdgeProcessing //purpose : modifies : // myNbEdges // myHasMultipleEdge // myHasFreeBound // . if multiple edge // - length < 100.*myTolerance -> several free edge // . if no multiple edge // - make the contigous edges sameparameter //======================================================================= void BRepBuilderAPI_Sewing::EdgeProcessing(const Handle(Message_ProgressIndicator)& thePI) { // constructs sectionEdge TopTools_MapOfShape MapFreeEdges; TopTools_DataMapOfShapeShape EdgeFace; Message_ProgressSentry aPS (thePI, "Edge processing", 0, myBoundFaces.Extent(), 1); for (Standard_Integer i = 1; i <= myBoundFaces.Extent() && aPS.More(); i++, aPS.Next()) { const TopoDS_Shape& bound = myBoundFaces.FindKey(i); const TopTools_ListOfShape& listFaces = myBoundFaces(i); if (listFaces.Extent() == 1) { if (myBoundSections.IsBound(bound)) { TopTools_ListIteratorOfListOfShape liter(myBoundSections(bound)); for (; liter.More(); liter.Next()) { if (!myMergedEdges.Contains(liter.Value())) { //myReShape->IsRecorded(liter.Value())) { TopoDS_Shape edge = myReShape->Apply(liter.Value()); if (!MapFreeEdges.Contains(edge)) { TopoDS_Shape face = listFaces.First(); EdgeFace.Bind(edge,face); MapFreeEdges.Add(edge); } } } } else { if (!myMergedEdges.Contains(bound)) { TopoDS_Shape edge = myReShape->Apply(bound); if (!MapFreeEdges.Contains(edge)) { TopoDS_Shape face = listFaces.First(); EdgeFace.Bind(edge,face); MapFreeEdges.Add(edge); } } } } } if (!MapFreeEdges.IsEmpty()) { TopTools_SequenceOfShape seqWires; GetFreeWires(MapFreeEdges,seqWires); for (Standard_Integer j = 1; j <= seqWires.Length(); j++) { TopoDS_Wire wire = TopoDS::Wire(seqWires.Value(j)); if (!IsDegeneratedWire(wire)) continue; for (TopoDS_Iterator Ie(wire,Standard_False); Ie.More(); Ie.Next()) { TopoDS_Shape aTmpShape = myReShape->Apply(Ie.Value()); //for porting TopoDS_Edge edge = TopoDS::Edge(aTmpShape); TopoDS_Shape face; if (EdgeFace.IsBound(edge)) face = EdgeFace.Find(edge); TopoDS_Shape degedge = DegeneratedSection(edge,face); if (degedge.IsNull()) continue; if (!degedge.IsSame(edge)) ReplaceEdge(edge,degedge,myReShape); if (BRep_Tool::Degenerated(TopoDS::Edge(degedge))) myDegenerated.Add(degedge); } } } myMergedEdges.Clear(); } //======================================================================= //function : CreateSewedShape //purpose : //======================================================================= void BRepBuilderAPI_Sewing::CreateSewedShape() { // --------------------- // create the new shapes // --------------------- BRepTools_Quilt aQuilt; Standard_Boolean isLocal = !myShape.IsNull(); if (isLocal) { // Local sewing TopoDS_Shape ns = myReShape->Apply(myShape); aQuilt.Add(ns); } Standard_Integer i; for (i = 1; i <= myOldShapes.Extent(); i++) { TopoDS_Shape sh = myOldShapes(i); if (!sh.IsNull()) { sh = myReShape->Apply(sh); myOldShapes(i) = sh; if (!isLocal) aQuilt.Add(sh); } } TopoDS_Shape aNewShape = aQuilt.Shells(); Standard_Integer numsh = 0; TopTools_IndexedMapOfShape OldShells; BRep_Builder aB; TopoDS_Compound aComp; aB.MakeCompound(aComp); for (TopoDS_Iterator aExpSh(aNewShape,Standard_False); aExpSh.More(); aExpSh.Next()) { TopoDS_Shape sh = aExpSh.Value(); Standard_Boolean hasEdges = Standard_False; if (sh.ShapeType() == TopAbs_SHELL) { if (myNonmanifold) hasEdges = !OldShells.Contains(sh); else { TopoDS_Shape face; Standard_Integer numf = 0; for (TopExp_Explorer aExpF(sh,TopAbs_FACE); aExpF.More() && (numf < 2); aExpF.Next()) { face = aExpF.Current(); numf++; } if (numf == 1) aB.Add(aComp,face); else if (numf > 1) aB.Add(aComp,sh); if (numf) numsh++; } } else if (sh.ShapeType() == TopAbs_FACE) { if (myNonmanifold) { TopoDS_Shell ss; aB.MakeShell(ss); aB.Add(ss,sh); sh = ss; hasEdges = Standard_True; } else { aB.Add(aComp,sh); numsh++; } } else { aB.Add(aComp,sh); numsh++; } if (hasEdges) OldShells.Add(sh); } // Process collected shells if (myNonmanifold) { Standard_Integer nbOldShells = OldShells.Extent(); if (nbOldShells == 1) { // Single shell - check for single face TopoDS_Shape sh = OldShells.FindKey(1); TopoDS_Shape face; Standard_Integer numf = 0; for (TopExp_Explorer aExpF(sh,TopAbs_FACE); aExpF.More() && (numf < 2); aExpF.Next()) { face = aExpF.Current(); numf++; } if (numf == 1) aB.Add(aComp,face); else if (numf > 1) aB.Add(aComp,sh); if (numf) numsh++; } else if (nbOldShells) { // Several shells should be merged TColStd_MapOfInteger IndexMerged; while (IndexMerged.Extent() < nbOldShells) { TopoDS_Shell NewShell; TopTools_MapOfShape NewEdges; for (i = 1; i <= nbOldShells; i++) { if (IndexMerged.Contains(i)) continue; TopoDS_Shell shell = TopoDS::Shell(OldShells.FindKey(i)); if (NewShell.IsNull()) { BRep_Builder aB; aB.MakeShell(NewShell); TopoDS_Iterator aItSS(shell) ; for( ; aItSS.More(); aItSS.Next()) aB.Add(NewShell,aItSS.Value()) ; // Fill map of edges for (TopExp_Explorer eexp(shell,TopAbs_EDGE); eexp.More(); eexp.Next()) { TopoDS_Shape edge = eexp.Current(); NewEdges.Add(edge); } IndexMerged.Add(i); } else { Standard_Boolean hasSharedEdge = Standard_False; TopExp_Explorer eexp(shell,TopAbs_EDGE); for (; eexp.More() && !hasSharedEdge; eexp.Next()) hasSharedEdge = NewEdges.Contains(eexp.Current()); if (hasSharedEdge) { // Add edges to the map for (TopExp_Explorer eexp1(shell,TopAbs_EDGE); eexp1.More(); eexp1.Next()) { TopoDS_Shape edge = eexp1.Current(); NewEdges.Add(edge); } // Add faces to the shell for (TopExp_Explorer fexp(shell,TopAbs_FACE); fexp.More(); fexp.Next()) { TopoDS_Shape face = fexp.Current(); aB.Add(NewShell,face); } IndexMerged.Add(i); } } } // Process new shell TopoDS_Shape face; Standard_Integer numf = 0; TopExp_Explorer aExpF(NewShell,TopAbs_FACE); for (; aExpF.More() && (numf < 2); aExpF.Next()) { face = aExpF.Current(); numf++; } if (numf == 1) aB.Add(aComp,face); else if (numf > 1) aB.Add(aComp,NewShell); if (numf) numsh++; } } } if (numsh == 1) { // Extract single component TopoDS_Iterator aIt(aComp,Standard_False); mySewedShape = aIt.Value(); } else mySewedShape = aComp; } //======================================================================= //function : CreateOutputInformations //purpose : constructs : // myEdgeSections // mySectionBound // myNbFreeEdges // myNbContigousEdges // myNbMultipleEdges // myNbDegenerated //======================================================================= void BRepBuilderAPI_Sewing::CreateOutputInformations() { // Construct edgeSections Standard_Integer i; //TopTools_DataMapOfShapeListOfShape edgeSections; TopTools_IndexedDataMapOfShapeListOfShape edgeSections; //use index map for regulating free edges for (i = 1; i <= myBoundFaces.Extent(); i++) { const TopoDS_Shape& bound = myBoundFaces.FindKey(i); TopTools_ListOfShape lsect; if (myBoundSections.IsBound(bound)) lsect = myBoundSections(bound); TopExp_Explorer aExp(myReShape->Apply(bound),TopAbs_EDGE); for (; aExp.More(); aExp.Next()) { TopoDS_Shape sec = bound, edge = aExp.Current(); TopTools_ListIteratorOfListOfShape aI(lsect); for (; aI.More(); aI.Next()) { const TopoDS_Shape& section = aI.Value(); if (edge.IsSame(myReShape->Apply(section))) { sec = section; break; } } if (edgeSections.Contains(edge)) edgeSections.ChangeFromKey(edge).Append(sec); else { TopTools_ListOfShape listSec; listSec.Append(sec); edgeSections.Add(edge,listSec); } } } // Fill maps of Free, Contigous and Multiple edges //TopTools_DataMapIteratorOfDataMapOfShapeListOfShape iter2(edgeSections); for (i = 1; i <= edgeSections.Extent(); i++) { const TopoDS_Shape& edge = edgeSections.FindKey(i); const TopTools_ListOfShape& listSection = edgeSections(i); if (listSection.Extent() == 1) { if (BRep_Tool::Degenerated(TopoDS::Edge(edge))) myDegenerated.Add(edge); else myFreeEdges.Add(edge); } else if (listSection.Extent() == 2) { myContigousEdges.Add(edge,listSection); } else { myMultipleEdges.Add(edge); } } // constructs myContigSectBound TopTools_DataMapOfShapeListOfShape aEdgeMap; //gka for (i = 1; i <= myBoundFaces.Extent(); i++) { TopoDS_Shape bound = myBoundFaces.FindKey(i); if (myBoundSections.IsBound(bound)) { TopTools_ListIteratorOfListOfShape iter(myBoundSections(bound)); for (; iter.More(); iter.Next()) { TopoDS_Shape section = iter.Value(); if(!myMergedEdges.Contains(section)) continue; //if (!myReShape->IsRecorded(section)) continue; // section is free TopoDS_Shape nedge = myReShape->Apply(section); if (nedge.IsNull()) continue; //szv debug if (!bound.IsSame(section)) if (myContigousEdges.Contains(nedge)) myContigSecBound.Bind(section, bound); } } } } //======================================================================= //function : ProjectPointsOnCurve //purpose : internal use //======================================================================= void BRepBuilderAPI_Sewing::ProjectPointsOnCurve(const TColgp_Array1OfPnt& arrPnt, const Handle(Geom_Curve)& c3d, const Standard_Real first, const Standard_Real last, TColStd_Array1OfReal& arrDist, TColStd_Array1OfReal& arrPara, TColgp_Array1OfPnt& arrProj, const Standard_Boolean isConsiderEnds) const { arrDist.Init(-1.0); GeomAdaptor_Curve GAC(c3d); Extrema_ExtPC locProj; locProj.Initialize(GAC, first, last); gp_Pnt pfirst = GAC.Value(first), plast = GAC.Value(last); for (Standard_Integer i1 = 1; i1 <= arrPnt.Length(); i1++) { gp_Pnt pt = arrPnt(i1); Standard_Real worktol = myTolerance; Standard_Real distF2 = pfirst.SquareDistance(pt); Standard_Real distL2 = plast.SquareDistance(pt); Standard_Boolean isProjected = Standard_False; try { // Project current point on curve locProj.Perform(pt); if (locProj.IsDone() && locProj.NbExt() > 0) { Standard_Real dist2Min = Min(distF2,distL2); Standard_Integer ind, indMin = 0; for (ind = 1; ind <= locProj.NbExt(); ind++) { Standard_Real dProj2 = locProj.SquareDistance(ind); if (dProj2 < dist2Min) { indMin = ind; dist2Min = dProj2; } } if (indMin) { isProjected = Standard_True; Extrema_POnCurv pOnC = locProj.Point(indMin); Standard_Real paramProj = pOnC.Parameter(); gp_Pnt ptProj = GAC.Value(paramProj); Standard_Real distProj2 = ptProj.SquareDistance(pt); if (!locProj.IsMin(indMin)) { if (Min(distF2,distL2) < dist2Min) { if (distF2 < distL2) { paramProj = first; distProj2 = distF2; ptProj = pfirst; } else { paramProj = last; distProj2 = distL2; ptProj = plast; } } } if (distProj2 < worktol * worktol || !isConsiderEnds) { arrDist(i1) = sqrt (distProj2); arrPara(i1) = paramProj; arrProj(i1) = ptProj; } } } } catch (Standard_Failure) { worktol = MinTolerance(); #ifdef DEB cout << "Exception in BRepBuilderAPI_Sewing::ProjectPointsOnCurve: "; Standard_Failure::Caught()->Print(cout); cout << endl; #endif } if (!isProjected && isConsiderEnds) { if (Min(distF2,distL2) < worktol * worktol) { if (distF2 < distL2) { arrDist(i1) = sqrt (distF2); arrPara(i1) = first; arrProj(i1) = pfirst; } else { arrDist(i1) = sqrt (distL2); arrPara(i1) = last; arrProj(i1) = plast; } } } } } //======================================================================= //function : CreateCuttingNodes //purpose : internal use //======================================================================= void BRepBuilderAPI_Sewing::CreateCuttingNodes(const TopTools_IndexedMapOfShape& MapVert, const TopoDS_Shape& bound, const TopoDS_Shape& vfirst, const TopoDS_Shape& vlast, const TColStd_Array1OfReal& arrDist, const TColStd_Array1OfReal& arrPara, const TColgp_Array1OfPnt& arrPnt, TopTools_SequenceOfShape& seqVert, TColStd_SequenceOfReal& seqPara) { Standard_Integer i, j, nbProj = MapVert.Extent(); // Reorder projections by distance TColStd_SequenceOfInteger seqOrderedIndex; { //szv: Use brackets to destroy local variables TColStd_SequenceOfReal seqOrderedDistance; for (i = 1; i <= nbProj; i++) { Standard_Real distProj = arrDist(i); if (distProj < 0.0) continue; // Skip vertex if not projected Standard_Boolean isInserted = Standard_False; for (j = 1; j <= seqOrderedIndex.Length() && !isInserted; j++) { isInserted = (distProj < seqOrderedDistance(j)); if (isInserted) { seqOrderedIndex.InsertBefore(j,i); seqOrderedDistance.InsertBefore(j,distProj); } } if (!isInserted) { seqOrderedIndex.Append(i); seqOrderedDistance.Append(distProj); } } } nbProj = seqOrderedIndex.Length(); if (!nbProj) return; BRep_Builder aBuilder; // Insert two initial vertices (to be removed later) TColStd_SequenceOfReal seqDist; TColgp_SequenceOfPnt seqPnt; { //szv: Use brackets to destroy local variables // Retrieve bound curve TopLoc_Location loc; Standard_Real first,last; Handle(Geom_Curve) c3d = BRep_Tool::Curve(TopoDS::Edge(bound), loc, first, last); if (!loc.IsIdentity()) { c3d = Handle(Geom_Curve)::DownCast(c3d->Copy()); c3d->Transform(loc.Transformation()); } GeomAdaptor_Curve GAC(c3d); seqVert.Prepend(vfirst); seqVert.Append(vlast); seqPara.Prepend(first); seqPara.Append(last); seqDist.Prepend(-1.0); seqDist.Append(-1.0); seqPnt.Prepend(GAC.Value(first)); seqPnt.Append(GAC.Value(last)); } TopTools_DataMapOfShapeShape NodeCuttingVertex; for (i = 1; i <= nbProj; i++) { const Standard_Integer index = seqOrderedIndex(i); Standard_Real disProj = arrDist(index); gp_Pnt pntProj = arrPnt(index); // Skip node if already bound to cutting vertex TopoDS_Shape node = myVertexNode.FindFromKey(MapVert(index)); if (NodeCuttingVertex.IsBound(node)) continue; // Find the closest vertex Standard_Integer indexMin = 1; Standard_Real dist, distMin = pntProj.Distance(seqPnt(1)); for (j = 2; j <= seqPnt.Length(); j++) { dist = pntProj.Distance(seqPnt(j)); if (dist < distMin) { distMin = dist; indexMin = j; } } // Check if current point is close to one of the existent if (distMin <= Max(disProj*0.1,MinTolerance())) { // Check distance if close Standard_Real jdist = seqDist.Value(indexMin); if (jdist < 0.0) { // Bind new cutting node (end vertex only) seqDist.SetValue(indexMin,disProj); TopoDS_Shape cvertex = seqVert.Value(indexMin); NodeCuttingVertex.Bind(node,cvertex); } else { // Bind secondary cutting nodes NodeCuttingVertex.Bind(node,TopoDS_Vertex()); } } else { // Build new cutting vertex TopoDS_Vertex cvertex; aBuilder.MakeVertex(cvertex, pntProj, Precision::Confusion()); // Bind new cutting vertex NodeCuttingVertex.Bind(node,cvertex); // Insert cutting vertex in the sequences Standard_Real parProj = arrPara(index); for (j = 2; j <= seqPara.Length(); j++) { if (parProj <= seqPara.Value(j)) { seqVert.InsertBefore(j,cvertex); seqPara.InsertBefore(j,parProj); seqDist.InsertBefore(j,disProj); seqPnt.InsertBefore (j,pntProj); break; } } } } // filling map for cutting nodes TopTools_DataMapIteratorOfDataMapOfShapeShape mit(NodeCuttingVertex); for (; mit.More(); mit.Next()) { TopoDS_Shape cnode = mit.Value(); // Skip secondary nodes if (cnode.IsNull()) continue; // Obtain vertex node TopoDS_Shape node = mit.Key(); if (myVertexNode.Contains(cnode)) { // This is an end vertex cnode = myVertexNode.FindFromKey(cnode); } else { // Create link: cutting vertex -> node TopTools_ListOfShape ls; ls.Append(node); myCuttingNode.Bind(cnode,ls); } // Create link: node -> cutting vertex if (myCuttingNode.IsBound(node)) { myCuttingNode.ChangeFind(node).Append(cnode); } else { TopTools_ListOfShape ls; ls.Append(cnode); myCuttingNode.Bind(node,ls); } } // Remove two initial vertices seqVert.Remove(1); seqVert.Remove(seqVert.Length()); seqPara.Remove(1); seqPara.Remove(seqPara.Length()); } //======================================================================= //function : CreateSections //purpose : internal use //======================================================================= void BRepBuilderAPI_Sewing::CreateSections(const TopoDS_Shape& section, const TopTools_SequenceOfShape& seqNode, const TColStd_SequenceOfReal& seqPara, TopTools_ListOfShape& listEdge) { const TopoDS_Edge& sec = TopoDS::Edge(section); // TopAbs_Orientation aInitOr = sec.Orientation(); //To keep NM vertices on edge TopTools_SequenceOfShape aSeqNMVert; TColStd_SequenceOfReal aSeqNMPars; findNMVertices(sec,aSeqNMVert,aSeqNMPars); BRep_Builder aBuilder; Standard_Real first, last; BRep_Tool::Range(sec, first, last); // Create cutting sections Standard_Real par1, par2; TopoDS_Shape V1, V2; Standard_Integer i, len = seqPara.Length() + 1; for (i = 1; i <= len; i++) { TopoDS_Edge edge = sec; edge.EmptyCopy(); if (i == 1) { par1 = first; par2 = seqPara(i); V1 = TopExp::FirstVertex(sec); V2 = seqNode(i); } else if (i == len) { par1 = seqPara(i-1); par2 = last; V1 = seqNode(i-1); V2 = TopExp::LastVertex(sec); } else { par1 = seqPara(i-1); par2 = seqPara(i); V1 = seqNode(i-1); V2 = seqNode(i); } TopoDS_Shape aTmpShape = edge.Oriented(TopAbs_FORWARD); TopoDS_Edge aTmpEdge = TopoDS::Edge (aTmpShape); // for porting aTmpShape = V1.Oriented(TopAbs_FORWARD); aBuilder.Add(aTmpEdge, aTmpShape); aTmpShape = V2.Oriented(TopAbs_REVERSED); aBuilder.Add(aTmpEdge, aTmpShape); aBuilder.Range(aTmpEdge, par1, par2); // if(aInitOr == TopAbs_REVERSED) // listEdge.Prepend(edge); // else Standard_Integer k =1; for( ; k <= aSeqNMPars.Length() ; k++) { Standard_Real apar = aSeqNMPars.Value(k); if(apar >= par1 && apar <= par2) { aBuilder.Add(aTmpEdge,aSeqNMVert.Value(k)); aSeqNMVert.Remove(k); aSeqNMPars.Remove(k); k--; } } listEdge.Append(edge); } const TopTools_ListOfShape& listFaces = myBoundFaces.FindFromKey(sec); if (!listFaces.Extent()) return; Standard_Real tolEdge = BRep_Tool::Tolerance(sec); // Add cutting pcurves TopTools_ListIteratorOfListOfShape itf(listFaces); for (; itf.More(); itf.Next()) { const TopoDS_Face& fac = TopoDS::Face(itf.Value()); // Retrieve curve on surface Standard_Real first2d=0., last2d=0.,first2d1=0,last2d1=0.; Handle(Geom2d_Curve) c2d = BRep_Tool::CurveOnSurface(sec, fac, first2d, last2d); if (c2d.IsNull()) continue; Handle(Geom2d_Curve) c2d1; Standard_Boolean isSeam = BRep_Tool::IsClosed(sec,fac); //gka - Convert to BSpline was commented because //it is not necessary to create BSpline instead of Lines or cIrcles. //Besides after conversion circles to BSpline //it is necessary to recompute parameters of cutting because paramerization of created //BSpline curve differs from parametrization of circle. // Convert pcurve to BSpline /*Handle(Geom2d_BSplineCurve) c2dBSP,c2dBSP1; if (c2d->IsKind(STANDARD_TYPE(Geom2d_BSplineCurve))) { c2dBSP = Handle(Geom2d_BSplineCurve)::DownCast(c2d); } else { if (first > (c2d->FirstParameter() + Precision::PConfusion()) || last < (c2d->LastParameter() - Precision::PConfusion())) { Handle(Geom2d_TrimmedCurve) TC = new Geom2d_TrimmedCurve(c2d, first, last); c2dBSP = Geom2dConvert::CurveToBSplineCurve(TC); } else c2dBSP = Geom2dConvert::CurveToBSplineCurve(c2d); } if (c2dBSP.IsNull()) continue;*/ //gka fix for bug OCC12203 21.04.06 addition second curve for seam edges if(isSeam) { TopoDS_Edge secRev = TopoDS::Edge(sec.Reversed()); c2d1 = BRep_Tool::CurveOnSurface(secRev, fac, first2d1, last2d1); if (c2d1.IsNull()) continue; /*if (c2d1->IsKind(STANDARD_TYPE(Geom2d_BSplineCurve))) { c2dBSP1 = Handle(Geom2d_BSplineCurve)::DownCast(c2d1); } else { if (first > (c2d1->FirstParameter() + Precision::PConfusion()) || last < (c2d1->LastParameter() - Precision::PConfusion())) { Handle(Geom2d_TrimmedCurve) TC = new Geom2d_TrimmedCurve(c2d1, first, last); //c2dBSP1 = Geom2dConvert::CurveToBSplineCurve(TC); } //else c2dBSP1 = Geom2dConvert::CurveToBSplineCurve(c2d); }*/ } /*first2d = c2dBSP->FirstParameter(); last2d = c2dBSP->LastParameter(); if(!c2dBSP1.IsNull()) { first2d1 = c2dBSP1->FirstParameter(); last2d1 = c2dBSP1->LastParameter(); }*/ // Update cutting sections Handle(Geom2d_Curve) c2dNew,c2d1New; TopTools_ListIteratorOfListOfShape ite(listEdge); for (; ite.More(); ite.Next()) { // Retrieve cutting section const TopoDS_Edge& edge = TopoDS::Edge(ite.Value()); BRep_Tool::Range(edge, par1, par2); // Cut BSpline pcurve // try { c2dNew = Handle(Geom2d_Curve)::DownCast(c2d->Copy()); //c2dNew = Handle(Geom2d_Curve)::DownCast(c2dBSP->Copy()); //Handle(Geom2d_BSplineCurve)::DownCast(c2dNew)->Segment(Max(first2d,par1),Min(par2,last2d)); if(!c2d1.IsNull()) { //if(!c2dBSP1.IsNull()) { c2d1New = Handle(Geom2d_Curve)::DownCast(c2d1->Copy()); //c2d1New = Handle(Geom2d_Curve)::DownCast(c2dBSP1->Copy()); //Handle(Geom2d_BSplineCurve)::DownCast(c2d1New)->Segment(Max(first2d1,par1),Min(par2,last2d1)); } //} /*catch (Standard_Failure) { #ifdef DEB cout << "Exception in CreateSections: segment [" << par1 << "," << par2 << "]: "; Standard_Failure::Caught()->Print(cout); cout << endl; #endif Handle(Geom2d_TrimmedCurve) c2dT = new Geom2d_TrimmedCurve(c2dNew,Max(first2d,par1),Min(par2,last2d)); c2dNew = c2dT; }*/ if(!isSeam && c2d1New.IsNull()) aBuilder.UpdateEdge(edge, c2dNew, fac, tolEdge); else { TopAbs_Orientation Ori = edge.Orientation(); if(fac.Orientation() == TopAbs_REVERSED) Ori = TopAbs::Reverse(Ori); if(Ori == TopAbs_FORWARD) aBuilder.UpdateEdge(edge, c2dNew,c2d1New ,fac, tolEdge); else aBuilder.UpdateEdge(edge, c2d1New,c2dNew ,fac, tolEdge); } } } } //======================================================================= //function : SameParameterShape //purpose : //======================================================================= void BRepBuilderAPI_Sewing::SameParameterShape() { if (!mySameParameterMode) return; TopExp_Explorer exp(mySewedShape, TopAbs_EDGE); // Le flag sameparameter est a false pour chaque edge cousue for (; exp.More(); exp.Next()) { const TopoDS_Edge& sec = TopoDS::Edge(exp.Current()); try { BRepLib::SameParameter(sec, BRep_Tool::Tolerance(sec)); } catch (Standard_Failure) { #ifdef DEB cout << "Fail: BRepBuilderAPI_Sewing::SameParameterShape exception in BRepLib::SameParameter" << endl; #endif continue; } } } //======================================================================= //function : Inspect //purpose : Used for selection and storage of coinciding points //======================================================================= NCollection_CellFilter_Action BRepBuilderAPI_VertexInspector::Inspect (const Standard_Integer theTarget) { /*gp_Pnt aPnt = gp_Pnt (myPoints.Value (theTarget - 1)); if (aPnt.SquareDistance (gp_Pnt (myCurrent)) <= myTol) myResInd.Append (theTarget);*/ const gp_XYZ& aPnt = myPoints.Value (theTarget - 1); Standard_Real aDx, aDy, aDz; aDx = myCurrent.X() - aPnt.X(); aDy = myCurrent.Y() - aPnt.Y(); aDz = myCurrent.Z() - aPnt.Z(); if ((aDx*aDx <= myTol) && (aDy*aDy <= myTol) && (aDz*aDz <= myTol)) myResInd.Append (theTarget); return CellFilter_Keep; }