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