Salome HOME
06acad4f48605d94c9b14f961ceff93ef25d986b
[modules/geom.git] / src / GEOMAlgo / GEOMAlgo_AlgoTools.cxx
1 // Copyright (C) 2007-2022  CEA/DEN, EDF R&D, OPEN CASCADE
2 //
3 // Copyright (C) 2003-2007  OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,
4 // CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS
5 //
6 // This library is free software; you can redistribute it and/or
7 // modify it under the terms of the GNU Lesser General Public
8 // License as published by the Free Software Foundation; either
9 // version 2.1 of the License, or (at your option) any later version.
10 //
11 // This library is distributed in the hope that it will be useful,
12 // but WITHOUT ANY WARRANTY; without even the implied warranty of
13 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14 // Lesser General Public License for more details.
15 //
16 // You should have received a copy of the GNU Lesser General Public
17 // License along with this library; if not, write to the Free Software
18 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
19 //
20 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
21 //
22 //  File    : GEOMAlgo_AlgoTools.cxx
23 //  Created :
24 //  Author  : Peter KURNEV
25
26 #include <GEOMAlgo_AlgoTools.hxx>
27
28 #include <gp_Pnt.hxx>
29 #include <gp_Pnt2d.hxx>
30 #include <gp_Dir2d.hxx>
31 #include <Bnd_Box.hxx>
32
33 #include <Geom2d_Curve.hxx>
34 #include <Geom2d_TrimmedCurve.hxx>
35 #include <Geom2d_Line.hxx>
36 #include <Geom2d_TrimmedCurve.hxx>
37
38 #include <Geom2dHatch_Intersector.hxx>
39 #include <Geom2dHatch_Hatcher.hxx>
40
41 #include <Geom2dAdaptor_Curve.hxx>
42 #include <HatchGen_Domain.hxx>
43
44 #include <Geom_Curve.hxx>
45 #include <Geom_Surface.hxx>
46
47 #include <GeomAdaptor_Surface.hxx>
48
49 #include <GeomAPI_ProjectPointOnSurf.hxx>
50 #include <GeomAPI_ProjectPointOnCurve.hxx>
51
52 #include <Poly_Triangulation.hxx>
53
54 #include <TopAbs_Orientation.hxx>
55
56 #include <TopLoc_Location.hxx>
57
58 #include <TopoDS.hxx>
59 #include <TopoDS_Iterator.hxx>
60 #include <TopoDS_Face.hxx>
61 #include <TopoDS_Edge.hxx>
62
63 #include <TopExp_Explorer.hxx>
64
65 #include <BRep_Tool.hxx>
66 #include <BRep_Builder.hxx>
67
68 #include <BRepTools.hxx>
69 #include <BRepBndLib.hxx>
70 #include <BRepMesh_IncrementalMesh.hxx>
71
72 #include <IntTools_Tools.hxx>
73
74 #include <TopTools_IndexedDataMapOfShapeListOfShape.hxx>
75 #include <TopTools_ListOfShape.hxx>
76
77 #include <TopTools_ListIteratorOfListOfShape.hxx>
78 #include <TopTools_IndexedMapOfShape.hxx>
79 #include <TopAbs_ShapeEnum.hxx>
80
81 #include <IntTools_Tools.hxx>
82
83 #include <BOPTools_AlgoTools3D.hxx>
84 #include <BOPTools_AlgoTools2D.hxx>
85
86 #include <GEOMAlgo_PassKeyShape.hxx>
87
88
89 static
90   void GetCount(const TopoDS_Shape& aS,
91                 Standard_Integer& iCnt);
92 static
93   void CopySource(const TopoDS_Shape& aS,
94     TopTools_IndexedDataMapOfShapeShape& aMapSS,
95     TopoDS_Shape& aSC);
96
97 //=======================================================================
98 //function : CopyShape
99 //purpose  :
100 //=======================================================================
101 void GEOMAlgo_AlgoTools::CopyShape(const TopoDS_Shape& aS,
102        TopoDS_Shape& aSC)
103 {
104   TopTools_IndexedDataMapOfShapeShape aMapSS;
105   //
106   CopySource(aS, aMapSS, aSC);
107 }
108 //=======================================================================
109 //function : CopyShape
110 //purpose  :
111 //=======================================================================
112 void GEOMAlgo_AlgoTools::CopyShape(const TopoDS_Shape& aS,
113        TopoDS_Shape& aSC,
114        TopTools_IndexedDataMapOfShapeShape& aMapSS)
115 {
116   CopySource(aS, aMapSS, aSC);
117 }
118 //=======================================================================
119 //function : CopySource
120 //purpose  :
121 //=======================================================================
122 void CopySource(const TopoDS_Shape& aS,
123                 TopTools_IndexedDataMapOfShapeShape& aMapSS,
124                 TopoDS_Shape& aSC)
125 {
126   Standard_Boolean bFree;
127   TopAbs_ShapeEnum aT;
128   TopoDS_Iterator aIt;
129   TopoDS_Shape aSF;
130   BRep_Builder BB;
131   //
132   aT=aS.ShapeType();
133   //
134   if (aMapSS.Contains(aS)) {
135     aSC=aMapSS.ChangeFromKey(aS);
136     aSC.Orientation(aS.Orientation());
137     return;
138   }
139   else {
140     aSC=aS.EmptyCopied();
141     aMapSS.Add(aS, aSC);
142   }
143   //
144   bFree=aSC.Free();
145   aSC.Free(Standard_True);
146   aSF=aS;
147   if (aT==TopAbs_EDGE){
148     TopAbs_Orientation aOr;
149     //
150     aOr=aS.Orientation();
151     if(aOr==TopAbs_INTERNAL) {
152       aSF.Orientation(TopAbs_FORWARD);
153     }
154   }
155   aIt.Initialize(aSF);
156   for (; aIt.More();  aIt.Next()) {
157     TopoDS_Shape aSCx;
158     //
159     const TopoDS_Shape& aSx=aIt.Value();
160     //
161     CopySource (aSx, aMapSS, aSCx);
162     //
163     aSCx.Orientation(aSx.Orientation());
164     BB.Add(aSC, aSCx);
165   }
166   aSC.Free(bFree);
167 }
168 //=======================================================================
169 //function : FaceNormal
170 //purpose  : 
171 //=======================================================================
172 void GEOMAlgo_AlgoTools::FaceNormal (const TopoDS_Face& aF,
173          const Standard_Real U,
174          const Standard_Real V,
175          gp_Vec& aN)
176 {
177   gp_Pnt aPnt ;
178   gp_Vec aD1U, aD1V;
179   Handle(Geom_Surface) aSurface;
180
181   aSurface=BRep_Tool::Surface(aF);
182   aSurface->D1 (U, V, aPnt, aD1U, aD1V);
183   aN=aD1U.Crossed(aD1V);
184   aN.Normalize();  
185   if (aF.Orientation() == TopAbs_REVERSED){
186     aN.Reverse();
187   }
188   return;
189 }
190 //=======================================================================
191 //function : BuildPCurveForEdgeOnFace
192 //purpose  :
193 //=======================================================================
194 Standard_Integer GEOMAlgo_AlgoTools::BuildPCurveForEdgeOnFace
195   (const TopoDS_Edge& aEold,
196    const TopoDS_Edge& aEnew,
197    const TopoDS_Face& aF,
198    const Handle(IntTools_Context)& aCtx)
199 {
200   Standard_Boolean bIsClosed, bUClosed, bHasOld;
201   Standard_Integer iRet, aNbPoints;
202   Standard_Real aTS, aTS1, aTS2, aT, aT1, aT2, aScPr, aTol;
203   Standard_Real aU, aV, aUS1, aVS1, aUS2, aVS2;
204   gp_Pnt aP;
205   gp_Pnt2d aP2DS1, aP2DS2, aP2D;
206   gp_Vec2d aV2DS1, aV2DS2;
207   Handle(Geom2d_Curve) aC2D, aC2DS1, aC2DS2;
208   Handle(Geom_Surface) aS;
209   TopoDS_Edge aES;
210   //
211   iRet=0;
212   //
213   bHasOld=BOPTools_AlgoTools2D::HasCurveOnSurface(aEnew, aF, aC2D, aT1, aT2, aTol);
214   if (bHasOld) {
215     return iRet;
216   }
217   //
218   // Try to copy PCurve from old edge to the new one.
219   iRet = BOPTools_AlgoTools2D::AttachExistingPCurve(aEold, aEnew, aF, aCtx);
220
221   if (iRet) {
222     // Do PCurve using projection algorithm.
223     iRet = 0;
224   } else {
225     // The PCurve is attached successfully.
226     return iRet;
227   }
228   //
229   BOPTools_AlgoTools2D::BuildPCurveForEdgeOnFace(aEnew, aF);
230   aC2D=BRep_Tool::CurveOnSurface(aEnew, aF, aT1, aT2);
231   if (aC2D.IsNull()){
232     iRet=1;
233     return iRet;
234   }
235   //
236   bIsClosed=BRep_Tool::IsClosed(aEold, aF);
237   if (!bIsClosed) {
238     return iRet;
239   }
240   //
241   aTol=1.e-7;
242   //
243   // 1. bUClosed - direction of closeness
244   //
245   aES=aEold;
246   aES.Orientation(TopAbs_FORWARD);
247   aC2DS1=BRep_Tool::CurveOnSurface(aES, aF, aTS1, aTS2);
248   //
249   aES.Orientation(TopAbs_REVERSED);
250   aC2DS2=BRep_Tool::CurveOnSurface(aES, aF, aTS1, aTS2);
251   //
252   aTS=IntTools_Tools::IntermediatePoint(aTS1, aTS2);
253   //
254   aC2DS1->D1(aTS, aP2DS1, aV2DS1);
255   aC2DS2->D1(aTS, aP2DS2, aV2DS2);
256   //
257   gp_Vec2d aV2DS12(aP2DS1, aP2DS2);
258   gp_Dir2d aD2DS12(aV2DS12);
259   const gp_Dir2d& aD2DX=gp::DX2d();
260   //
261   aScPr=aD2DS12*aD2DX;
262   bUClosed=Standard_True;
263   if (fabs(aScPr) < aTol) {
264     bUClosed=!bUClosed;
265   }
266   //
267   // 2. aP2D - point on curve aC2D, that corresponds to aP2DS1
268   aP2DS1.Coord(aUS1, aVS1);
269   aP2DS2.Coord(aUS2, aVS2);
270   //
271   aS=BRep_Tool::Surface(aF);
272   aS->D0(aUS1, aVS1, aP);
273   //
274   GeomAPI_ProjectPointOnCurve& aProjPC=aCtx->ProjPC(aEnew);
275   //
276   aProjPC.Perform(aP);
277   aNbPoints=aProjPC.NbPoints();
278   if (!aNbPoints) {
279     iRet=2;
280     return iRet;
281   }
282   //
283   aT=aProjPC.LowerDistanceParameter();
284
285   //
286   // 3. Build the second 2D curve
287   Standard_Boolean bRevOrder;
288   gp_Vec2d aV2DT, aV2D;
289   Handle(Geom2d_Curve) aC2Dnew;
290   Handle(Geom2d_TrimmedCurve) aC2DTnew;
291   BRep_Builder aBB;
292   //
293   aC2D->D1(aT, aP2D, aV2D);
294   aP2D.Coord(aU, aV);
295   //
296   aC2Dnew=Handle(Geom2d_Curve)::DownCast(aC2D->Copy());
297   aC2DTnew = new Geom2d_TrimmedCurve(aC2Dnew, aT1, aT2);
298   //
299   aV2DT=aV2DS12;
300   if (!bUClosed) {    // V Closed
301     if (fabs(aV-aVS2)<aTol) {
302       aV2DT.Reverse();
303     }
304   }
305   else {   // U Closed
306     if (fabs(aU-aUS2)<aTol) {
307       aV2DT.Reverse();
308     }
309   }
310   //
311   aC2DTnew->Translate(aV2DT);
312   //
313   // 4 Order the 2D curves
314   bRevOrder=Standard_False;
315   aScPr=aV2D*aV2DS1;
316   if(aScPr<0.) {
317     bRevOrder=!bRevOrder;
318   }
319   //
320   // 5. Update the edge
321   aTol=BRep_Tool::Tolerance(aEnew);
322   if (!bRevOrder) {
323     aBB.UpdateEdge(aEnew, aC2D, aC2DTnew, aF, aTol);
324   }
325   else {
326     aBB.UpdateEdge(aEnew, aC2DTnew, aC2D , aF, aTol);
327   }
328   //
329   return iRet;
330 }
331 //////////////////////////////////////////////////////////////////////////
332 //=======================================================================
333 // function: MakeContainer
334 // purpose:
335 //=======================================================================
336 void GEOMAlgo_AlgoTools::MakeContainer(const TopAbs_ShapeEnum theType,
337            TopoDS_Shape& theC)
338 {
339   BRep_Builder aBB;
340   //
341   switch(theType) {
342     case TopAbs_COMPOUND:{
343       TopoDS_Compound aC;
344       aBB.MakeCompound(aC);
345       theC=aC;
346     }
347       break;
348       //
349     case TopAbs_COMPSOLID:{
350       TopoDS_CompSolid aCS;
351       aBB.MakeCompSolid(aCS);
352       theC=aCS;
353     }
354       break;
355       //
356     case TopAbs_SOLID:{
357       TopoDS_Solid aSolid;
358       aBB.MakeSolid(aSolid);
359       theC=aSolid;
360     }
361       break;
362       //
363       //
364     case TopAbs_SHELL:{
365       TopoDS_Shell aShell;
366       aBB.MakeShell(aShell);
367       theC=aShell;
368     }
369       break;
370       //
371     case TopAbs_WIRE: {
372       TopoDS_Wire aWire;
373       aBB.MakeWire(aWire);
374       theC=aWire;
375     }
376       break;
377       //
378     default:
379       break;
380   }
381 }
382 //=======================================================================
383 //function : IsUPeriodic
384 //purpose  :
385 //=======================================================================
386 Standard_Boolean GEOMAlgo_AlgoTools::IsUPeriodic(const  Handle(Geom_Surface) &aS)
387 {
388   Standard_Boolean bRet;
389   GeomAbs_SurfaceType aType;
390   GeomAdaptor_Surface aGAS;
391   //
392   aGAS.Load(aS);
393   aType=aGAS.GetType();
394   bRet=(aType==GeomAbs_Cylinder||
395         aType==GeomAbs_Cone ||
396         aType==GeomAbs_Sphere);
397   //
398   return bRet;
399 }
400
401 //=======================================================================
402 //function : RefinePCurveForEdgeOnFace
403 //purpose  :
404 //=======================================================================
405 void GEOMAlgo_AlgoTools::RefinePCurveForEdgeOnFace(const TopoDS_Edge& aE,
406          const TopoDS_Face& aF,
407          const Standard_Real aUMin,
408          const Standard_Real aUMax)
409 {
410   Standard_Real aT1, aT2, aTx, aUx, aTol;
411   gp_Pnt2d aP2D;
412   Handle(Geom_Surface) aS;
413   Handle(Geom2d_Curve) aC2D;
414   BRep_Builder aBB;
415   //
416   aC2D=BRep_Tool::CurveOnSurface(aE, aF, aT1, aT2);
417   if (!aC2D.IsNull()) {
418     if (BRep_Tool::IsClosed(aE, aF)) {
419       return;
420     }
421     aTx=IntTools_Tools::IntermediatePoint(aT1, aT2);
422     aC2D->D0(aTx, aP2D);
423     aUx=aP2D.X();
424     if (aUx < aUMin || aUx > aUMax) {
425       // need to rebuild
426       Handle(Geom2d_Curve) aC2Dx;
427       //
428       aTol=BRep_Tool::Tolerance(aE);
429       aBB.UpdateEdge(aE, aC2Dx, aF, aTol);
430     }
431   }
432 }
433 //=======================================================================
434 //function :IsSplitToReverse
435 //purpose  : 
436 //=======================================================================
437 Standard_Boolean GEOMAlgo_AlgoTools::IsSplitToReverse
438   (const TopoDS_Edge& aEF1,
439    const TopoDS_Edge& aEF2,
440    const Handle(IntTools_Context)& aContext)
441 {
442   Standard_Boolean aFlag;
443   Standard_Real aT1, aT2, aScPr, a, b;
444   gp_Vec aV1, aV2;
445   gp_Pnt aP;
446   
447   
448   Handle(Geom_Curve)aC1=BRep_Tool::Curve(aEF1, a, b);
449   aT1=IntTools_Tools::IntermediatePoint(a, b);
450   aC1->D0(aT1, aP);
451   aFlag=BOPTools_AlgoTools2D::EdgeTangent(aEF1, aT1, aV1);
452
453   if(!aFlag) {
454     return Standard_False;
455   }
456
457   gp_Dir aDT1(aV1);
458   //
459   aFlag=aContext->ProjectPointOnEdge(aP, aEF2, aT2);
460   if(!aFlag) {
461     return Standard_False;
462   }
463   //
464   aFlag=BOPTools_AlgoTools2D::EdgeTangent(aEF2, aT2, aV2);
465   if(!aFlag) {
466     return Standard_False;
467   }
468
469   gp_Dir aDT2(aV2);
470
471   aScPr=aDT1*aDT2;
472
473   return (aScPr<0.);
474 }
475
476
477 //=======================================================================
478 //function : ProjectPointOnShape
479 //purpose  :
480 //=======================================================================
481 Standard_Boolean GEOMAlgo_AlgoTools::ProjectPointOnShape
482   (const gp_Pnt& aP1,
483    const TopoDS_Shape& aS,
484    gp_Pnt& aP2,
485    const Handle(IntTools_Context)& aCtx)
486 {
487   Standard_Boolean bIsDone = Standard_False;
488   Standard_Real aT2;
489   TopAbs_ShapeEnum aType;
490   //
491   aType = aS.ShapeType();
492   switch (aType)
493     {
494     case TopAbs_EDGE:
495       {
496         const TopoDS_Edge& aE2 = TopoDS::Edge(aS);
497         //
498         if (BRep_Tool::Degenerated(aE2)) { // jfa
499           return Standard_True;
500         }
501         else {
502           Standard_Real f, l;
503           Handle(Geom_Curve) aC3D = BRep_Tool::Curve (aE2, f, l);
504           if (aC3D.IsNull()) {
505             return Standard_True;
506           }
507           bIsDone = aCtx->ProjectPointOnEdge(aP1, aE2, aT2);
508         }
509         if (!bIsDone) {
510           return bIsDone;
511         }
512         //
513         GEOMAlgo_AlgoTools::PointOnEdge(aE2, aT2, aP2);
514       }
515       break;
516       //
517     case TopAbs_FACE:
518       {
519         const TopoDS_Face& aF2 = TopoDS::Face(aS);
520         GeomAPI_ProjectPointOnSurf& aProj = aCtx->ProjPS(aF2);
521         //
522         aProj.Perform(aP1);
523         bIsDone = aProj.IsDone();
524         if (!bIsDone) {
525           return bIsDone;
526         }
527         //
528         aP2 = aProj.NearestPoint();
529       }
530       break;
531       //
532     default:
533       break; // Err
534     }
535   return bIsDone;
536 }
537
538 //=======================================================================
539 //function : PointOnEdge
540 //purpose  :
541 //=======================================================================
542 void GEOMAlgo_AlgoTools::PointOnEdge(const TopoDS_Edge& aE,
543          gp_Pnt& aP3D)
544 {
545   Standard_Real aTx, aT1, aT2;
546   //
547   BRep_Tool::Curve(aE, aT1, aT2);
548   aTx=IntTools_Tools::IntermediatePoint(aT1, aT2);
549   GEOMAlgo_AlgoTools::PointOnEdge(aE, aTx, aP3D);
550 }
551 //=======================================================================
552 //function : PointOnEdge
553 //purpose  :
554 //=======================================================================
555 void GEOMAlgo_AlgoTools::PointOnEdge(const TopoDS_Edge& aE,
556          const Standard_Real aT,
557          gp_Pnt& aP3D)
558 {
559   Standard_Real aT1, aT2;
560   Handle(Geom_Curve) aC3D;
561   //
562   aC3D=BRep_Tool::Curve(aE, aT1, aT2);
563   aC3D->D0(aT, aP3D);
564 }
565 //=======================================================================
566 //function : PointOnFace
567 //purpose  :
568 //=======================================================================
569 void GEOMAlgo_AlgoTools::PointOnFace(const TopoDS_Face& aF,
570          const Standard_Real aU,
571          const Standard_Real aV,
572          gp_Pnt& aP3D)
573 {
574   Handle(Geom_Surface) aS;
575   //
576   aS=BRep_Tool::Surface(aF);
577   aS->D0(aU, aV, aP3D);
578 }
579 //=======================================================================
580 //function : PointOnFace
581 //purpose  :
582 //=======================================================================
583 void GEOMAlgo_AlgoTools::PointOnFace(const TopoDS_Face& aF,
584          gp_Pnt& aP3D)
585 {
586   Standard_Real aU, aV, aUMin, aUMax, aVMin, aVMax;
587   //
588   BRepTools::UVBounds(aF, aUMin, aUMax, aVMin, aVMax);
589   //
590   aU=IntTools_Tools::IntermediatePoint(aUMin, aUMax);
591   aV=IntTools_Tools::IntermediatePoint(aVMin, aVMax);
592   //
593   GEOMAlgo_AlgoTools::PointOnFace(aF, aU, aV, aP3D);
594 }
595 //=======================================================================
596 //function : PointOnShape
597 //purpose  :
598 //=======================================================================
599 void GEOMAlgo_AlgoTools::PointOnShape(const TopoDS_Shape& aS,
600           gp_Pnt& aP3D)
601 {
602   TopAbs_ShapeEnum aType;
603   //
604   aP3D.SetCoord(99.,99.,99.);
605   aType=aS.ShapeType();
606   switch(aType) {
607     case TopAbs_EDGE: {
608       const TopoDS_Edge& aE=TopoDS::Edge(aS);
609       GEOMAlgo_AlgoTools::PointOnEdge(aE, aP3D);
610       }
611       break;
612       //
613     case TopAbs_FACE: {
614       const TopoDS_Face& aF=TopoDS::Face(aS);
615       GEOMAlgo_AlgoTools::PointOnFace(aF, aP3D);
616       }
617       break;
618       //
619     default:
620       break; // Err
621   }
622 }
623 //=======================================================================
624 //function : FindSDShapes
625 //purpose  :
626 //=======================================================================
627 Standard_Integer GEOMAlgo_AlgoTools::FindSDShapes
628   (const TopoDS_Shape& aE1,
629    const TopTools_ListOfShape& aLE,
630    const Standard_Real aTol,
631    TopTools_ListOfShape& aLESD,
632    const Handle(IntTools_Context)& aCtx)
633 {
634   Standard_Boolean bIsDone;
635   Standard_Real aTol2, aD2;
636   gp_Pnt aP1, aP2;
637   TopTools_ListIteratorOfListOfShape aIt;
638   //
639   aTol2=aTol*aTol;
640   GEOMAlgo_AlgoTools::PointOnShape(aE1, aP1);
641   //
642   aIt.Initialize(aLE);
643   for (; aIt.More(); aIt.Next()) {
644     const TopoDS_Shape& aE2=aIt.Value();
645     if (aE2.IsSame(aE1)) {
646        aLESD.Append(aE2);
647     }
648     else {
649       bIsDone=GEOMAlgo_AlgoTools::ProjectPointOnShape(aP1, aE2, aP2, aCtx);
650       if (!bIsDone) {
651         //return 1;
652         continue; // jfa BUG 20361
653       }
654       aD2=aP1.SquareDistance(aP2);
655       if(aD2<aTol2) {
656         aLESD.Append(aE2);
657       }
658     }
659   }
660   return 0;
661 }
662
663 //=======================================================================
664 //function : FindSDShapes
665 //purpose  :
666 //=======================================================================
667 Standard_Integer GEOMAlgo_AlgoTools::FindSDShapes
668   (const TopTools_ListOfShape& aLE,
669    const Standard_Real aTol,
670    TopTools_IndexedDataMapOfShapeListOfShape& aMEE,
671    const Handle(IntTools_Context)& aCtx)
672 {
673   Standard_Integer aNbE, aNbEProcessed, aNbESD, iErr;
674   TopTools_ListOfShape aLESD;
675   TopTools_ListIteratorOfListOfShape aIt, aIt1;
676   TopTools_IndexedMapOfShape aMProcessed;
677   TopAbs_ShapeEnum aType;
678   //
679   aNbE=aLE.Extent();
680   if (!aNbE) {
681     return 3; // Err
682   }
683   if (aNbE==1) {
684     return 0; // Nothing to do
685   }
686   //
687   for(;;) {
688     aNbEProcessed=aMProcessed.Extent();
689     if (aNbEProcessed==aNbE) {
690       break;
691     }
692     //
693     aIt.Initialize(aLE);
694     for (; aIt.More(); aIt.Next()) {
695       const TopoDS_Shape& aS=aIt.Value();
696       //
697       if (aMProcessed.Contains(aS)) {
698         continue;
699       }
700       //
701       aType=aS.ShapeType();
702       if (aType==TopAbs_EDGE) {
703         const TopoDS_Edge& aE=TopoDS::Edge(aS);
704         if (BRep_Tool::Degenerated(aE)) {
705           aMProcessed.Add(aE);
706           continue;
707         }
708       }
709       //
710       aLESD.Clear();
711       iErr=GEOMAlgo_AlgoTools::FindSDShapes(aS, aLE, aTol, aLESD, aCtx);
712       if (iErr) {
713         return 2; // Err
714       }
715       //
716       aNbESD=aLESD.Extent();
717       if (!aNbESD) {
718         return 1; // Err
719       }
720       //
721       aMEE.Add(aS, aLESD);
722       //
723       aIt1.Initialize(aLESD);
724       for (; aIt1.More(); aIt1.Next()) {
725         const TopoDS_Shape& aE1=aIt1.Value();
726         aMProcessed.Add(aE1);
727       }
728     }
729   }
730   return 0;
731 }
732 //=======================================================================
733 //function : RefineSDShapes
734 //purpose  :
735 //=======================================================================
736 Standard_Integer GEOMAlgo_AlgoTools::RefineSDShapes
737   (GEOMAlgo_IndexedDataMapOfPassKeyShapeListOfShape& aMPKLE,
738    const Standard_Real aTol,
739    const Handle(IntTools_Context)& aCtx)
740 {
741   Standard_Integer i, aNbE, iErr, j, aNbEE, aNbToAdd;
742   TopTools_IndexedDataMapOfShapeListOfShape aMEE, aMSDE, aMEToAdd;
743   //
744   iErr=1;
745   //
746   aNbE=aMPKLE.Extent();
747   for (i=1; i<=aNbE; ++i) {
748     TopTools_ListOfShape& aLSDE=aMPKLE.ChangeFromIndex(i);
749     //
750     aMEE.Clear();
751     iErr=GEOMAlgo_AlgoTools::FindSDShapes(aLSDE, aTol, aMEE, aCtx);
752     if (iErr) {
753       return iErr;
754     }
755     //
756     aNbEE=aMEE.Extent();
757     if (aNbEE==1) {
758       continue;  // nothing to do
759     }
760     //
761     for (j=1; j<=aNbEE; ++j) {
762       TopTools_ListOfShape& aLEE=aMEE.ChangeFromIndex(j);
763       //
764       if (j==1) {
765         aLSDE.Clear();
766         aLSDE.Append(aLEE);
767       }
768       else {
769         const TopoDS_Shape& aE1=aLEE.First();
770         aMEToAdd.Add(aE1, aLEE);
771       }
772     }
773   }
774   //
775   aNbToAdd=aMEToAdd.Extent();
776   if (!aNbToAdd) {
777     return aNbToAdd;
778   }
779   //
780   for (i=1; i<=aNbToAdd; ++i) {
781     GEOMAlgo_PassKeyShape aPKE1;
782     //
783     const TopoDS_Shape& aE1=aMEToAdd.FindKey(i);
784     const TopTools_ListOfShape& aLE=aMEToAdd(i);
785     //
786     aPKE1.SetShapes(aE1);
787     aMPKLE.Add(aPKE1, aLE);
788   }
789   //
790   return 0;
791 }
792 //=======================================================================
793 //function : BuildTriangulation
794 //purpose  :
795 //=======================================================================
796 Standard_Boolean 
797   GEOMAlgo_AlgoTools::BuildTriangulation (const TopoDS_Shape& theShape)
798 {
799   // calculate deflection
800   Standard_Real aDeviationCoefficient = 0.001;
801
802   Bnd_Box B;
803   BRepBndLib::Add(theShape, B);
804   Standard_Real aXmin, aYmin, aZmin, aXmax, aYmax, aZmax;
805   B.Get(aXmin, aYmin, aZmin, aXmax, aYmax, aZmax);
806
807   Standard_Real dx = aXmax - aXmin, dy = aYmax - aYmin, dz = aZmax - aZmin;
808   Standard_Real aDeflection = Max(Max(dx, dy), dz) * aDeviationCoefficient * 4;
809   Standard_Real aHLRAngle = 0.349066;
810
811   // build triangulation
812   BRepMesh_IncrementalMesh Inc (theShape, aDeflection, Standard_False, aHLRAngle);
813
814   // check triangulation
815   bool isTriangulation = true;
816
817   TopExp_Explorer exp (theShape, TopAbs_FACE);
818   if (exp.More())
819   {
820     TopLoc_Location aTopLoc;
821     Handle(Poly_Triangulation) aTRF;
822     aTRF = BRep_Tool::Triangulation(TopoDS::Face(exp.Current()), aTopLoc);
823     if (aTRF.IsNull()) {
824       isTriangulation = false;
825     }
826   }
827   else // no faces, try edges
828   {
829     TopExp_Explorer expe (theShape, TopAbs_EDGE);
830     if (!expe.More()) {
831       isTriangulation = false;
832     }
833     else {
834       TopLoc_Location aLoc;
835       Handle(Poly_Polygon3D) aPE = BRep_Tool::Polygon3D(TopoDS::Edge(expe.Current()), aLoc);
836       if (aPE.IsNull()) {
837         isTriangulation = false;
838       }
839     }
840   }
841   return isTriangulation;
842 }
843
844 //=======================================================================
845 //function : IsCompositeShape
846 //purpose  :
847 //=======================================================================
848 Standard_Boolean GEOMAlgo_AlgoTools::IsCompositeShape(const TopoDS_Shape& aS)
849 {
850   Standard_Boolean bRet;
851   Standard_Integer iCnt;
852   TopoDS_Iterator aIt;
853   //
854   iCnt=0;
855   GetCount(aS, iCnt);
856   bRet=(iCnt>1);
857   //
858   return bRet;
859 }
860 //=======================================================================
861 //function : GetCount
862 //purpose  :
863 //=======================================================================
864 void GetCount(const TopoDS_Shape& aS,
865               Standard_Integer& iCnt)
866 {
867   TopoDS_Iterator aIt;
868   TopAbs_ShapeEnum aTS;
869   //
870   aTS=aS.ShapeType();
871   //
872   if (aTS==TopAbs_SHAPE) {
873     return;
874   }
875   if (aTS!=TopAbs_COMPOUND) {
876     ++iCnt;
877     return;
878   }
879   //
880   aIt.Initialize(aS);
881   for (; aIt.More(); aIt.Next()) {
882     const TopoDS_Shape& aSx=aIt.Value();
883     GetCount(aSx, iCnt);
884   }
885 }
886 //=======================================================================
887 //function : PntInFace
888 //purpose  :
889 //=======================================================================
890 Standard_Integer GEOMAlgo_AlgoTools::PntInFace(const TopoDS_Face& aF,
891                                                gp_Pnt& theP,
892                                                gp_Pnt2d& theP2D)
893 {
894   Standard_Boolean bIsDone, bHasFirstPoint, bHasSecondPoint;
895   Standard_Integer iErr, aIx, aNbDomains, i;
896   Standard_Real aUMin, aUMax, aVMin, aVMax;
897   Standard_Real aVx, aUx, aV1, aV2, aU1, aU2, aEpsT;
898   Standard_Real aTotArcIntr, aTolTangfIntr, aTolHatch2D, aTolHatch3D;
899   gp_Dir2d aD2D (0., 1.);
900   gp_Pnt2d aP2D;
901   gp_Pnt aPx;
902   Handle(Geom2d_Curve) aC2D;
903   Handle(Geom2d_TrimmedCurve) aCT2D;
904   Handle(Geom2d_Line) aL2D;
905   Handle(Geom_Surface) aS;
906   TopAbs_Orientation aOrE;
907   TopoDS_Face aFF;
908   TopExp_Explorer aExp;
909   //
910   aTolHatch2D=1.e-8;
911   aTolHatch3D=1.e-8;
912   aTotArcIntr=1.e-10;
913   aTolTangfIntr=1.e-10;
914   //
915   Geom2dHatch_Intersector aIntr(aTotArcIntr, aTolTangfIntr);
916   Geom2dHatch_Hatcher aHatcher(aIntr,
917           aTolHatch2D, aTolHatch3D,
918           Standard_True, Standard_False);
919   //
920   iErr=0;
921   aEpsT=1.e-12;
922   //
923   aFF=aF;
924   aFF.Orientation (TopAbs_FORWARD);
925   //
926   aS=BRep_Tool::Surface(aFF);
927   BRepTools::UVBounds(aFF, aUMin, aUMax, aVMin, aVMax);
928   //
929   // 1
930   aExp.Init (aFF, TopAbs_EDGE);
931   for (; aExp.More() ; aExp.Next()) {
932     const TopoDS_Edge& aE=*((TopoDS_Edge*)&aExp.Current());
933     aOrE=aE.Orientation();
934     //
935     aC2D=BRep_Tool::CurveOnSurface (aE, aFF, aU1, aU2);
936     if (aC2D.IsNull() ) {
937       iErr=1;
938       return iErr;
939     }
940     if (fabs(aU1-aU2) < aEpsT) {
941       iErr=2;
942       return iErr;
943     }
944     //
945     aCT2D=new Geom2d_TrimmedCurve(aC2D, aU1, aU2);
946     aHatcher.AddElement(aCT2D, aOrE);
947   }// for (; aExp.More() ; aExp.Next()) {
948   //
949   // 2
950   aUx=IntTools_Tools::IntermediatePoint(aUMin, aUMax);
951   aP2D.SetCoord(aUx, 0.);
952   aL2D=new Geom2d_Line (aP2D, aD2D);
953   Geom2dAdaptor_Curve aHCur(aL2D);
954   //
955   aIx=aHatcher.AddHatching(aHCur) ;
956   //
957   // 3.
958   aHatcher.Trim();
959   bIsDone=aHatcher.TrimDone(aIx);
960   if (!bIsDone) {
961     iErr=3;
962     return iErr;
963   }
964   //
965   aHatcher.ComputeDomains(aIx);
966   bIsDone=aHatcher.IsDone(aIx);
967   if (!bIsDone) {
968     iErr=4;
969     return iErr;
970   }
971   //
972   // 4.
973   aVx=aVMin;
974   aNbDomains=aHatcher.NbDomains(aIx);
975   if (!aNbDomains) {
976     iErr=5;
977     return iErr;
978   }
979   //
980   i=1;
981   const HatchGen_Domain& aDomain=aHatcher.Domain (aIx, i) ;
982   bHasFirstPoint=aDomain.HasFirstPoint();
983   if (!bHasFirstPoint) {
984     iErr=5;
985     return iErr;
986   }
987   //
988   aV1=aDomain.FirstPoint().Parameter();
989   //
990   bHasSecondPoint=aDomain.HasSecondPoint();
991   if (!bHasSecondPoint) {
992     iErr=6;
993     return iErr;
994   }
995   //
996   aV2=aDomain.SecondPoint().Parameter();
997   //
998   aVx=IntTools_Tools::IntermediatePoint(aV1, aV2);
999   //
1000   aS->D0(aUx, aVx, aPx);
1001   //
1002   theP2D.SetCoord(aUx, aVx);
1003   theP=aPx;
1004   //
1005   return iErr;
1006 }