0027565: [Regression to OCCT 7.0.0] Number of Intersections Is Wrong
[occt.git] / src / BRepTest / BRepTest_ExtremaCommands.cxx
1 // Created on: 1995-09-08
2 // Created by: Modelistation
3 // Copyright (c) 1995-1999 Matra Datavision
4 // Copyright (c) 1999-2014 OPEN CASCADE SAS
5 //
6 // This file is part of Open CASCADE Technology software library.
7 //
8 // This library is free software; you can redistribute it and/or modify it under
9 // the terms of the GNU Lesser General Public License version 2.1 as published
10 // by the Free Software Foundation, with special exception defined in the file
11 // OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
12 // distribution for complete text of the license and disclaimer of any warranty.
13 //
14 // Alternatively, this file may be used under the terms of Open CASCADE
15 // commercial license or contractual agreement.
16
17 // modified by mps (juillet 96) : ajout de la commande distmini
18
19 #include <DBRep.hxx>
20 #include <BRepTest.hxx>
21 #include <BRepExtrema_Poly.hxx>
22 #include <BRepExtrema_DistShapeShape.hxx>
23 #include <BRepExtrema_ShapeProximity.hxx>
24 #include <BRepExtrema_SelfIntersection.hxx>
25 #include <BRepLib_MakeEdge.hxx>
26 #include <BRepLib_MakeVertex.hxx>
27 #include <BRepBuilderAPI_MakeEdge.hxx>
28 #include <TopoDS_Builder.hxx>
29 #include <TopoDS_Compound.hxx>
30 #include <Draw.hxx>
31 #include <OSD_Timer.hxx>
32 #include <TCollection_AsciiString.hxx>
33 #include <TColStd_MapIteratorOfPackedMapOfInteger.hxx>
34 #include <Precision.hxx>
35
36
37 //#ifdef _MSC_VER
38 #include <stdio.h>
39 //#endif
40
41 //=======================================================================
42 //function : distance
43 //purpose  : 
44 //=======================================================================
45
46 static Standard_Integer distance (Draw_Interpretor& di,
47                                   Standard_Integer n,
48                                   const char** a)
49 {
50   if (n < 3) return 1;
51
52   const char *name1 = a[1];
53   const char *name2 = a[2];
54
55   TopoDS_Shape S1 = DBRep::Get(name1);
56   TopoDS_Shape S2 = DBRep::Get(name2);
57   if (S1.IsNull() || S2.IsNull()) return 1;
58   gp_Pnt P1,P2;
59   Standard_Real D;
60   if (!BRepExtrema_Poly::Distance(S1,S2,P1,P2,D)) return 1;
61   //cout << " distance : " << D << endl;
62   di << " distance : " << D << "\n";
63   TopoDS_Edge E = BRepLib_MakeEdge(P1,P2);
64   DBRep::Set("distance",E);
65   return 0;
66 }
67
68 static Standard_Integer distmini(Draw_Interpretor& di, Standard_Integer n, const char** a)
69 {
70   if (n != 4 && n != 5 )
71     return 1;
72
73   const char *ns1 = (a[2]), *ns2 = (a[3]), *ns0 = (a[1]);
74   TopoDS_Shape S1(DBRep::Get(ns1)), S2(DBRep::Get(ns2));
75
76   Standard_Real aDeflection = Precision::Confusion();
77   if (n == 5)
78     aDeflection = Draw::Atoi(a[4]);
79
80   BRepExtrema_DistShapeShape dst(S1 ,S2, aDeflection);
81
82   if (dst.IsDone()) 
83   { 
84 #ifdef OCCT_DEBUG
85     //dst.Dump(cout);
86     di << "*** Dump of \"BRepExtrema_DistShapeShape\" in DEBUG mode (begin) *****\n";
87     Standard_SStream aSStream;
88     dst.Dump(aSStream);
89     di << aSStream;
90     di << "*** Dump of \"BRepExtrema_DistShapeShape\" in DEBUG mode (end)   *****\n";
91 #endif
92
93     di << "\"distmini\" command returns:\n";
94
95     char named[100];
96     Sprintf(named, "%s%s" ,ns0,"_val");
97     char* tempd = named;
98     Draw::Set(tempd,dst.Value());
99     di << named << " ";
100
101     for (Standard_Integer i1 = 1; i1<= dst.NbSolution(); i1++)
102     {
103       gp_Pnt P1,P2;
104       P1 = (dst.PointOnShape1(i1));
105       P2 = (dst.PointOnShape2(i1));
106       if (dst.Value()<=1.e-9) 
107       {
108         TopoDS_Vertex V =BRepLib_MakeVertex(P1);
109         char namev[100];
110         if (i1==1) 
111           Sprintf(namev, "%s" ,ns0);
112         else
113           Sprintf(namev, "%s%d" ,ns0,i1);
114         char* tempv = namev;
115         DBRep::Set(tempv,V);
116         di << namev << " ";
117       }
118       else
119       {
120         char name[100];
121         TopoDS_Edge E = BRepLib_MakeEdge (P1, P2);
122         if (i1==1)
123         {
124           Sprintf(name,"%s",ns0);
125         }
126         else
127         {
128           Sprintf(name,"%s%d",ns0,i1);
129         }
130         
131         char* temp = name;
132         DBRep::Set(temp,E);
133         di << name << " " ;
134       }
135     }
136
137     di << "\nOutput is complete.\n";
138
139   }
140   
141   else di << "probleme\n";
142   //else cout << "probleme"<< endl;
143   return 0;
144 }
145
146 //==============================================================================
147 //function : ShapeProximity
148 //purpose  :
149 //==============================================================================
150 static int ShapeProximity (Draw_Interpretor& theDI, Standard_Integer theNbArgs, const char** theArgs)
151 {
152   if (theNbArgs < 3 || theNbArgs > 6)
153   {
154     std::cout << "Usage: " << theArgs[0] <<
155       " Shape1 Shape2 [-tol <value>] [-profile]" << std::endl;
156
157     return 1;
158   }
159
160   TopoDS_Shape aShape1 = DBRep::Get (theArgs[1]);
161   TopoDS_Shape aShape2 = DBRep::Get (theArgs[2]);
162
163   if (aShape1.IsNull() || aShape2.IsNull())
164   {
165     std::cout << "Error: Failed to find specified shapes" << std::endl;
166     return 1;
167   }
168
169   BRepExtrema_ShapeProximity aTool;
170
171   Standard_Boolean aProfile = Standard_False;
172
173   for (Standard_Integer anArgIdx = 3; anArgIdx < theNbArgs; ++anArgIdx)
174   {
175     TCollection_AsciiString aFlag (theArgs[anArgIdx]);
176     aFlag.LowerCase();
177
178     if (aFlag == "-tol")
179     {
180       if (++anArgIdx >= theNbArgs)
181       {
182         std::cout << "Error: wrong syntax at argument '" << aFlag << std::endl;
183         return 1;
184       }
185
186       const Standard_Real aTolerance = Draw::Atof (theArgs[anArgIdx]);
187       if (aTolerance < 0.0)
188       {
189         std::cout << "Error: Tolerance value should be non-negative" << std::endl;
190         return 1;
191       }
192       else
193       {
194         aTool.SetTolerance (aTolerance);
195       }
196     }
197
198     if (aFlag == "-profile")
199     {
200       aProfile = Standard_True;
201     }
202   }
203
204   Standard_Real aInitTime = 0.0;
205   Standard_Real aWorkTime = 0.0;
206
207   OSD_Timer aTimer;
208
209   if (aProfile)
210   {
211     aTimer.Start();
212   }
213
214   aTool.LoadShape1 (aShape1);
215   aTool.LoadShape2 (aShape2);
216
217   if (aProfile)
218   {
219     aInitTime = aTimer.ElapsedTime();
220     aTimer.Reset();
221     aTimer.Start();
222   }
223
224   // Perform shape proximity test
225   aTool.Perform();
226
227   if (aProfile)
228   {
229     aWorkTime = aTimer.ElapsedTime();
230     aTimer.Stop();
231   }
232
233   if (!aTool.IsDone())
234   {
235     std::cout << "Error: Failed to perform proximity test" << std::endl;
236     return 1;
237   }
238
239   if (aProfile)
240   {
241     theDI << "Number of primitives in shape 1: " << aTool.ElementSet1()->Size() << "\n";
242     theDI << "Number of primitives in shape 2: " << aTool.ElementSet2()->Size() << "\n";
243     theDI << "Building data structures: " << aInitTime << "\n";
244     theDI << "Executing proximity test: " << aWorkTime << "\n";
245   }
246
247   TopoDS_Builder aCompBuilder;
248
249   TopoDS_Compound aFaceCompound1;
250   aCompBuilder.MakeCompound (aFaceCompound1);
251
252   for (BRepExtrema_MapOfIntegerPackedMapOfInteger::Iterator anIt1 (aTool.OverlapSubShapes1()); anIt1.More(); anIt1.Next())
253   {
254     TCollection_AsciiString aStr = TCollection_AsciiString (theArgs[1]) + "_" + (anIt1.Key() + 1);
255
256     const TopoDS_Face& aFace = aTool.GetSubShape1 (anIt1.Key());
257     aCompBuilder.Add (aFaceCompound1, aFace);
258     DBRep::Set (aStr.ToCString(), aFace);
259
260     theDI << aStr << " \n";
261   }
262
263   TopoDS_Compound aFaceCompound2;
264   aCompBuilder.MakeCompound (aFaceCompound2);
265
266   for (BRepExtrema_MapOfIntegerPackedMapOfInteger::Iterator anIt2 (aTool.OverlapSubShapes2()); anIt2.More(); anIt2.Next())
267   {
268     TCollection_AsciiString aStr = TCollection_AsciiString (theArgs[2]) + "_" + (anIt2.Key() + 1);
269
270     const TopoDS_Face& aFace = aTool.GetSubShape2 (anIt2.Key());
271     aCompBuilder.Add (aFaceCompound2, aFace);
272     DBRep::Set (aStr.ToCString(), aFace);
273
274     theDI << aStr << " \n";
275   }
276
277   DBRep::Set ((TCollection_AsciiString (theArgs[1]) + "_" + "overlapped").ToCString(), aFaceCompound1);
278   DBRep::Set ((TCollection_AsciiString (theArgs[2]) + "_" + "overlapped").ToCString(), aFaceCompound2);
279
280   return 0;
281 }
282
283 //==============================================================================
284 //function : ShapeSelfIntersection
285 //purpose  :
286 //==============================================================================
287 static int ShapeSelfIntersection (Draw_Interpretor& theDI, Standard_Integer theNbArgs, const char** theArgs)
288 {
289   if (theNbArgs < 2 || theNbArgs > 5)
290   {
291     std::cout << "Usage: " << theArgs[0] <<
292       " Shape [-tol <value>] [-profile]" << std::endl;
293
294     return 1;
295   }
296
297   TopoDS_Shape aShape = DBRep::Get (theArgs[1]);
298
299   if (aShape.IsNull())
300   {
301     std::cout << "Error: Failed to find specified shape" << std::endl;
302     return 1;
303   }
304
305   Standard_Real    aTolerance = 0.0;
306   Standard_Boolean aToProfile = Standard_False;
307
308   for (Standard_Integer anArgIdx = 2; anArgIdx < theNbArgs; ++anArgIdx)
309   {
310     TCollection_AsciiString aFlag (theArgs[anArgIdx]);
311     aFlag.LowerCase();
312
313     if (aFlag == "-tol")
314     {
315       if (++anArgIdx >= theNbArgs)
316       {
317         std::cout << "Error: wrong syntax at argument '" << aFlag << std::endl;
318         return 1;
319       }
320
321       const Standard_Real aValue = Draw::Atof (theArgs[anArgIdx]);
322       if (aValue < 0.0)
323       {
324         std::cout << "Error: Tolerance value should be non-negative" << std::endl;
325         return 1;
326       }
327       else
328       {
329         aTolerance = aValue;
330       }
331     }
332
333     if (aFlag == "-profile")
334     {
335       aToProfile = Standard_True;
336     }
337   }
338
339   OSD_Timer aTimer;
340
341   Standard_Real aInitTime = 0.0;
342   Standard_Real aWorkTime = 0.0;
343
344   if (aToProfile)
345   {
346     aTimer.Start();
347   }
348
349   BRepExtrema_SelfIntersection aTool (aShape, aTolerance);
350
351   if (aToProfile)
352   {
353     aInitTime = aTimer.ElapsedTime();
354
355     aTimer.Reset();
356     aTimer.Start();
357   }
358
359   // Perform shape self-intersection test
360   aTool.Perform();
361
362   if (!aTool.IsDone())
363   {
364     std::cout << "Error: Failed to perform proximity test" << std::endl;
365     return 1;
366   }
367
368   if (aToProfile)
369   {
370     aWorkTime = aTimer.ElapsedTime();
371     aTimer.Stop();
372
373     theDI << "Building data structure (BVH):    " << aInitTime << "\n";
374     theDI << "Executing self-intersection test: " << aWorkTime << "\n";
375   }
376
377   // Extract output faces
378   TopoDS_Builder  aCompBuilder;
379   TopoDS_Compound aFaceCompound;
380
381   aCompBuilder.MakeCompound (aFaceCompound);
382
383   for (BRepExtrema_MapOfIntegerPackedMapOfInteger::Iterator anIt (aTool.OverlapElements()); anIt.More(); anIt.Next())
384   {
385     TCollection_AsciiString aStr = TCollection_AsciiString (theArgs[1]) + "_" + (anIt.Key() + 1);
386
387     const TopoDS_Face& aFace = aTool.GetSubShape (anIt.Key());
388     aCompBuilder.Add (aFaceCompound, aFace);
389     DBRep::Set (aStr.ToCString(), aFace);
390
391     theDI << aStr << " \n";
392   }
393
394   theDI << "Compound of overlapped sub-faces: " << theArgs[1] << "_overlapped\n";
395   DBRep::Set ((TCollection_AsciiString (theArgs[1]) + "_" + "overlapped").ToCString(), aFaceCompound);
396
397   return 0;
398 }
399
400 //=======================================================================
401 //function : ExtremaCommands
402 //purpose  : 
403 //=======================================================================
404
405 void BRepTest::ExtremaCommands (Draw_Interpretor& theCommands)
406 {
407   static const char*      aGroup = "TOPOLOGY Extrema commands";
408   static Standard_Boolean isDone = Standard_False;
409   if (isDone)
410   {
411     return;
412   }
413   isDone = Standard_True;
414
415   theCommands.Add ("dist",
416                    "dist Shape1 Shape2",
417                    __FILE__,
418                    distance,
419                    aGroup);
420
421   theCommands.Add ("distmini",
422                    "distmini name Shape1 Shape2 [deflection]",
423                    __FILE__,
424                    distmini,
425                    aGroup);
426
427   theCommands.Add ("proximity",
428                    "proximity Shape1 Shape2 [-tol <value>] [-profile]"
429                    "\n\t\t: Searches for pairs of overlapping faces of the given shapes."
430                    "\n\t\t: The options are:"
431                    "\n\t\t:   -tol     : non-negative tolerance value used for overlapping"
432                    "\n\t\t:              test (for zero tolerance, the strict intersection"
433                    "\n\t\t:              test will be performed)"
434                    "\n\t\t:   -profile : outputs execution time for main algorithm stages",
435                    __FILE__,
436                    ShapeProximity,
437                    aGroup);
438
439   theCommands.Add ("selfintersect",
440                    "selfintersect Shape [-tol <value>] [-profile]"
441                    "\n\t\t: Searches for intersected/overlapped faces in the given shape."
442                    "\n\t\t: The algorithm uses shape tessellation (should be computed in"
443                    "\n\t\t: advance), and provides approximate results. The options are:"
444                    "\n\t\t:   -tol     : non-negative tolerance value used for overlapping"
445                    "\n\t\t:              test (for zero tolerance, the strict intersection"
446                    "\n\t\t:              test will be performed)"
447                    "\n\t\t:   -profile : outputs execution time for main algorithm stages",
448                    __FILE__,
449                    ShapeSelfIntersection,
450                    aGroup);
451 }