Salome HOME
Merge from BR_new_bop4 (porting to new OCCT BOP) 13/09/2013
[modules/geom.git] / src / GEOMAlgo / GEOMAlgo_FinderShapeOn.cxx
1 // Copyright (C) 2007-2013  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
23 // File:        GEOMAlgo_FinderShapeOn.cxx
24 // Created:     Tue Jan 11 14:44:31 2005
25 // Author:      Peter KURNEV
26
27 #include <GEOMAlgo_FinderShapeOn.hxx>
28
29 #include <Basics_OCCTVersion.hxx>
30
31 #if OCC_VERSION_LARGE > 0x06050100 // for OCC-6.5.2 and higher version
32 #include <Precision.hxx>
33 #endif
34
35 #include <gp_Pnt.hxx>
36
37 #include <TopAbs_ShapeEnum.hxx>
38 #include <TopAbs_Orientation.hxx>
39
40 #include <TopoDS.hxx>
41 #include <TopoDS_Face.hxx>
42 #include <TopoDS_Shape.hxx>
43 #include <TopoDS_Compound.hxx>
44 #include <TopoDS_Shell.hxx>
45 #include <TopoDS_Solid.hxx>
46 #include <TopoDS_Vertex.hxx>
47 #include <TopoDS_Edge.hxx>
48 #include <TopoDS_Iterator.hxx>
49
50 #include <TopTools_ListIteratorOfListOfShape.hxx>
51 #include <TopTools_IndexedMapOfShape.hxx>
52 #include <TopTools_DataMapOfShapeShape.hxx>
53
54 #include <Bnd_Box.hxx>
55 #include <BRepBndLib.hxx>
56 #include <BRepMesh_IncrementalMesh.hxx>
57
58 #include <BRep_Builder.hxx>
59 #include <BRep_Tool.hxx>
60
61 #include <TopExp.hxx>
62 #include <TopExp_Explorer.hxx>
63
64 #include <BRepLib_MakeFace.hxx>
65 #include <BRepLib_FaceError.hxx>
66
67 //#include <BOPTools_DSFiller.hxx>
68
69 #include <GEOMAlgo_WireSolid.hxx>
70 #include <GEOMAlgo_ShellSolid.hxx>
71 #include <GEOMAlgo_VertexSolid.hxx>
72 #include <GEOMAlgo_ShapeSolid.hxx>
73 #include <GEOMAlgo_SolidSolid.hxx>
74 #include <GEOMAlgo_SurfaceTools.hxx>
75 #include <GEOMAlgo_AlgoTools.hxx>
76
77 #include <BOPAlgo_PaveFiller.hxx>
78 #include <BOPCol_ListOfShape.hxx>
79
80 //=======================================================================
81 //function : GEOMAlgo_FinderShapeOn
82 //purpose  :
83 //=======================================================================
84 GEOMAlgo_FinderShapeOn::GEOMAlgo_FinderShapeOn()
85 :
86   GEOMAlgo_ShapeAlgo()
87 {
88   myTolerance=0.0001;
89   myShapeType=TopAbs_VERTEX;
90   myState=GEOMAlgo_ST_UNKNOWN;
91   myIsAnalytic=Standard_True;
92 }
93 //=======================================================================
94 //function : ~
95 //purpose  :
96 //=======================================================================
97 GEOMAlgo_FinderShapeOn::~GEOMAlgo_FinderShapeOn()
98 {
99 }
100 //=======================================================================
101 //function : SetSurface
102 //purpose  :
103 //=======================================================================
104 void GEOMAlgo_FinderShapeOn::SetSurface(const Handle(Geom_Surface)& aS)
105 {
106   mySurface=aS;
107 }
108 //=======================================================================
109 //function : Surface
110 //purpose  :
111 //=======================================================================
112 const Handle(Geom_Surface)& GEOMAlgo_FinderShapeOn::Surface() const
113 {
114   return mySurface;
115 }
116 //=======================================================================
117 //function : SetShapeType
118 //purpose  :
119 //=======================================================================
120 void GEOMAlgo_FinderShapeOn::SetShapeType(const TopAbs_ShapeEnum aType)
121 {
122   myShapeType=aType;
123 }
124 //=======================================================================
125 //function : ShapeType
126 //purpose  :
127 //=======================================================================
128 TopAbs_ShapeEnum GEOMAlgo_FinderShapeOn::ShapeType()const
129 {
130   return myShapeType;
131 }
132 //=======================================================================
133 //function : SetState
134 //purpose  :
135 //=======================================================================
136 void GEOMAlgo_FinderShapeOn::SetState(const GEOMAlgo_State aState)
137 {
138   myState=aState;
139 }
140 //=======================================================================
141 //function : State
142 //purpose  :
143 //=======================================================================
144 GEOMAlgo_State GEOMAlgo_FinderShapeOn::State() const
145 {
146   return myState;
147 }
148 //=======================================================================
149 // function: Shapes
150 // purpose:
151 //=======================================================================
152 const TopTools_ListOfShape& GEOMAlgo_FinderShapeOn::Shapes() const
153 {
154   Standard_Boolean bIsConformState;
155   Standard_Integer i, aNb;
156   TopAbs_State aSt;
157   TopTools_ListOfShape* pL;
158   //
159   pL=(TopTools_ListOfShape*) &myLS;
160   pL->Clear();
161   //
162   aNb=myMSS.Extent();
163   for (i=1; i<=aNb; ++i) {
164     const TopoDS_Shape& aS=myMSS.FindKey(i);
165     aSt=myMSS.FindFromIndex(i);
166     //
167     bIsConformState=GEOMAlgo_SurfaceTools::IsConformState(aSt, myState);
168     if (bIsConformState) {
169       pL->Append(aS);
170     }
171   }
172   return myLS;
173 }
174 //=======================================================================
175 //function : Perform
176 //purpose  :
177 //=======================================================================
178 void GEOMAlgo_FinderShapeOn::Perform()
179 {
180   myErrorStatus=0;
181   myWarningStatus=0;
182   myLS.Clear();
183   myMSS.Clear();
184   //
185   if (!myResult.IsNull()){
186     myResult.Nullify();
187   }
188   //
189   CheckData();
190   if(myErrorStatus) {
191     return;
192   }
193   //
194   // Initialize the context
195   GEOMAlgo_ShapeAlgo::Perform();
196   //
197   myIsAnalytic=GEOMAlgo_SurfaceTools::IsAnalytic(mySurface);
198   //
199   MakeArgument1();
200   if(myErrorStatus) {
201     return;
202   }
203   //
204   if (myIsAnalytic && myShapeType==TopAbs_VERTEX) {
205     FindVertices();
206     return;
207   }
208   //
209   MakeArgument2();
210   if(myErrorStatus) {
211     return;
212   }
213   //
214   Find();
215   if(myErrorStatus || myWarningStatus) {
216     return;
217   }
218   //
219 }
220 //=======================================================================
221 //function : FindVertices
222 //purpose  :
223 //=======================================================================
224 void GEOMAlgo_FinderShapeOn::FindVertices()
225 {
226   Standard_Integer i, aNb, iErr;
227   TopAbs_State aSt;
228   TopAbs_Orientation aOr;
229   gp_Pnt aP;
230   TopTools_IndexedMapOfShape aM;
231   //
232   TopExp::MapShapes(myArg1, TopAbs_FACE, aM);
233   const TopoDS_Face& aF=TopoDS::Face(aM(1));
234   aOr=aF.Orientation();
235   //
236   aM.Clear();
237   TopExp::MapShapes(myShape, myShapeType, aM);
238   aNb=aM.Extent();
239   if (!aNb) {
240     myWarningStatus=10; // No found sub-shapes of type myShapeType
241     return;
242   }
243   //
244   for (i=1; i<=aNb; ++i) {
245     const TopoDS_Shape& aS=aM(i);
246     const TopoDS_Vertex& aV=TopoDS::Vertex(aS);
247     aP=BRep_Tool::Pnt(aV);
248     iErr=GEOMAlgo_SurfaceTools::GetState(aP, mySurface, myTolerance, aSt);
249     if (aOr==TopAbs_REVERSED) {
250       aSt=GEOMAlgo_SurfaceTools::ReverseState(aSt);
251     }
252     myMSS.Add(aS, aSt);
253   }
254 }
255 //=======================================================================
256 //function : Find
257 //purpose  :
258 //=======================================================================
259 void GEOMAlgo_FinderShapeOn::Find()
260 {
261   Standard_Integer i, aNb;
262   Standard_Boolean bICS;
263   TopTools_IndexedMapOfShape aM;
264   //
265   TopExp::MapShapes(myArg2, myShapeType, aM);
266   //
267   aNb=aM.Extent();
268   if (!aNb) {
269     myWarningStatus=10; // No found sub-shapes of type myShapeType
270     return;
271   }
272   //
273   bICS=GEOMAlgo_AlgoTools::IsCompositeShape(myArg2);
274   if (!bICS || myIsAnalytic) {
275     TopoDS_Compound aCmp;
276     BRep_Builder aBB;
277     //
278     aBB.MakeCompound(aCmp);
279     for (i=1; i<=aNb; ++i) {
280       const TopoDS_Shape& aSi=aM(i);
281       aBB.Add(aCmp, aSi);
282     }
283     //
284     aM.Clear();
285     aM.Add(aCmp);
286     aNb=1;
287   }
288   //
289   for (i=1; i<=aNb; ++i) {
290     const TopoDS_Shape& aS=aM(i);
291     Find(aS);
292     if (myErrorStatus) {
293       return;
294     }
295   }
296 }
297 //=======================================================================
298 //function : Find
299 //purpose  :
300 //=======================================================================
301 void GEOMAlgo_FinderShapeOn::Find(const TopoDS_Shape& aS)
302 {
303   myErrorStatus=0;
304   //
305   Standard_Boolean bIsDone;
306   Standard_Integer i, iErr;
307   TopAbs_State aSts[]={TopAbs_IN, TopAbs_OUT, TopAbs_ON};
308   TopTools_ListIteratorOfListOfShape aIt;
309   BOPCol_ListOfShape aLS;
310   BOPAlgo_PaveFiller aPF;
311   //
312   // 1. Prepare DSFiller
313   aLS.Append(myArg1);
314   aLS.Append(aS);
315   aPF.SetArguments(aLS);
316   //
317   aPF.Perform();
318   iErr=aPF.ErrorStatus();
319   if (iErr) {
320     myErrorStatus=31; //  PaveFiller is failed
321     return;
322   }
323   //
324   // 2. Find shapes
325   GEOMAlgo_ShapeSolid* pSS;
326   GEOMAlgo_VertexSolid aVXS;
327   GEOMAlgo_WireSolid aWRS;
328   GEOMAlgo_ShellSolid aSHS;
329   GEOMAlgo_SolidSolid aSLS;
330   //
331   pSS=NULL;
332   //
333   switch (myShapeType) {
334     case TopAbs_VERTEX:
335       pSS=&aVXS;
336       break;
337     case TopAbs_EDGE:
338       pSS=&aWRS;
339       break;
340     case TopAbs_FACE:
341       pSS=&aSHS;
342       break;
343     case TopAbs_SOLID:
344       aSLS.SetShape2(myArg2);
345       pSS=&aSLS;
346       break;
347     default:
348       myErrorStatus=12; // unallowed sub-shape type
349       return;
350   }
351   //
352   pSS->SetFiller(aPF);
353   pSS->Perform();
354   iErr=pSS->ErrorStatus();
355   if (iErr) {
356     myErrorStatus=32; // builder ShapeSolid failed
357     return;
358   }
359   //
360   for (i=0; i<3; ++i) {
361     const TopTools_ListOfShape& aLS=pSS->Shapes(aSts[i]);
362     aIt.Initialize(aLS);
363     for (; aIt.More(); aIt.Next()) {
364       const TopoDS_Shape& aSImage=aIt.Value();
365       if (myImages.IsBound(aSImage)) {
366         const TopoDS_Shape& aSx=myImages.Find(aSImage);
367         myMSS.Add(aSx, aSts[i]);
368       }
369       else {
370         myErrorStatus=33;// can not find original shape
371         return;
372       }
373     }
374   }
375 }
376 //=======================================================================
377 //function : MakeArgument1
378 //purpose  :
379 //=======================================================================
380 void GEOMAlgo_FinderShapeOn::MakeArgument1()
381 {
382   myErrorStatus=0;
383   //
384   Standard_Integer i, aNb;
385   TopAbs_ShapeEnum aType;
386   BRepLib_FaceError aFErr;
387   BRepLib_MakeFace aMF;
388   TopTools_IndexedMapOfShape aM;
389   BRep_Builder aBB;
390   TopoDS_Face aFace;
391   TopoDS_Shell aSh;
392   TopoDS_Solid aSd;
393   //
394   // Argument 1
395   if (!myIsAnalytic) {
396 #if OCC_VERSION_LARGE > 0x06050100 // for OCC-6.5.2 and higher version
397     aMF.Init(mySurface, Standard_True, Precision::Confusion());
398 #else
399     aMF.Init(mySurface, Standard_True);
400 #endif
401
402     aFErr=aMF.Error();
403     if (aFErr!=BRepLib_FaceDone) {
404       myErrorStatus=20; // can not build the face
405       return;
406     }
407     //
408     const TopoDS_Shape& aF=aMF.Shape();
409     aFace=TopoDS::Face(aF);
410     //
411     // update tolerances
412     aM.Add(aF);
413     TopExp::MapShapes(aF, TopAbs_VERTEX, aM);
414     TopExp::MapShapes(aF, TopAbs_EDGE, aM);
415
416     aNb=aM.Extent();
417     for (i=1; i<=aNb; ++i) {
418       const TopoDS_Shape& aS=aM(i);
419       aType=aS.ShapeType();
420       switch (aType) {
421       case TopAbs_VERTEX: {
422         const TopoDS_Vertex& aVx=TopoDS::Vertex(aS);
423         aBB.UpdateVertex(aVx, myTolerance);
424       }
425         break;
426       case TopAbs_EDGE: {
427         const TopoDS_Edge& aEx=TopoDS::Edge(aS);
428         aBB.UpdateEdge(aEx, myTolerance);
429       }
430         break;
431       case TopAbs_FACE: {
432         const TopoDS_Face& aFx=TopoDS::Face(aS);
433         aBB.UpdateFace(aFx, myTolerance);
434       }
435         break;
436       default:
437         break;
438       }
439     }
440   } //
441   else {
442     aBB.MakeFace(aFace, mySurface, myTolerance);
443   }
444   //
445   // make solid
446   aBB.MakeShell(aSh);
447   aBB.Add(aSh, aFace);
448   aBB.MakeSolid(aSd);
449   aBB.Add(aSd, aSh);
450   myArg1=aSd;
451 }
452 //=======================================================================
453 //function : MakeArgument2
454 //purpose  :
455 //=======================================================================
456 void GEOMAlgo_FinderShapeOn::MakeArgument2()
457 {
458   myErrorStatus=0;
459   //
460   TopoDS_Shape aSC;
461   TopTools_DataMapOfShapeShape aOriginals;
462   //
463   myImages.Clear();
464   //
465   GEOMAlgo_FinderShapeOn::CopySource(myShape, myImages, aOriginals, aSC);
466   //
467   myArg2=aSC;
468 }
469 //=======================================================================
470 //function : CheckData
471 //purpose  :
472 //=======================================================================
473 void GEOMAlgo_FinderShapeOn::CheckData()
474 {
475   myErrorStatus=0;
476   //
477   if(mySurface.IsNull()) {
478     myErrorStatus=10; // mySurface=NULL
479     return;
480   }
481   //
482   if (myShape.IsNull()) {
483     myErrorStatus=11; // myShape=NULL
484     return;
485   }
486   //
487   if (!(myShapeType==TopAbs_VERTEX ||
488         myShapeType==TopAbs_EDGE ||
489         myShapeType==TopAbs_FACE ||
490         myShapeType==TopAbs_SOLID)) {
491     myErrorStatus=12; // unallowed sub-shape type
492     return;
493   }
494   //
495   if (myState==GEOMAlgo_ST_UNKNOWN ||
496       myState==GEOMAlgo_ST_INOUT) {
497     myErrorStatus=13; // unallowed state type
498     return;
499   }
500 }
501 //
502 //=======================================================================
503 //function : CopySource
504 //purpose  :
505 //=======================================================================
506 void GEOMAlgo_FinderShapeOn::CopySource(const TopoDS_Shape& aE,
507                                         TopTools_DataMapOfShapeShape& aImages,
508                                         TopTools_DataMapOfShapeShape& aOriginals,
509                                         TopoDS_Shape& aEx)
510 {
511   Standard_Boolean bFree;
512   TopAbs_ShapeEnum aType;
513   Standard_Integer aR;
514   BRep_Builder BB;
515   TopoDS_Iterator aIt;
516   //
517   aType=aE.ShapeType();
518   //
519   if (aOriginals.IsBound(aE)) {
520     aEx=aOriginals.ChangeFind(aE);
521     return;
522   }
523   else {
524     aEx=aE.EmptyCopied();
525     aOriginals.Bind(aE, aEx);
526     aImages.Bind(aEx, aE);
527   }
528   //
529   aR=(Standard_Integer)aType+1;
530   if (aR>TopAbs_VERTEX) {
531     return;
532   }
533   //
534   bFree=aEx.Free();
535   aEx.Free(Standard_True);
536   //
537   aType=(TopAbs_ShapeEnum) aR;
538   //
539   aIt.Initialize(aE);//, Standard_False);
540   for (; aIt.More();  aIt.Next()) {
541     const TopoDS_Shape& aV=aIt.Value();
542     TopoDS_Shape aVx;
543     //
544     CopySource (aV, aImages, aOriginals, aVx);
545     //
546     aVx.Orientation(aV.Orientation());
547     BB.Add(aEx, aVx);
548   }
549   //
550   aEx.Free(bFree);
551 }
552 //
553 //=======================================================================
554 //function : BuildTriangulation
555 //purpose  :
556 //=======================================================================
557 Standard_Boolean
558   GEOMAlgo_FinderShapeOn::BuildTriangulation (const TopoDS_Shape& theShape)
559 {
560   // calculate deflection
561   Standard_Real aDeviationCoefficient = 0.001;
562
563   Bnd_Box B;
564   BRepBndLib::Add(theShape, B);
565   Standard_Real aXmin, aYmin, aZmin, aXmax, aYmax, aZmax;
566   B.Get(aXmin, aYmin, aZmin, aXmax, aYmax, aZmax);
567
568   Standard_Real dx = aXmax - aXmin, dy = aYmax - aYmin, dz = aZmax - aZmin;
569   Standard_Real aDeflection = Max(Max(dx, dy), dz) * aDeviationCoefficient * 4;
570   Standard_Real aHLRAngle = 0.349066;
571
572   // build triangulation
573   BRepMesh_IncrementalMesh Inc (theShape, aDeflection, Standard_False, aHLRAngle);
574
575   // check triangulation
576   bool isTriangulation = true;
577
578   TopExp_Explorer exp (theShape, TopAbs_FACE);
579   if (exp.More())
580   {
581     TopLoc_Location aTopLoc;
582     Handle(Poly_Triangulation) aTRF;
583     aTRF = BRep_Tool::Triangulation(TopoDS::Face(exp.Current()), aTopLoc);
584     if (aTRF.IsNull()) {
585       isTriangulation = false;
586     }
587   }
588   else // no faces, try edges
589   {
590     TopExp_Explorer expe (theShape, TopAbs_EDGE);
591     if (!expe.More()) {
592       isTriangulation = false;
593     }
594     else {
595       TopLoc_Location aLoc;
596       Handle(Poly_Polygon3D) aPE = BRep_Tool::Polygon3D(TopoDS::Edge(expe.Current()), aLoc);
597       if (aPE.IsNull()) {
598         isTriangulation = false;
599       }
600     }
601   }
602
603   return isTriangulation;
604 }
605
606 //
607 // myErrorStatus :
608 //
609 // 10 -mySurface=NULL
610 // 11 -myShape=NULL
611 // 12 -unallowed type of sub-shapes
612 // 13 -unallowed state
613 // 20 -can not build the face
614 // 30 -wrong args are used for DSFiller
615 // 31 -DSFiller failed
616 // 32 -builder ShapeSolid failed
617 // 33 -can not find original shape
618 //
619 // myWarningStatus
620 //
621 // 10 - sub-shapes of type myShapeType can not be fond in myShape