0031687: Draw Harness, ViewerTest - extend command vrenderparams with option updating...
[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   //std::cout << " distance : " << D << std::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::Atof(a[4]);
79
80   BRepExtrema_DistShapeShape dst(S1 ,S2, aDeflection);
81
82   if (dst.IsDone()) 
83   { 
84 #ifdef OCCT_DEBUG
85     //dst.Dump(std::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 << "problem: no distance is found\n";
142   return 0;
143 }
144
145 //==============================================================================
146 //function : ShapeProximity
147 //purpose  :
148 //==============================================================================
149 static int ShapeProximity (Draw_Interpretor& theDI, Standard_Integer theNbArgs, const char** theArgs)
150 {
151   if (theNbArgs < 3 || theNbArgs > 6)
152   {
153     std::cout << "Usage: " << theArgs[0] <<
154       " Shape1 Shape2 [-tol <value>] [-profile]" << std::endl;
155
156     return 1;
157   }
158
159   TopoDS_Shape aShape1 = DBRep::Get (theArgs[1]);
160   TopoDS_Shape aShape2 = DBRep::Get (theArgs[2]);
161
162   if (aShape1.IsNull() || aShape2.IsNull())
163   {
164     std::cout << "Error: Failed to find specified shapes" << std::endl;
165     return 1;
166   }
167
168   BRepExtrema_ShapeProximity aTool;
169
170   Standard_Boolean aProfile = Standard_False;
171
172   for (Standard_Integer anArgIdx = 3; anArgIdx < theNbArgs; ++anArgIdx)
173   {
174     TCollection_AsciiString aFlag (theArgs[anArgIdx]);
175     aFlag.LowerCase();
176
177     if (aFlag == "-tol")
178     {
179       if (++anArgIdx >= theNbArgs)
180       {
181         std::cout << "Error: wrong syntax at argument '" << aFlag << std::endl;
182         return 1;
183       }
184
185       const Standard_Real aTolerance = Draw::Atof (theArgs[anArgIdx]);
186       if (aTolerance < 0.0)
187       {
188         std::cout << "Error: Tolerance value should be non-negative" << std::endl;
189         return 1;
190       }
191       else
192       {
193         aTool.SetTolerance (aTolerance);
194       }
195     }
196
197     if (aFlag == "-profile")
198     {
199       aProfile = Standard_True;
200     }
201   }
202
203   Standard_Real aInitTime = 0.0;
204   Standard_Real aWorkTime = 0.0;
205
206   OSD_Timer aTimer;
207
208   if (aProfile)
209   {
210     aTimer.Start();
211   }
212
213   aTool.LoadShape1 (aShape1);
214   aTool.LoadShape2 (aShape2);
215
216   if (aProfile)
217   {
218     aInitTime = aTimer.ElapsedTime();
219     aTimer.Reset();
220     aTimer.Start();
221   }
222
223   // Perform shape proximity test
224   aTool.Perform();
225
226   if (aProfile)
227   {
228     aWorkTime = aTimer.ElapsedTime();
229     aTimer.Stop();
230   }
231
232   if (!aTool.IsDone())
233   {
234     std::cout << "Error: Failed to perform proximity test" << std::endl;
235     return 1;
236   }
237
238   if (aProfile)
239   {
240     theDI << "Number of primitives in shape 1: " << aTool.ElementSet1()->Size() << "\n";
241     theDI << "Number of primitives in shape 2: " << aTool.ElementSet2()->Size() << "\n";
242     theDI << "Building data structures: " << aInitTime << "\n";
243     theDI << "Executing proximity test: " << aWorkTime << "\n";
244   }
245
246   TopoDS_Builder aCompBuilder;
247
248   TopoDS_Compound aFaceCompound1;
249   aCompBuilder.MakeCompound (aFaceCompound1);
250
251   for (BRepExtrema_MapOfIntegerPackedMapOfInteger::Iterator anIt1 (aTool.OverlapSubShapes1()); anIt1.More(); anIt1.Next())
252   {
253     TCollection_AsciiString aStr = TCollection_AsciiString (theArgs[1]) + "_" + (anIt1.Key() + 1);
254
255     const TopoDS_Face& aFace = aTool.GetSubShape1 (anIt1.Key());
256     aCompBuilder.Add (aFaceCompound1, aFace);
257     DBRep::Set (aStr.ToCString(), aFace);
258
259     theDI << aStr << " \n";
260   }
261
262   TopoDS_Compound aFaceCompound2;
263   aCompBuilder.MakeCompound (aFaceCompound2);
264
265   for (BRepExtrema_MapOfIntegerPackedMapOfInteger::Iterator anIt2 (aTool.OverlapSubShapes2()); anIt2.More(); anIt2.Next())
266   {
267     TCollection_AsciiString aStr = TCollection_AsciiString (theArgs[2]) + "_" + (anIt2.Key() + 1);
268
269     const TopoDS_Face& aFace = aTool.GetSubShape2 (anIt2.Key());
270     aCompBuilder.Add (aFaceCompound2, aFace);
271     DBRep::Set (aStr.ToCString(), aFace);
272
273     theDI << aStr << " \n";
274   }
275
276   DBRep::Set ((TCollection_AsciiString (theArgs[1]) + "_" + "overlapped").ToCString(), aFaceCompound1);
277   DBRep::Set ((TCollection_AsciiString (theArgs[2]) + "_" + "overlapped").ToCString(), aFaceCompound2);
278
279   return 0;
280 }
281
282 //==============================================================================
283 //function : ShapeSelfIntersection
284 //purpose  :
285 //==============================================================================
286 static int ShapeSelfIntersection (Draw_Interpretor& theDI, Standard_Integer theNbArgs, const char** theArgs)
287 {
288   if (theNbArgs < 2 || theNbArgs > 5)
289   {
290     std::cout << "Usage: " << theArgs[0] <<
291       " Shape [-tol <value>] [-profile]" << std::endl;
292
293     return 1;
294   }
295
296   TopoDS_Shape aShape = DBRep::Get (theArgs[1]);
297
298   if (aShape.IsNull())
299   {
300     std::cout << "Error: Failed to find specified shape" << std::endl;
301     return 1;
302   }
303
304   Standard_Real    aTolerance = 0.0;
305   Standard_Boolean aToProfile = Standard_False;
306
307   for (Standard_Integer anArgIdx = 2; anArgIdx < theNbArgs; ++anArgIdx)
308   {
309     TCollection_AsciiString aFlag (theArgs[anArgIdx]);
310     aFlag.LowerCase();
311
312     if (aFlag == "-tol")
313     {
314       if (++anArgIdx >= theNbArgs)
315       {
316         std::cout << "Error: wrong syntax at argument '" << aFlag << std::endl;
317         return 1;
318       }
319
320       const Standard_Real aValue = Draw::Atof (theArgs[anArgIdx]);
321       if (aValue < 0.0)
322       {
323         std::cout << "Error: Tolerance value should be non-negative" << std::endl;
324         return 1;
325       }
326       else
327       {
328         aTolerance = aValue;
329       }
330     }
331
332     if (aFlag == "-profile")
333     {
334       aToProfile = Standard_True;
335     }
336   }
337
338   OSD_Timer aTimer;
339
340   Standard_Real aInitTime = 0.0;
341   Standard_Real aWorkTime = 0.0;
342
343   if (aToProfile)
344   {
345     aTimer.Start();
346   }
347
348   BRepExtrema_SelfIntersection aTool (aShape, aTolerance);
349
350   if (aToProfile)
351   {
352     aInitTime = aTimer.ElapsedTime();
353
354     aTimer.Reset();
355     aTimer.Start();
356   }
357
358   // Perform shape self-intersection test
359   aTool.Perform();
360
361   if (!aTool.IsDone())
362   {
363     std::cout << "Error: Failed to perform proximity test" << std::endl;
364     return 1;
365   }
366
367   if (aToProfile)
368   {
369     aWorkTime = aTimer.ElapsedTime();
370     aTimer.Stop();
371
372     theDI << "Building data structure (BVH):    " << aInitTime << "\n";
373     theDI << "Executing self-intersection test: " << aWorkTime << "\n";
374   }
375
376   // Extract output faces
377   TopoDS_Builder  aCompBuilder;
378   TopoDS_Compound aFaceCompound;
379
380   aCompBuilder.MakeCompound (aFaceCompound);
381
382   for (BRepExtrema_MapOfIntegerPackedMapOfInteger::Iterator anIt (aTool.OverlapElements()); anIt.More(); anIt.Next())
383   {
384     TCollection_AsciiString aStr = TCollection_AsciiString (theArgs[1]) + "_" + (anIt.Key() + 1);
385
386     const TopoDS_Face& aFace = aTool.GetSubShape (anIt.Key());
387     aCompBuilder.Add (aFaceCompound, aFace);
388     DBRep::Set (aStr.ToCString(), aFace);
389
390     theDI << aStr << " \n";
391   }
392
393   theDI << "Compound of overlapped sub-faces: " << theArgs[1] << "_overlapped\n";
394   DBRep::Set ((TCollection_AsciiString (theArgs[1]) + "_" + "overlapped").ToCString(), aFaceCompound);
395
396   return 0;
397 }
398
399 //=======================================================================
400 //function : ExtremaCommands
401 //purpose  : 
402 //=======================================================================
403
404 void BRepTest::ExtremaCommands (Draw_Interpretor& theCommands)
405 {
406   static const char*      aGroup = "TOPOLOGY Extrema commands";
407   static Standard_Boolean isDone = Standard_False;
408   if (isDone)
409   {
410     return;
411   }
412   isDone = Standard_True;
413
414   theCommands.Add ("dist",
415                    "dist Shape1 Shape2",
416                    __FILE__,
417                    distance,
418                    aGroup);
419
420   theCommands.Add ("distmini",
421                    "distmini name Shape1 Shape2 [deflection]",
422                    __FILE__,
423                    distmini,
424                    aGroup);
425
426   theCommands.Add ("proximity",
427                    "proximity Shape1 Shape2 [-tol <value>] [-profile]"
428                    "\n\t\t: Searches for pairs of overlapping faces of the given shapes."
429                    "\n\t\t: The options are:"
430                    "\n\t\t:   -tol     : non-negative tolerance value used for overlapping"
431                    "\n\t\t:              test (for zero tolerance, the strict intersection"
432                    "\n\t\t:              test will be performed)"
433                    "\n\t\t:   -profile : outputs execution time for main algorithm stages",
434                    __FILE__,
435                    ShapeProximity,
436                    aGroup);
437
438   theCommands.Add ("selfintersect",
439                    "selfintersect Shape [-tol <value>] [-profile]"
440                    "\n\t\t: Searches for intersected/overlapped faces in the given shape."
441                    "\n\t\t: The algorithm uses shape tessellation (should be computed in"
442                    "\n\t\t: advance), and provides approximate results. The options are:"
443                    "\n\t\t:   -tol     : non-negative tolerance value used for overlapping"
444                    "\n\t\t:              test (for zero tolerance, the strict intersection"
445                    "\n\t\t:              test will be performed)"
446                    "\n\t\t:   -profile : outputs execution time for main algorithm stages",
447                    __FILE__,
448                    ShapeSelfIntersection,
449                    aGroup);
450 }