Salome HOME
Update mail address
[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   NMTAlgo_Builder::ComputeWithFiller(aDSF);
319   //
320   myIsComputed=Standard_True;
321 }
322 //=======================================================================
323 //function : Build
324 //purpose  :
325 //=======================================================================
326   void NMTAlgo_Splitter::Build(const TopAbs_ShapeEnum aLimit)
327 {
328   myErrorStatus=0;
329   myLimit=aLimit;
330   //
331   if (!myIsComputed){
332     myErrorStatus=102;// DS is not computed
333     return;
334   }
335   //
336   TopoDS_Compound aCShape;
337   //
338   myBuilder.MakeCompound(aCShape);
339   myShape=aCShape;
340   //
341   // 1. VERTEX
342   //
343   if (myLimit==TopAbs_VERTEX) {
344     SplitVertices();
345     FillResult();
346     return;
347   }
348   //
349   // 2. EDGE
350   if (myLimit==TopAbs_EDGE) {
351     SplitsAndSections();
352     FillResult();
353     return;
354   }
355   //
356   // 3. WIRE
357   FillImageShape();
358   //
359   if (myLimit==TopAbs_WIRE) {
360     SplittedWires();
361     FillResult();
362     return;
363   }
364   //
365   // 4. FACE
366   //
367   if (myLimit==TopAbs_FACE) {
368     SplittedFaces();
369     FillResult();
370     return;
371   }
372   //
373   // 5.6. SHELL / SOLID
374   ShellsAndSolids();
375   BOP_CorrectTolerances::CorrectTolerances(myShape, 0.01);
376 }
377 //=======================================================================
378 // function: SplitsAndSections
379 // purpose: 
380 //=======================================================================
381   void NMTAlgo_Splitter::SplitsAndSections()
382 {
383   Standard_Integer i, aNbE, aNbF;
384   TopTools_ListIteratorOfListOfShape aItLS, aIt;
385   TopTools_IndexedMapOfShape aME, aMF;
386   //
387   myQueryShapes.Clear();
388   //
389   //  1. Splits / no splits
390   aItLS.Initialize(myListShapes);
391   for ( ;aItLS.More(); aItLS.Next()) {
392     const TopoDS_Shape& aS=aItLS.Value();
393     //
394     if (myToolShapes.Contains(aS)) {
395       continue; // skip tool Shapes
396     }
397     //
398     TopExp::MapShapes(aS, TopAbs_EDGE, aME);
399     TopExp::MapShapes(aS, TopAbs_FACE, aMF);
400   }    
401   //
402   //  1. Splits / no splits
403   aNbE=aME.Extent();
404   for (i=1; i<=aNbE; ++i) {
405     const TopoDS_Shape& aE=aME(i);
406     //
407     if (!myImagesEdges.HasImage(aE)) {
408       myQueryShapes.Add(aE);
409     }
410     else {
411       const TopTools_ListOfShape& aLSp=myImagesEdges.Image(aE);
412       //
413       aIt.Initialize(aLSp);
414       for (; aIt.More(); aIt.Next()) { 
415         const TopoDS_Shape& aSp=aIt.Value();
416         myQueryShapes.Add(aSp);
417       }
418     }
419   }
420   //
421   // 2. Sections
422   aNbF=aMF.Extent();
423   for (i=1; i<=aNbF; ++i) {
424     const TopoDS_Shape& aF=aMF(i);
425     if (mySectionParts.Contains(aF)) {
426       const TopTools_ListOfShape& aLSc=mySectionParts.FindFromKey(aF);
427       aIt.Initialize(aLSc);
428       for (; aIt.More(); aIt.Next()) { 
429         const TopoDS_Shape& aSc=aIt.Value();
430         myQueryShapes.Add(aSc);
431       }
432     }
433   }
434 }
435 //=======================================================================
436 // function: SplittedWires
437 // purpose: 
438 //=======================================================================
439   void NMTAlgo_Splitter::SplittedWires()
440 {
441   Standard_Integer i, aNbF;
442   TopoDS_Iterator aIt;
443   TopTools_IndexedMapOfShape aMF;
444   //
445   SplittedFaces();
446   //
447   aMF=myQueryShapes;
448   myQueryShapes.Clear();
449   //
450   aNbF=aMF.Extent();
451   for (i=1; i<=aNbF; ++i) {
452     const TopoDS_Shape& aF=aMF(i);
453     aIt.Initialize(aF);
454     for (; aIt.More(); aIt.Next()) {
455       const TopoDS_Shape& aW=aIt.Value();
456       myQueryShapes.Add(aW);
457     }
458   }
459 }
460 //=======================================================================
461 // function: SplittedFaces
462 // purpose: 
463 //=======================================================================
464   void NMTAlgo_Splitter::SplittedFaces()
465 {
466   TopTools_ListIteratorOfListOfShape aIt;
467   TopoDS_Iterator aItF;
468   //
469   myQueryShapes.Clear();
470   //
471   aIt.Initialize(myListShapes);
472   for (; aIt.More(); aIt.Next()) {
473     const TopoDS_Shape& aS=aIt.Value();
474     //
475     if (myToolShapes.Contains(aS)) {
476       continue;
477     }
478     //
479     const TopoDS_Shape& aFC = myImageShape.Image(aS).First();
480     aItF.Initialize(aFC);
481     for (; aItF.More(); aItF.Next()) {
482       const TopoDS_Shape& aF=aItF.Value();
483       myQueryShapes.Add(aF);
484     }
485   }
486 }
487 //=======================================================================
488 //function : FillImageShape
489 //purpose  :
490 //=======================================================================
491   void NMTAlgo_Splitter::FillImageShape()
492 {
493   Standard_Integer i, aNbF, iSense;
494   TopTools_ListIteratorOfListOfShape aItS, aItFI;
495   TopExp_Explorer aExp;
496   TopAbs_Orientation aOriFS; 
497   TopoDS_Face aFIx, aFIy;
498   BRep_Builder aBB;
499   //
500   myImageShape.Clear();
501   //modified by NIZNHY-PKV Mon Jan 24 09:48:15 2005f
502   myModifiedFaces.Clear();
503   //modified by NIZNHY-PKV Mon Jan 24 09:48:18 2005t
504   //
505   aItS.Initialize(myListShapes);
506   for ( ;aItS.More(); aItS.Next()) {
507     const TopoDS_Shape& aS=aItS.Value();
508     //
509     myQueryShapes.Clear();
510     //
511     aExp.Init(aS, TopAbs_FACE);
512     for (; aExp.More(); aExp.Next()) {
513       const TopoDS_Face& aFS=TopoDS::Face(aExp.Current());
514       aOriFS= aFS.Orientation();
515       //
516       if (!myImagesFaces.HasImage(aFS)) {
517         myQueryShapes.Add(aFS);
518         //modified by NIZNHY-PKV Mon Jan 24 09:50:42 2005 f
519         if (!myModifiedFaces.IsBound(aFS)) {
520           TopTools_ListOfShape aLS;
521           //
522           aLS.Append(aFS);
523           myModifiedFaces.Bind(aFS, aLS);
524         }
525         //modified by NIZNHY-PKV Mon Jan 24 09:50:44 2005 t
526         continue;
527       }
528       //
529       const TopTools_ListOfShape& aLFI=myImagesFaces.Image(aFS);
530       aItFI.Initialize(aLFI);
531       for (; aItFI.More(); aItFI.Next()) {
532         const TopoDS_Face& aFI=TopoDS::Face(aItFI.Value());
533         aFIx=aFI;
534         aFIx.Orientation(aOriFS);
535         //
536         if (mySDFaces.Contains(aFIx)) {
537           const TopoDS_Face& aFSDI=TopoDS::Face(mySDFaces.FindFromKey(aFIx));
538           TopoDS_Face aFSDIx=aFSDI;
539           //
540           iSense=NMTAlgo_Tools::Sense(aFIx, aFSDIx);
541           //
542           if (iSense < 0) {
543             aFSDIx.Reverse();
544           }
545           myQueryShapes.Add(aFSDIx);
546           //modified by NIZNHY-PKV Mon Jan 24 09:56:06 2005f
547           aFIy=aFSDIx;
548           //modified by NIZNHY-PKV Mon Jan 24 09:56:09 2005t
549         }
550         else {
551           myQueryShapes.Add(aFIx);
552           //modified by NIZNHY-PKV Mon Jan 24 09:56:06 2005f
553           aFIy=aFIx;
554           //modified by NIZNHY-PKV Mon Jan 24 09:56:09 2005t
555         }
556         //modified by NIZNHY-PKV Mon Jan 24 09:53:38 2005f
557         if (!myModifiedFaces.IsBound(aFS)) {
558           TopTools_ListOfShape aLS;
559           //
560           aLS.Append(aFIy);
561           myModifiedFaces.Bind(aFS, aLS);
562         }
563         else {
564           TopTools_ListOfShape& aLS=myModifiedFaces.ChangeFind(aFS);
565           aLS.Append(aFIy);
566         }
567         //modified by NIZNHY-PKV Mon Jan 24 09:53:43 2005t
568       }
569     }//for (; aExp.More(); aExp.Next()) {
570     //
571     TopoDS_Compound aCompound;
572     //
573     aBB.MakeCompound(aCompound);
574     //
575     aNbF=myQueryShapes.Extent();
576     for (i=1; i<=aNbF; ++i) {
577       const TopoDS_Shape& aF=myQueryShapes(i);
578       aBB.Add(aCompound, aF);
579     }
580     //
581     myImageShape.Bind(aS, aCompound);
582   }// for ( ;aItS.More(); aItS.Next())
583   //
584   myQueryShapes.Clear();
585 }
586 //=======================================================================
587 //function : FillResult
588 //purpose  :
589 //=======================================================================
590   void NMTAlgo_Splitter::FillResult()
591 {
592   Standard_Integer i, aNb;
593   //
594   aNb=myQueryShapes.Extent();
595   for (i=1; i<=aNb; ++i) {
596     const TopoDS_Shape& aS=myQueryShapes(i); 
597     myBuilder.Add (myShape, aS);
598   }
599   BOP_CorrectTolerances::CorrectTolerances(myShape, 0.01);
600 }
601 //=======================================================================
602 //function : isClosed
603 //purpose  : check id a shape is closed, ie is a solid or a closed shell
604 //=======================================================================
605  Standard_Boolean isClosed(const TopoDS_Shape& theShape)
606 {
607   Standard_Boolean isClosed = (theShape.ShapeType() == TopAbs_SOLID);
608   //
609   if (!isClosed && theShape.ShapeType() == TopAbs_SHELL) {
610     TopTools_IndexedDataMapOfShapeListOfShape MEF;
611     TopExp::MapShapesAndAncestors(theShape, TopAbs_EDGE, TopAbs_FACE, MEF);
612     for (Standard_Integer i=1;  isClosed && i<=MEF.Extent();  ++i)
613       isClosed = ( MEF(i).Extent() != 1 );
614   }
615   //
616   return isClosed;
617 }
618 //
619 //  myErrorStatus     
620 //
621 // 100 - DS is already computed
622 // 101 - Null shape is not allowed here
623 // 102 - DS is not computed
624 // 103 - No source shapes to treat