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