]> SALOME platform Git repositories - modules/geom.git/blob - src/GEOMAlgo/GEOMAlgo_GlueDetector.cxx
Salome HOME
0021434: Boolean operations generate a shape with big vertex tolerance.
[modules/geom.git] / src / GEOMAlgo / GEOMAlgo_GlueDetector.cxx
1 // Copyright (C) 2007-2011  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.
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 // File:        GEOMAlgo_GlueDetector.cxx
23 // Author:      Peter KURNEV
24
25 #include <GEOMAlgo_GlueDetector.hxx>
26
27 #include <GEOMAlgo_IndexedDataMapOfIntegerShape.hxx>
28 #include <GEOMAlgo_PassKeyShape.hxx>
29 #include <GEOMAlgo_IndexedDataMapOfPassKeyShapeListOfShape.hxx>
30 #include <GEOMAlgo_Tools.hxx>
31
32 #include <NMTDS_BndSphereTree.hxx>
33 #include <NMTDS_BndSphere.hxx>
34 #include <NMTDS_IndexedDataMapOfShapeBndSphere.hxx>
35
36 #include <Basics_OCCTVersion.hxx>
37
38 #include <NCollection_UBTreeFiller.hxx>
39
40 #include <TColStd_ListOfInteger.hxx>
41 #include <TColStd_ListIteratorOfListOfInteger.hxx>
42 #include <TColStd_MapIteratorOfMapOfInteger.hxx>
43
44 #include <TopoDS_Shape.hxx>
45 #include <TopoDS_Face.hxx>
46 #include <TopoDS_Edge.hxx>
47 #include <TopoDS_Compound.hxx>
48 #include <TopoDS_Vertex.hxx>
49 #include <TopoDS_Iterator.hxx>
50 #include <TopoDS_Compound.hxx>
51
52 #include <TopTools_IndexedMapOfShape.hxx>
53 #include <TopTools_ListOfShape.hxx>
54 #include <TopTools_ListIteratorOfListOfShape.hxx>
55 #include <TopTools_DataMapIteratorOfDataMapOfShapeListOfShape.hxx>
56 #include <TopTools_MapOfShape.hxx>
57 #include <TopTools_MapIteratorOfMapOfShape.hxx>
58
59 #include <TopExp.hxx>
60
61 #include <BRep_Tool.hxx>
62 #include <BRep_Builder.hxx>
63 #include <BRepBndLib.hxx>
64
65 #include <Bnd_Box.hxx>
66
67 //=======================================================================
68 //function : 
69 //purpose  : 
70 //=======================================================================
71 GEOMAlgo_GlueDetector::GEOMAlgo_GlueDetector()
72   : GEOMAlgo_GluerAlgo(),
73     GEOMAlgo_Algo()
74 {}
75 //=======================================================================
76 //function : ~
77 //purpose  : 
78 //=======================================================================
79 GEOMAlgo_GlueDetector::~GEOMAlgo_GlueDetector()
80 {}
81 //=======================================================================
82 //function : Perform
83 //purpose  : 
84 //=======================================================================
85 void GEOMAlgo_GlueDetector::Perform()
86 {
87   myErrorStatus=0;
88   myWarningStatus=0;
89   //
90   CheckData();
91   if (myErrorStatus) {
92     return;
93   }
94   //
95 #if OCC_VERSION_LARGE > 0x06050200
96   // Initialize the context
97   GEOMAlgo_GluerAlgo::Perform();
98 #endif
99   //
100   DetectVertices();
101   if (myErrorStatus) {
102     return;
103   }
104   //
105   DetectEdges();
106   if (myErrorStatus) {
107     return;
108   }
109   //
110   DetectFaces();
111   if (myErrorStatus) {
112     return;
113   }
114 }
115 //=======================================================================
116 //function : DetectVertices
117 //purpose  : 
118 //=======================================================================
119 void GEOMAlgo_GlueDetector::DetectVertices()
120 {
121   Standard_Integer j, i, aNbV, aNbVSD;
122   Standard_Real aTolV;
123   gp_Pnt aPV;
124   TColStd_ListIteratorOfListOfInteger aIt;
125   TopoDS_Shape aVF;
126   TopTools_IndexedMapOfShape aMV;
127   TopTools_MapOfShape aMVProcessed;
128   TopTools_ListIteratorOfListOfShape aItS;
129   TopTools_DataMapIteratorOfDataMapOfShapeListOfShape aItIm;
130   TopTools_DataMapOfShapeListOfShape aMVV;
131   GEOMAlgo_IndexedDataMapOfIntegerShape aMIS;
132   NMTDS_IndexedDataMapOfShapeBndSphere aMSB;
133   //
134   NMTDS_BndSphereTreeSelector aSelector;
135   NMTDS_BndSphereTree aBBTree;
136   NCollection_UBTreeFiller <Standard_Integer, NMTDS_BndSphere> aTreeFiller(aBBTree);
137   //
138   myErrorStatus=0;
139   //
140   TopExp::MapShapes(myArgument, TopAbs_VERTEX, aMV);
141   aNbV=aMV.Extent();
142   if (!aNbV) {
143     myErrorStatus=2; // no vertices in source shape
144     return;
145   }
146   //
147   for (i=1; i<=aNbV; ++i) {
148     NMTDS_BndSphere aBox;
149     //
150     const TopoDS_Vertex& aV=*((TopoDS_Vertex*)&aMV(i));
151     aPV=BRep_Tool::Pnt(aV);
152     aTolV=BRep_Tool::Tolerance(aV);
153     //
154     aBox.SetGap(myTolerance);
155     aBox.SetCenter(aPV);
156     aBox.SetRadius(aTolV);
157     //
158     aTreeFiller.Add(i, aBox);
159     //
160     aMIS.Add(i, aV);
161     aMSB.Add(aV, aBox); 
162   }
163   //
164   aTreeFiller.Fill();
165   //
166   //---------------------------------------------------
167   // Chains
168   for (i=1; i<=aNbV; ++i) {
169     const TopoDS_Shape& aV=aMV(i);
170     //
171     if (aMVProcessed.Contains(aV)) {
172       continue;
173     }
174     //
175     Standard_Integer aNbIP, aIP, aNbIP1, aIP1;
176     TopTools_ListOfShape aLVSD;
177     TColStd_MapOfInteger aMIP, aMIP1, aMIPC;
178     TColStd_MapIteratorOfMapOfInteger aIt1;
179     //
180     aMIP.Add(i);
181     while(1) {
182       aNbIP=aMIP.Extent();
183       aIt1.Initialize(aMIP);
184       for(; aIt1.More(); aIt1.Next()) {
185         aIP=aIt1.Key();
186         if (aMIPC.Contains(aIP)) {
187           continue;
188         }
189         //
190         const TopoDS_Shape& aVP=aMIS.FindFromKey(aIP);
191         const NMTDS_BndSphere& aBoxVP=aMSB.FindFromKey(aVP);
192         //
193         aSelector.Clear();
194         aSelector.SetBox(aBoxVP);
195         //
196         aNbVSD=aBBTree.Select(aSelector);
197         if (!aNbVSD) {
198           continue;  // it shoild not be so [at least IP itself]    
199         }
200         //
201         const TColStd_ListOfInteger& aLI=aSelector.Indices();
202         aIt.Initialize(aLI);
203         for (; aIt.More(); aIt.Next()) {
204           aIP1=aIt.Value();
205           if (aMIP.Contains(aIP1)) {
206             continue;
207           }
208           aMIP1.Add(aIP1);
209         } //for (; aIt.More(); aIt.Next()) {
210       }//for(; aIt1.More(); aIt1.Next()) {
211       //
212       aNbIP1=aMIP1.Extent();
213       if (!aNbIP1) {
214         break;
215       }
216       //
217       aIt1.Initialize(aMIP);
218       for(; aIt1.More(); aIt1.Next()) {
219         aIP=aIt1.Key();
220         aMIPC.Add(aIP);
221       }
222       //
223       aMIP.Clear();
224       aIt1.Initialize(aMIP1);
225       for(; aIt1.More(); aIt1.Next()) {
226         aIP=aIt1.Key();
227         aMIP.Add(aIP);
228       }
229       aMIP1.Clear();
230     }// while(1)
231     //
232     // Fill myImages
233     aNbIP=aMIPC.Extent();
234     //
235     if (!aNbIP) {// no SD vertices is found
236       aMVProcessed.Add(aV);
237       continue;
238     }
239     //else { // SD vertices founded [ aMIPC ]
240     aIt1.Initialize(aMIPC);
241     for(j=0; aIt1.More(); aIt1.Next(), ++j) {
242       aIP=aIt1.Key();
243       const TopoDS_Shape& aVP=aMIS.FindFromKey(aIP);
244       if (!j) {
245         aVF=aVP;
246       }
247       aLVSD.Append(aVP);
248       aMVProcessed.Add(aVP);
249     }
250     //}
251     myImages.Bind(aVF, aLVSD);
252   }// for (i=1; i<=aNbV; ++i) {
253   //------------------------------
254   // Origins
255   aItIm.Initialize(myImages);
256   for (; aItIm.More(); aItIm.Next()) {
257     const TopoDS_Shape& aV=aItIm.Key();
258     const TopTools_ListOfShape& aLVSD=aItIm.Value();
259     aItS.Initialize(aLVSD);
260     for (; aItS.More(); aItS.Next()) {
261       const TopoDS_Shape& aVSD=aItS.Value();
262       if (!myOrigins.IsBound(aVSD)) {
263         myOrigins.Bind(aVSD, aV);
264       }
265     }
266   }
267 }
268 //=======================================================================
269 //function : DetectFaces
270 //purpose  : 
271 //=======================================================================
272 void GEOMAlgo_GlueDetector::DetectFaces()
273 {
274   DetectShapes(TopAbs_FACE);
275 }
276 //=======================================================================
277 //function : DetectEdges
278 //purpose  : 
279 //=======================================================================
280 void GEOMAlgo_GlueDetector::DetectEdges()
281 {
282   DetectShapes(TopAbs_EDGE);
283 }
284 //=======================================================================
285 //function : DetectShapes
286 //purpose  : 
287 //=======================================================================
288 void GEOMAlgo_GlueDetector::DetectShapes(const TopAbs_ShapeEnum aType)
289 {
290   Standard_Boolean bDegenerated;
291   Standard_Integer i, aNbF, aNbSDF, iErr;
292   TopTools_IndexedMapOfShape aMF;
293   TopTools_ListIteratorOfListOfShape aItLS;
294   GEOMAlgo_PassKeyShape aPKF;
295   GEOMAlgo_IndexedDataMapOfPassKeyShapeListOfShape aMPKLF;
296   //
297   myErrorStatus=0;
298   //
299   TopExp::MapShapes(myArgument, aType, aMF);
300   //
301   aNbF=aMF.Extent();
302   for (i=1; i<=aNbF; ++i) {
303     const TopoDS_Shape& aS=aMF(i);
304     // 
305     if (aType==TopAbs_FACE) {
306       const TopoDS_Face& aF=*((TopoDS_Face*)&aS);
307       FacePassKey(aF, aPKF);
308     }
309     else if (aType==TopAbs_EDGE) {
310       const TopoDS_Edge& aE=*((TopoDS_Edge*)&aS);
311       EdgePassKey(aE, aPKF);
312     }
313     //
314     if (myErrorStatus) {
315       return;
316     }
317     //
318     if (aMPKLF.Contains(aPKF)) {
319       TopTools_ListOfShape& aLSDF=aMPKLF.ChangeFromKey(aPKF);
320       aLSDF.Append(aS);
321     }
322     else {
323       TopTools_ListOfShape aLSDF;
324       //
325       aLSDF.Append(aS);
326       aMPKLF.Add(aPKF, aLSDF);
327     }
328   }
329   // check geometric coincidence
330   if (myCheckGeometry) {
331     iErr=GEOMAlgo_Tools::RefineSDShapes(aMPKLF, myTolerance, myContext);
332     if (iErr) {
333       myErrorStatus=200;
334       return;
335     }
336   }
337   //
338   // Images/Origins
339   aNbF=aMPKLF.Extent();
340   for (i=1; i<=aNbF; ++i) {
341     const TopTools_ListOfShape& aLSDF=aMPKLF(i);
342     aNbSDF=aLSDF.Extent();
343     if (!aNbSDF) {
344       myErrorStatus=4; // it must not be
345     }
346     //
347     if (aNbSDF==1) {
348       continue;
349     }
350     //
351     const TopoDS_Shape& aS1=aLSDF.First();  
352     //
353     if (aType==TopAbs_EDGE) {
354       const TopoDS_Edge& aE1=*((TopoDS_Edge*)&aS1);
355       bDegenerated=BRep_Tool::Degenerated(aE1);
356       if (bDegenerated) {
357         continue;
358       }
359     }
360     //
361     myImages.Bind(aS1, aLSDF);
362     // origins
363     aItLS.Initialize(aLSDF);
364     for (; aItLS.More(); aItLS.Next()) {
365       const TopoDS_Shape& aFSD=aItLS.Value();
366       if (!myOrigins.IsBound(aFSD)) {
367         myOrigins.Bind(aFSD, aS1);
368       }
369     }
370   }// for (i=1; i<=aNbF; ++i)
371 }
372 //=======================================================================
373 //function : FacePassKey
374 //purpose  : 
375 //=======================================================================
376 void GEOMAlgo_GlueDetector::FacePassKey(const TopoDS_Face& aF, 
377                                         GEOMAlgo_PassKeyShape& aPK)
378 {
379   Standard_Integer i, aNbE;
380   TopoDS_Shape aER;
381   TopTools_ListOfShape aLE;
382   TopTools_IndexedMapOfShape aME;
383   //
384   TopExp::MapShapes(aF, TopAbs_EDGE, aME);
385   //
386   aNbE=aME.Extent();
387   for (i=1; i<=aNbE; ++i) {
388     const TopoDS_Shape& aE=aME(i);
389     //
390     const TopoDS_Edge& aEE=*((TopoDS_Edge*)&aE);
391     if (BRep_Tool::Degenerated(aEE)) {
392       continue;
393     }
394     // 
395     if (myOrigins.IsBound(aE)) {
396       aER=myOrigins.Find(aE);
397     }
398     else {
399       aER=aE;
400     }
401     aLE.Append(aER);
402   }
403   aPK.SetShapes(aLE);
404 }
405 //=======================================================================
406 //function : EdgePassKey
407 //purpose  : 
408 //=======================================================================
409 void GEOMAlgo_GlueDetector::EdgePassKey(const TopoDS_Edge& aE, 
410                                         GEOMAlgo_PassKeyShape& aPK)
411 {
412   TopAbs_Orientation aOr;
413   TopoDS_Shape aVR;
414   TopoDS_Iterator aIt;
415   TopTools_ListOfShape aLV;
416   //
417   aIt.Initialize(aE);
418   for (; aIt.More(); aIt.Next()) {
419     const TopoDS_Shape& aV=aIt.Value();
420     aOr=aV.Orientation();
421     if (aOr==TopAbs_FORWARD || aOr==TopAbs_REVERSED) {
422       if (myOrigins.IsBound(aV)) {
423         aVR=myOrigins.Find(aV);
424       }
425       else {
426         aVR=aV;
427       }
428       aLV.Append(aVR);
429     }
430   }
431   //
432   aPK.SetShapes(aLV);
433 }