Salome HOME
updated copyright message
[modules/shaper.git] / src / GeomAlgoImpl / GEOMAlgo_Gluer2.cxx
1 // Copyright (C) 2007-2023  CEA, EDF, 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, or (at your option) any later version.
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_Gluer2.cxx
24 // Author:      Peter KURNEV
25
26 #include <GEOMAlgo_Gluer2.hxx>
27
28 #include <TopAbs_ShapeEnum.hxx>
29
30 #include <TopoDS_Compound.hxx>
31 #include <TopoDS_Iterator.hxx>
32 #include <TopoDS_Shape.hxx>
33 #include <TopoDS_Vertex.hxx>
34
35 #include <BRep_Builder.hxx>
36 #include <TopExp.hxx>
37 #include <BRepLib.hxx>
38
39 #include <TopTools_MapOfShape.hxx>
40 #include <TopTools_MapIteratorOfMapOfShape.hxx>
41 #include <TopTools_DataMapOfShapeShape.hxx>
42 #include <TopTools_ListOfShape.hxx>
43 #include <TopTools_ListIteratorOfListOfShape.hxx>
44 #include <TopTools_DataMapIteratorOfDataMapOfShapeListOfShape.hxx>
45 #include <TopTools_IndexedMapOfShape.hxx>
46
47 #include <BOPTools_AlgoTools.hxx>
48
49 #include <GEOMAlgo_GlueDetector.hxx>
50 #include <GEOMAlgo_AlgoTools.hxx>
51
52
53 //=======================================================================
54 //function : GEOMAlgo_Gluer2
55 //purpose  :
56 //=======================================================================
57 GEOMAlgo_Gluer2::GEOMAlgo_Gluer2()
58   :GEOMAlgo_GluerAlgo()
59   ,GEOMAlgo_BuilderShape()
60 {
61   myTolerance=0.0001;
62 }
63
64 //=======================================================================
65 //function : ~GEOMAlgo_Gluer2
66 //purpose  :
67 //=======================================================================
68 GEOMAlgo_Gluer2::~GEOMAlgo_Gluer2()
69 {
70 }
71
72 //=======================================================================
73 //function : Clear
74 //purpose  :
75 //=======================================================================
76 void GEOMAlgo_Gluer2::Clear()
77 {
78   myErrorStatus=0;
79   myWarningStatus=0;
80   //
81   GEOMAlgo_GluerAlgo::Clear();
82   //
83   myImagesDetected.Clear();
84   myOriginsDetected.Clear();
85   myShapesToGlue.Clear();
86   myImagesToWork.Clear();
87   myOriginsToWork.Clear();
88   myKeepNonSolids=Standard_False;
89   myDetector.Clear();
90 }
91
92 //=======================================================================
93 //function : StickedShapes
94 //purpose  :
95 //=======================================================================
96 const TopTools_IndexedDataMapOfShapeListOfShape& GEOMAlgo_Gluer2::StickedShapes()
97 {
98   return myDetector.StickedShapes();
99 }
100
101 //=======================================================================
102 //function : SetShapesToGlue
103 //purpose  :
104 //=======================================================================
105 void GEOMAlgo_Gluer2::SetShapesToGlue(const TopTools_DataMapOfShapeListOfShape& aM)
106 {
107   myShapesToGlue=aM;
108 }
109
110 //=======================================================================
111 //function : ShapesToGlue
112 //purpose  :
113 //=======================================================================
114 const TopTools_DataMapOfShapeListOfShape& GEOMAlgo_Gluer2::ShapesToGlue() const
115 {
116   return myShapesToGlue;
117 }
118
119 //=======================================================================
120 //function : SetKeepNonSolids
121 //purpose  :
122 //=======================================================================
123 void GEOMAlgo_Gluer2::SetKeepNonSolids(const Standard_Boolean aFlag)
124 {
125   myKeepNonSolids=aFlag;
126 }
127
128 //=======================================================================
129 //function : KeepNonSolids
130 //purpose  :
131 //=======================================================================
132 Standard_Boolean GEOMAlgo_Gluer2::KeepNonSolids()const
133 {
134   return myKeepNonSolids;
135 }
136
137 //=======================================================================
138 //function : ShapesDetected
139 //purpose  :
140 //=======================================================================
141 const TopTools_DataMapOfShapeListOfShape& GEOMAlgo_Gluer2::ShapesDetected() const
142 {
143   return myImagesDetected;
144 }
145
146 //=======================================================================
147 //function : ImagesToWork
148 //purpose  :
149 //=======================================================================
150 const TopTools_DataMapOfShapeListOfShape& GEOMAlgo_Gluer2::ImagesToWork() const
151 {
152   return myImagesToWork;
153 }
154
155 //=======================================================================
156 //function : Perform
157 //purpose  :
158 //=======================================================================
159 void GEOMAlgo_Gluer2::Perform()
160 {
161   myErrorStatus=0;
162   myWarningStatus=0;
163   //
164   CheckData();
165   if (myErrorStatus) {
166     return;
167   }
168   //
169   // Initialize the context
170   GEOMAlgo_GluerAlgo::Perform();
171   //
172   PerformShapesToWork();
173   if (myErrorStatus) {
174     return;
175   }
176   if (myWarningStatus==1) {
177     // no shapes to glue
178     myShape=myArgument;
179     return;
180   }
181   //
182   FillVertices();
183   if (myErrorStatus) {
184     return;
185   }
186   //
187   FillEdges();
188   if (myErrorStatus) {
189     return;
190   }
191   //
192   FillWires();
193   if (myErrorStatus) {
194     return;
195   }
196   //
197   FillFaces();
198   if (myErrorStatus) {
199     return;
200   }
201   //
202   FillShells();
203   if (myErrorStatus) {
204     return;
205   }
206   //
207   FillSolids();
208   if (myErrorStatus) {
209     return;
210   }
211   //
212   FillCompSolids();
213   if (myErrorStatus) {
214     return;
215   }
216   //
217   FillCompounds();
218   if (myErrorStatus) {
219     return;
220   }
221   //
222   BuildResult();
223   if (myErrorStatus) {
224     return;
225   }
226   //
227   PrepareHistory();
228   if (myErrorStatus) {
229     return;
230   }
231   //
232   BRepLib::SameParameter(myShape, myTolerance, Standard_True);
233 }
234
235 //=======================================================================
236 //function : CheckData
237 //purpose  :
238 //=======================================================================
239 void GEOMAlgo_Gluer2::CheckData()
240 {
241   Standard_Integer aNbSG, i;
242   TopAbs_ShapeEnum aType, aTypeX;
243   TopTools_ListIteratorOfListOfShape aItLS;
244   TopTools_DataMapIteratorOfDataMapOfShapeListOfShape aItDMSLS;
245   //
246   myErrorStatus=0;
247   myWarningStatus=0;
248   //
249   aNbSG=myShapesToGlue.Extent();
250   aType=TopAbs_SHAPE;
251   if (aNbSG) {
252     // Check myShapesToGlue
253     aItDMSLS.Initialize(myShapesToGlue);
254     for (; aItDMSLS.More(); aItDMSLS.Next()) {
255       const TopTools_ListOfShape& aLSG=aItDMSLS.Value();
256       aItLS.Initialize(aLSG);
257       for (i=0; aItLS.More(); aItLS.Next(), ++i) {
258         const TopoDS_Shape& aSG=aItLS.Value();
259         aTypeX=aSG.ShapeType();
260         if (!i) {
261           aType=aTypeX;
262           if (!(aType==TopAbs_VERTEX ||
263                 aType==TopAbs_EDGE ||
264                 aType==TopAbs_FACE)) {
265             myErrorStatus=21;// non-brep shapes
266             return;
267           }
268           continue;
269         }
270         if (aTypeX!=aType) {
271           myErrorStatus=20;// non-homogeneous shapes
272           return;
273         }
274       }
275     }
276   }// if (aNbSG) {
277 }
278
279 //=======================================================================
280 //function : FillEdges
281 //purpose  :
282 //=======================================================================
283 void GEOMAlgo_Gluer2::FillEdges()
284 {
285   FillBRepShapes(TopAbs_EDGE);
286 }
287
288 //=======================================================================
289 //function : FillFaces
290 //purpose  :
291 //=======================================================================
292 void GEOMAlgo_Gluer2::FillFaces()
293 {
294   FillBRepShapes(TopAbs_FACE);
295 }
296
297 //=======================================================================
298 //function : FillWires
299 //purpose  :
300 //=======================================================================
301 void GEOMAlgo_Gluer2::FillWires()
302 {
303   FillContainers(TopAbs_WIRE);
304 }
305
306 //=======================================================================
307 //function : FillShells
308 //purpose  :
309 //=======================================================================
310 void GEOMAlgo_Gluer2::FillShells()
311 {
312   FillContainers(TopAbs_SHELL);
313 }
314
315 //=======================================================================
316 //function : FillSolids
317 //purpose  :
318 //=======================================================================
319 void GEOMAlgo_Gluer2::FillSolids()
320 {
321   FillContainers(TopAbs_SOLID);
322 }
323
324 //=======================================================================
325 //function : FillCompSolids
326 //purpose  :
327 //=======================================================================
328 void GEOMAlgo_Gluer2::FillCompSolids()
329 {
330   FillContainers(TopAbs_COMPSOLID);
331 }
332
333 //=======================================================================
334 //function : FillVertices
335 //purpose  :
336 //=======================================================================
337 void GEOMAlgo_Gluer2::FillVertices()
338 {
339   TopAbs_ShapeEnum aType;
340   TopoDS_Vertex aVnew;
341   TopTools_ListIteratorOfListOfShape aItLS;
342   TopTools_DataMapIteratorOfDataMapOfShapeListOfShape aItDMSLS;
343   //
344   myErrorStatus=0;
345   myWarningStatus=0;
346   //
347   aItDMSLS.Initialize(myImagesToWork);
348   for (; aItDMSLS.More(); aItDMSLS.Next()) {
349     const TopoDS_Shape& aSkey=aItDMSLS.Key();
350     aType=aSkey.ShapeType();
351     if (aType!=TopAbs_VERTEX) {
352       continue;
353     }
354     //
355     const TopTools_ListOfShape& aLSD=aItDMSLS.Value();
356     //
357     GEOMAlgo_Gluer2::MakeVertex(aLSD, aVnew);
358     //
359     myImages.Bind(aVnew, aLSD);
360     //
361     aItLS.Initialize(aLSD);
362     for (; aItLS.More(); aItLS.Next()) {
363       const TopoDS_Shape& aV=aItLS.Value();
364       myOrigins.Bind(aV, aVnew);
365     }
366   }
367 }
368
369 //=======================================================================
370 //function : FillBRepShapes
371 //purpose  :
372 //=======================================================================
373 void GEOMAlgo_Gluer2::FillBRepShapes(const TopAbs_ShapeEnum theType)
374 {
375   Standard_Boolean bHasImage, bIsToWork;
376   Standard_Integer i, aNbE;
377   TopoDS_Iterator aItS;
378   TopoDS_Shape aEnew;
379   TopTools_IndexedMapOfShape aME;
380   TopTools_MapOfShape aMFence;
381   TopTools_ListIteratorOfListOfShape aItLS;
382   //
383   myErrorStatus=0;
384   myWarningStatus=0;
385   //
386   TopExp::MapShapes(myArgument, theType, aME);
387   //
388   aNbE=aME.Extent();
389   for (i=1; i<=aNbE; ++i) {
390     const TopoDS_Shape& aE=aME(i);
391     //
392     if (!aMFence.Add(aE)) {
393       continue;
394     }
395     //
396     bIsToWork=myOriginsToWork.IsBound(aE);
397     bHasImage=HasImage(aE);
398     if (!bHasImage && !bIsToWork) {
399       continue;
400     }
401     //
402     MakeBRepShapes(aE, aEnew);
403     //
404     //myImages / myOrigins
405     if (bIsToWork) {
406       const TopoDS_Shape& aSkey=myOriginsToWork.Find(aE);
407       const TopTools_ListOfShape& aLSD=myImagesToWork.Find(aSkey);
408       //
409       myImages.Bind(aEnew, aLSD);
410       //
411       aItLS.Initialize(aLSD);
412       for (; aItLS.More(); aItLS.Next()) {
413         const TopoDS_Shape& aEx=aItLS.Value();
414         myOrigins.Bind(aEx, aEnew);
415         //
416         aMFence.Add(aEx);
417       }
418     }
419     else {
420       TopTools_ListOfShape aLSD;
421       //
422       aLSD.Append(aE);
423       myImages.Bind(aEnew, aLSD);
424       myOrigins.Bind(aE, aEnew);
425     }
426   }//for (i=1; i<=aNbF; ++i) {
427 }
428
429 //=======================================================================
430 //function : FillContainers
431 //purpose  :
432 //=======================================================================
433 void GEOMAlgo_Gluer2::FillContainers(const TopAbs_ShapeEnum aType)
434 {
435   Standard_Boolean bHasImage, bToReverse;
436   Standard_Integer i, aNbW;
437   TopoDS_Shape aWnew, aEnew;
438   TopoDS_Iterator aItS;
439   BRep_Builder aBB;
440   TopTools_IndexedMapOfShape aMW;
441   TopTools_MapOfShape aMFence;
442   //
443   myErrorStatus=0;
444   myWarningStatus=0;
445   //
446   TopExp::MapShapes(myArgument, aType, aMW);
447   //
448   aNbW=aMW.Extent();
449   for (i=1; i<=aNbW; ++i) {
450     const TopoDS_Shape& aW=aMW(i);
451     //
452     if (!aMFence.Add(aW)) {
453       continue;
454     }
455     //
456     bHasImage=HasImage(aW);
457     if (!bHasImage) {
458       continue;
459     }
460     //
461     GEOMAlgo_AlgoTools::MakeContainer(aType, aWnew);
462     aWnew.Orientation(aW.Orientation());
463     //
464     aItS.Initialize(aW);
465     for (; aItS.More(); aItS.Next()) {
466       const TopoDS_Shape& aE=aItS.Value();
467       if (myOrigins.IsBound(aE)) {
468         aEnew=myOrigins.Find(aE);
469         //
470         bToReverse=BOPTools_AlgoTools::IsSplitToReverse(aEnew, aE, myContext);
471         if (bToReverse) {
472           aEnew.Reverse();
473         }
474         //
475         aBB.Add(aWnew, aEnew);
476       }
477       else {
478         aBB.Add(aWnew, aE);
479       }
480     }
481     //
482     //myImages / myOrigins
483     TopTools_ListOfShape aLSD;
484     //
485     aLSD.Append(aW);
486     myImages.Bind(aWnew, aLSD);
487     myOrigins.Bind(aW, aWnew);
488     //
489   }//for (i=1; i<=aNbE; ++i) {
490 }
491
492 //=======================================================================
493 //function : FillCompounds
494 //purpose  :
495 //=======================================================================
496 void GEOMAlgo_Gluer2::FillCompounds()
497 {
498   TopAbs_ShapeEnum aType;
499   TopoDS_Iterator aItC;
500   //
501   myErrorStatus=0;
502   myWarningStatus=0;
503   //
504   aItC.Initialize(myArgument);
505   for (; aItC.More(); aItC.Next()) {
506     const TopoDS_Shape& aCx=aItC.Value();
507     aType=aCx.ShapeType();
508     if (aType==TopAbs_COMPOUND) {
509       FillCompound(aCx);
510     }
511   }
512 }
513
514 //=======================================================================
515 //function : FillCompound
516 //purpose  :
517 //=======================================================================
518 void GEOMAlgo_Gluer2::FillCompound(const TopoDS_Shape& aC)
519 {
520   Standard_Boolean bHasImage;
521   TopAbs_ShapeEnum aType;
522   TopoDS_Shape aCnew, aCXnew;
523   TopoDS_Iterator aItC;
524   BRep_Builder aBB;
525   //
526   bHasImage=HasImage(aC);
527   if (!bHasImage) {
528     return;
529   }
530   //
531   GEOMAlgo_AlgoTools::MakeContainer(TopAbs_COMPOUND, aCnew);
532   //
533   aItC.Initialize(aC);
534   for (; aItC.More(); aItC.Next()) {
535     const TopoDS_Shape& aCX=aItC.Value();
536     aType=aCX.ShapeType();
537     //
538     if (aType==TopAbs_COMPOUND) {
539       FillCompound(aCX);
540     }
541     //
542     if (myOrigins.IsBound(aCX)) {
543       aCXnew=myOrigins.Find(aCX);
544       aCXnew.Orientation(aCX.Orientation());
545       aBB.Add(aCnew, aCXnew);
546     }
547     else {
548       aBB.Add(aCnew, aCX);
549     }
550   }
551   //
552   //myImages / myOrigins
553   TopTools_ListOfShape aLSD;
554   //
555   aLSD.Append(aC);
556   myImages.Bind(aCnew, aLSD);
557   myOrigins.Bind(aC, aCnew);
558 }
559
560 //=======================================================================
561 //function : HasImage
562 //purpose  :
563 //=======================================================================
564 Standard_Boolean GEOMAlgo_Gluer2::HasImage(const TopoDS_Shape& aC)
565 {
566   Standard_Boolean bRet;
567   TopAbs_ShapeEnum aType;
568   TopoDS_Iterator aItC;
569   //
570   bRet=Standard_False;
571   aItC.Initialize(aC);
572   for (; aItC.More(); aItC.Next()) {
573     const TopoDS_Shape& aCx=aItC.Value();
574     aType=aCx.ShapeType();
575     //
576     if (aType==TopAbs_COMPOUND) {
577       bRet=HasImage(aCx);
578       if (bRet) {
579         return bRet;
580       }
581     }
582     else {
583       bRet=myOrigins.IsBound(aCx);
584       if (bRet) {
585         return bRet;
586       }
587     }
588   }
589   //
590   bRet=myOrigins.IsBound(aC);
591   //
592   return bRet;
593 }
594
595 //=======================================================================
596 //function : BuildResult
597 //purpose  :
598 //=======================================================================
599 void GEOMAlgo_Gluer2::BuildResult()
600 {
601   Standard_Boolean bHasImage;
602   TopoDS_Shape aCnew, aCXnew;
603   TopoDS_Iterator aItC;
604   BRep_Builder aBB;
605   //
606   myErrorStatus=0;
607   myWarningStatus=0;
608   //
609   bHasImage=Standard_False;
610   aItC.Initialize(myArgument);
611   for (; aItC.More(); aItC.Next()) {
612     const TopoDS_Shape& aCx=aItC.Value();
613     bHasImage=HasImage(aCx);
614     if (bHasImage) {
615       break;
616     }
617   }
618   //
619   if (!bHasImage) {
620     myShape=myArgument;
621     return;
622   }
623   //
624   GEOMAlgo_AlgoTools::MakeContainer(TopAbs_COMPOUND, aCnew);
625   //
626   aItC.Initialize(myArgument);
627   for (; aItC.More(); aItC.Next()) {
628     const TopoDS_Shape& aCX=aItC.Value();
629     if (myOrigins.IsBound(aCX)) {
630       aCXnew=myOrigins.Find(aCX);
631       aCXnew.Orientation(aCX.Orientation());
632       aBB.Add(aCnew, aCXnew);
633     }
634     else {
635       aBB.Add(aCnew, aCX);
636     }
637   }
638   //
639   if (!myKeepNonSolids) {
640     Standard_Integer i, aNb;
641     TopoDS_Shape aCnew1;
642     TopTools_IndexedMapOfShape aM;
643     //
644     GEOMAlgo_AlgoTools::MakeContainer(TopAbs_COMPOUND, aCnew1);
645     //
646     TopExp::MapShapes(aCnew, TopAbs_SOLID, aM);
647
648     aNb=aM.Extent();
649     for (i=1; i<=aNb; ++i) {
650       const TopoDS_Shape& aS=aM(i);
651       aBB.Add(aCnew1, aS);
652     }
653     aCnew=aCnew1;
654   }
655   //
656   myShape=aCnew;
657 }
658 //--------------------------------------------------------
659 //
660 // ErrorStatus
661 // 11   - GEOMAlgo_GlueDetector failed
662 // 13   - PerformImagesToWork failed
663 // 14   - PerformImagesToWork failed
664 //
665 // WarningStatus
666 // 1  - no shapes to glue
667 // 2  - sticked shapes are detected.
668 //      The value of myTolerance is so large that
669 //      subshapes of a shape start to interfere
670 //      (e.g. vertices of an edge).
671 //      In that case, the result can not be obtained