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
7 // under the terms of the GNU Lesser General Public 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.
15 #include <BOPTools_AlgoTools3D.ixx>
18 #include <TopExp_Explorer.hxx>
21 #include <TopoDS_Shape.hxx>
22 #include <TopoDS_Edge.hxx>
23 #include <TopoDS_Face.hxx>
24 #include <TopoDS_Vertex.hxx>
26 #include <BOPCol_IndexedMapOfShape.hxx>
27 #include <BOPCol_IndexedDataMapOfShapeListOfShape.hxx>
29 #include <BRep_Builder.hxx>
30 #include <BRep_Tool.hxx>
31 #include <BRepTools.hxx>
32 #include <BRepAdaptor_Surface.hxx>
34 #include <gp_Vec2d.hxx>
35 #include <gp_Pnt2d.hxx>
36 #include <gp_Lin2d.hxx>
37 #include <gp_Dir2d.hxx>
42 #include <Geom2d_Curve.hxx>
43 #include <Geom2d_TrimmedCurve.hxx>
44 #include <Geom2d_Line.hxx>
46 #include <Geom_Curve.hxx>
47 #include <Geom_Surface.hxx>
48 #include <Geom_BSplineSurface.hxx>
49 #include <Geom_BezierSurface.hxx>
51 #include <GeomAdaptor_Surface.hxx>
53 #include <IntTools_Tools.hxx>
55 #include <BOPTools_AlgoTools2D.hxx>
57 #include <GProp_GProps.hxx>
58 #include <BRepGProp.hxx>
59 #include <BRepBndLib.hxx>
60 #include <Bnd_Box.hxx>
61 #include <gp_Cylinder.hxx>
62 #include <BRep_TVertex.hxx>
63 #include <BRep_ListIteratorOfListOfPointRepresentation.hxx>
64 #include <BRep_PointRepresentation.hxx>
65 #include <BRep_TEdge.hxx>
66 #include <BRep_ListIteratorOfListOfCurveRepresentation.hxx>
67 #include <BRep_CurveRepresentation.hxx>
68 #include <BRep_TFace.hxx>
69 #include <Poly_Triangulation.hxx>
70 #include <BRep_Builder.hxx>
71 #include <BOPInt_Context.hxx>
72 #include <Geom2dAdaptor_Curve.hxx>
73 #include <Geom2dHatch_Hatcher.hxx>
74 #include <HatchGen_Domain.hxx>
76 static void Add(const TopoDS_Shape& aS,
77 BOPCol_IndexedMapOfShape& myShapes,
78 Standard_Boolean& bHasGeometry);
80 Standard_Boolean HasGeometry(const TopoDS_Shape& aS);
82 //=======================================================================
83 //function : DoSplitSEAMOnFace
85 //=======================================================================
86 void BOPTools_AlgoTools3D::DoSplitSEAMOnFace (const TopoDS_Edge& aSplit,
87 const TopoDS_Face& aF)
89 Standard_Boolean bIsUPeriodic, bIsVPeriodic, bIsLeft = Standard_False;
90 Standard_Real aTol, a, b, anUPeriod, anVPeriod, aT, anU, dU/*=1.e-7*/, anU1,
91 anV, dV/*=1.e-7*/, anV1;
95 Handle(Geom2d_Curve) aTmpC1, aTmpC2;
96 Handle(Geom2d_Curve) C2D1;
97 Handle(Geom2d_Line) aLD1;
98 Handle(Geom_Surface) aS;
103 aSp.Orientation(TopAbs_FORWARD);
104 aTol=BRep_Tool::Tolerance(aSp);
106 aS=BRep_Tool::Surface(aF);
107 bIsUPeriodic=aS->IsUPeriodic();
108 bIsVPeriodic=aS->IsVPeriodic();
110 anUPeriod = bIsUPeriodic ? aS->UPeriod() : 0.;
111 anVPeriod = bIsVPeriodic ? aS->VPeriod() : 0.;
113 if (!bIsUPeriodic && !bIsVPeriodic) {
114 Standard_Boolean bIsUClosed, bIsVClosed;
115 Standard_Real aUmin = 0., aUmax = 0., aVmin = 0., aVmax = 0.;
116 Handle(Geom_BSplineSurface) aBS;
117 Handle(Geom_BezierSurface) aBZ;
119 bIsUClosed=Standard_False;
120 bIsVClosed=Standard_False;
121 aBS=Handle(Geom_BSplineSurface)::DownCast(aS);
122 aBZ=Handle(Geom_BezierSurface) ::DownCast(aS);
125 bIsUClosed=aBS->IsUClosed();
126 bIsVClosed=aBS->IsVClosed();
127 aBS->Bounds(aUmin, aUmax, aVmin, aVmax);
129 else if (!aBZ.IsNull()) {
130 bIsUClosed=aBZ->IsUClosed();
131 bIsVClosed=aBZ->IsVClosed();
132 aBZ->Bounds(aUmin, aUmax, aVmin, aVmax);
134 if (!bIsUClosed && !bIsVClosed) {
139 anUPeriod=aUmax-aUmin;
142 anVPeriod=aVmax-aVmin;
146 C2D1=BRep_Tool::CurveOnSurface(aSp, aF, a, b);
148 aT=BOPTools_AlgoTools2D::IntermediatePoint(a, b);
149 C2D1->D1(aT, aP2D, aVec2D);
150 gp_Dir2d aDir2D1(aVec2D), aDOX(-1.,0.), aDOY(0.,1.);
158 GeomAdaptor_Surface aGAS(aS);
159 dU = aGAS.UResolution(aTol);
160 dV = aGAS.VResolution(aTol);
163 if (fabs (anU) < dU) {
164 bIsLeft=Standard_True;
167 else if (fabs (anU-anUPeriod) < dU) {
168 bIsLeft=Standard_False;
173 if (anVPeriod > 0.) {
174 if (fabs (anV) < dV) {
175 bIsLeft=Standard_True;
178 else if (fabs (anV-anVPeriod) < dV) {
179 bIsLeft=Standard_False;
184 if (anU1==anU && anV1==anV) {
188 aScPr = (anU1==anU) ? aDir2D1*aDOX : aDir2D1*aDOY;
190 aTmpC1=Handle(Geom2d_Curve)::DownCast(C2D1->Copy());
191 Handle(Geom2d_TrimmedCurve) aC1 = new Geom2d_TrimmedCurve(aTmpC1, a, b);
193 aTmpC2=Handle(Geom2d_Curve)::DownCast(C2D1->Copy());
194 Handle(Geom2d_TrimmedCurve) aC2 = new Geom2d_TrimmedCurve(aTmpC2, a, b);
195 gp_Vec2d aTrV(anU1-anU, anV1-anV);
196 aC2->Translate(aTrV);
200 BB.UpdateEdge(aSp, aC2, aC1, aF, aTol);
203 BB.UpdateEdge(aSp, aC1, aC2, aF, aTol);
208 BB.UpdateEdge(aSp, aC1, aC2, aF, aTol);
211 BB.UpdateEdge(aSp, aC2, aC1, aF, aTol);
216 //=======================================================================
217 //function : GetNormalToFaceOnEdge
219 //=======================================================================
220 void BOPTools_AlgoTools3D::GetNormalToFaceOnEdge (const TopoDS_Edge& aE,
221 const TopoDS_Face& aF,
224 Standard_Real aT, aT1, aT2;
226 BRep_Tool::CurveOnSurface(aE, aF, aT1, aT2);
227 aT=BOPTools_AlgoTools2D::IntermediatePoint(aT1, aT2);
229 BOPTools_AlgoTools3D::GetNormalToFaceOnEdge (aE, aF, aT, aDNF);
231 if (aF.Orientation()==TopAbs_REVERSED){
236 //=======================================================================
237 //function : GetNormalToFaceOnEdge
239 //=======================================================================
240 void BOPTools_AlgoTools3D::GetNormalToFaceOnEdge (const TopoDS_Edge& aE,
241 const TopoDS_Face& aF1,
242 const Standard_Real aT,
245 Standard_Real U, V, aTolPC;
250 Handle(Geom_Surface) aS1=BRep_Tool::Surface(aF1);
252 Handle(Geom2d_Curve)aC2D1;
253 BOPTools_AlgoTools2D::CurveOnSurface(aE, aF1, aC2D1, aTolPC);
259 aS1->D1(U, V, aP, aD1U, aD1V);
266 //=======================================================================
267 //function : SenseFlag
269 //=======================================================================
270 Standard_Integer BOPTools_AlgoTools3D::SenseFlag (const gp_Dir& aDNF1,
273 Standard_Boolean bIsDirsCoinside;
274 bIsDirsCoinside=IntTools_Tools::IsDirsCoinside(aDNF1, aDNF2);
275 if (!bIsDirsCoinside) {
291 //=======================================================================
292 //function : GetNormalToSurface
294 //=======================================================================
295 Standard_Boolean BOPTools_AlgoTools3D::GetNormalToSurface (const Handle(Geom_Surface)& aS,
296 const Standard_Real U,
297 const Standard_Real V,
300 Standard_Boolean bFlag;
305 aS->D1(U, V, aP, aD1U, aD1V);
310 bFlag=IntTools_Tools::IsDirsCoinside(aDD1U, aDD1U);
319 //=======================================================================
320 //function : GetApproxNormalToFaceOnEdge
322 //=======================================================================
324 void BOPTools_AlgoTools3D::GetApproxNormalToFaceOnEdge(const TopoDS_Edge& aE,
325 const TopoDS_Face& aF,
326 const Standard_Real aT,
331 Standard_Real aFirst, aLast;
332 Handle(Geom2d_Curve) aC2D= BRep_Tool::CurveOnSurface (aE, aF, aFirst, aLast);
338 PointNearEdge (aE, aF, aT, aDt2D, aPx2DNear, aPNear);
339 Handle(Geom_Surface) aS=BRep_Tool::Surface(aF);
341 BOPTools_AlgoTools3D::GetNormalToSurface (aS, aPx2DNear.X(), aPx2DNear.Y(), aDNF);
343 if (aF.Orientation()==TopAbs_REVERSED){
349 //=======================================================================
350 //function : GetApproxNormalToFaceOnEdge
352 //=======================================================================
353 void BOPTools_AlgoTools3D::GetApproxNormalToFaceOnEdge (const TopoDS_Edge& aE,
354 const TopoDS_Face& aF,
355 const Standard_Real aT,
358 Handle(BOPInt_Context)& theContext)
360 Standard_Real aFirst, aLast;
361 Handle(Geom2d_Curve) aC2D= BRep_Tool::CurveOnSurface (aE, aF, aFirst, aLast);
368 BOPTools_AlgoTools3D::PointNearEdge (aE, aF, aT, aPx2DNear, aPNear, theContext);
370 Handle(Geom_Surface) aS=BRep_Tool::Surface(aF);
372 BOPTools_AlgoTools3D::GetNormalToSurface (aS, aPx2DNear.X(), aPx2DNear.Y(), aDNF);
374 if (aF.Orientation()==TopAbs_REVERSED){
379 //=======================================================================
380 //function : PointNearEdge
382 //=======================================================================
383 void BOPTools_AlgoTools3D::PointNearEdge (const TopoDS_Edge& aE,
384 const TopoDS_Face& aF,
385 const Standard_Real aT,
386 const Standard_Real aDt2D,
390 Standard_Real aFirst, aLast, aETol, aFTol, transVal;
391 GeomAbs_SurfaceType aTS;
392 Handle(Geom2d_Curve) aC2D;
393 Handle(Geom_Surface) aS;
395 aC2D= BRep_Tool::CurveOnSurface (aE, aF, aFirst, aLast);
397 aPx2DNear.SetCoord (99., 99);
401 aS=BRep_Tool::Surface(aF);
405 aC2D->D1 (aT, aPx2D, aVx2D);
406 gp_Dir2d aDx2D(aVx2D);
409 aDP.SetCoord (-aDx2D.Y(), aDx2D.X());
411 if (aE.Orientation()==TopAbs_REVERSED){
415 if (aF.Orientation()==TopAbs_REVERSED) {
419 aETol = BRep_Tool::Tolerance(aE);
420 aFTol = BRep_Tool::Tolerance(aF);
422 GeomAdaptor_Surface aGAS(aS);
424 if (aTS==GeomAbs_BSplineSurface) {
429 if( aETol > 1.e-5 || aFTol > 1.e-5 ) {
430 //if( aETol > 1.e-5 && aFTol > 1.e-5 ) {
432 if(aTS!=GeomAbs_Sphere) {
433 gp_Vec2d transVec( aDP );
434 transVal = aDt2D + aETol + aFTol;
435 if (aTS==GeomAbs_Cylinder) {// pkv/909/F8
436 Standard_Real aR, dT;
438 gp_Cylinder aCyl=aGAS.Cylinder();
441 if (dT>=-1 && dT<=1) {
447 transVec.Multiply(transVal);
448 aPx2DNear = aPx2D.Translated( transVec );
451 aPx2DNear.SetCoord (aPx2D.X()+aDt2D*aDP.X(), aPx2D.Y()+aDt2D*aDP.Y());
455 aPx2DNear.SetCoord (aPx2D.X()+aDt2D*aDP.X(), aPx2D.Y()+aDt2D*aDP.Y());
458 aS->D0(aPx2DNear.X(), aPx2DNear.Y(), aPxNear);
461 //=======================================================================
462 //function : PointNearEdge
464 //=======================================================================
465 void BOPTools_AlgoTools3D::PointNearEdge (const TopoDS_Edge& aE,
466 const TopoDS_Face& aF,
467 const Standard_Real aT,
470 Handle(BOPInt_Context)& theContext)
472 Standard_Real aTolE, aTolF, dTx, dT2D;
473 Handle(Geom_Surface) aS;
474 GeomAdaptor_Surface aGAS;
476 dT2D=10.*BOPTools_AlgoTools3D::MinStepIn2d();//~1.e-5;
478 aS = BRep_Tool::Surface(aF);
480 if (aGAS.GetType()==GeomAbs_Cylinder ||
481 aGAS.GetType()==GeomAbs_Sphere) {
485 aTolE = BRep_Tool::Tolerance(aE);
486 aTolF = BRep_Tool::Tolerance(aF);
487 dTx = 2.*(aTolE + aTolF);
492 BOPTools_AlgoTools3D::PointNearEdge (aE, aF, aT, dT2D, aPx2DNear, aPxNear);
493 if (!theContext->IsPointInOnFace(aF, aPx2DNear)) {
494 Standard_Integer iErr;
495 Standard_Real aU1, aU2, aV1, aV2, dV, dU, dTresh;
499 BRepTools::UVBounds(aF, aU1, aU2, aV1, aV2);
509 if (dU < dTresh || dV < dTresh) {
510 iErr = BOPTools_AlgoTools3D::PointInFace(aF, aP, aP2d, theContext);
519 //=======================================================================
520 // function: PointNearEdge
522 //=======================================================================
523 void BOPTools_AlgoTools3D::PointNearEdge (const TopoDS_Edge& aE,
524 const TopoDS_Face& aF,
525 gp_Pnt2d& aPInFace2D,
527 Handle(BOPInt_Context)& theContext)
529 Standard_Real aT, aT1, aT2;
532 BRep_Tool::Range(aE, aT1, aT2);
533 aT=BOPTools_AlgoTools2D::IntermediatePoint(aT1, aT2);
535 // 2. a Point inside Face near aPOnEdge aPInFace;
538 aFF.Orientation(TopAbs_FORWARD);
539 BOPTools_AlgoTools3D::OrientEdgeOnFace (aE, aFF, aERight);
541 BOPTools_AlgoTools3D::PointNearEdge (aERight, aFF, aT, aPInFace2D, aPInFace, theContext);
544 //=======================================================================
545 //function : MinStepIn2d
547 //=======================================================================
548 Standard_Real BOPTools_AlgoTools3D::MinStepIn2d()
550 Standard_Real dt=1.e-5;
554 //=======================================================================
555 //function : IsEmptyShape
557 //=======================================================================
558 Standard_Boolean BOPTools_AlgoTools3D::IsEmptyShape(const TopoDS_Shape& aS)
560 Standard_Boolean bHasGeometry=Standard_False;
562 BOPCol_IndexedMapOfShape myShapes;
564 Add(aS, myShapes, bHasGeometry);
566 return !bHasGeometry;
569 //=======================================================================
572 //=======================================================================
573 void Add(const TopoDS_Shape& aS,
574 BOPCol_IndexedMapOfShape& myShapes,
575 Standard_Boolean& bHasGeometry)
577 Standard_Integer anIndex;
587 TopoDS_Shape aSx = aS;
589 anIndex=myShapes.FindIndex(aSx);
591 bHasGeometry=HasGeometry (aSx);
596 TopoDS_Iterator anIt(aSx, Standard_False, Standard_False);
597 for(; anIt.More(); anIt.Next()) {
598 const TopoDS_Shape& aSy=anIt.Value();
599 Add(aSy, myShapes, bHasGeometry);
610 //=======================================================================
611 //function : HasGeometry
613 //=======================================================================
614 Standard_Boolean HasGeometry(const TopoDS_Shape& aS)
616 Standard_Boolean bHasGeometry=Standard_True;
617 TopAbs_ShapeEnum aType= aS.ShapeType();
619 if (aType == TopAbs_VERTEX) {
621 Handle(BRep_TVertex) TV = Handle(BRep_TVertex)::DownCast(aS.TShape());
622 BRep_ListIteratorOfListOfPointRepresentation itrp(TV->Points());
624 while (itrp.More()) {
625 const Handle(BRep_PointRepresentation)& PR = itrp.Value();
627 if (PR->IsPointOnCurve()) {
631 else if (PR->IsPointOnCurveOnSurface()) {
635 else if (PR->IsPointOnSurface()) {
643 else if (aType == TopAbs_EDGE) {
644 Handle(BRep_TEdge) TE = Handle(BRep_TEdge)::DownCast(aS.TShape());
645 BRep_ListIteratorOfListOfCurveRepresentation itrc(TE->Curves());
647 while (itrc.More()) {
648 const Handle(BRep_CurveRepresentation)& CR = itrc.Value();
649 if (CR->IsCurve3D()) {
650 if (!CR->Curve3D().IsNull()) {
654 else if (CR->IsCurveOnSurface()) {
657 else if (CR->IsRegularity()) {
660 else if (!CR->Polygon3D().IsNull()) {
663 else if (CR->IsPolygonOnTriangulation()) {
666 else if (CR->IsPolygonOnSurface()) {
673 else if (aType == TopAbs_FACE) {
674 Handle(BRep_TFace) TF = Handle(BRep_TFace)::DownCast(aS.TShape());
675 if (!TF->Surface().IsNull()) {
678 Handle(Poly_Triangulation) Tr = TF->Triangulation();
684 return !bHasGeometry;
688 //=======================================================================
689 //function : OrientEdgeOnFace
691 //=======================================================================
692 void BOPTools_AlgoTools3D::OrientEdgeOnFace (const TopoDS_Edge& aE,
693 const TopoDS_Face& aF,
694 TopoDS_Edge& aERight)
696 if (BRep_Tool::IsClosed(aE, aF)) {
698 aERight.Orientation(aE.Orientation());
700 Standard_Integer iFoundCount = 0;
701 TopoDS_Edge anEdge = aE;
702 TopExp_Explorer anExp(aF, TopAbs_EDGE);
704 for (; anExp.More(); anExp.Next()) {
705 const TopoDS_Shape& aSS=anExp.Current();
707 if (aSS.IsSame(aE)) {
708 anEdge = TopoDS::Edge(aSS);
713 if(iFoundCount == 1) {
719 TopExp_Explorer anExp(aF, TopAbs_EDGE);
720 for (; anExp.More(); anExp.Next()) {
721 const TopoDS_Shape& aSS=anExp.Current();
722 if (aSS.IsSame(aE)) {
724 aERight.Orientation(aSS.Orientation());
729 aERight.Orientation(aE.Orientation());
732 //=======================================================================
733 //function : PointInFace
735 //=======================================================================
736 Standard_Integer BOPTools_AlgoTools3D::PointInFace(const TopoDS_Face& aF,
739 Handle(BOPInt_Context)& theContext)
741 Standard_Boolean bIsDone, bHasFirstPoint, bHasSecondPoint;
742 Standard_Integer iErr, aIx, aNbDomains;
743 Standard_Real aUMin, aUMax, aVMin, aVMax;
744 Standard_Real aVx = 0., aUx, aV1, aV2;
745 gp_Dir2d aD2D (0., 1.);
748 Handle(Geom2d_Curve) aC2D;
749 Handle(Geom2d_Line) aL2D;
750 Handle(Geom_Surface) aS;
753 Geom2dHatch_Hatcher& aHatcher = theContext->Hatcher(aF);
758 aFF.Orientation (TopAbs_FORWARD);
760 aS=BRep_Tool::Surface(aFF);
761 BRepTools::UVBounds(aFF, aUMin, aUMax, aVMin, aVMax);
763 aUx=IntTools_Tools::IntermediatePoint(aUMin, aUMax);
764 aP2D.SetCoord(aUx, 0.);
765 aL2D=new Geom2d_Line (aP2D, aD2D);
766 Geom2dAdaptor_Curve aHCur(aL2D);
768 aIx=aHatcher.AddHatching(aHCur) ;
771 bIsDone=aHatcher.TrimDone(aIx);
777 aHatcher.ComputeDomains(aIx);
778 bIsDone=aHatcher.IsDone(aIx);
784 aNbDomains=aHatcher.NbDomains(aIx);
785 if (aNbDomains > 0) {
786 const HatchGen_Domain& aDomain=aHatcher.Domain (aIx, 1) ;
787 bHasFirstPoint=aDomain.HasFirstPoint();
788 if (!bHasFirstPoint) {
793 aV1=aDomain.FirstPoint().Parameter();
795 bHasSecondPoint=aDomain.HasSecondPoint();
796 if (!bHasSecondPoint) {
801 aV2=aDomain.SecondPoint().Parameter();
803 aVx=IntTools_Tools::IntermediatePoint(aV1, aV2);
811 aS->D0(aUx, aVx, aPx);
813 theP2D.SetCoord(aUx, aVx);