Salome HOME
414dfa09af1fd7afbbb961913feb7b0307592bea
[modules/geom.git] / src / GEOMAlgo / GEOMAlgo_Tools.cxx
1 // Copyright (C) 2007-2011  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.
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_Tools.cxx
23 // Created:     Mon Dec  6 11:35:29 2004
24 // Author:      Peter KURNEV
25
26 #include <GEOMAlgo_Tools.ixx>
27
28 #include <gp.hxx>
29 #include <gp_Pnt.hxx>
30 #include <gp_Pnt2d.hxx>
31 #include <gp_Vec2d.hxx>
32 #include <gp_Dir2d.hxx>
33
34 #include <Geom2d_Curve.hxx>
35 #include <Geom2d_TrimmedCurve.hxx>
36
37 #include <Geom_Curve.hxx>
38 #include <Geom_Surface.hxx>
39
40 #include <GeomAdaptor_Surface.hxx>
41
42 #include <GeomAPI_ProjectPointOnSurf.hxx>
43 #include <GeomAPI_ProjectPointOnCurve.hxx>
44
45 #include <TopAbs_ShapeEnum.hxx>
46
47 #include <TopoDS.hxx>
48 #include <TopoDS_Shape.hxx>
49 #include <TopoDS_Edge.hxx>
50 #include <TopoDS_Iterator.hxx>
51
52 #include <TopTools_ListOfShape.hxx>
53 #include <TopTools_ListIteratorOfListOfShape.hxx>
54 #include <TopTools_IndexedMapOfShape.hxx>
55
56 #include <BRep_Tool.hxx>
57 #include <BRep_Builder.hxx>
58 #include <BRepTools.hxx>
59
60 #include <BOPTools_Tools2D.hxx>
61 #include <IntTools_Context.hxx>
62
63 #include <GEOMAlgo_PassKeyShape.hxx>
64 #include <GEOMAlgo_IndexedDataMapOfPassKeyShapeListOfShape.hxx>
65
66 static
67   void GetCount(const TopoDS_Shape& aS,
68                 Standard_Integer& iCnt);
69
70 //=======================================================================
71 //function : IsCompositeShape
72 //purpose  :
73 //=======================================================================
74 Standard_Boolean GEOMAlgo_Tools::IsCompositeShape(const TopoDS_Shape& aS)
75 {
76   Standard_Boolean bRet;
77   Standard_Integer iCnt;
78   TopoDS_Iterator aIt;
79   //
80   iCnt=0;
81   GetCount(aS, iCnt);
82   bRet=(iCnt>1);
83   //
84   return bRet;
85 }
86
87 //=======================================================================
88 //function : GetCount
89 //purpose  :
90 //=======================================================================
91 void GetCount(const TopoDS_Shape& aS,
92               Standard_Integer& iCnt)
93 {
94   TopoDS_Iterator aIt;
95   TopAbs_ShapeEnum aTS;
96   //
97   aTS=aS.ShapeType();
98   //
99   if (aTS==TopAbs_SHAPE) {
100     return;
101   }
102   if (aTS!=TopAbs_COMPOUND) {
103     ++iCnt;
104     return;
105   }
106   //
107   aIt.Initialize(aS);
108   for (; aIt.More(); aIt.Next()) {
109     const TopoDS_Shape& aSx=aIt.Value();
110     GetCount(aSx, iCnt);
111   }
112 }
113
114 //=======================================================================
115 //function : RefineSDShapes
116 //purpose  :
117 //=======================================================================
118   Standard_Integer GEOMAlgo_Tools::RefineSDShapes(GEOMAlgo_IndexedDataMapOfPassKeyShapeListOfShape& aMPKLE,
119                                                   const Standard_Real aTol,
120                                                   IntTools_Context& aCtx)
121 {
122   Standard_Integer i, aNbE, iErr, j, aNbEE, aNbToAdd;
123   TopTools_IndexedDataMapOfShapeListOfShape aMEE, aMSDE, aMEToAdd;
124   //
125   iErr=1;
126   //
127   aNbE=aMPKLE.Extent();
128   for (i=1; i<=aNbE; ++i) {
129     TopTools_ListOfShape& aLSDE=aMPKLE.ChangeFromIndex(i);
130     //
131     aMEE.Clear();
132     iErr=GEOMAlgo_Tools::FindSDShapes(aLSDE, aTol, aMEE, aCtx);
133     if (iErr) {
134       return iErr;
135     }
136     //
137     aNbEE=aMEE.Extent();
138     if (aNbEE==1) {
139       continue;  // nothing to do
140     }
141     //
142     for (j=1; j<=aNbEE; ++j) {
143       TopTools_ListOfShape& aLEE=aMEE.ChangeFromIndex(j);
144       //
145       if (j==1) {
146         aLSDE.Clear();
147         aLSDE.Append(aLEE);
148       }
149       else {
150         const TopoDS_Shape& aE1=aLEE.First();
151         aMEToAdd.Add(aE1, aLEE);
152       }
153     }
154   }
155   //
156   aNbToAdd=aMEToAdd.Extent();
157   if (!aNbToAdd) {
158     return aNbToAdd;
159   }
160   //
161   for (i=1; i<=aNbToAdd; ++i) {
162     GEOMAlgo_PassKeyShape aPKE1;
163     //
164     const TopoDS_Shape& aE1=aMEToAdd.FindKey(i);
165     const TopTools_ListOfShape& aLE=aMEToAdd(i);
166     //
167     //qf
168     //aPKE1.SetIds(aE1);
169     aPKE1.SetShapes(aE1);
170     //qt
171     aMPKLE.Add(aPKE1, aLE);
172   }
173   //
174   return 0;
175 }
176 //=======================================================================
177 //function : FindSDShapes
178 //purpose  :
179 //=======================================================================
180 Standard_Integer GEOMAlgo_Tools::FindSDShapes(const TopTools_ListOfShape& aLE,
181                                               const Standard_Real aTol,
182                                               TopTools_IndexedDataMapOfShapeListOfShape& aMEE,
183                                               IntTools_Context& aCtx)
184 {
185   Standard_Integer aNbE, aNbEProcessed, aNbESD, iErr;
186   TopTools_ListOfShape aLESD;
187   TopTools_ListIteratorOfListOfShape aIt, aIt1;
188   TopTools_IndexedMapOfShape aMProcessed;
189   TopAbs_ShapeEnum aType;
190   //
191   aNbE=aLE.Extent();
192   if (!aNbE) {
193     return 3; // Err
194   }
195   //modified by NIZNHY-PKV Thu Dec 30 10:56:52 2004 f
196   if (aNbE==1) {
197     return 0; // Nothing to do
198   }
199   //modified by NIZNHY-PKV Thu Dec 30 10:56:56 2004 t
200   //
201   while(1) {
202     aNbEProcessed=aMProcessed.Extent();
203     if (aNbEProcessed==aNbE) {
204       break;
205     }
206     //
207     aIt.Initialize(aLE);
208     for (; aIt.More(); aIt.Next()) {
209       const TopoDS_Shape& aS=aIt.Value();
210       //
211       if (aMProcessed.Contains(aS)) {
212         continue;
213       }
214       //
215       //modified by NIZNHY-PKV Thu Dec 30 10:57:01 2004 f
216       aType=aS.ShapeType();
217       if (aType==TopAbs_EDGE) {
218         const TopoDS_Edge& aE=TopoDS::Edge(aS);
219         if (BRep_Tool::Degenerated(aE)) {
220           aMProcessed.Add(aE);
221           continue;
222         }
223       }
224       //modified by NIZNHY-PKV Thu Dec 30 10:57:03 2004 t
225       //
226       aLESD.Clear();
227       iErr=GEOMAlgo_Tools::FindSDShapes(aS, aLE, aTol, aLESD, aCtx);
228       if (iErr) {
229         return 2; // Err
230       }
231       //
232       aNbESD=aLESD.Extent();
233       if (!aNbESD) {
234         return 1; // Err
235       }
236       //
237       aMEE.Add(aS, aLESD);
238       //
239       aIt1.Initialize(aLESD);
240       for (; aIt1.More(); aIt1.Next()) {
241         const TopoDS_Shape& aE1=aIt1.Value();
242         aMProcessed.Add(aE1);
243       }
244     }
245   }
246   return 0;
247 }
248 //=======================================================================
249 //function : FindSDShapes
250 //purpose  :
251 //=======================================================================
252 Standard_Integer GEOMAlgo_Tools::FindSDShapes(const TopoDS_Shape& aE1,
253                                               const TopTools_ListOfShape& aLE,
254                                               const Standard_Real aTol,
255                                               TopTools_ListOfShape& aLESD,
256                                               IntTools_Context& aCtx)
257 {
258   Standard_Boolean bIsDone;
259   Standard_Real aTol2, aD2;
260   gp_Pnt aP1, aP2;
261   TopTools_ListIteratorOfListOfShape aIt;
262   //
263   aTol2=aTol*aTol;
264   GEOMAlgo_Tools::PointOnShape(aE1, aP1);
265   //
266   aIt.Initialize(aLE);
267   for (; aIt.More(); aIt.Next()) {
268     const TopoDS_Shape& aE2=aIt.Value();
269     if (aE2.IsSame(aE1)) {
270        aLESD.Append(aE2);
271     }
272     else {
273       bIsDone=GEOMAlgo_Tools::ProjectPointOnShape(aP1, aE2, aP2, aCtx);
274       if (!bIsDone) {
275         //return 1;
276         continue; // jfa BUG 20361
277       }
278       aD2=aP1.SquareDistance(aP2);
279       if(aD2<aTol2) {
280         aLESD.Append(aE2);
281       }
282     }
283   }
284   return 0;
285 }
286
287 //=======================================================================
288 //function : ProjectPointOnShape
289 //purpose  :
290 //=======================================================================
291 Standard_Boolean GEOMAlgo_Tools::ProjectPointOnShape(const gp_Pnt& aP1,
292                                                      const TopoDS_Shape& aS,
293                                                      gp_Pnt& aP2,
294                                                      IntTools_Context& aCtx)
295 {
296   Standard_Boolean bIsDone = Standard_False;
297   Standard_Real aT2;
298   TopAbs_ShapeEnum aType;
299   //
300   aType = aS.ShapeType();
301   switch (aType)
302     {
303     case TopAbs_EDGE:
304       {
305         const TopoDS_Edge& aE2 = TopoDS::Edge(aS);
306         //
307         if (BRep_Tool::Degenerated(aE2)) { // jfa
308           return Standard_True;
309         }
310         else {
311           Standard_Real f, l;
312           Handle(Geom_Curve) aC3D = BRep_Tool::Curve (aE2, f, l);
313           if (aC3D.IsNull()) {
314             return Standard_True;
315           }
316           bIsDone = aCtx.ProjectPointOnEdge(aP1, aE2, aT2);
317         }
318         if (!bIsDone) {
319           return bIsDone;
320         }
321         //
322         GEOMAlgo_Tools::PointOnEdge(aE2, aT2, aP2);
323       }
324       break;
325       //
326     case TopAbs_FACE:
327       {
328         const TopoDS_Face& aF2 = TopoDS::Face(aS);
329         GeomAPI_ProjectPointOnSurf& aProj = aCtx.ProjPS(aF2);
330         //
331         aProj.Perform(aP1);
332         bIsDone = aProj.IsDone();
333         if (!bIsDone) {
334           return bIsDone;
335         }
336         //
337         aP2 = aProj.NearestPoint();
338       }
339       break;
340       //
341     default:
342       break; // Err
343     }
344   return bIsDone;
345 }
346 //=======================================================================
347 //function : PointOnShape
348 //purpose  :
349 //=======================================================================
350 void GEOMAlgo_Tools::PointOnShape(const TopoDS_Shape& aS,
351                                   gp_Pnt& aP3D)
352 {
353   TopAbs_ShapeEnum aType;
354   //
355   aP3D.SetCoord(99.,99.,99.);
356   aType=aS.ShapeType();
357   switch(aType) {
358     case TopAbs_EDGE: {
359       const TopoDS_Edge& aE=TopoDS::Edge(aS);
360       GEOMAlgo_Tools::PointOnEdge(aE, aP3D);
361       }
362       break;
363       //
364     case TopAbs_FACE: {
365       const TopoDS_Face& aF=TopoDS::Face(aS);
366       GEOMAlgo_Tools::PointOnFace(aF, aP3D);
367       }
368       break;
369       //
370     default:
371       break; // Err
372   }
373 }
374 //=======================================================================
375 //function : PointOnFace
376 //purpose  :
377 //=======================================================================
378 void GEOMAlgo_Tools::PointOnFace(const TopoDS_Face& aF,
379                                  gp_Pnt& aP3D)
380 {
381   Standard_Real aU, aV, aUMin, aUMax, aVMin, aVMax;
382   //
383   BRepTools::UVBounds(aF, aUMin, aUMax, aVMin, aVMax);
384   //
385   aU=BOPTools_Tools2D::IntermediatePoint(aUMin, aUMax);
386   aV=BOPTools_Tools2D::IntermediatePoint(aVMin, aVMax);
387   //
388   GEOMAlgo_Tools::PointOnFace(aF, aU, aV, aP3D);
389 }
390 //=======================================================================
391 //function : PointOnFace
392 //purpose  :
393 //=======================================================================
394 void GEOMAlgo_Tools::PointOnFace(const TopoDS_Face& aF,
395                                  const Standard_Real aU,
396                                  const Standard_Real aV,
397                                  gp_Pnt& aP3D)
398 {
399   Handle(Geom_Surface) aS;
400   //
401   aS=BRep_Tool::Surface(aF);
402   aS->D0(aU, aV, aP3D);
403 }
404 //=======================================================================
405 //function : PointOnEdge
406 //purpose  :
407 //=======================================================================
408 void GEOMAlgo_Tools::PointOnEdge(const TopoDS_Edge& aE,
409                                  gp_Pnt& aP3D)
410 {
411   Standard_Real aTx, aT1, aT2;
412   //
413   BRep_Tool::Curve(aE, aT1, aT2);
414   aTx=BOPTools_Tools2D::IntermediatePoint(aT1, aT2);
415   GEOMAlgo_Tools::PointOnEdge(aE, aTx, aP3D);
416 }
417 //=======================================================================
418 //function : PointOnEdge
419 //purpose  :
420 //=======================================================================
421 void GEOMAlgo_Tools::PointOnEdge(const TopoDS_Edge& aE,
422                                  const Standard_Real aT,
423                                  gp_Pnt& aP3D)
424 {
425   Standard_Real aT1, aT2;
426   Handle(Geom_Curve) aC3D;
427   //
428   aC3D=BRep_Tool::Curve(aE, aT1, aT2);
429   aC3D->D0(aT, aP3D);
430 }
431 //=======================================================================
432 //function : RefinePCurveForEdgeOnFace
433 //purpose  :
434 //=======================================================================
435 void GEOMAlgo_Tools::RefinePCurveForEdgeOnFace(const TopoDS_Edge& aE,
436                                                const TopoDS_Face& aF,
437                                                const Standard_Real aUMin,
438                                                const Standard_Real aUMax)
439 {
440   Standard_Real aT1, aT2, aTx, aUx, aTol;
441   gp_Pnt2d aP2D;
442   Handle(Geom_Surface) aS;
443   Handle(Geom2d_Curve) aC2D;
444   BRep_Builder aBB;
445   //
446   aC2D=BRep_Tool::CurveOnSurface(aE, aF, aT1, aT2);
447   if (!aC2D.IsNull()) {
448     if (BRep_Tool::IsClosed(aE, aF)) {
449       return;
450     }
451     aTx=BOPTools_Tools2D::IntermediatePoint(aT1, aT2);
452     aC2D->D0(aTx, aP2D);
453     aUx=aP2D.X();
454     if (aUx < aUMin || aUx > aUMax) {
455       // need to rebuild
456       Handle(Geom2d_Curve) aC2Dx;
457       //
458       aTol=BRep_Tool::Tolerance(aE);
459       aBB.UpdateEdge(aE, aC2Dx, aF, aTol);
460     }
461   }
462 }
463 //=======================================================================
464 //function : IsUPeriodic
465 //purpose  :
466 //=======================================================================
467 Standard_Boolean GEOMAlgo_Tools::IsUPeriodic(const  Handle(Geom_Surface) &aS)
468 {
469   Standard_Boolean bRet;
470   GeomAbs_SurfaceType aType;
471   GeomAdaptor_Surface aGAS;
472   //
473   aGAS.Load(aS);
474   aType=aGAS.GetType();
475   bRet=(aType==GeomAbs_Cylinder||
476         aType==GeomAbs_Cone ||
477         aType==GeomAbs_Sphere);
478   //
479   return bRet;
480 }
481
482 //modified by NIZNHY-PKV Fri Feb 03 11:16:35 2012f
483 //=======================================================================
484 //function : BuildPCurveForEdgeOnFace
485 //purpose  :
486 //=======================================================================
487 Standard_Integer
488   GEOMAlgo_Tools::BuildPCurveForEdgeOnFace(const TopoDS_Edge& aEold,
489                                            const TopoDS_Edge& aEnew,
490                                            const TopoDS_Face& aF,
491                                            IntTools_Context& aCtx)
492 {
493   Standard_Boolean bIsClosed, bUClosed, bHasOld;
494   Standard_Integer iRet, aNbPoints;
495   Standard_Real aTS, aTS1, aTS2, aT, aT1, aT2, aScPr, aTol;
496   Standard_Real aU, aV, aUS1, aVS1, aUS2, aVS2;
497   gp_Pnt aP;
498   gp_Pnt2d aP2DS1, aP2DS2, aP2D;
499   gp_Vec2d aV2DS1, aV2DS2;
500   Handle(Geom2d_Curve) aC2D, aC2DS1, aC2DS2;
501   Handle(Geom_Surface) aS;
502   TopoDS_Edge aES;
503   //
504   iRet=0;
505   //
506   bHasOld=BOPTools_Tools2D::HasCurveOnSurface(aEnew, aF, aC2D, aT1, aT2, aTol);
507   if (bHasOld) {
508     return iRet;
509   }
510   //
511   BOPTools_Tools2D::BuildPCurveForEdgeOnFace(aEnew, aF);
512   aC2D=BRep_Tool::CurveOnSurface(aEnew, aF, aT1, aT2);
513   if (aC2D.IsNull()){
514     iRet=1;
515     return iRet;
516   }
517   //
518   bIsClosed=BRep_Tool::IsClosed(aEold, aF);
519   if (!bIsClosed) {
520     return iRet;
521   }
522   //
523   aTol=1.e-7;
524   //
525   // 1. bUClosed - direction of closeness
526   //
527   aES=aEold;
528   aES.Orientation(TopAbs_FORWARD);
529   aC2DS1=BRep_Tool::CurveOnSurface(aES, aF, aTS1, aTS2);
530   //
531   aES.Orientation(TopAbs_REVERSED);
532   aC2DS2=BRep_Tool::CurveOnSurface(aES, aF, aTS1, aTS2);
533   //
534   aTS=BOPTools_Tools2D::IntermediatePoint(aTS1, aTS2);
535   //
536   aC2DS1->D1(aTS, aP2DS1, aV2DS1);
537   aC2DS2->D1(aTS, aP2DS2, aV2DS2);
538   //
539   gp_Vec2d aV2DS12(aP2DS1, aP2DS2);
540   gp_Dir2d aD2DS12(aV2DS12);
541   const gp_Dir2d& aD2DX=gp::DX2d();
542   //
543   aScPr=aD2DS12*aD2DX;
544   bUClosed=Standard_True;
545   if (fabs(aScPr) < aTol) {
546     bUClosed=!bUClosed;
547   }
548   //
549   // 2. aP2D - point on curve aC2D, that corresponds to aP2DS1
550   aP2DS1.Coord(aUS1, aVS1);
551   aP2DS2.Coord(aUS2, aVS2);
552   //
553   aS=BRep_Tool::Surface(aF);
554   aS->D0(aUS1, aVS1, aP);
555   //
556   GeomAPI_ProjectPointOnCurve& aProjPC=aCtx.ProjPC(aEnew);
557   //
558   aProjPC.Perform(aP);
559   aNbPoints=aProjPC.NbPoints();
560   if (!aNbPoints) {
561     iRet=2;
562     return iRet;
563   }
564   //
565   aT=aProjPC.LowerDistanceParameter();
566
567   //
568   // 3. Build the second 2D curve
569   Standard_Boolean bRevOrder;
570   gp_Vec2d aV2DT, aV2D;
571   Handle(Geom2d_Curve) aC2Dnew;
572   Handle(Geom2d_TrimmedCurve) aC2DTnew;
573   BRep_Builder aBB;
574   //
575   aC2D->D1(aT, aP2D, aV2D);
576   aP2D.Coord(aU, aV);
577   //
578   aC2Dnew=Handle(Geom2d_Curve)::DownCast(aC2D->Copy());
579   aC2DTnew = new Geom2d_TrimmedCurve(aC2Dnew, aT1, aT2);
580   //
581   aV2DT=aV2DS12;
582   if (!bUClosed) {    // V Closed
583     if (fabs(aV-aVS2)<aTol) {
584       aV2DT.Reverse();
585     }
586   }
587   else {   // U Closed
588     if (fabs(aU-aUS2)<aTol) {
589       aV2DT.Reverse();
590     }
591   }
592   //
593   aC2DTnew->Translate(aV2DT);
594   //
595   // 4 Order the 2D curves
596   bRevOrder=Standard_False;
597   aScPr=aV2D*aV2DS1;
598   if(aScPr<0.) {
599     bRevOrder=!bRevOrder;
600   }
601   //
602   // 5. Update the edge
603   aTol=BRep_Tool::Tolerance(aEnew);
604   if (!bRevOrder) {
605     aBB.UpdateEdge(aEnew, aC2D, aC2DTnew, aF, aTol);
606   }
607   else {
608     aBB.UpdateEdge(aEnew, aC2DTnew, aC2D , aF, aTol);
609   }
610   //
611   return iRet;
612 }