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