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