0025700: Ensuring uniform control of the functionalities of the Boolean operations...
[occt.git] / src / BOPTest / BOPTest_TolerCommands.cxx
1 // Created on: 2000-03-16
2 // Copyright (c) 2000-2014 OPEN CASCADE SAS
3 //
4 // This file is part of Open CASCADE Technology software library.
5 //
6 // This library is free software; you can redistribute it and/or modify it under
7 // the terms of the GNU Lesser General Public License version 2.1 as published
8 // by the Free Software Foundation, with special exception defined in the file
9 // OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
10 // distribution for complete text of the license and disclaimer of any warranty.
11 //
12 // Alternatively, this file may be used under the terms of Open CASCADE
13 // commercial license or contractual agreement.
14
15 #include <BOPTest.ixx>
16 #include <stdio.h>
17 #include <TCollection_AsciiString.hxx>
18 #include <TColStd_IndexedMapOfTransient.hxx>
19 #include <TopoDS_Shape.hxx>
20 #include <TopoDS_Vertex.hxx>
21 #include <Draw.hxx>
22 #include <DBRep.hxx>
23 #include <gp_Pnt2d.hxx>
24
25 #include <Geom_Curve.hxx>
26 #include <Geom2d_Curve.hxx>
27 #include <Geom_Surface.hxx>
28
29 #include <TopoDS.hxx>
30 #include <TopoDS_Vertex.hxx>
31 #include <TopoDS_Edge.hxx>
32 #include <TopoDS_Face.hxx>
33
34 #include <TopAbs_Orientation.hxx>
35
36 #include <TopTools_ListIteratorOfListOfShape.hxx>
37 #include <TopTools_ListOfShape.hxx>
38 #include <TopTools_IndexedDataMapOfShapeListOfShape.hxx>
39 #include <TopTools_MapOfShape.hxx>
40 #include <TopTools_IndexedMapOfShape.hxx>
41
42 #include <BRep_TVertex.hxx>
43 #include <BRep_TEdge.hxx>
44 #include <BRep_ListOfCurveRepresentation.hxx>
45 #include <BRep_ListIteratorOfListOfCurveRepresentation.hxx>
46 #include <BRep_CurveRepresentation.hxx>
47 #include <BRep_Tool.hxx>
48 #include <BRep_Builder.hxx>
49 #include <BRep_TFace.hxx>
50
51 #include <TopLoc_Location.hxx>
52
53 #include <BRepLib.hxx>
54
55 #include <TopExp.hxx>
56 #include <TopExp_Explorer.hxx>
57
58
59 //
60 static 
61   void ProcessVertex(const TopoDS_Vertex&,
62                      const TopTools_ListOfShape&,
63                      const TopTools_ListOfShape&);
64 static
65   void ProcessEdge(const TopoDS_Edge&, const Standard_Real);
66
67 static
68   void ReduceVertexTolerance (const TopoDS_Shape&);
69
70 static 
71   void ReduceFaceTolerance (const TopoDS_Shape&);
72
73 static
74   void ReduceEdgeTolerance (const TopoDS_Shape&, 
75                             const Standard_Real);
76
77 static
78   void PreparePCurves(const TopoDS_Shape& , 
79                       Draw_Interpretor& di);
80 //
81 static Standard_Integer breducetolerance (Draw_Interpretor&, Standard_Integer, const char** );
82 static Standard_Integer  btolx           (Draw_Interpretor&, Standard_Integer, const char** );
83 static Standard_Integer  bopaddpcs       (Draw_Interpretor&, Standard_Integer, const char** );
84 //=======================================================================
85 //function : TolerCommands
86 //purpose  : 
87 //=======================================================================
88   void  BOPTest::TolerCommands(Draw_Interpretor& theCommands)
89 {
90   static Standard_Boolean done = Standard_False;
91   if (done) 
92     return;
93
94   done = Standard_True;
95   // Chapter's name
96   const char* g = "BOPTest commands";
97   //
98   theCommands.Add("breducetolerance" ,  "use breducetolerance Shape",  
99                   __FILE__, breducetolerance, g);
100   theCommands.Add("btolx"     ,  "use btolx Shape [minTol=1.e-7]",  
101                   __FILE__, btolx, g);
102   theCommands.Add("bopaddpcs" ,  "Use >bopaddpcs Shape",
103                   __FILE__, bopaddpcs, g);
104 }
105 //=======================================================================
106 //function : btolx
107 //purpose  : 
108 //=======================================================================
109 Standard_Integer btolx(Draw_Interpretor& di, 
110                        Standard_Integer n,  
111                        const char** a)
112 {
113   if (n<2) {
114     di << " use btolx Shape [minTol=1.e-7]\n";
115     return 1;
116   }
117
118   TopoDS_Shape aS = DBRep::Get(a[1]);
119   
120   if (aS.IsNull()) {
121     di << " Null shape is not allowed\n";
122     return 1;
123   }
124   //
125   Standard_Real aTolEMin=1.e-7;
126   if (n==3) {
127     aTolEMin=Draw::Atof(a[2]);
128   }
129   //
130   // Edge Tolerances
131   ReduceEdgeTolerance(aS, aTolEMin);
132   //
133   // Face Tolerances
134   ReduceFaceTolerance(aS);
135   //
136   // Vertex Tolerances
137   ReduceVertexTolerance(aS);
138   //
139   BRepLib::SameParameter(aS, 1.e-7, Standard_True);
140   //
141   DBRep::Set (a[1], aS);
142   return 0;
143 }
144 //=======================================================================
145 //function : ReduceEdgeTolerance
146 //purpose  : 
147 //=======================================================================
148 void ReduceEdgeTolerance (const TopoDS_Shape& aS, 
149                           const Standard_Real aTolTreshold)
150 {
151   Standard_Integer i, aNbE;
152   TopTools_IndexedMapOfShape aEMap;
153   //
154   TopExp::MapShapes(aS, TopAbs_EDGE, aEMap);
155   //
156   aNbE=aEMap.Extent();
157   for (i=1; i<=aNbE; i++) {
158     const TopoDS_Edge& aE= TopoDS::Edge(aEMap(i));
159
160     ProcessEdge(aE, aTolTreshold);
161   } 
162 }
163 //=======================================================================
164 //function : ReduceFaceTolerance
165 //purpose  : 
166 //=======================================================================
167 void ReduceFaceTolerance (const TopoDS_Shape& aS)
168 {
169   Standard_Integer i, j, aNbF, aNbE;
170   Standard_Real aTolE, aTolx, aTolEMin;
171   TopTools_IndexedMapOfShape aFMap, aEMap;
172   //
173   aTolEMin=1.e-7;
174   //
175   TopExp::MapShapes(aS, TopAbs_FACE, aFMap);
176   aNbF=aFMap.Extent();
177   for (i=1; i<=aNbF; i++) {
178     aTolx=1.e6;
179     const TopoDS_Face& aF= TopoDS::Face(aFMap(i));
180     Handle(BRep_TFace)& aTF = *((Handle(BRep_TFace)*)&aF.TShape());
181     //
182     TopExp::MapShapes(aF, TopAbs_EDGE, aEMap);
183     aNbE=aEMap.Extent();
184     for (j=1; j<=aNbE; ++j) {
185       const TopoDS_Edge& aE= TopoDS::Edge(aEMap(j));
186       aTolE =BRep_Tool::Tolerance(aE);
187       if (aTolE<aTolx) {
188         aTolx=aTolE;
189       }
190     }
191     aTolE=(aTolx>aTolEMin) ? aTolx : aTolEMin;
192     aTF->Tolerance(aTolE);
193   }
194 }
195 //=======================================================================
196 //function : ReduceVertexTolerance
197 //purpose  : 
198 //=======================================================================
199 void ReduceVertexTolerance (const TopoDS_Shape& aS)
200 {
201   Standard_Integer i, aNbV;
202   TopTools_IndexedDataMapOfShapeListOfShape aVEMap, aVFMap;
203   
204   TopExp::MapShapesAndAncestors(aS, TopAbs_VERTEX, TopAbs_EDGE, aVEMap);
205   TopExp::MapShapesAndAncestors(aS, TopAbs_VERTEX, TopAbs_FACE, aVFMap);
206
207   aNbV=aVEMap.Extent();
208   for (i=1; i<=aNbV; i++) {
209     const TopoDS_Vertex& aV= TopoDS::Vertex(aVEMap.FindKey(i));
210     const TopTools_ListOfShape& aLE=aVEMap(i);
211     const TopTools_ListOfShape& aLF=aVFMap.FindFromKey(aV);
212     
213     ProcessVertex(aV, aLE, aLF);
214   }
215 }
216 //=======================================================================
217 //function : ProcessEdge
218 //purpose  : 
219 //=======================================================================
220 void ProcessEdge(const TopoDS_Edge& aE, const Standard_Real aTolTreshold)
221 {
222   Standard_Integer i, aNb=23;
223   Standard_Real aD2, aTolMax2, aT1, aT2, aT, dT;
224   gp_Pnt aPC3D, aP3D;
225   gp_Pnt2d aPC2D;
226
227   //TopTools_ListIteratorOfListOfShape anIt;// Wng in Gcc 3.0
228   BRep_ListIteratorOfListOfCurveRepresentation itcr;
229   //
230   Handle(Geom_Curve) aC3D=BRep_Tool::Curve(aE, aT1, aT2);
231   if (aC3D.IsNull()) {
232     return;
233   }
234   //
235   dT=(aT2-aT1)/aNb;
236   //
237   Handle(BRep_TEdge)& TE = *((Handle(BRep_TEdge)*)&aE.TShape());
238   const TopLoc_Location& Eloc = aE.Location();
239   //
240   aTolMax2=-1.e6;
241   const BRep_ListOfCurveRepresentation& aLCR=TE->Curves();
242   //
243   itcr.Initialize(aLCR);
244   for (; itcr.More(); itcr.Next()) {
245     const Handle(BRep_CurveRepresentation)& cr = itcr.Value();
246     const TopLoc_Location& loc = cr->Location();
247     TopLoc_Location L = (Eloc * loc);//.Predivided(aV.Location());
248     //
249     // 3D-Curve
250     if (cr->IsCurve3D()) {
251       continue;
252     }
253     //
254     // 2D-Curve
255     else if (cr->IsCurveOnSurface()) {
256       const Handle(Geom2d_Curve)& aC2D = cr->PCurve();
257       if (aC2D.IsNull()) {
258         continue;
259       }
260       // Surface
261       const Handle(Geom_Surface)& aS=cr->Surface();
262       //
263       // 2D-point treatment
264       for (i=0; i<=aNb; ++i) {
265         aT=aT1+i*dT;
266         if (i==aNb) {
267           aT=aT2;
268         }
269         aPC3D=aC3D->Value(aT);
270         aPC2D=aC2D->Value(aT);
271         aS->D0(aPC2D.X(), aPC2D.Y(), aP3D);
272         aP3D.Transform(L.Transformation());
273         aD2=aPC3D.SquareDistance(aP3D);
274         if (aD2 > aTolMax2) {
275           aTolMax2=aD2;
276         }
277       }
278     } //if (cr->IsCurveOnSurface())
279   }//for (; itcr.More(); itcr.Next())
280
281   //#########################################################
282   //
283   if (aTolMax2<0.){
284     return;
285   }
286   //
287   //
288   aTolMax2=sqrt(aTolMax2); 
289   
290   //printf(" aTolMax=%15.10lf, aTolWas=%15.10lf\n", aTolMax2, aTolE);
291
292   Standard_Real aTolSet;
293   aTolSet=(aTolMax2>aTolTreshold) ? aTolMax2 : aTolTreshold;
294
295   TE->Tolerance(aTolSet);
296 }
297 //=======================================================================
298 //function : ProcessVertex
299 //purpose  : 
300 //=======================================================================
301 void ProcessVertex(const TopoDS_Vertex& aV,
302                    const TopTools_ListOfShape& aLE,
303                    const TopTools_ListOfShape& aLF)
304 {
305   Standard_Real aTol, aD2, aTolMax2, aTolE, aParam;
306   gp_Pnt aPC3D;
307   gp_Pnt2d aPC2D;
308   TopAbs_Orientation anOrV;
309
310   TopTools_ListIteratorOfListOfShape anIt;
311   TopTools_MapOfShape aProcessedEdges;
312   TopExp_Explorer aVExp;
313   
314   BRep_ListIteratorOfListOfCurveRepresentation itcr;
315   //
316   aTolMax2=-1.e6;
317   //
318   Handle(BRep_TVertex)& TV = *((Handle(BRep_TVertex)*) &aV.TShape());
319   const gp_Pnt& aPV3D = TV->Pnt();
320   aTol =BRep_Tool::Tolerance(aV);
321   //
322   anIt.Initialize(aLE);
323   for (; anIt.More(); anIt.Next()) {
324     const TopoDS_Edge& aE=TopoDS::Edge(anIt.Value());
325     //
326     if (aProcessedEdges.Contains(aE)) {
327       continue;
328     }
329     aProcessedEdges.Add(aE);
330     //
331     Handle(BRep_TEdge)& TE = *((Handle(BRep_TEdge)*)&aE.TShape());
332     const TopLoc_Location& Eloc = aE.Location();
333     //
334     aVExp.Init(aE, TopAbs_VERTEX);
335     for (; aVExp.More(); aVExp.Next()) {
336       const TopoDS_Vertex& aVx=TopoDS::Vertex(aVExp.Current());
337       //
338       if (!aVx.IsSame(aV)) {
339         continue;
340       }
341       //
342       anOrV=aVx.Orientation();
343       if (!(anOrV==TopAbs_FORWARD || anOrV==TopAbs_REVERSED)) {
344         continue;
345       }
346       //
347       const BRep_ListOfCurveRepresentation& aLCR=TE->Curves();
348       itcr.Initialize(aLCR);
349       for (; itcr.More(); itcr.Next()) {
350         const Handle(BRep_CurveRepresentation)& cr = itcr.Value();
351         const TopLoc_Location& loc = cr->Location();
352         TopLoc_Location L = (Eloc * loc).Predivided(aV.Location());
353         //
354         // 3D-Curve
355         if (cr->IsCurve3D()) {
356           const Handle(Geom_Curve)& aC3D = cr->Curve3D();
357           //
358           if (aC3D.IsNull()) {
359             continue;
360           }
361           // 3D-point treatment
362           aParam=BRep_Tool::Parameter(aVx, aE);
363           aPC3D= aC3D->Value(aParam);
364           aPC3D.Transform(L.Transformation());
365           aD2=aPV3D.SquareDistance(aPC3D);
366           if (aD2 > aTolMax2) {
367             aTolMax2=aD2;
368           }
369           //
370         }//if (cr->IsCurve3D())
371         //
372         // 2D-Curve
373         else if (cr->IsCurveOnSurface()) {
374           const Handle(Geom2d_Curve)& aC2D = cr->PCurve();
375           if (aC2D.IsNull()) {
376             continue;
377           }
378           // Surface
379           const Handle(Geom_Surface)& aS=cr->Surface();
380           //
381           // 2D-point treatment
382           aParam=BRep_Tool::Parameter(aVx, aE, aS, L);
383           aPC2D=aC2D->Value(aParam);
384           aS->D0(aPC2D.X(), aPC2D.Y(), aPC3D);
385           aPC3D.Transform(L.Transformation());
386           aD2=aPV3D.SquareDistance(aPC3D);
387           if (aD2 > aTolMax2) {
388             aTolMax2=aD2;
389           }
390         } //if (cr->IsCurveOnSurface())
391         
392       }//for (; itcr.More(); itcr.Next())
393     }//for (; aVExp.More(); aVExp.Next()) 
394   }//for (; anIt.More(); anIt.Next()) 
395   //#########################################################
396   //
397   // Reducing
398   if (aTolMax2<0.){
399     return;
400   }
401   //
402   aTolMax2=sqrt(aTolMax2); 
403   if (aTolMax2>aTol) {
404     return;
405   }
406   //
407   aProcessedEdges.Clear();
408   anIt.Initialize(aLE);
409   for (; anIt.More(); anIt.Next()) {
410     const TopoDS_Edge& aE=TopoDS::Edge(anIt.Value());
411
412     if (aProcessedEdges.Contains(aE)) {
413       continue;
414     }
415     aProcessedEdges.Add(aE);
416
417     aTolE =BRep_Tool::Tolerance(aE);
418     if (aTolMax2 < aTolE) {
419       aTolMax2=aTolE;
420     }
421   }
422   //
423   aProcessedEdges.Clear();
424   anIt.Initialize(aLF);
425   for (; anIt.More(); anIt.Next()) {
426     const TopoDS_Face& aF=TopoDS::Face(anIt.Value());
427     
428     if (aProcessedEdges.Contains(aF)) {
429       continue;
430     }
431     aProcessedEdges.Add(aF);
432     
433     aTolE =BRep_Tool::Tolerance(aF);
434     if (aTolMax2 < aTolE) {
435       aTolMax2=aTolE;
436     }
437   }
438   //
439   if (aTolMax2>aTol) {
440     return;
441   }
442   //
443   // Update Tolerance
444   TV->Tolerance(aTolMax2);
445 }
446 //=======================================================================
447 //function : breducetolerance
448 //purpose  : 
449 //=======================================================================
450 Standard_Integer  breducetolerance(Draw_Interpretor& di, 
451                                    Standard_Integer n, 
452                                    const char** a)
453 {
454   if (n<2) {
455     di << " use bupdatetolerance Shape\n";
456     return 1;
457   }
458
459   TopoDS_Shape aS = DBRep::Get(a[1]);
460   
461   if (aS.IsNull()) {
462     di << " Null shape is not allowed \n";
463     return 1;
464   }
465   ReduceVertexTolerance(aS);
466   DBRep::Set (a[1], aS);
467   
468   return 0;
469 }
470 //
471 //=======================================================================
472 //function : bopaddpcs
473 //purpose  : Some Edges do not contain P-Curves on Faces to which 
474 //           they belong to. 
475 //           These faces usually based on Geom_Plane surface.
476 //           To prevent sophisticated treatment the Command "bopaddpcs:
477 //           adds P-Curves for the edges . 
478 //=======================================================================
479 Standard_Integer bopaddpcs(Draw_Interpretor& di, 
480                            Standard_Integer n,  
481                            const char** a)
482 {
483   if (n<2) {
484     di << " Use >bopaddpcs Shape\n";
485     return 1;
486   }
487
488   TopoDS_Shape aS = DBRep::Get(a[1]);
489   
490   if (aS.IsNull()) {
491     di << " Null shape is not allowed \n";
492     return 1;
493   }
494   //
495   PreparePCurves(aS, di);
496   //
497   DBRep::Set (a[1], aS);
498   return 0;
499 }
500 //=======================================================================
501 //function : PreparePCurves
502 //purpose  : 
503 //=======================================================================
504 void PreparePCurves(const TopoDS_Shape& aShape, Draw_Interpretor& di)
505 {
506   Standard_Integer i, aNbE;
507   Standard_Real aTolE, aT1, aT2;
508   TopTools_IndexedDataMapOfShapeListOfShape aEFMap;
509   TopLoc_Location aLoc;
510   Handle(Geom_Curve)   aC3D;
511   Handle(Geom2d_Curve) aC2D;
512   BRep_Builder aBB;
513   //
514   TopExp::MapShapesAndAncestors (aShape, TopAbs_EDGE, TopAbs_FACE, aEFMap);
515   //
516   aNbE=aEFMap.Extent();
517   for (i=1; i<=aNbE; ++i) {
518     const TopoDS_Edge& aE=TopoDS::Edge(aEFMap.FindKey(i));
519     //
520     if (BRep_Tool::Degenerated(aE)) {
521       continue;
522     }
523     //
524     aC3D=BRep_Tool::Curve(aE, aT1, aT2);
525     if (aC3D.IsNull()) {
526       continue;
527     }
528     aTolE=BRep_Tool::Tolerance(aE);
529     //
530     const TopTools_ListOfShape& aLF=aEFMap(i);
531     TopTools_ListIteratorOfListOfShape aFIt(aLF);
532     for (; aFIt.More(); aFIt.Next()) {
533       const TopoDS_Face& aF=TopoDS::Face(aFIt.Value());
534       //
535       // Map of surfaces on which the edge lays .
536       TColStd_IndexedMapOfTransient aSCRMap;
537       Handle(BRep_TEdge)& TE = *((Handle(BRep_TEdge)*)&aE.TShape());
538       const BRep_ListOfCurveRepresentation& aLCR=TE->Curves();
539       BRep_ListIteratorOfListOfCurveRepresentation itcr;
540       itcr.Initialize(aLCR);
541       for (; itcr.More(); itcr.Next()) {
542         const Handle(BRep_CurveRepresentation)& cr = itcr.Value();
543         //
544         if (cr->IsCurveOnSurface()) {
545           const Handle(Geom_Surface)& aSCR=cr->Surface();
546           aSCRMap.Add(aSCR);
547         }
548         //
549       }
550       //
551       const Handle(Geom_Surface)& aS=BRep_Tool::Surface(aF, aLoc);
552       if (!aSCRMap.Contains(aS)) {
553         // try to obtain 2D curve
554         aC2D=BRep_Tool::CurveOnSurface(aE, aS, aLoc, aT1, aT2);
555         if (aC2D.IsNull()) {
556           di << " Warning: Can not obtain P-Curve\n";
557           continue;
558         }
559         else {
560           aBB.UpdateEdge(aE, aC2D, aF, aTolE);
561         }
562       }
563     }
564   }
565 }