0024572: Improvement performance of BRepExtrema_DistShapeShape
[occt.git] / src / QADraw / QADraw.cxx
1 // Created on: 2002-02-04
2 // Created by: QA Admin
3 // Copyright (c) 2002-2014 OPEN CASCADE SAS
4 //
5 // This file is part of Open CASCADE Technology software library.
6 //
7 // This library is free software; you can redistribute it and/or modify it under
8 // the terms of the GNU Lesser General Public License version 2.1 as published
9 // by the Free Software Foundation, with special exception defined in the file
10 // OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
11 // distribution for complete text of the license and disclaimer of any warranty.
12 //
13 // Alternatively, this file may be used under the terms of Open CASCADE
14 // commercial license or contractual agreement.
15
16 #include <QADraw.hxx>
17 #include <Draw.hxx>
18 #include <Draw_Interpretor.hxx>
19 #include <Draw_Window.hxx>
20 #include <Draw_Viewer.hxx>
21 #include <Image_AlienPixMap.hxx>
22 #include <V3d_View.hxx>
23 #include <ViewerTest.hxx>
24 #include <ViewerTest_EventManager.hxx>
25 #include <TColStd_StackOfInteger.hxx>
26 #include <TColStd_ListOfInteger.hxx>
27 #include <TColStd_ListIteratorOfListOfInteger.hxx>
28 #include <TColStd_HSequenceOfReal.hxx>
29 #include <TopoDS_Shape.hxx>
30 #include <AIS_InteractiveContext.hxx>
31 #include <Aspect_Window.hxx>
32 #include <Aspect_WindowDriver.hxx>
33 #include <Aspect_DisplayConnection.hxx>
34 #include <Graphic3d.hxx>
35 #include <DBRep.hxx>
36 #include <Bnd_Box.hxx>
37 #include <BRepBndLib.hxx>
38 #include <BRepExtrema_DistShapeShape.hxx>
39 #include <BRepBuilderAPI_MakeVertex.hxx>
40 #include <TopTools_SequenceOfShape.hxx>
41 #include <TColgp_SequenceOfXYZ.hxx>
42 #include <OSD_Timer.hxx>
43 #include <stdio.h>
44
45 #if defined(_WIN32) || defined(__WIN32__)
46 #  include <windows.h>
47 #  include <io.h>
48 #else
49 #  include <unistd.h>
50 #endif
51
52 #include <Draw_PluginMacro.hxx>
53
54 Handle(TColStd_HSequenceOfReal) GetColorOfPixel (const Image_PixMap&    theImage,
55                                                  const Standard_Integer theCoordinateX,
56                                                  const Standard_Integer theCoordinateY,
57                                                  const Standard_Integer theRadius)
58 {
59   Handle(TColStd_HSequenceOfReal) aSeq = new TColStd_HSequenceOfReal();
60   if (theImage.IsEmpty()) {
61     std::cerr << "The image is null.\n";
62     return aSeq;
63   }
64   Standard_Integer aWidth   = (Standard_Integer )theImage.SizeX();
65   Standard_Integer anHeight = (Standard_Integer )theImage.SizeY();
66
67   Quantity_Color aColorTmp;
68   for (Standard_Integer anXIter = theCoordinateX - theRadius;
69        anXIter <= theCoordinateX + theRadius; ++anXIter)
70   {
71     if (anXIter < 0 || anXIter >= aWidth)
72     {
73       continue;
74     }
75     for (Standard_Integer anYIter = theCoordinateY - theRadius;
76          anYIter <= theCoordinateY + theRadius; ++anYIter)
77     {
78       if (anYIter < 0 || anYIter >= anHeight)
79       {
80         continue;
81       }
82       // Image_PixMap stores image upside-down in memory!
83       aColorTmp = theImage.PixelColor (anXIter, anYIter);
84       aSeq->Append (aColorTmp.Red());
85       aSeq->Append (aColorTmp.Green());
86       aSeq->Append (aColorTmp.Blue());
87     }
88   }
89   return aSeq;
90 }
91
92 static Standard_Integer QAAISGetPixelColor (Draw_Interpretor& theDi,
93                                             Standard_Integer  theArgsNb,
94                                             const char**      theArgs)
95 {
96   if (theArgsNb != 3 && theArgsNb != 6)
97   {
98     theDi << "Usage : " << theArgs[0] << " coordinate_X coordinate_Y [color_R color_G color_B]" << "\n";
99     return 1; // TCL_ERROR
100   }
101
102   Handle(V3d_View) aView3d = ViewerTest::CurrentView();
103   if (aView3d.IsNull())
104   {
105     theDi << "You must initialize AISViewer before this command.\n";
106     return 1; // TCL_ERROR
107   }
108
109   const Handle(Aspect_Window) anAISWindow = aView3d->Window();
110   Standard_Integer aWindowSizeX = 0;
111   Standard_Integer aWindowSizeY = 0;
112   anAISWindow->Size (aWindowSizeX, aWindowSizeY);
113
114   Standard_Integer anArgIter = 1;
115   const Standard_Integer aPickCoordX = Draw::Atoi (theArgs[anArgIter++]);
116   const Standard_Integer aPickCoordY = Draw::Atoi (theArgs[anArgIter++]);
117   const Standard_Integer aRadius = (theArgsNb == 3) ? 0 : 1;
118
119   Image_ColorRGBF aColorInput = {{ 0.0f, 0.0f, 0.0f }};
120   if (theArgsNb == 6)
121   {
122     aColorInput.r() = (Standard_ShortReal )Draw::Atof (theArgs[anArgIter++]);
123     aColorInput.g() = (Standard_ShortReal )Draw::Atof (theArgs[anArgIter++]);
124     aColorInput.b() = (Standard_ShortReal )Draw::Atof (theArgs[anArgIter++]);
125   }
126
127   Image_PixMap anImage;
128   aView3d->ToPixMap (anImage, aWindowSizeX, aWindowSizeY);
129   const Handle(TColStd_HSequenceOfReal) aSeq = GetColorOfPixel (anImage, aPickCoordX, aPickCoordY, aRadius);
130   cout << "Length = " << aSeq->Length() << endl;
131
132   Image_ColorRGBF aColorPicked = {{ 0.0f, 0.0f, 0.0f }};
133   Standard_Boolean isNotEqual = Standard_True;
134   for (Standard_Integer i = 1; i <= aSeq->Length(); i += 3)
135   {
136     aColorPicked.r() = (Standard_ShortReal )aSeq->Value (i + 0);
137     aColorPicked.g() = (Standard_ShortReal )aSeq->Value (i + 1);
138     aColorPicked.b() = (Standard_ShortReal )aSeq->Value (i + 2);
139
140     if (theArgsNb == 3 ||
141         ((Abs (aColorPicked.r() - aColorInput.r()) <= Precision::Confusion())
142       && (Abs (aColorPicked.g() - aColorInput.g()) <= Precision::Confusion())
143       && (Abs (aColorPicked.b() - aColorInput.b()) <= Precision::Confusion())))
144     {
145       isNotEqual = Standard_False;
146       break;
147     }
148   }
149
150   theDi << "RED :   " << aColorPicked.r() << " "
151         << "GREEN : " << aColorPicked.g() << " "
152         << "BLUE :  " << aColorPicked.b() << "\n";
153
154   if (theArgsNb == 6)
155   {
156     theDi << "User color: \n"
157           << "RED :   " << aColorInput.r() << " "
158           << "GREEN : " << aColorInput.g() << " "
159           << "BLUE :  " << aColorInput.b() << "\n";
160   }
161
162   if (isNotEqual)
163   {
164     theDi << "Faulty : colors are not equal.\n";
165     return 1; // TCL_ERROR
166   }
167   return 0;
168 }
169
170 //=======================================================================
171 #if ! defined(WNT)
172 extern ViewerTest_DoubleMapOfInteractiveAndName& GetMapOfAIS();
173 extern Handle(AIS_InteractiveContext)& TheAISContext();
174 #else
175 Standard_EXPORT ViewerTest_DoubleMapOfInteractiveAndName& GetMapOfAIS();
176 Standard_EXPORT Handle(AIS_InteractiveContext)& TheAISContext();
177 #endif
178 #include <ViewerTest_DoubleMapOfInteractiveAndName.hxx>
179 #include <AIS_Trihedron.hxx>
180 #include <AIS_Axis.hxx>
181 #include <Geom_Line.hxx>
182 #include <AIS_Line.hxx>
183
184 //==============================================================================
185 // function : VTrihedronOrigins
186 // author   : ota
187 // purpose  : draws triheron axis origin lines.
188 // Draw arg : vtri_orig trihedron_name
189 //==============================================================================
190 static int VTrihedronOrigins(Draw_Interpretor& di,
191                               Standard_Integer argc,
192                               const char ** argv)
193 {
194   if(argc != 2){
195     di <<"Usage : vtri_orig tri_name"<<"\n";
196     return 1;
197   }
198
199   if(TheAISContext().IsNull()){
200     di<<"Make 'vinit' before this method call"<<"\n";
201     return 1;
202   }
203
204   //get trihedron from AIS map.
205   TCollection_AsciiString aName(argv[1]);
206   if(!GetMapOfAIS().IsBound2(aName)){
207     di<<"No object named '"<<argv[1]<<"'"<<"\n";
208     return 1;
209   }
210
211   Handle(AIS_Trihedron) aTrih =
212     Handle(AIS_Trihedron)::DownCast(GetMapOfAIS().Find2(aName));
213   if(aTrih.IsNull()){
214     di<<"Trihedron is not found, try another name"<<"\n";
215     return 1;
216   }
217
218   //get axis
219   Handle(AIS_Axis) XAxis = aTrih->XAxis();
220   Handle(AIS_Axis) YAxis = aTrih->YAxis();
221   Handle(AIS_Axis) ZAxis = aTrih->Axis();
222
223   //get geometrical lines
224   Handle(Geom_Line) XGLine = XAxis->Component();
225   Handle(Geom_Line) YGLine = YAxis->Component();
226   Handle(Geom_Line) ZGLine = ZAxis->Component();
227
228   //make AIS_Lines
229   Handle(AIS_Line) XLine = new AIS_Line(XGLine);
230   Handle(AIS_Line) YLine = new AIS_Line(YGLine);
231   Handle(AIS_Line) ZLine = new AIS_Line(ZGLine);
232
233   //put them into AIS map:
234   GetMapOfAIS().Bind(XLine,aName+"_X");
235   GetMapOfAIS().Bind(YLine,aName+"_Y");
236   GetMapOfAIS().Bind(ZLine,aName+"_Z");
237   //print names of created objects:
238   di<<argv[1]<<"_X  "<<argv[1]<<"_Y  "<<argv[1]<<"_Z"<<"\n";
239
240   //try to draw them:
241   TheAISContext()->Display(XLine);
242   TheAISContext()->Display(YLine);
243   TheAISContext()->Display(ZLine);
244
245   return 0;
246 }
247
248 //=======================================================================
249 //function : QATestExtremaSS
250 //purpose  :
251 //=======================================================================
252 static Standard_Integer QATestExtremaSS (Draw_Interpretor& theInterpretor,
253                                          Standard_Integer  theArgNb,
254                                          const char**      theArgs)
255 {
256   if (theArgNb < 3
257    || theArgNb > 4)
258   {
259     std::cerr << "Usage: type help " << theArgs[0] << std::endl;
260     return 1;
261   }
262
263   // Get target shape
264   TopoDS_Shape aShape = DBRep::Get (theArgs[1]);
265   if (aShape.IsNull())
266   {
267     std::cerr << "Error: " << theArgs[1] << " shape is null\n";
268     return 1;
269   }
270
271   // Get step value
272   const Standard_Real aStep = Draw::Atof (theArgs[2]);
273   if (aStep <= 1e-5)
274   {
275     std::cerr << "Error: Step " << aStep << " is too small\n";
276     return 1;
277   }
278
279   Extrema_ExtFlag aFlag = Extrema_ExtFlag_MIN;
280   if (theArgNb > 3)
281   {
282     Standard_Integer aVal = Draw::Atoi (theArgs[3]);
283     if (aVal > 0)
284     {
285       aFlag = aVal == 1 ? Extrema_ExtFlag_MAX : Extrema_ExtFlag_MINMAX;
286     }
287   }
288
289   // Get bounding box of the shape
290   Bnd_Box aBounds;
291   BRepBndLib::Add (aShape, aBounds);
292
293   Standard_Real aXmin, aYmin, aZmin;
294   Standard_Real aXmax, aYmax, aZmax;
295   aBounds.Get (aXmin, aYmin, aZmin,
296                aXmax, aYmax, aZmax);
297
298   const Standard_Real aScaleFactor = 1.5;
299   aXmin *= aScaleFactor;
300   aYmin *= aScaleFactor;
301   aZmin *= aScaleFactor;
302   aXmax *= aScaleFactor;
303   aYmax *= aScaleFactor;
304   aZmax *= aScaleFactor;
305
306   TopTools_SequenceOfShape aList;
307   TColgp_SequenceOfXYZ     aPoints;
308   for (Standard_Real aX = aXmin + 0.5 * aStep; aX < aXmax; aX += aStep)
309   {
310     for (Standard_Real aY = aYmin + 0.5 * aStep; aY < aYmax; aY += aStep)
311     {
312       aList.Append (BRepBuilderAPI_MakeVertex (gp_Pnt (aX, aY, aZmin)));
313       aList.Append (BRepBuilderAPI_MakeVertex (gp_Pnt (aX, aY, aZmax)));
314
315       aPoints.Append (gp_XYZ (aX, aY, aZmin));
316       aPoints.Append (gp_XYZ (aX, aY, aZmax));
317     }
318
319     for (Standard_Real aZ = aZmin + 0.5 * aStep; aZ < aZmax; aZ += aStep)
320     {
321       aList.Append (BRepBuilderAPI_MakeVertex (gp_Pnt (aX, aYmin, aZ)));
322       aList.Append (BRepBuilderAPI_MakeVertex (gp_Pnt (aX, aYmax, aZ)));
323
324       aPoints.Append (gp_XYZ (aX, aYmin, aZ));
325       aPoints.Append (gp_XYZ (aX, aYmax, aZ));
326     }
327   }
328
329   for (Standard_Real aY = aYmin + 0.5 * aStep; aY < aYmax; aY += aStep)
330   {
331     for (Standard_Real aZ = aZmin + 0.5 * aStep; aZ < aZmax; aZ += aStep)
332     {
333       aList.Append (BRepBuilderAPI_MakeVertex (gp_Pnt (aXmin, aY, aZ)));
334       aList.Append (BRepBuilderAPI_MakeVertex (gp_Pnt (aXmax, aY, aZ)));
335
336       aPoints.Append (gp_XYZ (aXmin, aY, aZ));
337       aPoints.Append (gp_XYZ (aXmax, aY, aZ));
338     }
339   }
340
341   const Standard_Integer aNbPoints = aList.Length();
342   theInterpretor << "Number of sampled points: " << aNbPoints << "\n";
343
344   // Perform projection of points
345   OSD_Timer aTimer;
346   aTimer.Start();
347
348   // Perform projection using standard method
349   BRepExtrema_DistShapeShape aTool;
350   aTool.SetFlag (aFlag);
351   aTool.LoadS1 (aShape);
352   for (Standard_Integer anIdx = 1; anIdx <= aNbPoints; ++anIdx)
353   {
354     aTool.LoadS2 (aList (anIdx));
355     aTool.Perform();
356   }
357
358   aTimer.Stop();
359   theInterpretor << "Test for gradient descent complete in: " << aTimer.ElapsedTime() << "\n";
360   return 0;
361 }
362
363 //=======================================================================
364 //function : CommonCommands
365 //purpose  :
366 //=======================================================================
367 void QADraw::CommonCommands (Draw_Interpretor& theCommands)
368 {
369   const char* group = "QA_Commands";
370
371   theCommands.Add ("QAGetPixelColor",
372                    "QAGetPixelColor coordinate_X coordinate_Y [color_R color_G color_B]",
373                    __FILE__,
374                    QAAISGetPixelColor,
375                    group);
376
377   theCommands.Add ("vtri_orig",
378                    "vtri_orig         : vtri_orig trihedron_name  -  draws axis origin lines",
379                    __FILE__,
380                    VTrihedronOrigins,
381                    group);
382
383   theCommands.Add ("QATestExtremaSS",
384                    "QATestExtremaSS Shape Step [Flag { MIN = 0 | MAX = 1 | MINMAX = 2 }]",
385                    __FILE__,
386                    QATestExtremaSS,
387                    group);
388
389 // adding commands "rename" leads to the fact that QA commands doesn't work properly OCC23410, use function "renamevar"
390 // theCommands.Add("rename","rename name1 toname1 name2 toname2 ...",__FILE__,QArename,group);
391 }
392
393 //==============================================================================
394 // QADraw::Factory
395 //==============================================================================
396 void QADraw::Factory(Draw_Interpretor& theCommands)
397 {
398   // definition of QA Command
399   QADraw::CommonCommands(theCommands);
400   QADraw::AdditionalCommands(theCommands);
401 }
402
403 // Declare entry point PLUGINFACTORY
404 DPLUGIN(QADraw)