Salome HOME
ae4b4c70b333ba4262be385de7acd3a844c14ba2
[modules/geom.git] / src / GEOMAlgo / GEOMAlgo_GlueDetector.cxx
1 // Copyright (C) 2007-2023  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, 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_GlueDetector.cxx
24 // Author:      Peter KURNEV
25
26 #include <GEOMAlgo_GlueDetector.hxx>
27
28 #include <Bnd_Box.hxx>
29 #include <NCollection_UBTreeFiller.hxx>
30
31 #include <TColStd_ListOfInteger.hxx>
32 #include <TColStd_ListIteratorOfListOfInteger.hxx>
33 #include <TColStd_MapIteratorOfMapOfInteger.hxx>
34
35 #include <TopoDS_Shape.hxx>
36 #include <TopoDS_Face.hxx>
37 #include <TopoDS_Edge.hxx>
38 #include <TopoDS_Compound.hxx>
39 #include <TopoDS_Vertex.hxx>
40 #include <TopoDS_Iterator.hxx>
41 #include <TopoDS_Compound.hxx>
42
43 #include <TopTools_IndexedMapOfShape.hxx>
44 #include <TopTools_ListOfShape.hxx>
45 #include <TopTools_ListIteratorOfListOfShape.hxx>
46 #include <TopTools_DataMapIteratorOfDataMapOfShapeListOfShape.hxx>
47 #include <TopTools_MapOfShape.hxx>
48 #include <TopTools_MapIteratorOfMapOfShape.hxx>
49
50 #include <TopExp.hxx>
51 #include <BRep_Tool.hxx>
52 #include <BRep_Builder.hxx>
53 #include <BRepBndLib.hxx>
54
55 #include <TopTools_IndexedDataMapOfShapeListOfShape.hxx>
56 #include <TopExp.hxx>
57 #include <TopExp_Explorer.hxx>
58 #include <TopTools_MapOfShape.hxx>
59
60 #include <GEOMAlgo_BndSphereTree.hxx>
61 #include <GEOMAlgo_BndSphere.hxx>
62 #include <GEOMAlgo_IndexedDataMapOfShapeBndSphere.hxx>
63
64 #include <GEOMAlgo_IndexedDataMapOfIntegerShape.hxx>
65 #include <GEOMAlgo_PassKeyShape.hxx>
66 #include <GEOMAlgo_IndexedDataMapOfPassKeyShapeListOfShape.hxx>
67 #include <GEOMAlgo_AlgoTools.hxx>
68
69 //
70 static
71   Standard_Integer CheckAncesstors
72   (const TopoDS_Shape& aVSD,
73    const TopTools_MapOfShape& aMVSD,
74    const TopTools_IndexedDataMapOfShapeListOfShape& aMVE,
75    const TopTools_IndexedDataMapOfShapeListOfShape& aMEV,
76    TopTools_IndexedDataMapOfShapeListOfShape& aMEVZ);
77
78 //=======================================================================
79 //function :
80 //purpose  :
81 //=======================================================================
82 GEOMAlgo_GlueDetector::GEOMAlgo_GlueDetector()
83 :
84   GEOMAlgo_GluerAlgo(),
85   GEOMAlgo_Algo()
86 {}
87 //=======================================================================
88 //function : ~
89 //purpose  :
90 //=======================================================================
91 GEOMAlgo_GlueDetector::~GEOMAlgo_GlueDetector()
92 {}
93 //=======================================================================
94 //function : StickedShapes
95 //purpose  :
96 //=======================================================================
97 const TopTools_IndexedDataMapOfShapeListOfShape&
98   GEOMAlgo_GlueDetector::StickedShapes()
99 {
100   return myStickedShapes;
101 }
102 //=======================================================================
103 //function : Perform
104 //purpose  :
105 //=======================================================================
106 void GEOMAlgo_GlueDetector::Perform()
107 {
108   myErrorStatus=0;
109   myWarningStatus=0;
110   myStickedShapes.Clear();
111   //
112   CheckData();
113   if (myErrorStatus) {
114     return;
115   }
116   //
117   // Initialize the context
118   GEOMAlgo_GluerAlgo::Perform();
119   //
120   DetectVertices();
121   if (myErrorStatus) {
122     return;
123   }
124   //
125   CheckDetected();
126   if (myErrorStatus) {
127     return;
128   }
129   //
130   DetectEdges();
131   if (myErrorStatus) {
132     return;
133   }
134   //
135   DetectFaces();
136   if (myErrorStatus) {
137     return;
138   }
139 }
140 //=======================================================================
141 //function : DetectVertices
142 //purpose  :
143 //=======================================================================
144 void GEOMAlgo_GlueDetector::DetectVertices()
145 {
146   Standard_Integer j, i, aNbV, aNbVSD;
147   Standard_Real aTolV;
148   gp_Pnt aPV;
149   TColStd_ListIteratorOfListOfInteger aIt;
150   TopoDS_Shape aVF;
151   TopTools_IndexedMapOfShape aMV;
152   TopTools_MapOfShape aMVProcessed;
153   TopTools_ListIteratorOfListOfShape aItS;
154   TopTools_DataMapIteratorOfDataMapOfShapeListOfShape aItIm;
155   TopTools_DataMapOfShapeListOfShape aMVV;
156   GEOMAlgo_IndexedDataMapOfIntegerShape aMIS;
157   GEOMAlgo_IndexedDataMapOfShapeBndSphere aMSB;
158   GEOMAlgo_BndSphereTreeSelector aSelector;
159   GEOMAlgo_BndSphereTree aBBTree;
160   NCollection_UBTreeFiller <Standard_Integer, GEOMAlgo_BndSphere> aTreeFiller(aBBTree);
161   //
162   myErrorStatus=0;
163   //
164   TopExp::MapShapes(myArgument, TopAbs_VERTEX, aMV);
165   aNbV=aMV.Extent();
166   if (!aNbV) {
167     myErrorStatus=2; // no vertices in source shape
168     return;
169   }
170   //
171   for (i=1; i<=aNbV; ++i) {
172     GEOMAlgo_BndSphere aBox;
173     //
174     const TopoDS_Vertex& aV=*((TopoDS_Vertex*)&aMV(i));
175     aPV=BRep_Tool::Pnt(aV);
176     aTolV=BRep_Tool::Tolerance(aV);
177     //
178     aBox.SetGap(myTolerance);
179     aBox.SetCenter(aPV);
180     aBox.SetRadius(aTolV);
181     //
182     aTreeFiller.Add(i, aBox);
183     //
184     aMIS.Add(i, aV);
185     aMSB.Add(aV, aBox);
186   }
187   //
188   aTreeFiller.Fill();
189   //
190   //---------------------------------------------------
191   // Chains
192   for (i=1; i<=aNbV; ++i) {
193     const TopoDS_Shape& aV=aMV(i);
194     //
195     if (aMVProcessed.Contains(aV)) {
196       continue;
197     }
198     //
199     Standard_Integer aNbIP, aIP, aNbIP1, aIP1;
200     TopTools_ListOfShape aLVSD;
201     TColStd_MapOfInteger aMIP, aMIP1, aMIPC;
202     TColStd_MapIteratorOfMapOfInteger aIt1;
203     //
204     aMIP.Add(i);
205     for(;;) {
206       aNbIP=aMIP.Extent();
207       aIt1.Initialize(aMIP);
208       for(; aIt1.More(); aIt1.Next()) {
209         aIP=aIt1.Key();
210         if (aMIPC.Contains(aIP)) {
211           continue;
212         }
213         //
214         const TopoDS_Shape& aVP=aMIS.FindFromKey(aIP);
215         const GEOMAlgo_BndSphere& aBoxVP=aMSB.FindFromKey(aVP);
216         //
217         aSelector.Clear();
218         aSelector.SetBox(aBoxVP);
219         //
220         aNbVSD=aBBTree.Select(aSelector);
221         if (!aNbVSD) {
222           continue;  // it should not be so [at least IP itself]
223         }
224         //
225         const TColStd_ListOfInteger& aLI=aSelector.Indices();
226         aIt.Initialize(aLI);
227         for (; aIt.More(); aIt.Next()) {
228           aIP1=aIt.Value();
229           if (aMIP.Contains(aIP1)) {
230             continue;
231           }
232           aMIP1.Add(aIP1);
233         } //for (; aIt.More(); aIt.Next()) {
234       }//for(; aIt1.More(); aIt1.Next()) {
235       //
236       aNbIP1=aMIP1.Extent();
237       if (!aNbIP1) {
238         break;
239       }
240       //
241       aIt1.Initialize(aMIP);
242       for(; aIt1.More(); aIt1.Next()) {
243         aIP=aIt1.Key();
244         aMIPC.Add(aIP);
245       }
246       //
247       aMIP.Clear();
248       aIt1.Initialize(aMIP1);
249       for(; aIt1.More(); aIt1.Next()) {
250         aIP=aIt1.Key();
251         aMIP.Add(aIP);
252       }
253       aMIP1.Clear();
254     }// while(1)
255     //
256     // Fill myImages
257     aNbIP=aMIPC.Extent();
258     //
259     if (!aNbIP) {// no SD vertices is found
260       aMVProcessed.Add(aV);
261       continue;
262     }
263     //else { // SD vertices founded [ aMIPC ]
264     aIt1.Initialize(aMIPC);
265     for(j=0; aIt1.More(); aIt1.Next(), ++j) {
266       aIP=aIt1.Key();
267       const TopoDS_Shape& aVP=aMIS.FindFromKey(aIP);
268       if (!j) {
269         aVF=aVP;
270       }
271       aLVSD.Append(aVP);
272       aMVProcessed.Add(aVP);
273     }
274     //}
275     myImages.Bind(aVF, aLVSD);
276   }// for (i=1; i<=aNbV; ++i) {
277   //------------------------------
278   // Origins
279   aItIm.Initialize(myImages);
280   for (; aItIm.More(); aItIm.Next()) {
281     const TopoDS_Shape& aV=aItIm.Key();
282     const TopTools_ListOfShape& aLVSD=aItIm.Value();
283     aItS.Initialize(aLVSD);
284     for (; aItS.More(); aItS.Next()) {
285       const TopoDS_Shape& aVSD=aItS.Value();
286       if (!myOrigins.IsBound(aVSD)) {
287         myOrigins.Bind(aVSD, aV);
288       }
289     }
290   }
291 }
292 //=======================================================================
293 //function : DetectFaces
294 //purpose  :
295 //=======================================================================
296 void GEOMAlgo_GlueDetector::DetectFaces()
297 {
298   DetectShapes(TopAbs_FACE);
299 }
300 //=======================================================================
301 //function : DetectEdges
302 //purpose  :
303 //=======================================================================
304 void GEOMAlgo_GlueDetector::DetectEdges()
305 {
306   DetectShapes(TopAbs_EDGE);
307 }
308 //=======================================================================
309 //function : DetectShapes
310 //purpose  :
311 //=======================================================================
312 void GEOMAlgo_GlueDetector::DetectShapes(const TopAbs_ShapeEnum aType)
313 {
314   Standard_Boolean bDegenerated;
315   Standard_Integer i, aNbF, aNbSDF, iErr;
316   TopTools_IndexedMapOfShape aMF;
317   TopTools_ListIteratorOfListOfShape aItLS;
318   GEOMAlgo_PassKeyShape aPKF;
319   GEOMAlgo_IndexedDataMapOfPassKeyShapeListOfShape aMPKLF;
320   //
321   myErrorStatus=0;
322   //
323   TopExp::MapShapes(myArgument, aType, aMF);
324   //
325   aNbF=aMF.Extent();
326   for (i=1; i<=aNbF; ++i) {
327     const TopoDS_Shape& aS=aMF(i);
328     //
329     if (aType==TopAbs_FACE) {
330       const TopoDS_Face& aF=*((TopoDS_Face*)&aS);
331       FacePassKey(aF, aPKF);
332     }
333     else if (aType==TopAbs_EDGE) {
334       const TopoDS_Edge& aE=*((TopoDS_Edge*)&aS);
335       EdgePassKey(aE, aPKF);
336     }
337     //
338     if (myErrorStatus) {
339       return;
340     }
341     //
342     if (aMPKLF.Contains(aPKF)) {
343       TopTools_ListOfShape& aLSDF=aMPKLF.ChangeFromKey(aPKF);
344       aLSDF.Append(aS);
345     }
346     else {
347       TopTools_ListOfShape aLSDF;
348       //
349       aLSDF.Append(aS);
350       aMPKLF.Add(aPKF, aLSDF);
351     }
352   }
353   // check geometric coincidence
354   if (myCheckGeometry) {
355     iErr=GEOMAlgo_AlgoTools::RefineSDShapes(aMPKLF, myTolerance, myContext);
356     if (iErr) {
357       myErrorStatus=200;
358       return;
359     }
360   }
361   //
362   // Images/Origins
363   aNbF=aMPKLF.Extent();
364   for (i=1; i<=aNbF; ++i) {
365     const TopTools_ListOfShape& aLSDF=aMPKLF(i);
366     aNbSDF=aLSDF.Extent();
367     if (!aNbSDF) {
368       myErrorStatus=4; // it must not be
369     }
370     //
371     if (aNbSDF==1) {
372       continue;
373     }
374     //
375     const TopoDS_Shape& aS1=aLSDF.First();
376     //
377     if (aType==TopAbs_EDGE) {
378       const TopoDS_Edge& aE1=*((TopoDS_Edge*)&aS1);
379       bDegenerated=BRep_Tool::Degenerated(aE1);
380       if (bDegenerated) {
381         continue;
382       }
383     }
384     //
385     myImages.Bind(aS1, aLSDF);
386     //
387     // origins
388     aItLS.Initialize(aLSDF);
389     for (; aItLS.More(); aItLS.Next()) {
390       const TopoDS_Shape& aFSD=aItLS.Value();
391       if (!myOrigins.IsBound(aFSD)) {
392         myOrigins.Bind(aFSD, aS1);
393       }
394     }
395   }// for (i=1; i<=aNbF; ++i)
396 }
397 //=======================================================================
398 //function : FacePassKey
399 //purpose  :
400 //=======================================================================
401 void GEOMAlgo_GlueDetector::FacePassKey(const TopoDS_Face& aF,
402                                         GEOMAlgo_PassKeyShape& aPK)
403 {
404   Standard_Integer i, aNbE;
405   TopoDS_Shape aER;
406   TopTools_ListOfShape aLE;
407   TopTools_IndexedMapOfShape aME;
408   //
409   TopExp::MapShapes(aF, TopAbs_EDGE, aME);
410   //
411   aNbE=aME.Extent();
412   for (i=1; i<=aNbE; ++i) {
413     const TopoDS_Shape& aE=aME(i);
414     //
415     const TopoDS_Edge& aEE=*((TopoDS_Edge*)&aE);
416     if (BRep_Tool::Degenerated(aEE)) {
417       continue;
418     }
419     //
420     if (myOrigins.IsBound(aE)) {
421       aER=myOrigins.Find(aE);
422     }
423     else {
424       aER=aE;
425     }
426     aLE.Append(aER);
427   }
428   aPK.SetShapes(aLE);
429 }
430 //=======================================================================
431 //function : EdgePassKey
432 //purpose  :
433 //=======================================================================
434 void GEOMAlgo_GlueDetector::EdgePassKey(const TopoDS_Edge& aE,
435                                         GEOMAlgo_PassKeyShape& aPK)
436 {
437   TopAbs_Orientation aOr;
438   TopoDS_Shape aVR;
439   TopoDS_Iterator aIt;
440   TopTools_ListOfShape aLV;
441   //
442   aIt.Initialize(aE);
443   for (; aIt.More(); aIt.Next()) {
444     const TopoDS_Shape& aV=aIt.Value();
445     aOr=aV.Orientation();
446     if (aOr==TopAbs_FORWARD || aOr==TopAbs_REVERSED) {
447       if (myOrigins.IsBound(aV)) {
448         aVR=myOrigins.Find(aV);
449       }
450       else {
451         aVR=aV;
452       }
453       aLV.Append(aVR);
454     }
455   }
456   //
457   aPK.SetShapes(aLV);
458 }
459 //=======================================================================
460 //function : CheckDetected
461 //purpose  :
462 //=======================================================================
463 void GEOMAlgo_GlueDetector::CheckDetected()
464 {
465   TopoDS_Iterator aItA;
466   TopExp_Explorer aExp;
467   TopTools_ListOfShape aLV;
468   TopTools_MapOfShape aMFence;
469   TopTools_DataMapIteratorOfDataMapOfShapeListOfShape aItIm;
470   TopTools_IndexedDataMapOfShapeListOfShape aMVE, aMEV;
471   //
472   // 1. aMVE, aMEV
473   TopExp::MapShapesAndAncestors(myArgument, TopAbs_VERTEX, TopAbs_EDGE, aMVE);
474   //
475   aExp.Init(myArgument, TopAbs_EDGE);
476   for (; aExp.More(); aExp.Next()) {
477     const TopoDS_Shape& aE=aExp.Current();
478     //
479     aLV.Clear();
480     aMFence.Clear();
481     aItA.Initialize(aE);
482     for (; aItA.More(); aItA.Next()) {
483       const TopoDS_Shape& aV=aItA.Value();
484       if (aMFence.Add(aV)) {
485         aLV.Append(aV);
486       }
487     }
488     //
489     aMEV.Add(aE, aLV);
490   }
491   // 2. Checking
492   aItIm.Initialize(myImages);
493   for (; aItIm.More(); aItIm.Next()) {
494     //const TopoDS_Shape& aV=aItIm.Key();
495     const TopTools_ListOfShape& aLVSD=aItIm.Value();
496     CheckDetected(aLVSD, aMVE, aMEV);
497   }
498 }
499 //=======================================================================
500 //function : CheckDetected
501 //purpose  :
502 //=======================================================================
503 void GEOMAlgo_GlueDetector::CheckDetected
504   (const TopTools_ListOfShape& aLVSD,
505    const TopTools_IndexedDataMapOfShapeListOfShape& aMVE,
506    const TopTools_IndexedDataMapOfShapeListOfShape& aMEV)
507 {
508   Standard_Integer aNbVSD, iRet;
509   TopExp_Explorer aExp, aExpA;
510   TopTools_MapOfShape aMFence, aMVSD;
511   TopTools_ListOfShape aLV;
512   TopTools_ListIteratorOfListOfShape aItLS;
513   //
514   myErrorStatus=0;
515   //
516   aNbVSD=aLVSD.Extent();
517   if (aNbVSD < 2) {
518     return ;
519   }
520   //
521   aItLS.Initialize(aLVSD);
522   for (; aItLS.More(); aItLS.Next()) {
523     const TopoDS_Shape& aVSD=aItLS.Value();
524     aMVSD.Add(aVSD);
525   }
526   //
527   aItLS.Initialize(aLVSD);
528   for (; aItLS.More(); aItLS.Next()) {
529     const TopoDS_Shape& aVSD=aItLS.Value();
530     //
531     iRet=CheckAncesstors(aVSD, aMVSD, aMVE, aMEV, myStickedShapes);
532     if (iRet) {
533       // Sticked shapes detected
534       myWarningStatus=2;
535     }
536   }
537 }
538 //=======================================================================
539 //function : CheckAncesstors
540 //purpose  :
541 //=======================================================================
542 Standard_Integer CheckAncesstors
543   (const TopoDS_Shape& aVSD,
544    const TopTools_MapOfShape& aMVSD,
545    const TopTools_IndexedDataMapOfShapeListOfShape& aMVE,
546    const TopTools_IndexedDataMapOfShapeListOfShape& aMEV,
547    TopTools_IndexedDataMapOfShapeListOfShape& aMEVZ)
548 {
549   TopTools_ListOfShape *pLE, *pLV, *pLVZ;
550   Standard_Integer iRet, aNbVX;
551   TopTools_ListIteratorOfListOfShape aItLE, aItLV;
552   TopTools_MapOfShape aMFence;
553   TopTools_ListOfShape aLVX;
554   //
555   iRet=0;
556   //
557   pLE=const_cast<TopTools_IndexedDataMapOfShapeListOfShape&>(aMVE).ChangeSeek(aVSD);
558   if (!pLE) {
559     return iRet;
560   }
561   aItLE.Initialize(*pLE);
562   for (; aItLE.More(); aItLE.Next()) {
563     const TopoDS_Shape& aE=aItLE.Value();
564     //
565     pLV=const_cast<TopTools_IndexedDataMapOfShapeListOfShape&>(aMEV).ChangeSeek(aE);
566     if (!pLV) {
567       continue; // it should be not so
568     }
569     aLVX.Clear();
570     aItLV.Initialize(*pLV);
571     for (; aItLV.More(); aItLV.Next()) {
572       const TopoDS_Shape& aV=aItLV.Value();
573       if (!aV.IsSame(aVSD)) {
574         if (aMVSD.Contains(aV)) {
575           if (aMFence.Add(aV)) {
576             aLVX.Append(aV);
577           }
578         }
579       }
580     }
581     //
582     aNbVX=aLVX.Extent();
583     if (!aNbVX) {
584       continue;
585     }
586     //
587     iRet=1;
588     //
589     pLVZ=aMEVZ.ChangeSeek(aE);
590     if (!pLVZ) {
591       aMEVZ.Add(aE, aLVX);
592     }
593     else {
594       TopTools_ListOfShape& aLVZ=*pLVZ;
595       aLVZ.Append(aLVX);
596     }
597   }
598   //
599   return iRet;
600 }