Salome HOME
PAL7508: Development of GetInPlace() functionality
[modules/geom.git] / src / NMTAlgo / NMTAlgo_Splitter.cxx
1 // File:        NMTAlgo_Splitter.cxx
2 // Created:     Thu Jan 29 17:13:03 2004
3 // Author:      Peter KURNEV
4 //              <pkv@irinox>
5
6
7 #include <NMTAlgo_Splitter.ixx>
8
9 #include <Precision.hxx>
10 #include <TopAbs_Orientation.hxx>
11 #include <TopExp.hxx>
12 #include <TopExp_Explorer.hxx>
13
14 #include <TopTools_DataMapIteratorOfDataMapOfShapeListOfShape.hxx>
15 #include <TopTools_DataMapOfShapeListOfShape.hxx>
16 #include <TopTools_IndexedDataMapOfShapeListOfShape.hxx>
17 #include <TopTools_IndexedMapOfShape.hxx>
18 #include <TopTools_ListIteratorOfListOfShape.hxx>
19 #include <TopTools_ListOfShape.hxx>
20 #include <TopTools_MapIteratorOfMapOfShape.hxx>
21 #include <TopTools_SequenceOfShape.hxx>
22
23 #include <Geom2d_Curve.hxx>
24 #include <Geom_Curve.hxx>
25 #include <Geom_Surface.hxx>
26 #include <Geom_TrimmedCurve.hxx>
27 #include <gp_Pnt.hxx>
28 #include <gp_Pnt2d.hxx>
29 #include <gp_Vec.hxx>
30
31 #include <TopoDS.hxx>
32 #include <TopoDS_Compound.hxx>
33 #include <TopoDS_Edge.hxx>
34 #include <TopoDS_Face.hxx>
35 #include <TopoDS_Iterator.hxx>
36 #include <TopoDS_Shell.hxx>
37 #include <TopoDS_Solid.hxx>
38 #include <TopoDS_Vertex.hxx>
39 #include <TopoDS_Wire.hxx>
40
41 #include <BRepBndLib.hxx>
42 #include <BRepClass3d_SolidClassifier.hxx>
43 #include <BRepLib.hxx>
44 #include <BRep_Tool.hxx>
45
46 #include <Extrema_ExtPC.hxx>
47 #include <GeomAdaptor_Curve.hxx>
48 #include <TopOpeBRepTool_CurveTool.hxx>
49 //
50 #include <NMTTools_DSFiller.hxx>
51 #include <NMTAlgo_Tools.hxx>
52 #include <NMTAlgo_Loop3d.hxx>
53 #include <BOP_CorrectTolerances.hxx>
54
55
56 static 
57   Standard_Boolean isClosed(const TopoDS_Shape& theShape);
58
59 //=======================================================================
60 //function : NMTAlgo_Spliter::NMTAlgo_Splitter
61 //purpose  : 
62 //=======================================================================
63   NMTAlgo_Splitter::NMTAlgo_Splitter()
64 :
65   NMTAlgo_Builder()
66 {
67   myErrorStatus=0;
68 }
69 //=======================================================================
70 // function: ~NMTAlgo_Splitter
71 // purpose: 
72 //=======================================================================
73   NMTAlgo_Splitter::~NMTAlgo_Splitter()
74 {
75   Clear();
76   
77   if (myDSFiller){
78     delete myDSFiller;
79   }
80 }
81 //=======================================================================
82 // function: SourceShapes
83 // purpose: 
84 //=======================================================================
85   const TopTools_ListOfShape& NMTAlgo_Splitter::SourceShapes()const
86 {
87   return mySourceShapes;
88 }
89 //=======================================================================
90 //function : Clear
91 //purpose  : 
92 //=======================================================================
93   void NMTAlgo_Splitter::Clear()
94 {
95   NMTAlgo_Builder::Clear();
96   //
97   myListShapes.Clear();
98   myMapFaces.Clear();
99   myMapTools.Clear();
100   myClosedShapes.Clear();
101   myEqualEdges.Clear();
102   myNewSection.Clear();
103   myWrappingSolid.Clear();
104   myFaceShapeMap.Clear();
105   myInternalFaces.Clear();
106   myIntNotClFaces.Clear();
107   //
108   myImageShape.Clear();
109   myAddedFacesMap.Clear();
110   //
111   myDoneStep = TopAbs_SHAPE;
112   myIsComputed=Standard_False;
113   mySourceShapes.Clear();
114   myObjShapes.Clear();
115   myToolShapes.Clear();
116   myMapSIFC.Clear();
117   //modified by NIZNHY-PKV Mon Jan 24 09:47:37 2005f
118   myModifiedFaces.Clear();
119   //modified by NIZNHY-PKV Mon Jan 24 09:47:41 2005t
120   myErrorStatus=0;
121 }
122 //=======================================================================
123 //function : AddShape
124 //purpose  : add object Shape to be splited
125 //=======================================================================
126   void NMTAlgo_Splitter::AddShape(const TopoDS_Shape& aS)
127 {
128   myErrorStatus=0;
129   if (myIsComputed) {
130     // DS is already computed
131     myErrorStatus=100;
132     return;
133   }
134   //
135   if (aS.IsNull()){
136     // Null shape is not allowed here
137     myErrorStatus=101;
138     return;
139   }
140   //
141   TopAbs_ShapeEnum aType=aS.ShapeType(); 
142   //
143   if (aType < TopAbs_SOLID) { 
144     // compound or compsolid
145     TopoDS_Iterator it (aS);
146     for (; it.More(); it.Next()) {
147       const TopoDS_Shape& aSS=it.Value();
148       AddShape(aSS);
149       // to know compound by shape
150       myFaceShapeMap.Bind(aSS, aS); 
151     }
152     return;
153   }
154   //---
155   myObjShapes.Add(aS);
156   mySourceShapes.Append(aS);  
157   //---
158   //
159   TopExp_Explorer exp(aS, TopAbs_FACE);
160   if (!exp.More()) { 
161     // do not split edges and vertices
162     return;
163   }
164   // not to add twice the same S
165   Standard_Integer nbFacesBefore = myMapFaces.Extent(); 
166   //
167   for (; exp.More(); exp.Next()) {
168     const TopoDS_Shape& aFace = exp.Current();
169     if (!myFaceShapeMap.IsBound(aFace)) {
170       // keep shape of tool face added as object
171       myFaceShapeMap.Bind(aFace, aS);
172     }
173     if (myMapFaces.Add(aFace)){
174       myImagesFaces.SetRoot(aFace);
175     }
176   }
177   //
178   if (nbFacesBefore == myMapFaces.Extent()){
179     return;
180   }
181   // solids must be processed before all
182   if (aType==TopAbs_SOLID){
183     myListShapes.Prepend(aS);
184   }
185   else{
186     myListShapes.Append(aS);
187   }
188   if (isClosed(aS)){
189     myClosedShapes.Add(aS);
190   }
191 }
192 //=======================================================================
193 //function : AddTool
194 //purpose  : add cutting tool that will _NOT_ be in result
195 //=======================================================================
196   void NMTAlgo_Splitter::AddTool(const TopoDS_Shape& aS)
197 {
198   myErrorStatus=0;
199   if (myIsComputed) {
200     // DS is already computed
201     myErrorStatus=100;
202     return;
203   }
204   //
205   if (aS.IsNull()){
206     // Null shape is not allowed here
207     myErrorStatus=101;
208     return;
209   }
210   //
211   TopAbs_ShapeEnum aType=aS.ShapeType(); 
212   
213   if (aType < TopAbs_SOLID) { // compound or compsolid
214     TopoDS_Iterator it (aS);
215     for (; it.More(); it.Next()) {
216       const TopoDS_Shape& aSS=it.Value();
217       AddTool(aSS);
218       myFaceShapeMap.Bind(aSS, aS); // to know compound by shape
219     }
220     return;
221   }
222   //---
223   myToolShapes.Add(aS);
224   mySourceShapes.Append(aS);  
225   //---
226   //
227   TopExp_Explorer exp(aS, TopAbs_FACE);
228   for (; exp.More(); exp.Next()) {
229     const TopoDS_Shape& aFace = exp.Current();
230     myMapTools.Add(aFace);
231     myFaceShapeMap.Bind(aFace, aS);
232   }
233   //
234   // solids must be processed before all
235   if (aType==TopAbs_SOLID){
236     myListShapes.Prepend(aS);
237   }
238   else{
239     myListShapes.Append(aS);
240   }
241   //
242   if (isClosed(aS)) { 
243     myClosedShapes.Add(aS);
244   }
245 }
246 //=======================================================================
247 // function: Compute
248 // purpose: 
249 //=======================================================================
250   void NMTAlgo_Splitter::Compute()
251 {
252   if (!mySourceShapes.Extent()){
253     // No source shapes to treat
254     myErrorStatus=103; 
255     return;
256   }
257   //
258   BRep_Builder aBB;
259   TopoDS_Compound aCS;
260   TopTools_ListIteratorOfListOfShape aIt;
261   //
262   aBB.MakeCompound(aCS);
263   //
264   aIt.Initialize(mySourceShapes);
265   for (; aIt.More(); aIt.Next()) {
266     const TopoDS_Shape& aS=aIt.Value();
267     aBB.Add(aCS, aS);
268   }
269   //
270   NMTTools_DSFiller* pDSF=new NMTTools_DSFiller;
271   //
272   pDSF->SetCompositeShape(aCS);
273   pDSF->Perform();
274   //
275   myIsComputed=Standard_False;
276   //
277   NMTAlgo_Splitter::ComputeWithFiller(*pDSF);
278 }
279 //=======================================================================
280 // function: ComputeWithFiller
281 // purpose: 
282 //=======================================================================
283   void NMTAlgo_Splitter::ComputeWithFiller(const NMTTools_DSFiller& aDSF)
284 {
285   myErrorStatus=0;
286   //
287   if (myIsComputed) {
288     // DS is already computed
289     myErrorStatus=100; 
290     return;
291   }
292   //
293   if (!mySourceShapes.Extent()){
294     // No source shapes to treat
295     myErrorStatus=103; 
296     return;
297   }
298   //
299   NMTAlgo_Builder::ComputeWithFiller(aDSF);
300   //
301   myIsComputed=Standard_True;
302 }
303 //=======================================================================
304 //function : Build
305 //purpose  :
306 //=======================================================================
307   void NMTAlgo_Splitter::Build(const TopAbs_ShapeEnum aLimit)
308 {
309   myErrorStatus=0;
310   myLimit=aLimit;
311   //
312   if (!myIsComputed){
313     myErrorStatus=102;// DS is not computed
314     return;
315   }
316   //
317   TopoDS_Compound aCShape;
318   //
319   myBuilder.MakeCompound(aCShape);
320   myShape=aCShape;
321   //
322   // 1. VERTEX
323   //
324   if (myLimit==TopAbs_VERTEX) {
325     SplitVertices();
326     FillResult();
327     return;
328   }
329   //
330   // 2. EDGE
331   if (myLimit==TopAbs_EDGE) {
332     SplitsAndSections();
333     FillResult();
334     return;
335   }
336   //
337   // 3. WIRE
338   FillImageShape();
339   //
340   if (myLimit==TopAbs_WIRE) {
341     SplittedWires();
342     FillResult();
343     return;
344   }
345   //
346   // 4. FACE
347   //
348   if (myLimit==TopAbs_FACE) {
349     SplittedFaces();
350     FillResult();
351     return;
352   }
353   //
354   // 5.6. SHELL / SOLID
355   ShellsAndSolids();
356   BOP_CorrectTolerances::CorrectTolerances(myShape, 0.01);
357 }
358 //=======================================================================
359 // function: SplitsAndSections
360 // purpose: 
361 //=======================================================================
362   void NMTAlgo_Splitter::SplitsAndSections()
363 {
364   Standard_Integer i, aNbE, aNbF;
365   TopTools_ListIteratorOfListOfShape aItLS, aIt;
366   TopTools_IndexedMapOfShape aME, aMF;
367   //
368   myQueryShapes.Clear();
369   //
370   //  1. Splits / no splits
371   aItLS.Initialize(myListShapes);
372   for ( ;aItLS.More(); aItLS.Next()) {
373     const TopoDS_Shape& aS=aItLS.Value();
374     //
375     if (myToolShapes.Contains(aS)) {
376       continue; // skip tool Shapes
377     }
378     //
379     TopExp::MapShapes(aS, TopAbs_EDGE, aME);
380     TopExp::MapShapes(aS, TopAbs_FACE, aMF);
381   }    
382   //
383   //  1. Splits / no splits
384   aNbE=aME.Extent();
385   for (i=1; i<=aNbE; ++i) {
386     const TopoDS_Shape& aE=aME(i);
387     //
388     if (!myImagesEdges.HasImage(aE)) {
389       myQueryShapes.Add(aE);
390     }
391     else {
392       const TopTools_ListOfShape& aLSp=myImagesEdges.Image(aE);
393       //
394       aIt.Initialize(aLSp);
395       for (; aIt.More(); aIt.Next()) { 
396         const TopoDS_Shape& aSp=aIt.Value();
397         myQueryShapes.Add(aSp);
398       }
399     }
400   }
401   //
402   // 2. Sections
403   aNbF=aMF.Extent();
404   for (i=1; i<=aNbF; ++i) {
405     const TopoDS_Shape& aF=aMF(i);
406     if (mySectionParts.Contains(aF)) {
407       const TopTools_ListOfShape& aLSc=mySectionParts.FindFromKey(aF);
408       aIt.Initialize(aLSc);
409       for (; aIt.More(); aIt.Next()) { 
410         const TopoDS_Shape& aSc=aIt.Value();
411         myQueryShapes.Add(aSc);
412       }
413     }
414   }
415 }
416 //=======================================================================
417 // function: SplittedWires
418 // purpose: 
419 //=======================================================================
420   void NMTAlgo_Splitter::SplittedWires()
421 {
422   Standard_Integer i, aNbF;
423   TopoDS_Iterator aIt;
424   TopTools_IndexedMapOfShape aMF;
425   //
426   SplittedFaces();
427   //
428   aMF=myQueryShapes;
429   myQueryShapes.Clear();
430   //
431   aNbF=aMF.Extent();
432   for (i=1; i<=aNbF; ++i) {
433     const TopoDS_Shape& aF=aMF(i);
434     aIt.Initialize(aF);
435     for (; aIt.More(); aIt.Next()) {
436       const TopoDS_Shape& aW=aIt.Value();
437       myQueryShapes.Add(aW);
438     }
439   }
440 }
441 //=======================================================================
442 // function: SplittedFaces
443 // purpose: 
444 //=======================================================================
445   void NMTAlgo_Splitter::SplittedFaces()
446 {
447   TopTools_ListIteratorOfListOfShape aIt;
448   TopoDS_Iterator aItF;
449   //
450   myQueryShapes.Clear();
451   //
452   aIt.Initialize(myListShapes);
453   for (; aIt.More(); aIt.Next()) {
454     const TopoDS_Shape& aS=aIt.Value();
455     //
456     if (myToolShapes.Contains(aS)) {
457       continue;
458     }
459     //
460     const TopoDS_Shape& aFC = myImageShape.Image(aS).First();
461     aItF.Initialize(aFC);
462     for (; aItF.More(); aItF.Next()) {
463       const TopoDS_Shape& aF=aItF.Value();
464       myQueryShapes.Add(aF);
465     }
466   }
467 }
468 //=======================================================================
469 //function : FillImageShape
470 //purpose  :
471 //=======================================================================
472   void NMTAlgo_Splitter::FillImageShape()
473 {
474   Standard_Integer i, aNbF, iSense;
475   TopTools_ListIteratorOfListOfShape aItS, aItFI;
476   TopExp_Explorer aExp;
477   TopAbs_Orientation aOriFS; 
478   TopoDS_Face aFIx, aFIy;
479   BRep_Builder aBB;
480   //
481   myImageShape.Clear();
482   //modified by NIZNHY-PKV Mon Jan 24 09:48:15 2005f
483   myModifiedFaces.Clear();
484   //modified by NIZNHY-PKV Mon Jan 24 09:48:18 2005t
485   //
486   aItS.Initialize(myListShapes);
487   for ( ;aItS.More(); aItS.Next()) {
488     const TopoDS_Shape& aS=aItS.Value();
489     //
490     myQueryShapes.Clear();
491     //
492     aExp.Init(aS, TopAbs_FACE);
493     for (; aExp.More(); aExp.Next()) {
494       const TopoDS_Face& aFS=TopoDS::Face(aExp.Current());
495       aOriFS= aFS.Orientation();
496       //
497       if (!myImagesFaces.HasImage(aFS)) {
498         myQueryShapes.Add(aFS);
499         //modified by NIZNHY-PKV Mon Jan 24 09:50:42 2005 f
500         if (!myModifiedFaces.IsBound(aFS)) {
501           TopTools_ListOfShape aLS;
502           //
503           aLS.Append(aFS);
504           myModifiedFaces.Bind(aFS, aLS);
505         }
506         //modified by NIZNHY-PKV Mon Jan 24 09:50:44 2005 t
507         continue;
508       }
509       //
510       const TopTools_ListOfShape& aLFI=myImagesFaces.Image(aFS);
511       aItFI.Initialize(aLFI);
512       for (; aItFI.More(); aItFI.Next()) {
513         const TopoDS_Face& aFI=TopoDS::Face(aItFI.Value());
514         aFIx=aFI;
515         aFIx.Orientation(aOriFS);
516         //
517         if (mySDFaces.Contains(aFIx)) {
518           const TopoDS_Face& aFSDI=TopoDS::Face(mySDFaces.FindFromKey(aFIx));
519           TopoDS_Face aFSDIx=aFSDI;
520           //
521           iSense=NMTAlgo_Tools::Sense(aFIx, aFSDIx);
522           //
523           if (iSense < 0) {
524             aFSDIx.Reverse();
525           }
526           myQueryShapes.Add(aFSDIx);
527           //modified by NIZNHY-PKV Mon Jan 24 09:56:06 2005f
528           aFIy=aFSDIx;
529           //modified by NIZNHY-PKV Mon Jan 24 09:56:09 2005t
530         }
531         else {
532           myQueryShapes.Add(aFIx);
533           //modified by NIZNHY-PKV Mon Jan 24 09:56:06 2005f
534           aFIy=aFIx;
535           //modified by NIZNHY-PKV Mon Jan 24 09:56:09 2005t
536         }
537         //modified by NIZNHY-PKV Mon Jan 24 09:53:38 2005f
538         if (!myModifiedFaces.IsBound(aFS)) {
539           TopTools_ListOfShape aLS;
540           //
541           aLS.Append(aFIy);
542           myModifiedFaces.Bind(aFS, aLS);
543         }
544         else {
545           TopTools_ListOfShape& aLS=myModifiedFaces.ChangeFind(aFS);
546           aLS.Append(aFIy);
547         }
548         //modified by NIZNHY-PKV Mon Jan 24 09:53:43 2005t
549       }
550     }//for (; aExp.More(); aExp.Next()) {
551     //
552     TopoDS_Compound aCompound;
553     //
554     aBB.MakeCompound(aCompound);
555     //
556     aNbF=myQueryShapes.Extent();
557     for (i=1; i<=aNbF; ++i) {
558       const TopoDS_Shape& aF=myQueryShapes(i);
559       aBB.Add(aCompound, aF);
560     }
561     //
562     myImageShape.Bind(aS, aCompound);
563   }// for ( ;aItS.More(); aItS.Next())
564   //
565   myQueryShapes.Clear();
566 }
567 //=======================================================================
568 //function : FillResult
569 //purpose  :
570 //=======================================================================
571   void NMTAlgo_Splitter::FillResult()
572 {
573   Standard_Integer i, aNb;
574   //
575   aNb=myQueryShapes.Extent();
576   for (i=1; i<=aNb; ++i) {
577     const TopoDS_Shape& aS=myQueryShapes(i); 
578     myBuilder.Add (myShape, aS);
579   }
580   BOP_CorrectTolerances::CorrectTolerances(myShape, 0.01);
581 }
582 //=======================================================================
583 //function : isClosed
584 //purpose  : check id a shape is closed, ie is a solid or a closed shell
585 //=======================================================================
586  Standard_Boolean isClosed(const TopoDS_Shape& theShape)
587 {
588   Standard_Boolean isClosed = (theShape.ShapeType() == TopAbs_SOLID);
589   //
590   if (!isClosed && theShape.ShapeType() == TopAbs_SHELL) {
591     TopTools_IndexedDataMapOfShapeListOfShape MEF;
592     TopExp::MapShapesAndAncestors(theShape, TopAbs_EDGE, TopAbs_FACE, MEF);
593     for (Standard_Integer i=1;  isClosed && i<=MEF.Extent();  ++i)
594       isClosed = ( MEF(i).Extent() != 1 );
595   }
596   //
597   return isClosed;
598 }
599 //
600 //  myErrorStatus     
601 //
602 // 100 - DS is already computed
603 // 101 - Null shape is not allowed here
604 // 102 - DS is not computed
605 // 103 - No source shapes to treat