// Created on: 1996-09-03 // Created by: Yves FRICAUD // Copyright (c) 1996-1999 Matra Datavision // Copyright (c) 1999-2014 OPEN CASCADE SAS // // This file is part of Open CASCADE Technology software library. // // This library is free software; you can redistribute it and/or modify it under // the terms of the GNU Lesser General Public License version 2.1 as published // by the Free Software Foundation, with special exception defined in the file // OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT // distribution for complete text of the license and disclaimer of any warranty. // // Alternatively, this file may be used under the terms of Open CASCADE // commercial license or contractual agreement. // Modified by skv - Wed Dec 24 18:08:39 2003 OCC4455 #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 #ifdef DRAW #include Standard_IMPORT extern Standard_Boolean AffichInt2d; static Standard_Integer NbF2d = 0; static Standard_Integer NbE2d = 0; static Standard_Integer NbNewVertices = 0; #endif //======================================================================= //function : CommonVertex //purpose : //======================================================================= static TopoDS_Vertex CommonVertex(TopoDS_Edge& E1, TopoDS_Edge& E2) { TopoDS_Vertex V1[2],V2[2],V; // Modified by skv - Wed Dec 24 18:08:39 2003 OCC4455 Begin // TopExp::Vertices(E1,V1[0],V1[1]); // TopExp::Vertices(E2,V2[0],V2[1]); TopExp::Vertices(E1,V1[0],V1[1], Standard_True); TopExp::Vertices(E2,V2[0],V2[1], Standard_True); // The first edge is the current one, the second edge is the next one. // We check last vertex of the first edge first. // if (V1[0].IsSame(V2[0]) || V1[0].IsSame(V2[1])) return V1[0]; // if (V1[1].IsSame(V2[0]) || V1[1].IsSame(V2[1])) return V1[1]; if (V1[1].IsSame(V2[0]) || V1[1].IsSame(V2[1])) return V1[1]; if (V1[0].IsSame(V2[0]) || V1[0].IsSame(V2[1])) return V1[0]; // Modified by skv - Wed Dec 24 18:08:40 2003 OCC4455 End return V; } //======================================================================= //function : Store //purpose : //======================================================================= static void Store (const TopoDS_Edge& E1, const TopoDS_Edge& E2, TopTools_ListOfShape& LV1, TopTools_ListOfShape& LV2, Handle(BRepAlgo_AsDes) AsDes, Standard_Real Tol) { //------------------------------------------------------------- // Test if the points of intersection correspond to existing // vertices. Otherwise add edges in the descendants. // Note: at this stage only vertices of intersection are in the descendants. //------------------------------------------------------------- const TopTools_ListOfShape& VOnE1 = AsDes->Descendant(E1); const TopTools_ListOfShape& VOnE2 = AsDes->Descendant(E2); TopTools_ListOfShape NewVOnE1; TopTools_ListOfShape NewVOnE2; gp_Pnt P,P1,P2; TopoDS_Vertex V1,V2; TopTools_ListIteratorOfListOfShape it, itLV1, itLV2; BRep_Builder B; TopAbs_Orientation O1,O2; Standard_Real U1,U2; Standard_Boolean OnE1,OnE2; for (itLV1.Initialize(LV1),itLV2.Initialize(LV2); itLV1.More(); itLV1.Next() ,itLV2.Next()) { TopoDS_Vertex V = TopoDS::Vertex(itLV1.Value()); U1 = (BRep_Tool::Degenerated(E1))? BRep_Tool::Parameter(TopoDS::Vertex(V.Oriented(TopAbs_INTERNAL)), E1) : BRep_Tool::Parameter(V, E1); U2 = (BRep_Tool::Degenerated(E2))? BRep_Tool::Parameter(TopoDS::Vertex(V.Oriented(TopAbs_INTERNAL)), E2) : BRep_Tool::Parameter(V, E2); O1 = V.Orientation(); O2 = itLV2.Value().Orientation(); P = BRep_Tool::Pnt(V); OnE1 = OnE2 = Standard_False; if (!VOnE1.IsEmpty()) { //----------------------------------------------------------------- // Find if the point of intersection corresponds to a vertex of E1. //----------------------------------------------------------------- for (it.Initialize(VOnE1); it.More(); it.Next()) { P1 = BRep_Tool::Pnt(TopoDS::Vertex(it.Value())); if (P.IsEqual(P1,Tol)) { V = TopoDS::Vertex(it.Value()); V1 = V; OnE1 = Standard_True; break; } } } if (!VOnE2.IsEmpty()) { if (OnE1) { //----------------------------------------------------------------- // Find if the vertex found on E1 is not already on E2. //----------------------------------------------------------------- for (it.Initialize(VOnE2); it.More(); it.Next()) { if (it.Value().IsSame(V)) { OnE2 = Standard_True; V2 = V; break; } } } for (it.Initialize(VOnE2); it.More(); it.Next()) { //----------------------------------------------------------------- // Find if the point of intersection corresponds to a vertex of E2. //----------------------------------------------------------------- P2 = BRep_Tool::Pnt(TopoDS::Vertex(it.Value())); if (P.IsEqual(P2,Tol)) { V = TopoDS::Vertex(it.Value()); V2 = V; OnE2 = Standard_True; break; } } } if (OnE1 && OnE2) { if (!V1.IsSame(V2)) { //--------------------------------------------------------------- // Two vertices are actually the same. // V2 will be replaced by V1. // update the parameters of vertex on edges. //--------------------------------------------------------------- Standard_Real UV2; TopoDS_Edge EWE2; const TopTools_ListOfShape& EdgeWithV2 = AsDes->Ascendant(V2); for (it.Initialize(EdgeWithV2); it.More(); it.Next()) { EWE2 = TopoDS::Edge(it.Value()); TopoDS_Shape aLocalShape =V2.Oriented(TopAbs_INTERNAL); UV2 = BRep_Tool::Parameter(TopoDS::Vertex(aLocalShape),EWE2); // UV2 = // BRep_Tool::Parameter(TopoDS::Vertex(V2.Oriented(TopAbs_INTERNAL)),EWE2); aLocalShape = V1.Oriented(TopAbs_INTERNAL); B.UpdateVertex(TopoDS::Vertex(aLocalShape),UV2,EWE2,Tol); // B.UpdateVertex(TopoDS::Vertex(V1.Oriented(TopAbs_INTERNAL)), // UV2,EWE2,Tol); } AsDes->Replace(V2,V1); } } if (!OnE1) { if (OnE2) { TopoDS_Shape aLocalShape = V.Oriented(TopAbs_INTERNAL); B.UpdateVertex(TopoDS::Vertex(aLocalShape),U1,E1,Tol); // B.UpdateVertex(TopoDS::Vertex(V.Oriented(TopAbs_INTERNAL)), // U1,E1,Tol); } NewVOnE1.Append(V.Oriented(O1)); } if (!OnE2) { if (OnE1) { TopoDS_Shape aLocalShape = V.Oriented(TopAbs_INTERNAL); B.UpdateVertex(TopoDS::Vertex(aLocalShape),U2,E2,Tol); // B.UpdateVertex(TopoDS::Vertex(V.Oriented(TopAbs_INTERNAL)), // U2,E2,Tol); } NewVOnE2.Append(V.Oriented(O2)); } #ifdef DRAW if (AffichInt2d) { if (!OnE1 && !OnE2) { char name[256]; sprintf(name,"VV_%d",NbNewVertices++); DBRep::Set(name,V); } } #endif } if (!NewVOnE1.IsEmpty()) AsDes->Add(E1,NewVOnE1); if (!NewVOnE2.IsEmpty()) AsDes->Add(E2,NewVOnE2); } //======================================================================= //function : EdgeInter //purpose : //======================================================================= static void EdgeInter(const TopoDS_Face& F, const TopoDS_Edge& E1, const TopoDS_Edge& E2, const Handle(BRepAlgo_AsDes)& AsDes, Standard_Real Tol, Standard_Boolean WithOri) { #ifdef DRAW if (AffichInt2d) { char name[256]; sprintf(name,"E2d_%d_%d",NbF2d,NbE2d++); DBRep::Set(name,E1); sprintf(name,"E2d_%d_%d",NbF2d,NbE2d++); DBRep::Set(name,E2); } #endif if (E1.IsSame(E2)) return; Standard_Real f[3],l[3]; Standard_Real TolDub = 1.e-7; Standard_Integer i; BRep_Tool::Range(E1, f[1], l[1]); BRep_Tool::Range(E2, f[2], l[2]); BRepAdaptor_Curve CE1(E1,F); BRepAdaptor_Curve CE2(E2,F); TopoDS_Edge EI[3]; EI[1] = E1; EI[2] = E2; TopTools_ListOfShape LV1; TopTools_ListOfShape LV2; BRep_Builder B; TopoDS_Vertex CV; if (!TopExp::CommonVertex( E1, E2, CV )) { BRepLib::BuildCurve3d(E1); BRepLib::BuildCurve3d(E2); Standard_Real TolSum = BRep_Tool::Tolerance(E1) + BRep_Tool::Tolerance(E2); TolSum = Max( TolSum, 1.e-5 ); TColgp_SequenceOfPnt ResPoints; TColStd_SequenceOfReal ResParamsOnE1, ResParamsOnE2; gp_Pnt DegPoint; Standard_Boolean WithDegen = BRep_Tool::Degenerated(E1) || BRep_Tool::Degenerated(E2); if (WithDegen) { Standard_Integer ideg = (BRep_Tool::Degenerated(E1))? 1 : 2; TopoDS_Iterator iter( EI[ideg] ); if (iter.More()) { const TopoDS_Vertex& vdeg = TopoDS::Vertex(iter.Value()); DegPoint = BRep_Tool::Pnt(vdeg); } else { BRepAdaptor_Curve CEdeg( EI[ideg], F ); DegPoint = CEdeg.Value( CEdeg.FirstParameter() ); } } BRepAdaptor_Surface BAsurf(F); Handle(Geom2d_Curve) pcurve1 = BRep_Tool::CurveOnSurface(E1, F, f[1], l[1]); Handle(Geom2d_Curve) pcurve2 = BRep_Tool::CurveOnSurface(E2, F, f[2], l[2]); Geom2dAdaptor_Curve GAC1(pcurve1, f[1], l[1]); Geom2dAdaptor_Curve GAC2(pcurve2, f[2], l[2]); Geom2dInt_GInter Inter2d( GAC1, GAC2, TolDub, TolDub ); for (i = 1; i <= Inter2d.NbPoints(); i++) { gp_Pnt P3d; if (WithDegen) P3d = DegPoint; else { gp_Pnt2d P2d = Inter2d.Point(i).Value(); P3d = BAsurf.Value( P2d.X(), P2d.Y() ); } ResPoints.Append( P3d ); ResParamsOnE1.Append( Inter2d.Point(i).ParamOnFirst() ); ResParamsOnE2.Append( Inter2d.Point(i).ParamOnSecond() ); } for (i = 1; i <= ResPoints.Length(); i++) { Standard_Real aT1 = ResParamsOnE1(i); //ponc1.Parameter(); Standard_Real aT2 = ResParamsOnE2(i); //ponc2.Parameter(); if (Precision::IsInfinite(aT1) || Precision::IsInfinite(aT2)) { #ifdef DEB cout << "Inter2d : Solution rejected due to infinite parameter"< l[1]+Tol) { cout << "out of limit"< l[1]+Tol) { cout << "out of limit"< 1) { //cout << "IFV - RefEdgeInter: remove vertex" << endl; Standard_Real dmin = RealLast(); TopoDS_Vertex Vmin; for (it1LV1.Initialize(LV1); it1LV1.More(); it1LV1.Next()) { gp_Pnt P = BRep_Tool::Pnt(TopoDS::Vertex(it1LV1.Value())); Standard_Real d = P.SquareDistance(Pref); if(d < dmin) { dmin = d; Vmin = TopoDS::Vertex(it1LV1.Value()); } } for (it1LV1.Initialize(LV1),it1LV2.Initialize(LV2); it1LV1.More(); it1LV1.Next(),it1LV2.Next()) { if(!Vmin.IsSame(it1LV1.Value())) { LV1.Remove(it1LV1); LV2.Remove(it1LV2); if(!it1LV1.More()) break; } } } ////----------------------------------------------------- // Modified by skv - Tue Jan 13 15:14:30 2004 Begin Standard_Real TolStore = BRep_Tool::Tolerance(E1) + BRep_Tool::Tolerance(E2); TolStore = Max(TolStore, 10.*Tol); Store (E1,E2,LV1,LV2,AsDes,TolStore); // Store (E1,E2,LV1,LV2,AsDes,10.*Tol); // Store (E1,E2,LV1,LV2,AsDes,Tol); // Modified by skv - Tue Jan 13 15:14:30 2004 End } } //====================================================================== //function : EvaluateMaxSegment //purpose : return MaxSegment to pass in approximation //====================================================================== static Standard_Integer evaluateMaxSegment(const Adaptor3d_CurveOnSurface& aCurveOnSurface) { Handle(Adaptor3d_HSurface) aSurf = aCurveOnSurface.GetSurface(); Handle(Adaptor2d_HCurve2d) aCurv2d = aCurveOnSurface.GetCurve(); Standard_Real aNbSKnots = 0, aNbC2dKnots = 0; if (aSurf->GetType() == GeomAbs_BSplineSurface) { Handle(Geom_BSplineSurface) aBSpline = aSurf->BSpline(); aNbSKnots = Max(aBSpline->NbUKnots(), aBSpline->NbVKnots()); } if (aCurv2d->GetType() == GeomAbs_BSplineCurve) { aNbC2dKnots = aCurv2d->NbKnots(); } Standard_Integer aReturn = (Standard_Integer) ( 30 + Max(aNbSKnots, aNbC2dKnots) ) ; return aReturn; } //======================================================================= //function : ExtendPCurve //purpose : //======================================================================= static Standard_Boolean ExtendPCurve(const Handle(Geom2d_Curve)& aPCurve, const Standard_Real anEf, const Standard_Real anEl, const Standard_Real a2Offset, Handle(Geom2d_Curve)& NewPCurve) { NewPCurve = aPCurve; if (NewPCurve->IsInstance(STANDARD_TYPE(Geom2d_TrimmedCurve))) NewPCurve = (*((Handle(Geom2d_TrimmedCurve)*)&NewPCurve))->BasisCurve(); Standard_Real FirstPar = NewPCurve->FirstParameter(); Standard_Real LastPar = NewPCurve->LastParameter(); if (NewPCurve->IsKind(STANDARD_TYPE(Geom2d_BoundedCurve)) && (FirstPar > anEf - a2Offset || LastPar < anEl + a2Offset)) { if (NewPCurve->IsInstance(STANDARD_TYPE(Geom2d_BezierCurve))) { Handle(Geom2d_BezierCurve) aBezier = *((Handle(Geom2d_BezierCurve)*)&NewPCurve); if (aBezier->NbPoles() == 2) { TColgp_Array1OfPnt2d thePoles(1,2); aBezier->Poles(thePoles); gp_Vec2d aVec(thePoles(1), thePoles(2)); NewPCurve = new Geom2d_Line(thePoles(1), aVec); return Standard_True; } } else if (NewPCurve->IsInstance(STANDARD_TYPE(Geom2d_BSplineCurve))) { Handle(Geom2d_BSplineCurve) aBSpline = *((Handle(Geom2d_BSplineCurve)*)&NewPCurve); if (aBSpline->NbKnots() == 2 && aBSpline->NbPoles() == 2) { TColgp_Array1OfPnt2d thePoles(1,2); aBSpline->Poles(thePoles); gp_Vec2d aVec(thePoles(1), thePoles(2)); NewPCurve = new Geom2d_Line(thePoles(1), aVec); return Standard_True; } } } FirstPar = aPCurve->FirstParameter(); LastPar = aPCurve->LastParameter(); Handle(Geom2d_TrimmedCurve) aTrCurve = new Geom2d_TrimmedCurve(aPCurve, FirstPar, LastPar); // The curve is not prolonged on begin or end. // Trying to prolong it adding a segment to its bound. gp_Pnt2d aPBnd; gp_Vec2d aVBnd; gp_Pnt2d aPBeg; gp_Dir2d aDBnd; Handle(Geom2d_Line) aLin; Handle(Geom2d_TrimmedCurve) aSegment; Geom2dConvert_CompCurveToBSplineCurve aCompCurve(aTrCurve, Convert_RationalC1); Standard_Real aTol = Precision::Confusion(); Standard_Real aDelta = Max(a2Offset, 1.); if (FirstPar > anEf - a2Offset) { aPCurve->D1(FirstPar, aPBnd, aVBnd); aDBnd.SetXY(aVBnd.XY()); aPBeg = aPBnd.Translated(gp_Vec2d(-aDelta*aDBnd.XY())); aLin = new Geom2d_Line(aPBeg, aDBnd); aSegment = new Geom2d_TrimmedCurve(aLin, 0, aDelta); if (!aCompCurve.Add(aSegment, aTol)) return Standard_False; } if (LastPar < anEl + a2Offset) { aPCurve->D1(LastPar, aPBeg, aVBnd); aDBnd.SetXY(aVBnd.XY()); aLin = new Geom2d_Line(aPBeg, aDBnd); aSegment = new Geom2d_TrimmedCurve(aLin, 0, aDelta); if (!aCompCurve.Add(aSegment, aTol)) return Standard_False; } NewPCurve = aCompCurve.BSplineCurve(); return Standard_True; } //======================================================================= //function : ExtentEdge //purpose : //======================================================================= // Modified by skv - Fri Dec 26 17:00:55 2003 OCC4455 Begin //static void ExtentEdge(const TopoDS_Edge& E,TopoDS_Edge& NE) static void ExtentEdge(const TopoDS_Edge& E,TopoDS_Edge& NE, const Standard_Real theOffset) { //BRepLib::BuildCurve3d(E); TopoDS_Shape aLocalShape = E.EmptyCopied(); Standard_Real anEf; Standard_Real anEl; Standard_Real a2Offset = 2.*Abs(theOffset); BRep_Builder BB; Standard_Integer i, j; BRep_Tool::Range(E, anEf, anEl); NE = TopoDS::Edge(aLocalShape); // NE = TopoDS::Edge(E.EmptyCopied()); // Enough for analytic edges, for general case reconstruct the // geometry of the edge recalculating the intersection of surfaces. //BRepLib::BuildCurve3d(E); Standard_Integer NbPCurves = 0; Standard_Real FirstParOnPC = RealFirst(), LastParOnPC = RealLast(); Handle(Geom2d_Curve) MinPC; Handle(Geom_Surface) MinSurf; TopLoc_Location MinLoc; BRep_ListIteratorOfListOfCurveRepresentation itr( (Handle(BRep_TEdge)::DownCast(NE.TShape()))->ChangeCurves() ); for (; itr.More(); itr.Next()) { Handle( BRep_CurveRepresentation ) CurveRep = itr.Value(); Standard_Real FirstPar, LastPar; if (CurveRep->IsCurveOnSurface()) { NbPCurves++; Handle(Geom2d_Curve) theCurve = CurveRep->PCurve(); FirstPar = theCurve->FirstParameter(); LastPar = theCurve->LastParameter(); if (theCurve->IsKind(STANDARD_TYPE(Geom2d_BoundedCurve)) && (FirstPar > anEf - a2Offset || LastPar < anEl + a2Offset)) { Handle(Geom2d_Curve) NewPCurve; if (ExtendPCurve(theCurve, anEf, anEl, a2Offset, NewPCurve)) { CurveRep->PCurve(NewPCurve); FirstPar = NewPCurve->FirstParameter(); LastPar = NewPCurve->LastParameter(); if (CurveRep->IsCurveOnClosedSurface()) { Handle(Geom2d_Curve) PCurve2 = CurveRep->PCurve2(); if (ExtendPCurve(PCurve2, anEf, anEl, a2Offset, NewPCurve)) CurveRep->PCurve2(NewPCurve); } } } else if (theCurve->IsPeriodic()) { Standard_Real delta = (theCurve->Period() - (anEl - anEf))*0.5; delta *= 0.95; FirstPar = anEf - delta; LastPar = anEl + delta; } else if (theCurve->IsClosed()) LastPar -= 0.05*(LastPar - FirstPar); //check FirstPar and LastPar: the pcurve should be in its surface theCurve = CurveRep->PCurve(); Handle(Geom_Surface) theSurf = CurveRep->Surface(); Standard_Real Umin, Umax, Vmin, Vmax; theSurf->Bounds(Umin, Umax, Vmin, Vmax); TColGeom2d_SequenceOfCurve BoundLines; if (!Precision::IsInfinite(Vmin)) { Handle(Geom2d_Line) aLine = new Geom2d_Line(gp_Pnt2d( 0., Vmin ), gp_Dir2d( 1., 0. )); BoundLines.Append(aLine); } if (!Precision::IsInfinite(Umin)) { Handle(Geom2d_Line) aLine = new Geom2d_Line(gp_Pnt2d( Umin, 0. ), gp_Dir2d( 0., 1. )); BoundLines.Append(aLine); } if (!Precision::IsInfinite(Vmax)) { Handle(Geom2d_Line) aLine = new Geom2d_Line(gp_Pnt2d( 0., Vmax ), gp_Dir2d( 1., 0. )); BoundLines.Append(aLine); } if (!Precision::IsInfinite(Umax)) { Handle(Geom2d_Line) aLine = new Geom2d_Line(gp_Pnt2d( Umax, 0. ), gp_Dir2d( 0., 1. )); BoundLines.Append(aLine); } TColStd_SequenceOfReal params; Geom2dInt_GInter IntCC; Geom2dAdaptor_Curve GAcurve(theCurve); for (i = 1; i <= BoundLines.Length(); i++) { Geom2dAdaptor_Curve GAline( BoundLines(i) ); IntCC.Perform( GAcurve, GAline, Precision::PConfusion(), Precision::PConfusion()); if (IntCC.IsDone()) { for (j = 1; j <= IntCC.NbPoints(); j++) { const IntRes2d_IntersectionPoint& ip = IntCC.Point(j); gp_Pnt2d aPoint = ip.Value(); if (aPoint.X() >= Umin && aPoint.X() <= Umax && aPoint.Y() >= Vmin && aPoint.Y() <= Vmax) params.Append( ip.ParamOnFirst() ); } for (j = 1; j <= IntCC.NbSegments(); j++) { const IntRes2d_IntersectionSegment& is = IntCC.Segment(j); if (is.HasFirstPoint()) { const IntRes2d_IntersectionPoint& ip = is.FirstPoint(); gp_Pnt2d aPoint = ip.Value(); if (aPoint.X() >= Umin && aPoint.X() <= Umax && aPoint.Y() >= Vmin && aPoint.Y() <= Vmax) params.Append( ip.ParamOnFirst() ); } if (is.HasLastPoint()) { const IntRes2d_IntersectionPoint& ip = is.LastPoint(); gp_Pnt2d aPoint = ip.Value(); if (aPoint.X() >= Umin && aPoint.X() <= Umax && aPoint.Y() >= Vmin && aPoint.Y() <= Vmax) params.Append( ip.ParamOnFirst() ); } } } } if (!params.IsEmpty()) { if (params.Length() == 1) { gp_Pnt2d PntFirst = theCurve->Value(FirstPar); if (PntFirst.X() >= Umin && PntFirst.X() <= Umax && PntFirst.Y() >= Vmin && PntFirst.Y() <= Vmax) { if (LastPar > params(1)) LastPar = params(1); } else if (FirstPar < params(1)) FirstPar = params(1); } else { Standard_Real fpar = RealLast(), lpar = RealFirst(); for (i = 1; i <= params.Length(); i++) { if (params(i) < fpar) fpar = params(i); if (params(i) > lpar) lpar = params(i); } if (FirstPar < fpar) FirstPar = fpar; if (LastPar > lpar) LastPar = lpar; } } //// end of check //// (Handle(BRep_GCurve)::DownCast(CurveRep))->SetRange( FirstPar, LastPar ); //gp_Pnt2d Pfirst = theCurve->Value(FirstPar); //gp_Pnt2d Plast = theCurve->Value(LastPar); //(Handle(BRep_CurveOnSurface)::DownCast(CurveRep))->SetUVPoints( Pfirst, Plast ); //update FirstParOnPC and LastParOnPC if (FirstPar > FirstParOnPC) { FirstParOnPC = FirstPar; MinPC = theCurve; MinSurf = theSurf; MinLoc = CurveRep->Location(); } if (LastPar < LastParOnPC) { LastParOnPC = LastPar; MinPC = theCurve; MinSurf = theSurf; MinLoc = CurveRep->Location(); } } } Standard_Real f, l; Handle(Geom_Curve) C3d = BRep_Tool::Curve( NE, f, l ); if (NbPCurves) { MinLoc = E.Location() * MinLoc; if (!C3d.IsNull()) { if (MinPC->IsClosed()) { f = FirstParOnPC; l = LastParOnPC; } else if (C3d->IsPeriodic()) { Standard_Real delta = (C3d->Period() - (l - f))*0.5; delta *= 0.95; f -= delta; l += delta; } else if (C3d->IsClosed()) l -= 0.05*(l - f); else { f = FirstParOnPC; l = LastParOnPC; GeomAPI_ProjectPointOnCurve Projector; if (!Precision::IsInfinite(FirstParOnPC)) { gp_Pnt2d P2d1 = MinPC->Value(FirstParOnPC); gp_Pnt P1 = MinSurf->Value( P2d1.X(), P2d1.Y() ); P1.Transform(MinLoc.Transformation()); Projector.Init( P1, C3d ); if (Projector.NbPoints() > 0) f = Projector.LowerDistanceParameter(); #ifdef DEB else cout<<"ProjectPointOnCurve not done"<Value(LastParOnPC); gp_Pnt P2 = MinSurf->Value( P2d2.X(), P2d2.Y() ); P2.Transform(MinLoc.Transformation()); Projector.Init( P2, C3d ); if (Projector.NbPoints() > 0) l = Projector.LowerDistanceParameter(); #ifdef DEB else cout<<"ProjectPointOnCurve not done"<Transformed(MinLoc.Transformation())); Standard_Real max_deviation = 0.; if (Precision::IsInfinite(FirstParOnPC) || Precision::IsInfinite(LastParOnPC)) { if (MinPC->IsInstance(STANDARD_TYPE(Geom2d_Line))) { Standard_Boolean IsLine = Standard_False; if (MinSurf->IsInstance(STANDARD_TYPE(Geom_Plane))) IsLine = Standard_True; else if (MinSurf->IsInstance(STANDARD_TYPE(Geom_CylindricalSurface)) || MinSurf->IsInstance(STANDARD_TYPE(Geom_ConicalSurface))) { Handle(Geom2d_Line) theLine = *((Handle(Geom2d_Line)*)&MinPC); gp_Dir2d LineDir = theLine->Direction(); if (LineDir.IsParallel( gp::DY2d(), Precision::Angular() )) IsLine = Standard_True; } if (IsLine) { gp_Pnt2d P2d1 = MinPC->Value(0.), P2d2 = MinPC->Value(1.); gp_Pnt P1 = MinSurf->Value(P2d1.X(), P2d1.Y()); gp_Pnt P2 = MinSurf->Value(P2d2.X(), P2d2.Y()); gp_Vec aVec(P1, P2); C3d = new Geom_Line( P1, aVec ); } } } else { Geom2dAdaptor_Curve AC2d( MinPC, FirstParOnPC, LastParOnPC ); GeomAdaptor_Surface GAsurf( MinSurf ); Handle(Geom2dAdaptor_HCurve) HC2d = new Geom2dAdaptor_HCurve( AC2d ); Handle(GeomAdaptor_HSurface) HSurf = new GeomAdaptor_HSurface( GAsurf ); Adaptor3d_CurveOnSurface ConS( HC2d, HSurf ); Standard_Real /*max_deviation,*/ average_deviation; GeomAbs_Shape Continuity = GeomAbs_C1; Standard_Integer MaxDegree = 14; Standard_Integer MaxSegment = evaluateMaxSegment(ConS); GeomLib::BuildCurve3d(Precision::Confusion(), ConS, FirstParOnPC, LastParOnPC, C3d, max_deviation, average_deviation, Continuity, MaxDegree, MaxSegment); } BB.UpdateEdge( NE, C3d, max_deviation ); //BB.Range( NE, FirstParOnPC, LastParOnPC ); Standard_Boolean ProjectionSuccess = Standard_True; if (NbPCurves > 1) //BRepLib::SameParameter( NE, Precision::Confusion(), Standard_True ); for (itr.Initialize((Handle(BRep_TEdge)::DownCast(NE.TShape()))->ChangeCurves()); itr.More(); itr.Next()) { Handle( BRep_CurveRepresentation ) CurveRep = itr.Value(); Standard_Real FirstPar, LastPar; if (CurveRep->IsCurveOnSurface()) { Handle(Geom2d_Curve) theCurve = CurveRep->PCurve(); Handle(Geom_Surface) theSurf = CurveRep->Surface(); TopLoc_Location theLoc = CurveRep->Location(); if (theCurve == MinPC && theSurf == MinSurf && theLoc == MinLoc) continue; FirstPar = (Handle(BRep_GCurve)::DownCast(CurveRep))->First(); LastPar = (Handle(BRep_GCurve)::DownCast(CurveRep))->Last(); if (Abs(FirstPar - FirstParOnPC) > Precision::PConfusion() || Abs(LastPar - LastParOnPC) > Precision::PConfusion()) { theLoc = E.Location() * theLoc; theSurf = Handle(Geom_Surface)::DownCast (theSurf->Transformed(theLoc.Transformation())); if (theCurve->IsInstance(STANDARD_TYPE(Geom2d_Line)) && theSurf->IsKind(STANDARD_TYPE(Geom_BoundedSurface))) { gp_Dir2d theDir = (*((Handle(Geom2d_Line)*)&theCurve))->Direction(); if (theDir.IsParallel(gp::DX2d(), Precision::Angular()) || theDir.IsParallel(gp::DY2d(), Precision::Angular())) { Standard_Real U1, U2, V1, V2; theSurf->Bounds(U1, U2, V1, V2); gp_Pnt2d Origin = (*((Handle(Geom2d_Line)*)&theCurve))->Location(); if (Abs(Origin.X()-U1) <= Precision::Confusion() || Abs(Origin.X()-U2) <= Precision::Confusion() || Abs(Origin.Y()-V1) <= Precision::Confusion() || Abs(Origin.Y()-V2) <= Precision::Confusion()) { BRepLib::SameParameter( NE, Precision::Confusion(), Standard_True ); break; } } } Handle(Geom2d_Curve) ProjPCurve = GeomProjLib::Curve2d( C3d, FirstParOnPC, LastParOnPC, theSurf ); if (ProjPCurve.IsNull()) ProjectionSuccess = Standard_False; else CurveRep->PCurve( ProjPCurve ); } } } if (ProjectionSuccess) BB.Range( NE, FirstParOnPC, LastParOnPC ); else { BB.Range( NE, FirstParOnPC, LastParOnPC, Standard_True ); BRepLib::SameParameter( NE, Precision::Confusion(), Standard_True ); } } } else //no pcurves { Standard_Real FirstPar = C3d->FirstParameter(); Standard_Real LastPar = C3d->LastParameter(); if (C3d->IsKind(STANDARD_TYPE(Geom_BoundedCurve)) && (FirstPar > anEf - a2Offset || LastPar < anEl + a2Offset)) { Handle(Geom_TrimmedCurve) aTrCurve = new Geom_TrimmedCurve(C3d, FirstPar, LastPar); // The curve is not prolonged on begin or end. // Trying to prolong it adding a segment to its bound. gp_Pnt aPBnd; gp_Vec aVBnd; gp_Pnt aPBeg; gp_Dir aDBnd; Handle(Geom_Line) aLin; Handle(Geom_TrimmedCurve) aSegment; GeomConvert_CompCurveToBSplineCurve aCompCurve(aTrCurve, Convert_RationalC1); Standard_Real aTol = Precision::Confusion(); Standard_Real aDelta = Max(a2Offset, 1.); if (FirstPar > anEf - a2Offset) { C3d->D1(FirstPar, aPBnd, aVBnd); aDBnd.SetXYZ(aVBnd.XYZ()); aPBeg = aPBnd.Translated(gp_Vec(-aDelta*aDBnd.XYZ())); aLin = new Geom_Line(aPBeg, aDBnd); aSegment = new Geom_TrimmedCurve(aLin, 0, aDelta); if (!aCompCurve.Add(aSegment, aTol)) return; } if (LastPar < anEl + a2Offset) { C3d->D1(LastPar, aPBeg, aVBnd); aDBnd.SetXYZ(aVBnd.XYZ()); aLin = new Geom_Line(aPBeg, aDBnd); aSegment = new Geom_TrimmedCurve(aLin, 0, aDelta); if (!aCompCurve.Add(aSegment, aTol)) return; } C3d = aCompCurve.BSplineCurve(); FirstPar = C3d->FirstParameter(); LastPar = C3d->LastParameter(); BB.UpdateEdge(NE, C3d, Precision::Confusion()); } else if (C3d->IsPeriodic()) { Standard_Real delta = (C3d->Period() - (anEl - anEf))*0.5; delta *= 0.95; FirstPar = anEf - delta; LastPar = anEl + delta; } else if (C3d->IsClosed()) LastPar -= 0.05*(LastPar - FirstPar); BB.Range( NE, FirstPar, LastPar ); } } // Modified by skv - Fri Dec 26 17:00:57 2003 OCC4455 End //======================================================================= //function : UpdateVertex //purpose : //======================================================================= static Standard_Boolean UpdateVertex(TopoDS_Vertex V, TopoDS_Edge& OE, TopoDS_Edge& NE, Standard_Real TolConf) { BRepAdaptor_Curve OC(OE); BRepAdaptor_Curve NC(NE); Standard_Real Of = OC.FirstParameter(); Standard_Real Ol = OC.LastParameter(); Standard_Real Nf = NC.FirstParameter(); Standard_Real Nl = NC.LastParameter(); Standard_Real U = 0.; Standard_Real ParTol = Precision::PConfusion(); gp_Pnt P = BRep_Tool::Pnt(V); Standard_Boolean OK = Standard_False; if (P.Distance(OC.Value(Of)) < TolConf) { if (Of >= Nf + ParTol && Of <= Nl + ParTol && P.Distance(NC.Value(Of)) < TolConf) { OK = Standard_True; U = Of; } } if (P.Distance(OC.Value(Ol)) < TolConf) { if (Ol >= Nf + ParTol && Ol <= Nl + ParTol && P.Distance(NC.Value(Ol)) < TolConf) { OK = Standard_True; U = Ol; } } if (OK) { BRep_Builder B; TopoDS_Shape aLocalShape = NE.Oriented(TopAbs_FORWARD); TopoDS_Edge EE = TopoDS::Edge(aLocalShape); // TopoDS_Edge EE = TopoDS::Edge(NE.Oriented(TopAbs_FORWARD)); aLocalShape = V.Oriented(TopAbs_INTERNAL); B.UpdateVertex(TopoDS::Vertex(aLocalShape), U,NE,BRep_Tool::Tolerance(NE)); // B.UpdateVertex(TopoDS::Vertex(V.Oriented(TopAbs_INTERNAL)), // U,NE,BRep_Tool::Tolerance(NE)); } return OK; } //======================================================================= //function : Compute //purpose : //======================================================================= void BRepOffset_Inter2d::Compute (const Handle(BRepAlgo_AsDes)& AsDes, const TopoDS_Face& F, const TopTools_IndexedMapOfShape& NewEdges, const Standard_Real Tol) { #ifdef DRAW NbF2d++; NbE2d = 0; #endif //Do not intersect the edges of face TopTools_MapOfShape EdgesOfFace; TopExp_Explorer Explo( F, TopAbs_EDGE ); for (; Explo.More(); Explo.Next()) EdgesOfFace.Add( Explo.Current() ); //----------------------------------------------------------- // calculate intersections2d on faces touched by // intersection3d //--------------------------------------------------------- TopTools_ListIteratorOfListOfShape it1LE ; TopTools_ListIteratorOfListOfShape it2LE ; //----------------------------------------------- // Intersection of edges 2*2. //----------------------------------------------- const TopTools_ListOfShape& LE = AsDes->Descendant(F); TopoDS_Vertex V1,V2; Standard_Integer j, i = 1; for ( it1LE.Initialize(LE) ; it1LE.More(); it1LE.Next()) { const TopoDS_Edge& E1 = TopoDS::Edge(it1LE.Value()); j = 1; it2LE.Initialize(LE); while (j < i && it2LE.More()) { const TopoDS_Edge& E2 = TopoDS::Edge(it2LE.Value()); //-------------------------------------------------------------- // Intersections of New edges obtained by intersection // between them and with edges of restrictions //------------------------------------------------------ if ( (!EdgesOfFace.Contains(E1) || !EdgesOfFace.Contains(E2)) && (NewEdges.Contains(E1) || NewEdges.Contains(E2)) ) { TopoDS_Shape aLocalShape = F.Oriented(TopAbs_FORWARD); EdgeInter(TopoDS::Face(aLocalShape),E1,E2,AsDes,Tol,Standard_True); // EdgeInter(TopoDS::Face(F.Oriented(TopAbs_FORWARD)),E1,E2,AsDes,Tol,Standard_True); } it2LE.Next(); j++; } i++; } } //======================================================================= //function : ConnexIntByInt //purpose : //======================================================================= // Modified by skv - Fri Dec 26 16:53:16 2003 OCC4455 Begin // Add another parameter: offset value. void BRepOffset_Inter2d::ConnexIntByInt (const TopoDS_Face& FI, BRepOffset_Offset& OFI, TopTools_DataMapOfShapeShape& MES, const TopTools_DataMapOfShapeShape& Build, const Handle(BRepAlgo_AsDes)& AsDes, const Standard_Real Offset, const Standard_Real Tol) // Modified by skv - Fri Dec 26 16:53:18 2003 OCC4455 End { TopTools_DataMapOfShapeListOfShape MVE; BRepOffset_Tool::MapVertexEdges(FI,MVE); //--------------------- // Extension of edges. //--------------------- TopoDS_Edge NE; TopTools_DataMapIteratorOfDataMapOfShapeListOfShape it(MVE); for ( ; it.More(); it.Next()) { const TopTools_ListOfShape& L = it.Value(); Standard_Boolean YaBuild = 0; TopTools_ListIteratorOfListOfShape itL(L); for (; itL.More(); itL.Next()) { YaBuild = Build.IsBound(itL.Value()); if (YaBuild) break; } if (YaBuild) { for (itL.Initialize(L); itL.More(); itL.Next()) { const TopoDS_Edge& EI = TopoDS::Edge(itL.Value()); TopoDS_Shape aLocalShape = OFI.Generated(EI); const TopoDS_Edge& OE = TopoDS::Edge(aLocalShape); // const TopoDS_Edge& OE = TopoDS::Edge(OFI.Generated(EI)); if (!MES.IsBound(OE) && !Build.IsBound(EI)) { // Modified by skv - Fri Dec 26 16:59:52 2003 OCC4455 Begin // ExtentEdge(OE,NE); ExtentEdge(OE,NE, Offset); // Modified by skv - Fri Dec 26 16:59:54 2003 OCC4455 End MES.Bind (OE,NE); } } } } TopoDS_Face FIO = TopoDS::Face(OFI.Face()); if (MES.IsBound(FIO)) FIO = TopoDS::Face(MES(FIO)); TopExp_Explorer exp(FI.Oriented(TopAbs_FORWARD),TopAbs_WIRE); for (; exp.More(); exp.Next()) { const TopoDS_Wire& W = TopoDS::Wire(exp.Current()); BRepTools_WireExplorer wexp; Standard_Boolean end = Standard_False ; TopoDS_Edge FirstE,CurE,NextE; TopoDS_Shape aLocalWire = W .Oriented(TopAbs_FORWARD); TopoDS_Shape aLocalFace = FI.Oriented(TopAbs_FORWARD); wexp.Init(TopoDS::Wire(aLocalWire),TopoDS::Face(aLocalFace)); // wexp.Init(TopoDS::Wire(W .Oriented(TopAbs_FORWARD)), // TopoDS::Face(FI.Oriented(TopAbs_FORWARD))); CurE = FirstE = wexp.Current(); while (!end) { wexp.Next(); if (wexp.More()) { NextE = wexp.Current(); } else { NextE = FirstE; end = Standard_True; } if (CurE.IsSame(NextE)) continue; //IFV------------ TopoDS_Vertex Vref = CommonVertex(CurE, NextE); gp_Pnt Pref = BRep_Tool::Pnt(Vref); //IFV------------ TopoDS_Shape aLocalShape = OFI.Generated(CurE); TopoDS_Edge CEO = TopoDS::Edge(aLocalShape); aLocalShape = OFI.Generated(NextE); TopoDS_Edge NEO = TopoDS::Edge(aLocalShape); // TopoDS_Edge CEO = TopoDS::Edge(OFI.Generated(CurE)); // TopoDS_Edge NEO = TopoDS::Edge(OFI.Generated(NextE)); //------------------------------------------ // Inter processing of images of CurE NextE. //------------------------------------------ TopTools_ListOfShape LV1,LV2; Standard_Boolean DoInter = 1; TopoDS_Shape NE1,NE2; if (Build.IsBound(CurE) && Build.IsBound(NextE)) { NE1 = Build(CurE ); NE2 = Build(NextE); } else if (Build.IsBound(CurE) && MES.IsBound(NEO)) { NE1 = Build(CurE); NE2 = MES (NEO); } else if (Build.IsBound(NextE) && MES.IsBound(CEO)) { NE1 = Build(NextE); NE2 = MES(CEO); } else { DoInter = 0; } if (DoInter) { //------------------------------------ // NE1,NE2 can be a compound of Edges. //------------------------------------ TopExp_Explorer Exp1,Exp2; for (Exp1.Init(NE1,TopAbs_EDGE) ; Exp1.More(); Exp1.Next()) { for (Exp2.Init(NE2,TopAbs_EDGE) ; Exp2.More(); Exp2.Next()) { RefEdgeInter(FIO,TopoDS::Edge(Exp1.Current()),TopoDS::Edge(Exp2.Current()), AsDes,Tol,Standard_True/*Standard_False*/, Pref); } } } else { if (MES.IsBound(CEO)) { TopoDS_Vertex V = CommonVertex(CEO,NEO); UpdateVertex (V,CEO,TopoDS::Edge(MES(CEO)),Tol); AsDes->Add (MES(CEO),V); } else if (MES.IsBound(NEO)) { TopoDS_Vertex V = CommonVertex(CEO,NEO); UpdateVertex (V,NEO,TopoDS::Edge(MES(NEO)),Tol); AsDes->Add (MES(NEO),V); } } CurE = NextE; } } }