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 <Bnd_Box.hxx>
17 #include <BOPCol_IndexedDataMapOfShapeListOfShape.hxx>
18 #include <BOPCol_IndexedMapOfShape.hxx>
19 #include <BOPTools_AlgoTools2D.hxx>
20 #include <BOPTools_AlgoTools3D.hxx>
21 #include <BRep_Builder.hxx>
22 #include <BRep_CurveRepresentation.hxx>
23 #include <BRep_ListIteratorOfListOfCurveRepresentation.hxx>
24 #include <BRep_ListIteratorOfListOfPointRepresentation.hxx>
25 #include <BRep_PointRepresentation.hxx>
26 #include <BRep_TEdge.hxx>
27 #include <BRep_TFace.hxx>
28 #include <BRep_Tool.hxx>
29 #include <BRep_TVertex.hxx>
30 #include <BRepAdaptor_Surface.hxx>
31 #include <BRepBndLib.hxx>
32 #include <BRepGProp.hxx>
33 #include <BRepTools.hxx>
34 #include <Geom2d_Curve.hxx>
35 #include <Geom2d_Line.hxx>
36 #include <Geom2d_TrimmedCurve.hxx>
37 #include <Geom2dAdaptor_Curve.hxx>
38 #include <Geom2dHatch_Hatcher.hxx>
39 #include <Geom_BezierSurface.hxx>
40 #include <Geom_BSplineSurface.hxx>
41 #include <Geom_Curve.hxx>
42 #include <Geom_RectangularTrimmedSurface.hxx>
43 #include <Geom_Surface.hxx>
44 #include <GeomAdaptor_Surface.hxx>
45 #include <gp_Cylinder.hxx>
47 #include <gp_Dir2d.hxx>
48 #include <gp_Lin2d.hxx>
51 #include <gp_Pnt2d.hxx>
53 #include <gp_Vec2d.hxx>
54 #include <GProp_GProps.hxx>
55 #include <HatchGen_Domain.hxx>
56 #include <IntTools_Context.hxx>
57 #include <IntTools_Tools.hxx>
58 #include <Poly_Triangulation.hxx>
60 #include <TopExp_Explorer.hxx>
62 #include <TopoDS_Edge.hxx>
63 #include <TopoDS_Face.hxx>
64 #include <TopoDS_Shape.hxx>
65 #include <TopoDS_Vertex.hxx>
67 static void Add(const TopoDS_Shape& aS,
68 BOPCol_IndexedMapOfShape& myShapes,
69 Standard_Boolean& bHasGeometry);
71 Standard_Boolean HasGeometry(const TopoDS_Shape& aS);
73 //=======================================================================
74 //function : DoSplitSEAMOnFace
76 //=======================================================================
77 void BOPTools_AlgoTools3D::DoSplitSEAMOnFace (const TopoDS_Edge& aSplit,
78 const TopoDS_Face& aF)
80 Standard_Boolean bIsUPeriodic, bIsVPeriodic, bIsLeft;
81 Standard_Real aTol, a, b, anUPeriod, anVPeriod, aT, anU, dU, anU1;
82 Standard_Real aScPr, anV, dV, anV1;
83 Standard_Real aUmin, aUmax, aVmin, aVmax;
86 Handle(Geom2d_Curve) aTmpC1, aTmpC2;
87 Handle(Geom2d_Curve) C2D1;
88 Handle(Geom2d_Line) aLD1;
89 Handle(Geom_Surface) aS;
93 bIsLeft = Standard_False;
95 aSp.Orientation(TopAbs_FORWARD);
96 aTol=BRep_Tool::Tolerance(aSp);
98 aS=BRep_Tool::Surface(aF);
100 aS->Bounds(aUmin, aUmax, aVmin, aVmax);
102 bIsUPeriodic=aS->IsUPeriodic();
103 bIsVPeriodic=aS->IsVPeriodic();
105 anUPeriod = bIsUPeriodic ? aS->UPeriod() : 0.;
106 anVPeriod = bIsVPeriodic ? aS->VPeriod() : 0.;
108 if (!bIsUPeriodic && !bIsVPeriodic) {
109 Standard_Boolean bIsUClosed, bIsVClosed;
110 Handle(Geom_BSplineSurface) aBS;
111 Handle(Geom_BezierSurface) aBZ;
112 Handle(Geom_RectangularTrimmedSurface) aRTS;
114 bIsUClosed=Standard_False;
115 bIsVClosed=Standard_False;
116 aBS=Handle(Geom_BSplineSurface)::DownCast(aS);
117 aBZ=Handle(Geom_BezierSurface) ::DownCast(aS);
118 aRTS=Handle(Geom_RectangularTrimmedSurface)::DownCast(aS);
121 bIsUClosed=aBS->IsUClosed();
122 bIsVClosed=aBS->IsVClosed();
124 else if (!aBZ.IsNull()) {
125 bIsUClosed=aBZ->IsUClosed();
126 bIsVClosed=aBZ->IsVClosed();
128 else if (!aRTS.IsNull()) {
129 Handle(Geom_Surface) aSB;
131 aSB=aRTS->BasisSurface();
132 bIsUPeriodic=aSB->IsUPeriodic();
133 bIsVPeriodic=aSB->IsVPeriodic();
135 if (!(bIsUPeriodic || bIsVPeriodic)) {
138 anUPeriod = bIsUPeriodic ? aSB->UPeriod() : 0.;
139 anVPeriod = bIsVPeriodic ? aSB->VPeriod() : 0.;
143 if (!bIsUClosed && !bIsVClosed) {
148 anUPeriod=aUmax-aUmin;
151 anVPeriod=aVmax-aVmin;
156 //---------------------------------------------------
157 C2D1=BRep_Tool::CurveOnSurface(aSp, aF, a, b);
159 aT=BOPTools_AlgoTools2D::IntermediatePoint(a, b);
160 C2D1->D1(aT, aP2D, aVec2D);
161 gp_Dir2d aDir2D1(aVec2D), aDOX(-1.,0.), aDOY(0.,1.);
169 GeomAdaptor_Surface aGAS(aS);
170 dU = aGAS.UResolution(aTol);
171 dV = aGAS.VResolution(aTol);
174 if (fabs (anU-aUmin) < dU) {
175 bIsLeft=Standard_True;
178 else if (fabs (anU-aUmax) < dU) {
179 bIsLeft=Standard_False;
184 if (anVPeriod > 0.) {
185 if (fabs (anV-aVmin) < dV) {
186 bIsLeft=Standard_True;
189 else if (fabs (anV-aVmax) < dV) {
190 bIsLeft=Standard_False;
195 if (anU1==anU && anV1==anV) {
199 aScPr = (anU1==anU) ? aDir2D1*aDOX : aDir2D1*aDOY;
201 aTmpC1=Handle(Geom2d_Curve)::DownCast(C2D1->Copy());
202 Handle(Geom2d_TrimmedCurve) aC1 =
203 new Geom2d_TrimmedCurve(aTmpC1, a, b);
205 aTmpC2=Handle(Geom2d_Curve)::DownCast(C2D1->Copy());
206 Handle(Geom2d_TrimmedCurve) aC2 =
207 new Geom2d_TrimmedCurve(aTmpC2, a, b);
208 gp_Vec2d aTrV(anU1-anU, anV1-anV);
209 aC2->Translate(aTrV);
213 BB.UpdateEdge(aSp, aC2, aC1, aF, aTol);
216 BB.UpdateEdge(aSp, aC1, aC2, aF, aTol);
221 BB.UpdateEdge(aSp, aC1, aC2, aF, aTol);
224 BB.UpdateEdge(aSp, aC2, aC1, aF, aTol);
228 //=======================================================================
229 //function : GetNormalToFaceOnEdge
231 //=======================================================================
232 void BOPTools_AlgoTools3D::GetNormalToFaceOnEdge (const TopoDS_Edge& aE,
233 const TopoDS_Face& aF,
235 const Handle(IntTools_Context)& theContext)
237 Standard_Real aT, aT1, aT2;
239 BRep_Tool::CurveOnSurface(aE, aF, aT1, aT2);
240 aT=BOPTools_AlgoTools2D::IntermediatePoint(aT1, aT2);
242 BOPTools_AlgoTools3D::GetNormalToFaceOnEdge (aE, aF, aT, aDNF, theContext);
244 if (aF.Orientation()==TopAbs_REVERSED){
248 //=======================================================================
249 //function : GetNormalToFaceOnEdge
251 //=======================================================================
252 void BOPTools_AlgoTools3D::GetNormalToFaceOnEdge (const TopoDS_Edge& aE,
253 const TopoDS_Face& aF1,
254 const Standard_Real aT,
256 const Handle(IntTools_Context)& theContext)
258 Standard_Real U, V, aTolPC;
263 Handle(Geom_Surface) aS1=BRep_Tool::Surface(aF1);
265 Handle(Geom2d_Curve)aC2D1;
266 BOPTools_AlgoTools2D::CurveOnSurface(aE, aF1, aC2D1, aTolPC, theContext);
272 aS1->D1(U, V, aP, aD1U, aD1V);
278 //=======================================================================
279 //function : SenseFlag
281 //=======================================================================
282 Standard_Integer BOPTools_AlgoTools3D::SenseFlag (const gp_Dir& aDNF1,
285 Standard_Boolean bIsDirsCoinside;
287 bIsDirsCoinside=IntTools_Tools::IsDirsCoinside(aDNF1, aDNF2);
288 if (!bIsDirsCoinside) {
303 //=======================================================================
304 //function : GetNormalToSurface
306 //=======================================================================
307 Standard_Boolean BOPTools_AlgoTools3D::GetNormalToSurface
308 (const Handle(Geom_Surface)& aS,
309 const Standard_Real U,
310 const Standard_Real V,
313 Standard_Boolean bFlag;
318 aS->D1(U, V, aP, aD1U, aD1V);
323 bFlag=IntTools_Tools::IsDirsCoinside(aDD1U, aDD1U);
331 //=======================================================================
332 //function : GetApproxNormalToFaceOnEdge
334 //=======================================================================
335 void BOPTools_AlgoTools3D::GetApproxNormalToFaceOnEdge
336 (const TopoDS_Edge& aE,
337 const TopoDS_Face& aF,
338 const Standard_Real aT,
343 Standard_Real aFirst, aLast;
344 Handle(Geom2d_Curve) aC2D=
345 BRep_Tool::CurveOnSurface (aE, aF, aFirst, aLast);
351 PointNearEdge (aE, aF, aT, aDt2D, aPx2DNear, aPNear);
352 Handle(Geom_Surface) aS=BRep_Tool::Surface(aF);
354 BOPTools_AlgoTools3D::GetNormalToSurface
355 (aS, aPx2DNear.X(), aPx2DNear.Y(), aDNF);
357 if (aF.Orientation()==TopAbs_REVERSED){
361 //=======================================================================
362 //function : GetApproxNormalToFaceOnEdge
364 //=======================================================================
365 void BOPTools_AlgoTools3D::GetApproxNormalToFaceOnEdge
366 (const TopoDS_Edge& aE,
367 const TopoDS_Face& aF,
368 const Standard_Real aT,
371 Handle(IntTools_Context)& theContext)
373 Standard_Real aFirst, aLast;
374 Handle(Geom2d_Curve) aC2D=
375 BRep_Tool::CurveOnSurface (aE, aF, aFirst, aLast);
382 BOPTools_AlgoTools3D::PointNearEdge
383 (aE, aF, aT, aPx2DNear, aPNear, theContext);
385 Handle(Geom_Surface) aS=BRep_Tool::Surface(aF);
387 BOPTools_AlgoTools3D::GetNormalToSurface
388 (aS, aPx2DNear.X(), aPx2DNear.Y(), aDNF);
390 if (aF.Orientation()==TopAbs_REVERSED){
394 //=======================================================================
395 //function : PointNearEdge
397 //=======================================================================
398 void BOPTools_AlgoTools3D::PointNearEdge (const TopoDS_Edge& aE,
399 const TopoDS_Face& aF,
400 const Standard_Real aT,
401 const Standard_Real aDt2D,
405 Standard_Real aFirst, aLast, aETol, aFTol, transVal;
406 GeomAbs_SurfaceType aTS;
407 Handle(Geom2d_Curve) aC2D;
408 Handle(Geom_Surface) aS;
410 aC2D= BRep_Tool::CurveOnSurface (aE, aF, aFirst, aLast);
412 aPx2DNear.SetCoord (99., 99);
416 aS=BRep_Tool::Surface(aF);
420 aC2D->D1 (aT, aPx2D, aVx2D);
421 gp_Dir2d aDx2D(aVx2D);
424 aDP.SetCoord (-aDx2D.Y(), aDx2D.X());
426 if (aE.Orientation()==TopAbs_REVERSED){
430 if (aF.Orientation()==TopAbs_REVERSED) {
434 aETol = BRep_Tool::Tolerance(aE);
435 aFTol = BRep_Tool::Tolerance(aF);
437 GeomAdaptor_Surface aGAS(aS);
439 if (aTS==GeomAbs_BSplineSurface) {
444 if( aETol > 1.e-5 || aFTol > 1.e-5 ) {
446 if(aTS!=GeomAbs_Sphere) {
447 gp_Vec2d transVec( aDP );
448 transVal = aDt2D + aETol + aFTol;
449 if (aTS==GeomAbs_Cylinder) {// pkv/909/F8
450 Standard_Real aR, dT;
452 gp_Cylinder aCyl=aGAS.Cylinder();
455 if (dT>=-1 && dT<=1) {
461 transVec.Multiply(transVal);
462 aPx2DNear = aPx2D.Translated( transVec );
466 (aPx2D.X()+aDt2D*aDP.X(), aPx2D.Y()+aDt2D*aDP.Y());
471 (aPx2D.X()+aDt2D*aDP.X(), aPx2D.Y()+aDt2D*aDP.Y());
474 aS->D0(aPx2DNear.X(), aPx2DNear.Y(), aPxNear);
476 //=======================================================================
477 //function : PointNearEdge
479 //=======================================================================
480 void BOPTools_AlgoTools3D::PointNearEdge
481 (const TopoDS_Edge& aE,
482 const TopoDS_Face& aF,
483 const Standard_Real aT,
486 Handle(IntTools_Context)& theContext)
488 Standard_Real aTolE, aTolF, dTx, dT2D;
489 Handle(Geom_Surface) aS;
490 GeomAdaptor_Surface aGAS;
492 dT2D=10.*BOPTools_AlgoTools3D::MinStepIn2d();//~1.e-5;
494 aS = BRep_Tool::Surface(aF);
496 if (aGAS.GetType()==GeomAbs_Cylinder ||
497 aGAS.GetType()==GeomAbs_Sphere) {
501 aTolE = BRep_Tool::Tolerance(aE);
502 aTolF = BRep_Tool::Tolerance(aF);
503 dTx = 2.*(aTolE + aTolF);
508 BOPTools_AlgoTools3D::PointNearEdge
509 (aE, aF, aT, dT2D, aPx2DNear, aPxNear);
510 if (!theContext->IsPointInOnFace(aF, aPx2DNear)) {
511 Standard_Integer iErr;
512 Standard_Real aU1, aU2, aV1, aV2, dV, dU, dTresh;
516 if (theContext.IsNull()) {
517 BRepTools::UVBounds(aF, aU1, aU2, aV1, aV2);
520 theContext->UVBounds(aF, aU1, aU2, aV1, aV2);
531 if (dU < dTresh || dV < dTresh) {
532 iErr = BOPTools_AlgoTools3D::PointInFace
533 (aF, aP, aP2d, theContext);
541 //=======================================================================
542 // function: PointNearEdge
544 //=======================================================================
545 void BOPTools_AlgoTools3D::PointNearEdge
546 (const TopoDS_Edge& aE,
547 const TopoDS_Face& aF,
548 gp_Pnt2d& aPInFace2D,
550 Handle(IntTools_Context)& theContext)
552 Standard_Real aT, aT1, aT2;
555 BRep_Tool::Range(aE, aT1, aT2);
556 aT=BOPTools_AlgoTools2D::IntermediatePoint(aT1, aT2);
558 // 2. a Point inside Face near aPOnEdge aPInFace;
561 aFF.Orientation(TopAbs_FORWARD);
562 BOPTools_AlgoTools3D::OrientEdgeOnFace (aE, aFF, aERight);
564 BOPTools_AlgoTools3D::PointNearEdge
565 (aERight, aFF, aT, aPInFace2D, aPInFace, theContext);
567 //=======================================================================
568 //function : MinStepIn2d
570 //=======================================================================
571 Standard_Real BOPTools_AlgoTools3D::MinStepIn2d()
573 Standard_Real dt=1.e-5;
576 //=======================================================================
577 //function : IsEmptyShape
579 //=======================================================================
580 Standard_Boolean BOPTools_AlgoTools3D::IsEmptyShape
581 (const TopoDS_Shape& aS)
583 Standard_Boolean bHasGeometry=Standard_False;
585 BOPCol_IndexedMapOfShape myShapes;
587 Add(aS, myShapes, bHasGeometry);
589 return !bHasGeometry;
591 //=======================================================================
594 //=======================================================================
595 void Add(const TopoDS_Shape& aS,
596 BOPCol_IndexedMapOfShape& myShapes,
597 Standard_Boolean& bHasGeometry)
599 Standard_Integer anIndex;
609 TopoDS_Shape aSx = aS;
611 anIndex=myShapes.FindIndex(aSx);
613 bHasGeometry=HasGeometry (aSx);
618 TopoDS_Iterator anIt(aSx, Standard_False, Standard_False);
619 for(; anIt.More(); anIt.Next()) {
620 const TopoDS_Shape& aSy=anIt.Value();
621 Add(aSy, myShapes, bHasGeometry);
631 //=======================================================================
632 //function : HasGeometry
634 //=======================================================================
635 Standard_Boolean HasGeometry(const TopoDS_Shape& aS)
637 Standard_Boolean bHasGeometry=Standard_True;
638 TopAbs_ShapeEnum aType= aS.ShapeType();
640 if (aType == TopAbs_VERTEX) {
644 else if (aType == TopAbs_EDGE) {
645 Handle(BRep_TEdge) TE = Handle(BRep_TEdge)::DownCast(aS.TShape());
646 BRep_ListIteratorOfListOfCurveRepresentation itrc(TE->Curves());
648 while (itrc.More()) {
649 const Handle(BRep_CurveRepresentation)& CR = itrc.Value();
650 if (CR->IsCurve3D()) {
651 if (!CR->Curve3D().IsNull()) {
655 else if (CR->IsCurveOnSurface()) {
658 else if (CR->IsRegularity()) {
661 else if (!CR->Polygon3D().IsNull()) {
664 else if (CR->IsPolygonOnTriangulation()) {
667 else if (CR->IsPolygonOnSurface()) {
674 else if (aType == TopAbs_FACE) {
675 Handle(BRep_TFace) TF = Handle(BRep_TFace)::DownCast(aS.TShape());
676 if (!TF->Surface().IsNull()) {
679 Handle(Poly_Triangulation) Tr = TF->Triangulation();
685 return !bHasGeometry;
687 //=======================================================================
688 //function : OrientEdgeOnFace
690 //=======================================================================
691 void BOPTools_AlgoTools3D::OrientEdgeOnFace (const TopoDS_Edge& aE,
692 const TopoDS_Face& aF,
693 TopoDS_Edge& aERight)
695 if (BRep_Tool::IsClosed(aE, aF)) {
697 aERight.Orientation(aE.Orientation());
699 Standard_Integer iFoundCount = 0;
700 TopoDS_Edge anEdge = aE;
701 TopExp_Explorer anExp(aF, TopAbs_EDGE);
703 for (; anExp.More(); anExp.Next()) {
704 const TopoDS_Shape& aSS=anExp.Current();
706 if (aSS.IsSame(aE)) {
707 anEdge = TopoDS::Edge(aSS);
712 if(iFoundCount == 1) {
718 TopExp_Explorer anExp(aF, TopAbs_EDGE);
719 for (; anExp.More(); anExp.Next()) {
720 const TopoDS_Shape& aSS=anExp.Current();
721 if (aSS.IsSame(aE)) {
723 aERight.Orientation(aSS.Orientation());
728 aERight.Orientation(aE.Orientation());
730 //=======================================================================
731 //function : PointInFace
733 //=======================================================================
734 Standard_Integer BOPTools_AlgoTools3D::PointInFace
735 (const TopoDS_Face& aF,
738 Handle(IntTools_Context)& theContext)
740 Standard_Boolean bIsDone, bHasFirstPoint, bHasSecondPoint;
741 Standard_Integer iErr, aIx = 0, aNbDomains = 0;
742 Standard_Real aUMin, aUMax, aVMin, aVMax;
743 Standard_Real aVx = 0., aUx, aV1, aV2;
744 gp_Dir2d aD2D (0., 1.);
747 Handle(Geom2d_Curve) aC2D;
748 Handle(Geom2d_Line) aL2D;
749 Handle(Geom_Surface) aS;
752 Geom2dHatch_Hatcher& aHatcher = theContext->Hatcher(aF);
757 aFF.Orientation (TopAbs_FORWARD);
759 aS=BRep_Tool::Surface(aFF);
760 if (theContext.IsNull()) {
761 BRepTools::UVBounds(aFF, aUMin, aUMax, aVMin, aVMax);
764 theContext->UVBounds(aFF, aUMin, aUMax, aVMin, aVMax);
767 aUx=IntTools_Tools::IntermediatePoint(aUMin, aUMax);
769 for(i = 1; i <= 2; ++i)
771 aP2D.SetCoord(aUx, 0.);
772 aL2D=new Geom2d_Line (aP2D, aD2D);
773 Geom2dAdaptor_Curve aHCur(aL2D);
775 aIx=aHatcher.AddHatching(aHCur) ;
778 bIsDone=aHatcher.TrimDone(aIx);
784 if(aHatcher.NbPoints(aIx) > 1)
786 aHatcher.ComputeDomains(aIx);
787 bIsDone=aHatcher.IsDone(aIx);
796 aUx = aUMax - (aUx - aUMin);
800 if(!aHatcher.IsDone(aIx))
806 aNbDomains=aHatcher.NbDomains(aIx);
807 if (aNbDomains > 0) {
808 const HatchGen_Domain& aDomain=aHatcher.Domain (aIx, 1);
809 bHasFirstPoint=aDomain.HasFirstPoint();
810 if (!bHasFirstPoint) {
815 aV1=aDomain.FirstPoint().Parameter();
817 bHasSecondPoint=aDomain.HasSecondPoint();
818 if (!bHasSecondPoint) {
823 aV2=aDomain.SecondPoint().Parameter();
825 aVx=IntTools_Tools::IntermediatePoint(aV1, aV2);
833 aS->D0(aUx, aVx, aPx);
835 theP2D.SetCoord(aUx, aVx);