1 // Created by: Peter KURNEV
2 // Copyright (c) 1999-2014 OPEN CASCADE SAS
4 // This file is part of Open CASCADE Technology software library.
6 // This library is free software; you can redistribute it and/or modify it under
7 // the terms of the GNU Lesser General Public License version 2.1 as published
8 // by the Free Software Foundation, with special exception defined in the file
9 // OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
10 // distribution for complete text of the license and disclaimer of any warranty.
12 // Alternatively, this file may be used under the terms of Open CASCADE
13 // commercial license or contractual agreement.
16 #include <BOPTools_AlgoTools2D.hxx>
17 #include <BRep_Builder.hxx>
18 #include <BRep_CurveRepresentation.hxx>
19 #include <BRep_GCurve.hxx>
20 #include <BRep_ListIteratorOfListOfCurveRepresentation.hxx>
21 #include <BRep_TEdge.hxx>
22 #include <BRep_Tool.hxx>
23 #include <BRepAdaptor_Curve.hxx>
24 #include <BRepAdaptor_HSurface.hxx>
25 #include <BRepAdaptor_Surface.hxx>
26 #include <BRepClass_FaceClassifier.hxx>
27 #include <BRepTools.hxx>
28 #include <Geom2d_BSplineCurve.hxx>
29 #include <Geom2d_Circle.hxx>
30 #include <Geom2d_Curve.hxx>
31 #include <Geom2d_Ellipse.hxx>
32 #include <Geom2d_Hyperbola.hxx>
33 #include <Geom2d_Line.hxx>
34 #include <Geom2d_Parabola.hxx>
35 #include <Geom2d_TrimmedCurve.hxx>
36 #include <Geom2dAdaptor.hxx>
37 #include <Geom_Curve.hxx>
38 #include <Geom_Plane.hxx>
39 #include <Geom_RectangularTrimmedSurface.hxx>
40 #include <Geom_Surface.hxx>
41 #include <Geom_TrimmedCurve.hxx>
42 #include <GeomAdaptor_Curve.hxx>
43 #include <GeomAdaptor_HCurve.hxx>
44 #include <GeomAdaptor_HSurface.hxx>
45 #include <GeomAdaptor_Surface.hxx>
46 #include <GeomInt.hxx>
47 #include <GeomLib.hxx>
48 #include <GeomProjLib.hxx>
50 #include <gp_Cylinder.hxx>
52 #include <gp_Pnt2d.hxx>
54 #include <gp_Vec2d.hxx>
55 #include <IntTools_Context.hxx>
56 #include <IntTools_Tools.hxx>
57 #include <Precision.hxx>
58 #include <ProjLib_ProjectedCurve.hxx>
59 #include <ProjLib.hxx>
60 #include <Standard_ConstructionError.hxx>
61 #include <Standard_NotImplemented.hxx>
63 #include <TopExp_Explorer.hxx>
64 #include <TopLoc_Location.hxx>
65 #include <TopoDS_Edge.hxx>
66 #include <TopoDS_Face.hxx>
69 Standard_Real MaxToleranceEdge (const TopoDS_Face& );
71 //=======================================================================
72 //function : BuildPCurveForEdgeOnFace
74 //=======================================================================
75 void BOPTools_AlgoTools2D::BuildPCurveForEdgeOnFace (const TopoDS_Edge& aE,
76 const TopoDS_Face& aF,
77 const Handle(IntTools_Context)& theContext)
80 Handle(Geom2d_Curve) aC2D;
81 Standard_Real aTolPC, aTolFact, aTolEdge, aFirst, aLast;
83 Standard_Boolean aHasOld;
84 aHasOld=BOPTools_AlgoTools2D::HasCurveOnSurface (aE, aF, aC2D,
92 BOPTools_AlgoTools2D::CurveOnSurface(aE, aF, aC2D, aTolPC, theContext);
94 aTolEdge=BRep_Tool::Tolerance(aE);
96 aTolFact=Max(aTolEdge, aTolPC);
98 aBB.UpdateEdge(aE, aC2D, aF, aTolFact);
102 //=======================================================================
103 //function : EdgeTangent
105 //=======================================================================
106 Standard_Boolean BOPTools_AlgoTools2D::EdgeTangent
107 (const TopoDS_Edge& anEdge,
108 const Standard_Real aT,
111 Standard_Boolean isdgE;
112 Standard_Real first, last;
114 isdgE = BRep_Tool::Degenerated(anEdge);
116 return Standard_False;
119 Handle(Geom_Curve) aC=BRep_Tool::Curve(anEdge, first, last);
121 aC->D1(aT, aP, aTau);
122 Standard_Real mod = aTau.Magnitude();
123 if(mod > gp::Resolution()) {
127 return Standard_False;
130 if (anEdge.Orientation() == TopAbs_REVERSED){
133 return Standard_True;
136 //=======================================================================
137 //function : PointOnOnSurface
139 //=======================================================================
140 void BOPTools_AlgoTools2D::PointOnSurface (const TopoDS_Edge& aE,
141 const TopoDS_Face& aF,
142 const Standard_Real aParameter,
145 const Handle(IntTools_Context)& theContext)
148 Handle(Geom2d_Curve) aC2D;
149 Standard_Real aToler, aFirst, aLast;
151 BOPTools_AlgoTools2D::CurveOnSurface (aE, aF, aC2D, aFirst, aLast, aToler, theContext);
152 aC2D->D0(aParameter, aP2D);
158 //=======================================================================
159 //function : CurveOnSurface
161 //=======================================================================
162 void BOPTools_AlgoTools2D::CurveOnSurface (const TopoDS_Edge& aE,
163 const TopoDS_Face& aF,
164 Handle(Geom2d_Curve)& aC2D,
165 Standard_Real& aToler,
166 const Handle(IntTools_Context)& theContext)
168 Standard_Real aFirst, aLast;
170 BOPTools_AlgoTools2D::CurveOnSurface(aE, aF, aC2D, aFirst, aLast, aToler, theContext);
174 //=======================================================================
175 //function : CurveOnSurface
177 //=======================================================================
178 void BOPTools_AlgoTools2D::CurveOnSurface (const TopoDS_Edge& aE,
179 const TopoDS_Face& aF,
180 Handle(Geom2d_Curve)& aC2D,
181 Standard_Real& aFirst,
182 Standard_Real& aLast,
183 Standard_Real& aToler,
184 const Handle(IntTools_Context)& theContext)
186 Standard_Boolean aHasOld;
187 Handle(Geom2d_Curve) C2D;
189 aHasOld=BOPTools_AlgoTools2D::HasCurveOnSurface (aE, aF, C2D,
197 BOPTools_AlgoTools2D::Make2D(aE, aF, C2D, aFirst, aLast, aToler, theContext);
201 //=======================================================================
202 //function : HasCurveOnSurface
204 //=======================================================================
205 Standard_Boolean BOPTools_AlgoTools2D::HasCurveOnSurface
206 (const TopoDS_Edge& aE,
207 const TopoDS_Face& aF,
208 Handle(Geom2d_Curve)& aC2D,
209 Standard_Real& aFirst,
210 Standard_Real& aLast,
211 Standard_Real& aToler)
213 Standard_Boolean aHasOld;
215 aToler=BRep_Tool::Tolerance(aE);
216 BRep_Tool::Range(aE, aFirst, aLast);
218 if((aLast - aFirst) < Precision::PConfusion()) {
219 return Standard_False;
222 aC2D=BRep_Tool::CurveOnSurface(aE, aF, aFirst, aLast);
223 aHasOld=!aC2D.IsNull();
226 //=======================================================================
227 //function : HasCurveOnSurface
229 //=======================================================================
230 Standard_Boolean BOPTools_AlgoTools2D::HasCurveOnSurface
231 (const TopoDS_Edge& aE,
232 const TopoDS_Face& aF)
234 Standard_Boolean bHasOld;
235 Handle(Geom2d_Curve) aC2D;
236 Standard_Real aFirst, aLast;
238 BRep_Tool::Range(aE, aFirst, aLast);
240 if((aLast - aFirst) < Precision::PConfusion()) {
241 return Standard_False;
244 aC2D=BRep_Tool::CurveOnSurface(aE, aF, aFirst, aLast);
245 bHasOld=!aC2D.IsNull();
249 //=======================================================================
250 //function : AdjustPCurveOnFace
252 //=======================================================================
253 void BOPTools_AlgoTools2D::AdjustPCurveOnFace
254 (const TopoDS_Face& theF,
255 const Handle(Geom_Curve)& theC3D,
256 const Handle(Geom2d_Curve)& theC2D,
257 Handle(Geom2d_Curve)& theC2DA,
258 const Handle(IntTools_Context)& theContext)
260 Standard_Real aT1 = theC3D->FirstParameter();
261 Standard_Real aT2 = theC3D->LastParameter();
263 BOPTools_AlgoTools2D::AdjustPCurveOnFace (theF, aT1, aT2, theC2D, theC2DA, theContext);
265 //=======================================================================
266 //function : AdjustPCurveOnFace
268 //=======================================================================
269 void BOPTools_AlgoTools2D::AdjustPCurveOnFace
270 (const TopoDS_Face& theF,
271 const Standard_Real theFirst,
272 const Standard_Real theLast,
273 const Handle(Geom2d_Curve)& theC2D,
274 Handle(Geom2d_Curve)& theC2DA,
275 const Handle(IntTools_Context)& theContext)
277 BRepAdaptor_Surface aBASTmp;
278 const BRepAdaptor_Surface* pBAS;
279 if (!theContext.IsNull()) {
280 pBAS = &theContext->SurfaceAdaptor(theF);
283 aBASTmp.Initialize(theF, Standard_True);
287 BOPTools_AlgoTools2D::AdjustPCurveOnSurf(*pBAS, theFirst, theLast, theC2D, theC2DA);
289 //=======================================================================
290 //function : AdjustPCurveOnFace
292 //=======================================================================
293 void BOPTools_AlgoTools2D::AdjustPCurveOnSurf
294 (const BRepAdaptor_Surface& aBAS,
295 const Standard_Real aFirst,
296 const Standard_Real aLast,
297 const Handle(Geom2d_Curve)& aC2D,
298 Handle(Geom2d_Curve)& aC2DA)
300 Standard_Boolean mincond, maxcond;
301 Standard_Real UMin, UMax, VMin, VMax, aT, u2, v2, du, dv, aDelta;
302 Standard_Real aUPeriod;
304 const TopoDS_Face& aF=aBAS.Face();
305 UMin=aBAS.FirstUParameter();
306 UMax=aBAS.LastUParameter();
307 VMin=aBAS.FirstVParameter();
308 VMax=aBAS.LastVParameter();
310 aDelta=Precision::PConfusion();
312 aT =.5*(aFirst+aLast);
322 if (aBAS.IsUPeriodic()) {
323 aUPeriod = aBAS.UPeriod();
326 // a. try to clarify u2 using the precision (aDelta)
327 if (fabs(u2-UMin) < aDelta) {
330 else if (fabs(u2-UMin-aUPeriod) < aDelta) {
333 // b. compute du again using clarified value of u2
334 GeomInt::AdjustPeriodic(u2, UMin, UMax, aUPeriod, u2, du, 0.);
337 if (aBAS.GetType()==GeomAbs_Cylinder) {
338 Standard_Real aR, dFi, aTol;
340 gp_Cylinder aCylinder=aBAS.Cylinder();
341 aR=aCylinder.Radius();
342 aTol=MaxToleranceEdge(aF);
348 mincond = (UMin - u2 > dFi);
349 maxcond = (u2 - UMax > dFi);
350 if (mincond || maxcond) {
351 du = ( mincond ) ? aUPeriod : -aUPeriod;
359 if (aBAS.IsVPeriodic()) {
360 Standard_Real aVPeriod, aVm, aVr, aVmid, dVm, dVr;
362 aVPeriod = aBAS.VPeriod();
363 mincond = (VMin - v2 > aDelta);
364 maxcond = (v2 - VMax > aDelta);
366 if (mincond || maxcond) {
367 dv = ( mincond ) ? aVPeriod : -aVPeriod;
370 if ((VMax-VMin<aVPeriod) && dv) {
373 aVmid=0.5*(VMin+VMax);
383 //check the point with classifier
387 if (aBAS.IsUPeriodic()) {
388 aUPeriod = aBAS.UPeriod();
389 if ((UMax - UMin - 2*aDelta) > aUPeriod) {
390 if ((u > (UMin + aDelta + aUPeriod)) ||
391 (u < (UMax - aDelta - aUPeriod))) {
392 BRepClass_FaceClassifier aClassifier;
393 aClassifier.Perform(aF, gp_Pnt2d(u, v), aDelta);
394 TopAbs_State Status = aClassifier.State();
395 if (Status == TopAbs_OUT) {
396 du += (u > (UMin + aDelta + aUPeriod)) ? -aUPeriod : aUPeriod;
403 if (aBAS.IsVPeriodic()) {
404 Standard_Real aVPeriod = aBAS.VPeriod();
405 if ((VMax - VMin - 2*aDelta) > aVPeriod) {
406 if ((v > (VMin + aDelta + aVPeriod)) ||
407 (v < (VMax - aDelta - aVPeriod))) {
408 BRepClass_FaceClassifier aClassifier;
409 aClassifier.Perform(aF, gp_Pnt2d(u, v), aDelta);
410 TopAbs_State Status = aClassifier.State();
411 if (Status == TopAbs_OUT) {
412 dv += (v > (VMin + aDelta + aVPeriod)) ? -aVPeriod : aVPeriod;
418 // Translation if necessary
419 Handle(Geom2d_Curve) aC2Dx=aC2D;
421 if ( du != 0. || dv != 0.) {
422 Handle(Geom2d_Curve) PCT = Handle(Geom2d_Curve)::DownCast(aC2Dx->Copy());
423 gp_Vec2d aV2D(du,dv);
424 PCT->Translate(aV2D);
431 //=======================================================================
432 //function : IntermediatePoint
434 //=======================================================================
435 Standard_Real BOPTools_AlgoTools2D::IntermediatePoint
436 (const Standard_Real aFirst,
437 const Standard_Real aLast)
439 //define parameter division number as 10*e^(-PI) = 0.43213918
440 const Standard_Real PAR_T = 0.43213918;
442 aParm=(1.-PAR_T)*aFirst + PAR_T*aLast;
445 //=======================================================================
446 //function : IntermediatePoint
448 //=======================================================================
449 Standard_Real BOPTools_AlgoTools2D::IntermediatePoint
450 (const TopoDS_Edge& aE)
453 Standard_Real aT, aT1, aT2;
455 Handle(Geom_Curve)aC1=BRep_Tool::Curve(aE, aT1, aT2);
457 BRep_Tool::Range(aE, aT1, aT2);
459 aT=BOPTools_AlgoTools2D::IntermediatePoint(aT1, aT2);
462 //=======================================================================
465 //=======================================================================
466 void BOPTools_AlgoTools2D::Make2D (const TopoDS_Edge& aE,
467 const TopoDS_Face& aF,
468 Handle(Geom2d_Curve)& aC2D,
469 Standard_Real& aFirst,
470 Standard_Real& aLast,
471 Standard_Real& aToler,
472 const Handle(IntTools_Context)& theContext)
474 Standard_Boolean aLocIdentity;
475 Standard_Real f3d, l3d;
476 TopLoc_Location aLoc;
478 Handle(Geom2d_Curve) C2D;
481 C2D=BRep_Tool::CurveOnSurface(aE, aF, aFirst, aLast);
488 Handle(Geom_Curve) C3D2, C3D;
489 C3D = BRep_Tool::Curve(aE, aLoc, f3d, l3d);
492 // aE has no 3D curve, so nothing is done
495 aLocIdentity=aLoc.IsIdentity();
501 C3D2 = Handle(Geom_Curve)::
502 DownCast(C3D->Transformed(aLoc.Transformation()));
506 aToler = BRep_Tool::Tolerance(aE);
507 BOPTools_AlgoTools2D::MakePCurveOnFace(aF, C3D2, f3d, l3d, aC2D, aToler, theContext);
513 //=======================================================================
514 //function : MakePCurveOnFace
516 //=======================================================================
517 void BOPTools_AlgoTools2D::MakePCurveOnFace (const TopoDS_Face& aF,
518 const Handle(Geom_Curve)& aC3D,
519 Handle(Geom2d_Curve)& aC2D, //->
520 Standard_Real& TolReached2d,
521 const Handle(IntTools_Context)& theContext)
523 Standard_Real aFirst, aLast;
525 aFirst = aC3D -> FirstParameter();
526 aLast = aC3D -> LastParameter();
530 BOPTools_AlgoTools2D::MakePCurveOnFace
531 (aF, aC3D, aFirst, aLast, aC2D, TolReached2d, theContext);
534 //=======================================================================
535 //function : MakePCurveOnFace
537 //=======================================================================
538 void BOPTools_AlgoTools2D::MakePCurveOnFace
539 (const TopoDS_Face& aF,
540 const Handle(Geom_Curve)& aC3D,
541 const Standard_Real aT1,
542 const Standard_Real aT2,
543 Handle(Geom2d_Curve)& aC2D,
544 Standard_Real& TolReached2d,
545 const Handle(IntTools_Context)& theContext)
547 BRepAdaptor_Surface aBASTmp;
548 const BRepAdaptor_Surface* pBAS;
549 if (!theContext.IsNull()) {
550 pBAS = &theContext->SurfaceAdaptor(aF);
553 aBASTmp.Initialize(aF, Standard_True);
557 Handle(BRepAdaptor_HSurface) aBAHS = new BRepAdaptor_HSurface(*pBAS);
558 Handle(GeomAdaptor_HCurve) aBAHC = new GeomAdaptor_HCurve(aC3D, aT1, aT2);
561 Standard_Real aTR = Precision::Confusion();//1.e-7;
562 Standard_Real aMaxTol = 1.e3 * aTR; //0.0001
563 Standard_Boolean isAnaSurf = ProjLib::IsAnaSurf(aBAHS);
565 //when the type of surface is GeomAbs_SurfaceOfRevolution
566 if (pBAS->GetType() == GeomAbs_SurfaceOfRevolution)
568 if (TolReached2d > aTR) {
572 ProjLib_ProjectedCurve aProj1(aBAHS, aBAHC, aTR);
573 ProjLib::MakePCurveOfType(aProj1, aC2D);
574 aTolR = aProj1.GetTolerance();
578 ProjLib_ProjectedCurve aProjCurv(aBAHS);
579 Standard_Integer aDegMin = -1, aDegMax = -1, aMaxSegments = -1;
580 Standard_Real aMaxDist = -1;
581 AppParCurves_Constraint aBndPnt = AppParCurves_TangencyPoint;
582 if ((TolReached2d >= 10. * aTR) && (TolReached2d <= aMaxTol || isAnaSurf))
584 aTR = Min(aMaxTol, 0.1*TolReached2d);
586 aMaxDist = 1.e3*TolReached2d;
587 if(!isAnaSurf || TolReached2d > 1.)
589 aBndPnt = AppParCurves_PassPoint;
592 else if(TolReached2d > aMaxTol)
594 aTR = Min(TolReached2d, 1.e3 * aMaxTol);
595 aMaxDist = 1.e2 * aTR;
599 aProjCurv.SetDegree(aDegMin, aDegMax);
600 aProjCurv.SetMaxSegments(aMaxSegments);
601 aProjCurv.SetBndPnt(aBndPnt);
602 aProjCurv.SetMaxDist(aMaxDist);
603 aProjCurv.Perform(aBAHC);
604 ProjLib::MakePCurveOfType(aProjCurv, aC2D);
605 aTolR=aProjCurv.GetTolerance();
608 if (aC2D.IsNull() && (aTR < aMaxTol || aTR < TolReached2d))
610 aTR = Max(TolReached2d, aMaxTol);
611 ProjLib_ProjectedCurve aProjCurvAgain(aBAHS, aBAHC, aTR);// 2
612 ProjLib::MakePCurveOfType(aProjCurvAgain, aC2D);
613 aTolR = aProjCurvAgain.GetTolerance();
618 throw Standard_ConstructionError("BOPTools_AlgoTools2D::MakePCurveOnFace : PCurve is Null");
623 // Adjust curve for periodic surface
624 Handle(Geom2d_Curve) aC2DA;
625 BOPTools_AlgoTools2D::AdjustPCurveOnSurf (*pBAS, aT1, aT2, aC2D, aC2DA);
628 // Make sure that the range of the 2D curve is sufficient for representation of the 3D curve.
629 Standard_Real aTCFirst = aC2D->FirstParameter();
630 Standard_Real aTCLast = aC2D->LastParameter();
631 if ((aTCFirst - aT1) > Precision::PConfusion() ||
632 (aT2 - aTCLast ) > Precision::PConfusion())
634 if (aTCFirst < aT1) aTCFirst = aT1;
635 if (aTCLast > aT2) aTCLast = aT2;
637 GeomLib::SameRange(Precision::PConfusion(), aC2D,
638 aTCFirst, aTCLast, aT1, aT2, aC2D);
641 // compute the appropriate tolerance for the edge
642 Handle(Geom_Surface) aS = pBAS->Surface().Surface();
643 aS = Handle(Geom_Surface)::DownCast(aS->Transformed(pBAS->Trsf()));
646 if (IntTools_Tools::ComputeTolerance
647 (aC3D, aC2D, aS, aT1, aT2, aTolR, aT)) {
648 if (aTolR > TolReached2d) {
649 TolReached2d = aTolR;
654 //=======================================================================
655 //function : MaxToleranceEdge
657 //=======================================================================
658 Standard_Real MaxToleranceEdge (const TopoDS_Face& aF)
660 Standard_Real aTol, aTolMax;
661 TopExp_Explorer aExp;
664 aExp.Init(aF, TopAbs_EDGE);
665 for (; aExp.More(); aExp.Next()) {
666 const TopoDS_Edge& aE=*((TopoDS_Edge *)&aExp.Current());
667 aTol=BRep_Tool::Tolerance(aE);
675 //=======================================================================
676 //function : IsEdgeIsoline
678 //=======================================================================
679 void BOPTools_AlgoTools2D::IsEdgeIsoline( const TopoDS_Edge& theE,
680 const TopoDS_Face& theF,
681 Standard_Boolean& isTheUIso,
682 Standard_Boolean& isTheVIso)
684 isTheUIso = isTheVIso = Standard_False;
688 Standard_Real aFirst = 0.0, aLast = 0.0;
689 const Handle(Geom2d_Curve) aPC = BRep_Tool::CurveOnSurface(theE, theF, aFirst, aLast);
691 aPC->D1(0.5*(aFirst+aLast), aP, aT);
693 const Standard_Real aSqMagn = aT.SquareMagnitude();
694 if(aSqMagn <= gp::Resolution())
700 //sin(da) ~ da, when da->0.
701 const Standard_Real aTol = Precision::Angular();
702 const gp_Vec2d aRefVDir(0.0, 1.0), aRefUDir(1.0, 0.0);
704 const Standard_Real aDPv = aT.CrossMagnitude(aRefVDir),
705 aDPu = aT.CrossMagnitude(aRefUDir);
707 isTheUIso = (aDPv <= aTol);
708 isTheVIso = (aDPu <= aTol);