0027457: Modeling - Raise exception if scaled transformation is used for shape location
[occt.git] / src / BRepTest / BRepTest_BasicCommands.cxx
1 // Created on: 1994-12-13
2 // Created by: Jacques GOUSSARD
3 // Copyright (c) 1994-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 #include <Standard_Stream.hxx>
18 #include <Standard_Macro.hxx>
19
20 #include <BRepTest.hxx>
21
22 #include <DBRep.hxx>
23 #include <Draw_Appli.hxx>
24 #include <Draw_Interpretor.hxx>
25 #include <Draw_Box.hxx>
26
27 #include <BRepBuilderAPI.hxx>
28 #include <BRepBuilderAPI_FindPlane.hxx>
29 #include <BRepBuilderAPI_Copy.hxx>
30 #include <BRepBuilderAPI_Transform.hxx>
31 #include <BRepBuilderAPI_GTransform.hxx>
32 #include <BRepBuilderAPI_NurbsConvert.hxx>
33 #include <gp_Ax2.hxx>
34 #include <gp_Mat.hxx>
35 #include <gp_GTrsf.hxx>
36 #include <BRepOffsetAPI_NormalProjection.hxx>
37 #include <BRepLib.hxx>
38 #include <BRep_Builder.hxx>
39 #include <BRepBndLib.hxx>
40 #include <Bnd_Box.hxx>
41 #include <Bnd_Box2d.hxx>
42 #include <Message.hxx>
43 #include <TopExp_Explorer.hxx>
44 #include <TopoDS.hxx>
45 #include <BRepTools_WireExplorer.hxx>
46
47 #include <GCPnts_QuasiUniformAbscissa.hxx>
48 #include <Geom2dAdaptor_Curve.hxx>
49 #include <GeomAdaptor_Curve.hxx>
50 #include <ProjLib_ComputeApproxOnPolarSurface.hxx>
51 #include <DrawTrSurf.hxx>
52 #include <Geom_Plane.hxx>
53
54 #include <OSD_Timer.hxx>
55 #include <Draw_Segment3D.hxx>
56 #include <Draw_Marker3D.hxx>
57 #include <Draw_MarkerShape.hxx>
58 #include <BRepPrimAPI_MakeBox.hxx>
59 #include <BRepTools_PurgeLocations.hxx>
60 #include <BRepTools.hxx>
61 #include <Standard_Dump.hxx>
62
63 #include <stdio.h>
64
65 Standard_IMPORT Draw_Viewer dout;
66
67 //=======================================================================
68 //function : ConvertBndToShape
69 //purpose  : Creates TopoDS_Solid from theBox
70 //=======================================================================
71 static void ConvertBndToShape(const Bnd_OBB& theBox,
72                               const char* const theName)
73 {
74   if (theBox.IsVoid())
75   {
76     DBRep::Set (theName, TopoDS_Shape());
77     return;
78   }
79
80   const gp_Pnt &aBaryCenter = theBox.Center();
81   const gp_XYZ &aXDir = theBox.XDirection(),
82                &aYDir = theBox.YDirection(),
83                &aZDir = theBox.ZDirection();
84   Standard_Real aHalfX = theBox.XHSize(),
85                 aHalfY = theBox.YHSize(),
86                 aHalfZ = theBox.ZHSize();
87
88   gp_Ax2 anAxes(aBaryCenter, aZDir, aXDir);
89   anAxes.SetLocation(aBaryCenter.XYZ() - aHalfX*aXDir - aHalfY*aYDir - aHalfZ*aZDir);
90   TopoDS_Solid aBox = BRepPrimAPI_MakeBox(anAxes, 2.0*aHalfX, 2.0*aHalfY, 2.0*aHalfZ);
91   DBRep::Set(theName, aBox);
92 }
93
94 //=======================================================================
95 // addpcurve
96 //=======================================================================
97
98 static Standard_Integer addpcurve(Draw_Interpretor& , Standard_Integer n, const char** a)
99 {
100   if(n < 4) return 1;
101   TopoDS_Shape E = DBRep::Get(a[1]);
102   if (E.IsNull()) return 1;
103   Handle(Geom2d_Curve) PC = DrawTrSurf::GetCurve2d(a[2]);
104   TopoDS_Shape F = DBRep::Get(a[3]);
105   Standard_Real tol = 1.e-7;
106   if (n > 4) {
107     tol = Draw::Atof(a[4]);
108   }
109   BRep_Builder BB;
110   BB.UpdateEdge(TopoDS::Edge(E), PC, TopoDS::Face(F),tol); 
111   DBRep::Set(a[1], E);
112   return 0;
113 }
114
115
116 //=======================================================================
117 // transform
118 //=======================================================================
119
120 static Standard_Integer transform(Draw_Interpretor&,Standard_Integer n,const char** a)
121 {
122   if (n <= 1) return 1;
123
124   gp_Trsf T;
125   Standard_Integer last = n;
126   const char* aName = a[0];
127
128   Standard_Boolean isBasic = Standard_False;
129   Standard_Boolean isForced = Standard_False;
130   Standard_Boolean isCopy = Standard_False;
131
132   // Check "copy" flag.
133   if (!strcmp(a[n-1], "-copy")) {
134     isCopy = Standard_True;
135     last = --n;
136   }
137
138   if (!strcmp(aName,"reset")) {
139   }
140   else {
141     isBasic = (aName[0] == 'b');
142     isForced = (aName[0] == 'f');
143
144     aName++;
145
146     if (!strcmp(aName,"move")) {
147       if (n < 3) return 1;
148       TopoDS_Shape SL = DBRep::Get(a[n-1]);
149       if (SL.IsNull()) return 0;
150       T = SL.Location().Transformation();
151       last = n-1;
152       isBasic = Standard_True;
153     }
154     else if (!strcmp(aName,"translate")) {
155       if (n < 5) return 1;
156       T.SetTranslation(gp_Vec(Draw::Atof(a[n-3]),Draw::Atof(a[n-2]),Draw::Atof(a[n-1])));
157       last = n-3;
158     }
159     else if (!strcmp(aName,"rotate")) {
160       if (n < 9) return 1;
161       T.SetRotation(gp_Ax1(gp_Pnt(Draw::Atof(a[n-7]),Draw::Atof(a[n-6]),Draw::Atof(a[n-5])),
162                     gp_Vec(Draw::Atof(a[n-4]),Draw::Atof(a[n-3]),Draw::Atof(a[n-2]))),
163                     Draw::Atof(a[n-1])* (M_PI / 180.0));
164       last = n-7;
165     }
166     else if (!strcmp(aName,"mirror")) {
167       if (n < 8) return 1;
168       T.SetMirror(gp_Ax2(gp_Pnt(Draw::Atof(a[n-6]),Draw::Atof(a[n-5]),Draw::Atof(a[n-4])),
169                   gp_Vec(Draw::Atof(a[n-3]),Draw::Atof(a[n-2]),Draw::Atof(a[n-1]))));
170
171       last = n-6;
172     }
173     else if (!strcmp(aName,"scale")) {
174       if (n < 6) return 1;
175       T.SetScale(gp_Pnt(Draw::Atof(a[n-4]),Draw::Atof(a[n-3]),Draw::Atof(a[n-2])),Draw::Atof(a[n-1]));
176       last = n-4;
177     }
178   }
179
180   if (T.Form() == gp_Identity || isBasic || isForced) {
181     Standard_Boolean isExeption = Standard_True;
182     if (isForced)
183     {
184       isExeption = Standard_False;
185     }
186     TopLoc_Location L(T);
187     for (Standard_Integer i = 1; i < last; i++) {
188       TopoDS_Shape S = DBRep::Get(a[i]);
189       if (S.IsNull())
190       {
191         Message::SendFail() << "Error: " << a[i] << " is not a valid shape";
192         return 1;
193       }
194       else
195       {
196         try
197         {
198           if (!strcmp(aName, "move") || !strcmp(aName, "reset"))
199           {
200             DBRep::Set(a[i], S.Located(L, isExeption));
201           }
202           else
203           {
204             DBRep::Set(a[i], S.Moved(L, isExeption));
205           }
206         }
207         catch (const Standard_DomainError&)
208         {
209           TCollection_AsciiString aScale(T.ScaleFactor());
210           Message::SendWarning() << "Operation is not done: " << aName << " is not a valid transformation - scale = " << aScale;
211           return 0;
212         }
213       }
214     }
215   }
216   else {
217     BRepBuilderAPI_Transform trf(T);
218     for (Standard_Integer i = 1; i < last; i++) {
219       TopoDS_Shape S = DBRep::Get(a[i]);
220       if (S.IsNull()) {
221         Message::SendFail() << "Error: " << a[i] << " is not a valid shape";
222         return 1;
223       }
224       else {
225         trf.Perform(S, isCopy);
226         if (!trf.IsDone())
227           return 1;
228         DBRep::Set(a[i],trf.Shape());
229       }
230     }
231   }
232   return 0;
233 }
234
235 ///=======================================================================
236 // gtransform
237 //=======================================================================
238
239 static Standard_Integer deform(Draw_Interpretor& di,Standard_Integer n,const char** a)
240 {
241   if (n != 6)
242   {
243     di << "Syntax error: wrong number of arguments";
244     return 1;
245   }
246
247   gp_Trsf T;
248   gp_GTrsf GT(T);
249
250 //  gp_Mat rot(Draw::Atof(a[last-3]),0,0,0,Draw::Atof(a[last-2]),0,0,0,Draw::Atof(a[last-1]));
251   gp_Mat rot(Draw::Atof(a[3]),0,0,0,Draw::Atof(a[4]),0,0,0,Draw::Atof(a[5]));
252   GT.SetVectorialPart(rot);
253   BRepBuilderAPI_GTransform gtrf(GT);
254   BRepBuilderAPI_NurbsConvert nbscv;
255   //  Standard_Integer last = n - 3;
256   //  for (Standard_Integer i = 1; i < last; i++) {
257   //    TopoDS_Shape aShape = DBRep::Get(a[i]);
258   TopoDS_Shape aShape = DBRep::Get(a[2]);
259   if (aShape.IsNull())
260   {
261     di << "Syntax error: '" << a[2] << "' is not a valid shape";
262     return 1;
263   }
264
265   gtrf.Perform (aShape);
266   if (!gtrf.IsDone())
267   {
268     di << "Error: transformation failed";
269     return 1;
270   }
271
272   DBRep::Set (a[1], gtrf.Shape());
273   return 0;
274 }
275
276 //=======================================================================
277 // tcopy
278 //=======================================================================
279
280 static Standard_Integer tcopy(Draw_Interpretor& di,Standard_Integer n,const char** a)
281 {
282   Standard_Boolean copyGeom = Standard_True;
283   Standard_Boolean copyMesh = Standard_False;
284   Standard_Integer iFirst = 1; // index of first shape argument
285
286   if (n > 1)
287   {
288     for (Standard_Integer i = 1; i <= 2; i++)
289     {
290       if (a[i][0] != '-')
291         break;
292       if (a[i][1] == 'n')
293       {
294         copyGeom = Standard_False;
295         iFirst++;
296       }
297       else if (a[i][1] == 'm')
298       {
299         copyMesh = Standard_True;
300         iFirst++;
301       }
302     }
303   }
304
305   if (n < 3 || (n - iFirst) % 2) {
306     Message::SendFail() << "Use: " << a[0] << " [-n(ogeom)] [-m(esh)] shape1 copy1 [shape2 copy2 [...]]\n"
307                         << "Option -n forbids copying of geometry (it will be shared)\n"
308                         << "Option -m forces copying of mesh (disabled by default)";
309     return 1;
310   }
311
312   BRepBuilderAPI_Copy cop;
313   Standard_Integer nbPairs = (n - iFirst) / 2;
314   for (Standard_Integer i=0; i < nbPairs; i++) {
315     cop.Perform(DBRep::Get(a[i+iFirst]), copyGeom, copyMesh);
316     DBRep::Set(a[i+iFirst+1],cop.Shape());
317     di << a[i+iFirst+1] << " ";
318   }
319   return 0;
320 }
321
322
323 //=======================================================================
324 // NurbsConvert
325 //=======================================================================
326
327 static Standard_Integer nurbsconvert(Draw_Interpretor& di,Standard_Integer n,const char** a)
328 {
329   if (n < 3) return 1;
330   if ((n-1)%2 != 0) return 1;
331   BRepBuilderAPI_NurbsConvert nbscv;
332   for (Standard_Integer i=0; i<(n-1)/2; i++) {
333     TopoDS_Shape S = DBRep::Get(a[2*i+2]);
334     if (S.IsNull()) {
335       //std::cout << a[2*i+2] << " is not a valid shape" << std::endl;
336       di << a[2*i+2] << " is not a valid shape\n";
337     }
338     else {
339       nbscv.Perform(S);
340       if (nbscv.IsDone()){
341         DBRep::Set(a[2*i+1],nbscv.Shape());
342       }
343       else {
344         return 1;
345       }
346     }
347   }
348   
349   return 0;
350   
351 }
352
353 //=======================================================================
354 // make a 3D edge curve
355 //=======================================================================
356
357 static Standard_Integer mkedgecurve (Draw_Interpretor& ,Standard_Integer n,const char** a)
358 {
359
360   if (n < 3) return 1;
361   Standard_Real Tolerance = Draw::Atof(a[2]) ;
362
363   TopoDS_Shape S = DBRep::Get(a[1]);
364   
365   if (S.IsNull()) return 1;
366   
367    BRepLib::BuildCurves3d(S,
368                           Tolerance) ;
369    return 0 ;
370 }
371
372 //=======================================================================
373 // sameparameter
374 //=======================================================================
375
376 static Standard_Integer sameparameter(Draw_Interpretor& di,Standard_Integer n,const char** a)
377 {
378   if (n < 2) 
379   {
380     di << "Use sameparameter [result] shape [toler]\n";
381     di << "shape is an initial shape\n";
382     di << "result is a result shape. if skipped = > initial shape will be modified\n";
383     di << "toler is tolerance (default is 1.e-7)";
384     return 1;
385   }
386   Standard_Real aTol = 1.e-7;
387   Standard_Boolean force  = !strcmp(a[0],"fsameparameter");
388
389   Standard_Real aTol1 = Draw::Atof(a[n-1]);
390   Standard_Boolean IsUseTol = aTol1>0;
391   if (IsUseTol)
392     aTol = aTol1;
393
394   TopoDS_Shape anInpS = DBRep::Get(IsUseTol ? a[n-2] : a[n-1]);
395   if (anInpS.IsNull())
396     return 1;
397
398   if ((n == 4 && IsUseTol) || (n == 3 && !IsUseTol))
399   {
400     TopoDS_Shape aResultSh;
401     BRepTools_ReShape aResh;
402     BRepLib::SameParameter(anInpS,aResh,aTol,force);
403     aResultSh = aResh.Apply(anInpS);
404     DBRep::Set(a[1],aResultSh); 
405   }
406   else
407   {
408     BRepLib::SameParameter(anInpS,aTol,force);
409     DBRep::Set(a[1],anInpS); 
410   }
411
412   return 0;
413 }
414 //=======================================================================
415 //function : updatetol
416 //purpose  : 
417 //=======================================================================
418 static Standard_Integer updatetol(Draw_Interpretor& di,Standard_Integer n,const char** a)
419 {
420   if (n < 2) 
421   {
422     di << "Use updatetololerance [result] shape [param]\n";
423     di << "shape is an initial shape\n";
424     di << "result is a result shape. if skipped = > initial shape will be modified\n";
425     di << "if [param] is absent - not verify of face tolerance, else - perform it";
426     return 1;
427   }
428   TopoDS_Shape aSh1 = DBRep::Get(a[n-1]);
429   Standard_Boolean IsF = aSh1.IsNull();
430
431   TopoDS_Shape anInpS = IsF ? DBRep::Get(a[n-2]) : aSh1;
432   if (anInpS.IsNull())
433     return 1;
434
435   if ((n == 4 && IsF) || (n == 3 && !IsF))
436   {
437     TopoDS_Shape aResultSh;
438     BRepTools_ReShape aResh;
439     BRepLib::UpdateTolerances(anInpS,aResh, IsF);
440     aResultSh = aResh.Apply(anInpS);
441     DBRep::Set(a[1],aResultSh); 
442   }
443   else
444   {
445     BRepLib::UpdateTolerances(anInpS, IsF);
446     DBRep::Set(a[1],anInpS); 
447   }
448
449   return 0;
450 }
451
452 //=======================================================================
453 //function : OrienSolid
454 //purpose  : 
455 //=======================================================================
456 static Standard_Integer orientsolid(Draw_Interpretor& ,Standard_Integer n,const char** a)
457 {
458   if (n < 2) return 1;
459
460   TopoDS_Shape S = DBRep::Get(a[1]);
461   if (S.IsNull()) return 1;
462   if (S.ShapeType()!=TopAbs_SOLID) return 1;
463
464   BRepLib::OrientClosedSolid(TopoDS::Solid(S));
465
466   DBRep::Set(a[1],S);
467   return 0;
468
469 }
470
471 //=======================================================================
472 //function : getcoords
473 //purpose  : 
474 //=======================================================================
475 static Standard_Integer getcoords(Draw_Interpretor& di,Standard_Integer n,const char** a)
476 {
477   if(n < 2) 
478     return 1;
479
480   for (Standard_Integer i = 1; i < n; i++) 
481   {
482     const TopoDS_Shape aShape = DBRep::Get (a[i]);
483
484     if (aShape.IsNull())
485       continue;
486
487     if (aShape.ShapeType() == TopAbs_VERTEX)
488     {
489       const TopoDS_Vertex& aVertex = TopoDS::Vertex(aShape);
490       gp_Pnt aPnt = BRep_Tool::Pnt(aVertex);
491
492       di << a[i] << " (x,y,z) : " << aPnt.X() << " " << aPnt.Y() << " " << aPnt.Z() << "\n";
493     }
494   }
495
496   return 0;
497 }
498
499 //! Parse 6 real values for defining AABB.
500 static Standard_Boolean parseMinMax (const char** theArgVec, Bnd_Box& theBox)
501 {
502   const TCollection_AsciiString aMin[3] = { theArgVec[0], theArgVec[1], theArgVec[2] };
503   const TCollection_AsciiString aMax[3] = { theArgVec[3], theArgVec[4], theArgVec[5] };
504   if (!aMin[0].IsRealValue()
505    || !aMin[1].IsRealValue()
506    || !aMin[2].IsRealValue()
507    || !aMax[0].IsRealValue()
508    || !aMax[1].IsRealValue()
509    || !aMax[2].IsRealValue())
510   {
511     return Standard_False;
512   }
513
514   const gp_Pnt aPntMin (aMin[0].RealValue(), aMin[1].RealValue(), aMin[2].RealValue());
515   const gp_Pnt aPntMax (aMax[0].RealValue(), aMax[1].RealValue(), aMax[2].RealValue());
516   theBox.SetVoid();
517   theBox.Add (aPntMin);
518   theBox.Add (aPntMax);
519   return Standard_True;
520 }
521
522 //=======================================================================
523 //function : BoundBox
524 //purpose  : 
525 //=======================================================================
526 static Standard_Integer BoundBox(Draw_Interpretor& theDI,
527                                  Standard_Integer theNArg,
528                                  const char** theArgVal)
529 {
530   // 1. Parse arguments
531
532   TopoDS_Shape aShape;
533   Bnd_Box anAABB;
534
535   Standard_Boolean doPrint = Standard_False;
536   Standard_Boolean doDumpJson = Standard_False;
537   Standard_Boolean useOldSyntax = Standard_False;
538   Standard_Boolean isOBB = Standard_False;
539   Standard_Boolean isTriangulationReq = Standard_True;
540   Standard_Boolean isOptimal = Standard_False;
541   Standard_Boolean isTolerUsed = Standard_False;
542   Standard_Boolean isFinitePart = Standard_False;
543   Standard_Boolean hasToDraw = Standard_True;
544   
545   TCollection_AsciiString anOutVars[6];
546   TCollection_AsciiString aResShapeName;
547   for (Standard_Integer anArgIter = 1; anArgIter < theNArg; ++anArgIter)
548   {
549     TCollection_AsciiString anArgCase (theArgVal[anArgIter]);
550     anArgCase.LowerCase();
551     if (anArgCase == "-obb")
552     {
553       isOBB = Standard_True;
554     }
555     else if (anArgCase == "-aabb")
556     {
557       isOBB = Standard_False;
558     }
559     else if (anArgCase == "-shape"
560           && anArgIter + 1 < theNArg
561           && aResShapeName.IsEmpty())
562     {
563       aResShapeName = theArgVal[++anArgIter];
564       hasToDraw = Standard_False;
565     }
566     else if (anArgCase == "-dump"
567           || anArgCase == "-print")
568     {
569       doPrint = Standard_True;
570     }
571     else if (anArgCase == "-dumpjson")
572     {
573       doDumpJson = Standard_True;
574     }
575     else if (anArgCase == "-save"
576           && anArgIter + 6 < theNArg
577           && anOutVars[0].IsEmpty())
578     {
579       for (int aCompIter = 0; aCompIter < 6; ++aCompIter)
580       {
581         anOutVars[aCompIter] = theArgVal[anArgIter + aCompIter + 1];
582       }
583       anArgIter += 6;
584     }
585     else if (anArgCase == "-notriangulation")
586     {
587       isTriangulationReq = Standard_False;
588     }
589     else if (anArgCase == "-optimal")
590     {
591       isOptimal = Standard_True;
592     }
593     else if (anArgCase == "-exttoler")
594     {
595       isTolerUsed = Standard_True;
596     }
597     else if (anArgCase == "-nodraw")
598     {
599       hasToDraw = Standard_False;
600     }
601     else if (anArgCase == "-finite"
602           || anArgCase == "-finitepart")
603     {
604       isFinitePart = Standard_True;
605     }
606     else if (aShape.IsNull()
607          && !DBRep::Get (theArgVal[anArgIter]).IsNull())
608     {
609       aShape = DBRep::Get (theArgVal[anArgIter]);
610     }
611     else if (anAABB.IsVoid()
612           && anArgIter + 5 < theNArg
613           && parseMinMax (theArgVal + anArgIter, anAABB))
614     {
615       anArgIter += 5;
616     }
617     else
618     {
619       Message::SendFail() << "Syntax error at argument '" << theArgVal[anArgIter] << "'";
620       return 1;
621     }
622   }
623
624   if (anAABB.IsVoid()
625    && aShape.IsNull())
626   {
627     Message::SendFail() << "Syntax error: input is not specified (neither shape nor coordinates)";
628     return 1;
629   }
630   else if (!anAABB.IsVoid()
631         && (isOBB || isOptimal || isTolerUsed))
632   {
633     Message::SendFail() << "Syntax error: Options -obb, -optimal and -extToler cannot be used for explicitly defined AABB";
634     return 1;
635   }
636   else if (isOBB
637        && !anOutVars[0].IsEmpty())
638   {
639     Message::SendFail() << "Error: Option -save works only with axes-aligned boxes";
640     return 1;
641   }
642
643   // enable printing (old syntax) if neither saving to shape nor to DRAW variables is requested
644   if (! doPrint && ! doDumpJson && anOutVars[0].IsEmpty() && aResShapeName.IsEmpty())
645   {
646     doPrint = Standard_True;
647     useOldSyntax = Standard_True;
648   }
649
650   // 2. Compute box and save results
651   Handle(Draw_Box) aDB;
652   if (isOBB)
653   {
654     Bnd_OBB anOBB;
655     BRepBndLib::AddOBB(aShape, anOBB, isTriangulationReq, isOptimal, isTolerUsed);
656
657     if (anOBB.IsVoid())
658     {
659       theDI << "Void box.\n";
660     }
661     else if (doPrint)
662     {
663       const gp_Pnt &aBaryCenter= anOBB.Center();
664       const gp_XYZ &aXDir = anOBB.XDirection(),
665                    &aYDir = anOBB.YDirection(),
666                    &aZDir = anOBB.ZDirection();
667       theDI << "Oriented bounding box\n";
668       theDI << "Center: " << aBaryCenter.X() << " " << 
669                              aBaryCenter.Y() << " " <<
670                              aBaryCenter.Z() << "\n";
671       theDI << "X-axis: " << aXDir.X() << " " << aXDir.Y() << " " << aXDir.Z() << "\n";
672       theDI << "Y-axis: " << aYDir.X() << " " << aYDir.Y() << " " << aYDir.Z() << "\n";
673       theDI << "Z-axis: " << aZDir.X() << " " << aZDir.Y() << " " << aZDir.Z() << "\n";
674       theDI << "Half X: " << anOBB.XHSize() << "\n"
675             << "Half Y: " << anOBB.YHSize() << "\n"
676             << "Half Z: " << anOBB.ZHSize() << "\n";
677     }
678
679     if (doDumpJson)
680     {
681       Standard_SStream aStream;
682       anOBB.DumpJson (aStream);
683
684       theDI << "Oriented bounding box\n";
685       theDI << Standard_Dump::FormatJson (aStream);
686     }
687
688     if (hasToDraw
689     && !anOBB.IsVoid())
690     {
691       aDB = new Draw_Box (anOBB, Draw_orange);
692     }
693
694     if (!aResShapeName.IsEmpty())
695     {
696       ConvertBndToShape (anOBB, aResShapeName.ToCString());
697     }
698   }
699   else // if(!isOBB)
700   {
701     if (!aShape.IsNull())
702     {
703       anAABB.SetVoid ();
704       if(isOptimal)
705       {
706         BRepBndLib::AddOptimal (aShape, anAABB, isTriangulationReq, isTolerUsed);
707       }
708       else
709       {
710         BRepBndLib::Add (aShape, anAABB, isTriangulationReq);
711       }
712     }
713
714     if (anAABB.IsVoid())
715     {
716       theDI << "Void box.\n";
717     }
718     else
719     {
720       if (isFinitePart && anAABB.IsOpen())
721       {
722         anAABB = anAABB.FinitePart();
723       }
724       const gp_Pnt aMin = anAABB.CornerMin();
725       const gp_Pnt aMax = anAABB.CornerMax();
726
727       // print to DRAW
728       if (doPrint)
729       {
730         if (useOldSyntax)
731         {
732           theDI << aMin.X() << " " << aMin.Y() << " " << aMin.Z() << " "
733                 << aMax.X() << " " << aMax.Y() << " " << aMax.Z() << "\n";
734         }
735         else
736         {
737           theDI << "Axes-aligned bounding box\n";
738           theDI << "X-range: " << aMin.X() << " " << aMax.X() << "\n"
739                 << "Y-range: " << aMin.Y() << " " << aMax.Y() << "\n"
740                 << "Z-range: " << aMin.Z() << " " << aMax.Z() << "\n";
741           if (anAABB.IsOpen()
742            && anAABB.HasFinitePart())
743           {
744             Bnd_Box aFinitAabb = anAABB.FinitePart();
745             const gp_Pnt aFinMin = aFinitAabb.CornerMin();
746             const gp_Pnt aFinMax = aFinitAabb.CornerMax();
747             theDI << "Finite part\n";
748             theDI << "X-range: " << aFinMin.X() << " " << aFinMax.X() << "\n"
749                   << "Y-range: " << aFinMin.Y() << " " << aFinMax.Y() << "\n"
750                   << "Z-range: " << aFinMin.Z() << " " << aFinMax.Z() << "\n";
751           }
752         }
753       }
754
755       if (doDumpJson)
756       {
757         Standard_SStream aStream;
758         anAABB.DumpJson (aStream);
759
760         theDI << "Bounding box\n";
761         theDI << Standard_Dump::FormatJson (aStream);
762       }
763
764       // save DRAW variables
765       if (!anOutVars[0].IsEmpty())
766       {
767         Draw::Set (anOutVars[0].ToCString(), aMin.X());
768         Draw::Set (anOutVars[1].ToCString(), aMin.Y());
769         Draw::Set (anOutVars[2].ToCString(), aMin.Z());
770         Draw::Set (anOutVars[3].ToCString(), aMax.X());
771         Draw::Set (anOutVars[4].ToCString(), aMax.Y());
772         Draw::Set (anOutVars[5].ToCString(), aMax.Z());
773       }
774
775       // add presentation to DRAW viewer
776       if (hasToDraw)
777       {
778         aDB = new Draw_Box (anAABB, Draw_orange);
779       }
780     }
781
782     // save as shape
783     if (!aResShapeName.IsEmpty())
784     {
785       ConvertBndToShape (anAABB, aResShapeName.ToCString());
786     }
787   }
788
789   if (!aDB.IsNull())
790   {
791     dout << aDB;
792   }
793   return 0;
794 }
795
796 //=======================================================================
797 //function : IsBoxesInterfered
798 //purpose  : 
799 //=======================================================================
800 static Standard_Integer IsBoxesInterfered(Draw_Interpretor& theDI,
801                                           Standard_Integer theNArg,
802                                           const char** theArgVal)
803 {
804   if(theNArg < 2)
805   {
806     theDI << "Use: isbbinterf shape1 shape2 [-o].\n";
807     return 1;
808   }
809
810   const TopoDS_Shape aShape1 = DBRep::Get(theArgVal[1]);
811   const TopoDS_Shape aShape2 = DBRep::Get(theArgVal[2]);
812
813   Standard_Boolean isOBB = (theNArg > 3) && (!strcmp(theArgVal[3], "-o"));
814
815   if(isOBB)
816   {
817     Bnd_OBB anOBB1, anOBB2;
818     BRepBndLib::AddOBB(aShape1, anOBB1);
819     BRepBndLib::AddOBB(aShape2, anOBB2);
820
821     if(anOBB1.IsOut(anOBB2))
822     {
823       theDI << "The shapes are NOT interfered by OBB.\n";
824     }
825     else
826     {
827       theDI << "The shapes are interfered by OBB.\n";
828     }
829   }
830   else
831   {
832     Bnd_Box anAABB1, anAABB2;
833     BRepBndLib::Add(aShape1, anAABB1);
834     BRepBndLib::Add(aShape2, anAABB2);
835
836     if(anAABB1.IsOut(anAABB2))
837     {
838       theDI << "The shapes are NOT interfered by AABB.\n";
839     }
840     else
841     {
842       theDI << "The shapes are interfered by AABB.\n";
843     }
844   }
845
846   return 0;
847 }
848
849 //=======================================================================
850 //function : gbounding
851 //purpose  : 
852 //=======================================================================
853 #include <GeomAdaptor_Surface.hxx>
854 #include <BndLib_AddSurface.hxx>
855 #include <BndLib_Add3dCurve.hxx>
856 #include <BndLib_Add2dCurve.hxx>
857 #include <Draw_Segment2D.hxx>
858 static Standard_Integer gbounding(Draw_Interpretor& di,Standard_Integer n,const char** a)
859 {
860   if (n != 2 && n != 3) 
861   {
862     di << "Usage: gbounding surf/curve/curve2d [-o] \n";
863     di << "[-o] turn on Optimal mode ('off' by default) \n";
864     return 1;
865   }
866   else
867   {
868     Standard_Boolean IsOptimal = Standard_False;
869     if (n == 3 && !strcmp(a[2], "-o"))
870       IsOptimal = Standard_True;
871     
872     Standard_Real axmin,aymin,azmin,axmax,aymax,azmax;
873     Bnd_Box B;
874     Bnd_Box2d B2d;
875     Handle(Draw_Box) DB;
876     Standard_Boolean Is3d = Standard_True;
877     Handle(Geom_Curve) C;
878     Handle(Geom_Surface) S;
879     Handle_Geom2d_Curve C2d;
880     S = DrawTrSurf::GetSurface(a[1]);
881     if (!S.IsNull())
882     {
883       //add surf
884       GeomAdaptor_Surface aGAS(S);
885       if (IsOptimal)
886         BndLib_AddSurface::AddOptimal(aGAS, Precision::Confusion(), B);
887       else
888         BndLib_AddSurface::Add(aGAS, Precision::Confusion(), B);
889     }
890     else
891     {
892       C = DrawTrSurf::GetCurve(a[1]);
893       if (!C.IsNull())
894       {
895         // add cur
896         GeomAdaptor_Curve aGAC(C);
897         if (IsOptimal)
898           BndLib_Add3dCurve::AddOptimal(aGAC, Precision::Confusion(), B);
899         else
900           BndLib_Add3dCurve::Add(aGAC, Precision::Confusion(), B);
901       }
902       else
903       {
904         C2d = DrawTrSurf::GetCurve2d(a[1]);
905         if (!C2d.IsNull())
906         {
907           //add cur2d
908           Is3d = Standard_False;
909           if (IsOptimal)
910             BndLib_Add2dCurve::AddOptimal(C2d, C2d->FirstParameter(), C2d->LastParameter(), Precision::Confusion(), B2d); 
911           else
912             BndLib_Add2dCurve::Add(C2d, C2d->FirstParameter(), C2d->LastParameter(), Precision::Confusion(), B2d); 
913         }
914         else
915         {
916           di << "Wrong argument \n";
917           return 1;
918         }
919       }
920     }
921
922     if (Is3d)
923     {
924       B.Get(axmin,aymin,azmin,axmax,aymax,azmax);
925       DB = new Draw_Box(B, Draw_vert);
926       dout<<DB;
927       di << axmin<<" "<< aymin<<" "<< azmin<<" "<< axmax<<" "<< aymax<<" "<< azmax;
928     }
929     else
930     {
931       B2d.Get(axmin,aymin,axmax,aymax);
932       gp_Pnt2d p1(axmin, aymin);
933       gp_Pnt2d p2(axmax, aymin);
934       gp_Pnt2d p3(axmax, aymax);
935       gp_Pnt2d p4(axmin, aymax);
936       Draw_Segment2D* S1 = new Draw_Segment2D(p1, p2, Draw_vert);
937       Draw_Segment2D* S2 = new Draw_Segment2D(p2, p3, Draw_vert);
938       Draw_Segment2D* S3 = new Draw_Segment2D(p3, p4, Draw_vert);
939       Draw_Segment2D* S4 = new Draw_Segment2D(p4, p1, Draw_vert);
940       dout << S1 << S2 << S3 << S4;
941       di << axmin<<" "<< aymin<<" "<< axmax<<" "<< aymax;
942     }
943   }
944   return 0;
945 }
946
947 //=======================================================================
948 //function : findplane
949 //purpose  : 
950 //=======================================================================
951 static Standard_Integer findplane(Draw_Interpretor& di,Standard_Integer n,const char** a)
952 {
953   if (n < 3) return 1;
954   TopoDS_Shape S = DBRep::Get(a[1]);
955   if (S.IsNull()) return 1;
956   Standard_Real tolerance = 1.0e-5 ;
957   BRepBuilderAPI_FindPlane a_plane_finder(S,
958                                    tolerance) ;
959   if (a_plane_finder.Found()) {
960     //std::cout << " a plane is found "   ;
961     di << " a plane is found \n";
962     const Handle(Geom_Geometry)& aSurf = a_plane_finder.Plane(); // to avoid ambiguity
963     DrawTrSurf::Set(a[2],aSurf) ;
964   }
965   return 0 ;
966 }
967 //=======================================================================
968 //function : precision
969 //purpose  : 
970 //=======================================================================
971
972 static Standard_Integer precision(Draw_Interpretor& di,Standard_Integer n,const char** a)
973 {
974   n--;
975
976   if ( n == 0) {
977     //std::cout << " Current Precision = " << BRepBuilderAPI::Precision() << std::endl;
978     di << " Current Precision = " << BRepBuilderAPI::Precision() << "\n";
979   }
980   else {
981     BRepBuilderAPI::Precision(Draw::Atof(a[1]));
982   }
983   return 0;
984 }
985
986
987 //=======================================================================
988 //function : reperage shape (Int lin Shape) + pointe double click   + maxtol
989 //purpose  : 
990 //=======================================================================
991 #include <IntCurvesFace_ShapeIntersector.hxx>
992 #include <gp_Lin.hxx>
993
994 static Standard_Integer reperageshape(Draw_Interpretor& di, Standard_Integer narg , const char** a) 
995 {
996   Standard_Integer details=0;
997   if(narg<2) return 1;
998   if(narg==3) details=1;
999   const char *id1 = a[1];
1000   TopoDS_Shape TheShape1 = DBRep::Get(id1);
1001   
1002   //std::cout << "Pick positions with button "<<std::endl;
1003   di << "Pick positions with button \n";
1004   Standard_Integer id,X,Y,b;
1005   gp_Trsf T;
1006   gp_Pnt P1,P2;
1007   dout.Select(id,X,Y,b);
1008   
1009   dout.GetTrsf(id,T);
1010   T.Invert();
1011   Standard_Real z = dout.Zoom(id);
1012   P2.SetCoord((Standard_Real)X /z,(Standard_Real)Y /z, 0.0);
1013   P2.Transform(T);
1014   P1.SetCoord((Standard_Real)X /z,(Standard_Real)Y /z,-1.0);
1015   P1.Transform(T);
1016   
1017   
1018   gp_Ax1 Axe(P1,gp_Vec(P1,P2));
1019   IntCurvesFace_ShapeIntersector Inter;
1020   Inter.Load(TheShape1,1e-7);
1021   
1022   Inter.Perform(Axe,-RealLast(),RealLast());
1023   
1024   //std::cout<<"\n --> ";
1025   di <<"\n --> ";
1026   if(Inter.NbPnt()) { 
1027     for(Standard_Integer i=1; i<=Inter.NbPnt(); i++) { 
1028       Standard_Integer numface=1;
1029       TopExp_Explorer ExF;
1030       for(ExF.Init(TheShape1,TopAbs_FACE);
1031           ExF.More();
1032           ExF.Next(),numface++) { 
1033         TopoDS_Face Face=TopoDS::Face(ExF.Current());
1034         if(Face.IsEqual(Inter.Face(i))) { 
1035           //std::cout<<" "<<a[1]<<"_"<<numface;
1036           di<<" "<<a[1]<<"_"<<numface;
1037           continue;       
1038         }
1039       }
1040       const gp_Pnt& P = Inter.Pnt(i);
1041       Standard_Real PMin = Inter.WParameter(i);
1042       if(details) { 
1043         //std::cout<<" w:"<<PMin<<std::endl;
1044         di<<" w:"<<PMin<< "\n";
1045       }
1046       if(Inter.Transition(i) == IntCurveSurface_In) { 
1047         if(Inter.State(i) == TopAbs_IN) { 
1048           Handle(Draw_Marker3D) p = new Draw_Marker3D(P, Draw_Square, Draw_rouge,2); 
1049           dout << p;   dout.Flush();
1050         }
1051         else if(Inter.State(i) == TopAbs_ON) { 
1052           Handle(Draw_Marker3D) p = new Draw_Marker3D(P, Draw_Square, Draw_vert,2); 
1053           dout << p;   dout.Flush();
1054         }
1055       }
1056       else { 
1057         if(Inter.Transition(i) == IntCurveSurface_Out) { 
1058           if(Inter.State(i) == TopAbs_IN) { 
1059             Handle(Draw_Marker3D) p = new Draw_Marker3D(P, Draw_X, Draw_rouge,2); 
1060             dout << p;   dout.Flush();
1061           }
1062           else if(Inter.State(i) == TopAbs_ON) { 
1063             Handle(Draw_Marker3D) p = new Draw_Marker3D(P, Draw_X, Draw_vert,2); 
1064             dout << p;   dout.Flush();
1065           }
1066         } 
1067       }
1068     }
1069   }
1070   //std::cout<<std::endl;
1071   di << "\n";
1072   return(0);
1073 }
1074
1075
1076 static Standard_Integer maxtolerance(Draw_Interpretor& theCommands, 
1077                                      Standard_Integer n, const char** a) { 
1078   if(n<2) return(1);
1079   TopoDS_Shape TheShape = DBRep::Get(a[1]);
1080   if(TheShape.IsNull()) return(1);
1081
1082   Standard_Real T,TMF,TME,TMV,TmF,TmE,TmV;
1083   Standard_Integer nbF,nbE,nbV;
1084   TMF=TME=TMV=-RealLast();
1085   TmF=TmE=TmV=RealLast();
1086   
1087   TopTools_MapOfShape mapS;
1088   mapS.Clear();
1089
1090   for(TopExp_Explorer ex(TheShape,TopAbs_FACE);
1091       ex.More();
1092       ex.Next()) { 
1093     TopoDS_Face Face=TopoDS::Face(ex.Current());
1094     T=BRep_Tool::Tolerance(Face);
1095     if(T>TMF) TMF=T;
1096     if(T<TmF) TmF=T;
1097     mapS.Add(Face);
1098   }
1099   
1100   nbF = mapS.Extent();
1101   mapS.Clear();
1102   
1103   for(TopExp_Explorer ex(TheShape,TopAbs_EDGE);
1104       ex.More();
1105       ex.Next()) { 
1106     TopoDS_Edge Edge=TopoDS::Edge(ex.Current());
1107     T=BRep_Tool::Tolerance(Edge);
1108     if(T>TME) TME=T;
1109     if(T<TmE) TmE=T;
1110     mapS.Add(Edge);
1111   }
1112
1113   nbE = mapS.Extent();
1114   mapS.Clear();
1115
1116   for(TopExp_Explorer ex(TheShape,TopAbs_VERTEX);
1117       ex.More();
1118       ex.Next()) { 
1119     TopoDS_Vertex Vertex=TopoDS::Vertex(ex.Current());
1120     T=BRep_Tool::Tolerance(Vertex);
1121     if(T>TMV) TMV=T;
1122     if(T<TmV) TmV=T;
1123     mapS.Add(Vertex);
1124   }
1125
1126   nbV = mapS.Extent();
1127
1128   Standard_SStream sss;
1129   sss << "\n## Tolerances on the shape " << a[1] << "  (nbFaces:" << nbF
1130       << "  nbEdges:" << nbE << " nbVtx:" << nbV << ")\n" ;
1131   sss.precision(5);
1132   sss.setf(std::ios::scientific);
1133   if(TmF<=TMF) sss << "\n    Face   : Min " << std::setw(8) << TmF <<"    Max  " << std::setw(8) << TMF << " \n ";
1134   if(TmE<=TME) sss << "\n    Edge   : Min " << std::setw(8) << TmE <<"    Max  " << std::setw(8) << TME << " \n ";
1135   if(TmV<=TMV) sss << "\n    Vertex : Min " << std::setw(8) << TmV <<"    Max  " << std::setw(8) << TMV << " \n ";
1136   theCommands << sss;
1137
1138   return 0;
1139 }
1140
1141
1142 static Standard_Integer vecdc(Draw_Interpretor& di,Standard_Integer ,const char** ) {
1143   //std::cout << "Pick positions with button "<<std::endl;
1144   di << "Pick positions with button \n";
1145
1146   Standard_Integer id,X,Y,b;
1147   gp_Trsf T;
1148   gp_Pnt P1,P2,PP1,PP2;
1149   
1150   //-----------------------------------------------------------
1151   dout.Select(id,X,Y,b);    dout.GetTrsf(id,T);
1152   T.Invert();
1153   Standard_Real z = dout.Zoom(id);
1154   P1.SetCoord((Standard_Real)X /z,(Standard_Real)Y /z,0.0);
1155   P1.Transform(T);
1156   
1157   dout.Select(id,X,Y,b);  dout.GetTrsf(id,T);
1158   T.Invert();  z = dout.Zoom(id);
1159   
1160   P2.SetCoord((Standard_Real)X /z,(Standard_Real)Y /z,0.0);
1161   P2.Transform(T);
1162   Standard_Real xa,ya,za;
1163   if(Abs(P1.X())>Abs(P2.X())) xa = P1.X(); else xa = P2.X();
1164   if(Abs(P1.Y())>Abs(P2.Y())) ya = P1.Y(); else ya = P2.Y();
1165   if(Abs(P1.Z())>Abs(P2.Z())) za = P1.Z(); else za = P2.Z();
1166   P1.SetCoord(xa,ya,za);
1167   Handle(Draw_Marker3D) D0 = new Draw_Marker3D(gp_Pnt(P1.X(),
1168                                                       P1.Y(),
1169                                                       P1.Z()),
1170                                                Draw_Square,Draw_blanc,1);
1171   
1172   dout << D0;
1173   dout.Flush();
1174   //-----------------------------------------------------------
1175   dout.Select(id,X,Y,b);  
1176   dout.GetTrsf(id,T);
1177   T.Invert();
1178   z = dout.Zoom(id);
1179   PP1.SetCoord((Standard_Real)X /z,(Standard_Real)Y /z,0.0);
1180   PP1.Transform(T);
1181   dout.Select(id,X,Y,b);
1182   dout.GetTrsf(id,T);
1183   T.Invert();
1184   z = dout.Zoom(id);
1185   PP2.SetCoord((Standard_Real)X /z,(Standard_Real)Y /z,0.0);
1186   PP2.Transform(T);
1187   if(Abs(PP1.X())>Abs(PP2.X())) xa = PP1.X(); else xa = PP2.X();
1188   if(Abs(PP1.Y())>Abs(PP2.Y())) ya = PP1.Y(); else ya = PP2.Y();
1189   if(Abs(PP1.Z())>Abs(PP2.Z())) za = PP1.Z(); else za = PP2.Z();
1190   PP1.SetCoord(xa,ya,za);
1191   Handle(Draw_Segment3D) d = new Draw_Segment3D(P1,PP1,Draw_blanc);
1192   dout << d;
1193   dout.Flush();
1194   //std::cout<<"\nttran   "<<PP1.X()-P1.X()<<" "<<PP1.Y()-P1.Y()<<" "<<PP1.Z()-P1.Z()<<std::endl;
1195   di <<"\nttran   "<<PP1.X()-P1.X()<<" "<<PP1.Y()-P1.Y()<<" "<<PP1.Z()-P1.Z()<< "\n";
1196
1197   static Standard_Integer nboxvecdp=0;
1198   //std::cout<<"\nbox  b"<<++nboxvecdp<<" "<<Min(P1.X(),PP1.X())<<" "<<Min(P1.Y(),PP1.Y())<<" "<<Min(PP1.Z(),P1.Z());
1199   //std::cout<<"  "<<Abs(PP1.X()-P1.X())<<" "<<Abs(PP1.Y()-P1.Y())<<" "<<Abs(PP1.Z()-P1.Z())<<std::endl;
1200
1201   //std::cout<<"\nDistance :"<<sqrt( (PP1.X()-P1.X())*(PP1.X()-P1.X())
1202         //                   +(PP1.Y()-P1.Y())*(PP1.Y()-P1.Y())
1203         //                   +(PP1.Z()-P1.Z())*(PP1.Z()-P1.Z()))<<std::endl;
1204
1205   di <<"\nbox  b"<<++nboxvecdp<<" "<<Min(P1.X(),PP1.X())<<" "<<Min(P1.Y(),PP1.Y())<<" "<<Min(PP1.Z(),P1.Z());
1206   di <<"  "<<Abs(PP1.X()-P1.X())<<" "<<Abs(PP1.Y()-P1.Y())<<" "<<Abs(PP1.Z()-P1.Z())<< "\n";
1207
1208   di <<"\nDistance :"<<sqrt( (PP1.X()-P1.X())*(PP1.X()-P1.X())
1209                              +(PP1.Y()-P1.Y())*(PP1.Y()-P1.Y())
1210                              +(PP1.Z()-P1.Z())*(PP1.Z()-P1.Z()))<< "\n";
1211   return(0);
1212 }
1213 //=======================================================================
1214 // nproject
1215 //=======================================================================
1216
1217 #include <TopTools_SequenceOfShape.hxx>
1218  static Standard_Integer nproject(Draw_Interpretor& di, Standard_Integer n, const char** a)
1219 {
1220   if ( n < 4) return 1;
1221   TopoDS_Shape InpShape;
1222   Standard_Integer arg = 2, i;
1223   TopTools_SequenceOfShape Args; 
1224
1225   Standard_Real Tol = 1.e-4;        
1226   Standard_Real Tol2d;
1227   Standard_Real MaxDistance = 1.e-3;
1228   GeomAbs_Shape Continuity = GeomAbs_C2;  
1229   Standard_Integer MaxDeg = 14;           
1230   Standard_Integer MaxSeg = 16;           
1231
1232   while((n > arg) && !(InpShape = DBRep::Get(a[arg])).IsNull()){
1233     Args.Append(InpShape);
1234     arg++;
1235   }
1236   if(Args.Length() < 2) return 1;
1237   
1238   BRepOffsetAPI_NormalProjection OrtProj(Args.Last());
1239
1240   for(i = 1; i < Args.Length(); i++)
1241     OrtProj.Add(Args(i));
1242
1243   if(n > arg)
1244     if (!strcmp(a[arg],"-g")) {
1245       OrtProj.SetLimit(Standard_False);
1246       arg++;
1247     }
1248   
1249   if(n > arg)
1250     if (!strcmp(a[arg],"-d")) {
1251       arg++;
1252       if(n > arg)
1253         MaxDistance = Draw::Atof(a[arg++]);
1254       OrtProj.SetMaxDistance(MaxDistance);
1255     }
1256   if(n > arg) {
1257     Tol = Max(Draw::Atof(a[arg++]),1.e-10);
1258   }
1259
1260   if(n > arg) {
1261     if (Draw::Atoi(a[arg]) == 0) Continuity = GeomAbs_C0;
1262     else if (Draw::Atoi(a[arg]) == 1) Continuity = GeomAbs_C1;
1263     arg++;
1264   }
1265
1266  
1267   if(n > arg) {
1268     MaxDeg = Draw::Atoi(a[arg++]);
1269     if (MaxDeg<1 || MaxDeg>14) MaxDeg = 14;
1270   }
1271
1272   if(n > arg) MaxSeg = Draw::Atoi(a[arg]);
1273     
1274   Tol2d = Pow(Tol, 2./3);
1275
1276   OrtProj.SetParams(Tol, Tol2d, Continuity, MaxDeg, MaxSeg);
1277   OrtProj.Build();
1278   TopTools_ListOfShape Wire;
1279   Standard_Boolean IsWire=OrtProj.BuildWire(Wire);
1280   if (IsWire) {
1281     //std::cout << " BuildWire OK " << std::endl;
1282     di << " BuildWire OK \n";
1283   }
1284   DBRep::Set(a[1], OrtProj.Shape());
1285   return 0;  
1286 }
1287
1288 //==========================================================================
1289 //function : wexplo
1290 //           exploration of a wire 
1291 //==========================================================================
1292 static Standard_Integer wexplo (Draw_Interpretor&, 
1293                                 Standard_Integer argc, const char** argv)
1294
1295   char name[100];
1296   if (argc < 2) return 1;
1297   
1298   TopoDS_Shape C1 = DBRep::Get (argv[1],TopAbs_WIRE);
1299   TopoDS_Shape C2 ;
1300
1301   if (argc > 2)  C2 = DBRep::Get (argv[2],TopAbs_FACE);
1302
1303   if (C1.IsNull()) return 1;
1304
1305   BRepTools_WireExplorer we;
1306   if (C2.IsNull()) we.Init(TopoDS::Wire(C1));
1307   else             we.Init(TopoDS::Wire(C1),TopoDS::Face(C2));
1308
1309   Standard_Integer k = 1;
1310   while (we.More()) {
1311     TopoDS_Edge E = we.Current();
1312     Sprintf(name,"WEDGE_%d",k); 
1313           DBRep::Set(name,E);
1314     we.Next();
1315     k++;
1316   }
1317
1318   return 0;
1319 }
1320
1321 static Standard_Integer scalexyz(Draw_Interpretor& /*di*/, Standard_Integer n, const char** a)
1322 {
1323   if (n < 6) return 1;
1324
1325   TopoDS_Shape aShapeBase = DBRep::Get(a[2]);
1326   if (aShapeBase.IsNull()) return 1;
1327   
1328   Standard_Real aFactorX = Draw::Atof(a[3]);
1329   Standard_Real aFactorY = Draw::Atof(a[4]);
1330   Standard_Real aFactorZ = Draw::Atof(a[5]);
1331
1332   gp_GTrsf aGTrsf;
1333   gp_Mat rot (aFactorX, 0, 0,
1334               0, aFactorY, 0,
1335               0, 0, aFactorZ);
1336   aGTrsf.SetVectorialPart(rot);
1337   BRepBuilderAPI_GTransform aBRepGTrsf (aShapeBase, aGTrsf, Standard_False);
1338   if (!aBRepGTrsf.IsDone())
1339     throw Standard_ConstructionError("Scaling not done");
1340   TopoDS_Shape Result = aBRepGTrsf.Shape();
1341
1342   DBRep::Set(a[1], Result);
1343   return 0;  
1344 }
1345
1346 //=======================================================================
1347 //function : compareshapes
1348 //purpose  : 
1349 //=======================================================================
1350 static Standard_Integer compareshapes(Draw_Interpretor& di,
1351                                       Standard_Integer n,
1352                                       const char** a)
1353 {
1354   if (n != 3) {
1355     di << "Compare shapes. Usage: compare shape1 shape2\n";
1356     return 1;
1357   }
1358   // get shapes
1359   TopoDS_Shape aS1 = DBRep::Get(a[1]);
1360   TopoDS_Shape aS2 = DBRep::Get(a[2]);
1361   // compare shapes
1362   if (aS1.IsSame(aS2)) {
1363     di << "same shapes\n";
1364     if (aS1.IsEqual(aS2)) {
1365       di << "equal shapes\n";
1366     }
1367   }
1368   else {
1369     di << "shapes are not same\n";
1370   }
1371   return 0;
1372 }
1373
1374 //=======================================================================
1375 //function : issubshape
1376 //purpose  : 
1377 //=======================================================================
1378 static Standard_Integer issubshape(Draw_Interpretor& di,
1379                                    Standard_Integer n,
1380                                    const char** a)
1381 {  
1382   if (n != 3) {
1383     di << "Check if the shape is sub-shape of other shape and get its index in the shape.\n";
1384     di << "Usage: issubshape subshape shape\n";
1385     return 1;
1386   }
1387   // get shapes
1388   TopoDS_Shape aSubShape = DBRep::Get(a[1]);
1389   TopoDS_Shape aShape    = DBRep::Get(a[2]);
1390   // check shapes
1391   if (aSubShape.IsNull() || aShape.IsNull()) {
1392     di << "null shapes\n";
1393     return 0;
1394   }
1395   // find index of the sub-shape in the shape
1396   TopTools_MapOfShape aMShapes;
1397   // try to find the SubShape in Shape
1398   TopExp_Explorer anExp(aShape, aSubShape.ShapeType());
1399   for (; anExp.More(); anExp.Next()) {
1400     const TopoDS_Shape& aSS = anExp.Current();
1401     if (aMShapes.Add(aSS)) {
1402       if (aSS.IsSame(aSubShape)) {
1403         break;
1404       }
1405     }
1406   }
1407   //
1408   if (anExp.More()) {
1409     di << a[1] << " is sub-shape of " << a[2] << ". Index in the shape: " << aMShapes.Extent() << ".\n";
1410   }
1411   else {
1412     di << a[1] << " is NOT sub-shape of " << a[2] << ".\n";
1413   }
1414   //
1415   return 0;
1416 }
1417 //=======================================================================
1418 //function : purgeloc
1419 //purpose  : 
1420 //=======================================================================
1421 static Standard_Integer purgeloc(Draw_Interpretor& di, Standard_Integer /*n*/, const char** a)
1422 {
1423
1424   TopoDS_Shape aShapeBase = DBRep::Get(a[2]);
1425   if (aShapeBase.IsNull()) return 1;
1426
1427
1428   BRepTools_PurgeLocations aRemLoc;
1429   Standard_Boolean isDone = aRemLoc.Perform(aShapeBase);
1430   TopoDS_Shape Result = aRemLoc.GetResult();
1431
1432   DBRep::Set(a[1], Result);
1433   if (isDone)
1434   {
1435     di << "All problematic locations are purged \n";
1436   }
1437   else
1438   {
1439     di << "Not all problematic locations are purged \n";
1440   }
1441   return 0;
1442 }
1443 //=======================================================================
1444 //function : checkloc
1445 //purpose  : 
1446 //=======================================================================
1447
1448 static Standard_Integer checkloc(Draw_Interpretor& di, Standard_Integer /*n*/, const char** a)
1449 {
1450
1451   TopoDS_Shape aShapeBase = DBRep::Get(a[1]);
1452   if (aShapeBase.IsNull()) return 1;
1453
1454   TopTools_ListOfShape aLS;
1455   BRepTools::CheckLocations(aShapeBase, aLS);
1456   if (aLS.IsEmpty())
1457   {
1458     di << "There are no problematic shapes" << "\n";
1459     return 0;
1460   }
1461   TopTools_ListIteratorOfListOfShape anIt(aLS);
1462   Standard_Integer i;
1463   for (i = 1; anIt.More(); anIt.Next(), ++i)
1464   {
1465     TCollection_AsciiString aName(a[1]);
1466     aName += "_";
1467     aName.AssignCat(i);
1468     DBRep::Set(aName.ToCString(), anIt.Value());
1469     di << aName << " ";
1470   }
1471   di << "\n";
1472   return 0;
1473 }
1474
1475 void  BRepTest::BasicCommands(Draw_Interpretor& theCommands)
1476 {
1477   static Standard_Boolean done = Standard_False;
1478   if (done) return;
1479   done = Standard_True;
1480
1481   DBRep::BasicCommands(theCommands);
1482
1483   const char* g = "TOPOLOGY Basic shape commands";
1484
1485   theCommands.Add("addpcurve",
1486                   "addpcurve edge 2dcurve face [tol (default 1.e-7)]",
1487                   __FILE__,
1488                   addpcurve,g);
1489
1490   theCommands.Add("reset",
1491                   "reset name1 name2 ..., remove location",
1492                   __FILE__,
1493                   transform,g);
1494
1495   theCommands.Add("tmove",
1496                   "tmove name1 name2 ... name, set location from name [-copy]",
1497                   __FILE__,
1498                   transform,g);
1499
1500   theCommands.Add("ttranslate",
1501                   "ttranslate name1 name2 ... dx dy dz [-copy]",
1502                   __FILE__,
1503                   transform,g);
1504
1505   theCommands.Add("trotate",
1506                   "trotate name1 name2 ... x y z dx dy dz angle [-copy]",
1507                   __FILE__,
1508                   transform,g);
1509
1510   theCommands.Add("tmirror",
1511                   "tmirror name x y z dx dy dz [-copy]",
1512                   __FILE__,
1513                   transform,g);
1514
1515   theCommands.Add("tscale",
1516                   "tscale name x y z scale [-copy]",
1517                   __FILE__,
1518                   transform,g);
1519
1520   theCommands.Add("tcopy",
1521                   "tcopy [-n(ogeom)] [-m(esh)] name1 result1 [name2 result2 ...]",
1522                   __FILE__,
1523                   tcopy,g);
1524
1525   theCommands.Add("bmove",
1526                   "bmove name1 name2 ... name, set location from name",
1527                   __FILE__,
1528                   transform,g);
1529
1530   theCommands.Add("fmove",
1531                   "fmove name1 name2 ... name, set location from name",
1532                   __FILE__,
1533                   transform, g);
1534
1535   theCommands.Add("btranslate",
1536                   "btranslate name1 name2 ... dx dy dz",
1537                   __FILE__,
1538                   transform,g);
1539
1540   theCommands.Add("brotate",
1541                   "brotate name1 name2 ... x y z dx dy dz angle",
1542                   __FILE__,
1543                   transform,g);
1544
1545   theCommands.Add("bmirror",
1546                   "bmirror name x y z dx dy dz",
1547                   __FILE__,
1548                   transform,g);
1549
1550   theCommands.Add("fmirror",
1551                   "fmirror name x y z dx dy dz",
1552                   __FILE__,
1553                    transform, g);
1554
1555   theCommands.Add("bscale",
1556                   "bscale name x y z scale",
1557                   __FILE__,
1558                   transform,g);
1559
1560   theCommands.Add("fscale",
1561                   "fscale name x y z scale",
1562                   __FILE__,
1563                   transform, g);
1564
1565   theCommands.Add("precision",
1566                   "precision [preci]",
1567                   __FILE__,
1568                   precision,g);
1569
1570   theCommands.Add("mkedgecurve",
1571                   "mkedgecurve name tolerance",
1572                   __FILE__,
1573                   mkedgecurve,g);
1574
1575   theCommands.Add("fsameparameter",
1576                   "fsameparameter shapename [tol (default 1.e-7)], \nforce sameparameter on all edges of the shape",
1577                   __FILE__,
1578                   sameparameter,g);
1579
1580   theCommands.Add("sameparameter",
1581                   "sameparameter [result] shape [tol]",
1582                   __FILE__,
1583                   sameparameter,g);
1584
1585   theCommands.Add("updatetolerance",
1586                   "updatetolerance [result] shape [param] \n  if [param] is absent - not verify of face tolerance, else - perform it",
1587                   __FILE__,
1588                   updatetol,g);
1589
1590   theCommands.Add("solidorientation",
1591                   "orientsolid myClosedSolid",
1592                   __FILE__,
1593                   orientsolid,g);
1594
1595   theCommands.Add("getcoords",
1596     "getcoords vertex1 vertex 2... ; shows coords of input vertices",
1597     __FILE__,
1598     getcoords,g);
1599   
1600   theCommands.Add ("bounding",
1601                    "bounding {shape | xmin ymin zmin xmax ymax zmax}"
1602          "\n\t\t:            [-obb] [-noTriangulation] [-optimal] [-extToler]"
1603          "\n\t\t:            [-dump] [-print] [-dumpJson] [-shape name] [-nodraw] [-finitePart]"
1604          "\n\t\t:            [-save xmin ymin zmin xmax ymax zmax]"
1605          "\n\t\t:"
1606          "\n\t\t: Computes a bounding box. Two types of the source data are supported:"
1607          "\n\t\t: a shape or AABB corners (xmin, ymin, zmin, xmax, ymax, zmax)."
1608          "\n\t\t:"
1609          "\n\t\t: Calculation options (applicable only if input is a shape):"
1610          "\n\t\t:  -obb     Compute Oriented Bounding Box (OBB) instead of AABB."
1611          "\n\t\t:  -noTriangulation Force use of exact geometry for calculation"
1612          "\n\t\t:                   even if triangulation is present."
1613          "\n\t\t:  -optimal Force calculation of optimal (more tight) AABB."
1614          "\n\t\t:           In case of OBB:"
1615          "\n\t\t:           - for PCA approach applies to initial AABB used in OBB calculation"
1616          "\n\t\t:           - for DiTo approach modifies the DiTo algorithm to check more axes."
1617          "\n\t\t:  -extToler Include tolerance of the shape in the resulting box."
1618          "\n\t\t:"
1619          "\n\t\t: Output options:"
1620          "\n\t\t:  -dump    Prints the information about computed Bounding Box."
1621          "\n\t\t:  -print   Prints the information about computed Bounding Box."
1622          "\n\t\t:           It is enabled by default (with plain old syntax for AABB)"
1623          "\n\t\t:           if neither -shape nor -save is specified."
1624          "\n\t\t:  -dumpJson Prints DumpJson information about Bounding Box."
1625          "\n\t\t:  -shape   Stores computed box as solid in DRAW variable with specified name."
1626          "\n\t\t:  -save    Stores min and max coordinates of AABB in specified variables."
1627          "\n\t\t:  -noDraw  Avoid drawing resulting Bounding Box in DRAW viewer."
1628          "\n\t\t:  -finite  Return finite part of infinite box.",
1629                   __FILE__, BoundBox, g);
1630
1631  //
1632   theCommands.Add("gbounding",
1633                   "gbounding surf/curve/curve2d [-o] ",
1634                   __FILE__,
1635                   gbounding,g);
1636
1637   theCommands.Add("isbbinterf", "isbbinterf shape1 shape2 [-o]\n"
1638                   "Checks whether the bounding-boxes created from "
1639                   "the given shapes are interfered. If \"-o\"-option "
1640                   "is switched on then the oriented boxes will be checked. "
1641                   "Otherwise, axes-aligned boxes will be checked.",
1642                   __FILE__, IsBoxesInterfered, g);
1643
1644   theCommands.Add("nurbsconvert",
1645                   "nurbsconvert result name [result name]",
1646                   __FILE__,
1647                   nurbsconvert,g);
1648
1649   theCommands.Add("deform",
1650                   "deform newname name CoeffX CoeffY CoeffZ",
1651                   __FILE__,
1652                   deform,g);
1653   
1654   theCommands.Add("findplane",
1655                   "findplane name planename ",
1656                   __FILE__,
1657                   findplane,g) ;
1658   
1659   theCommands.Add("maxtolerance",
1660                   "maxtolerance shape ",
1661                   __FILE__,
1662                   maxtolerance,g) ;
1663
1664   theCommands.Add("reperageshape",
1665                   "reperage shape -> list of shape (result of interstion shape , line)",
1666                   __FILE__,
1667                   reperageshape,g) ;
1668
1669   theCommands.Add("vecdc",
1670                   "vecdc + Pointe double click ",
1671                   __FILE__,
1672                   vecdc,g) ;
1673
1674   theCommands.Add("nproject","nproject pj e1 e2 e3 ... surf -g -d [dmax] [Tol [continuity [maxdeg [maxseg]]]",
1675                   __FILE__,
1676                   nproject,g);
1677
1678   theCommands.Add("wexplo","wexplo wire [face] create WEDGE_i",
1679                   __FILE__,
1680                   wexplo,g);
1681
1682   theCommands.Add("scalexyz",
1683                   "scalexyz res shape factor_x factor_y factor_z",
1684                   __FILE__,
1685                   scalexyz, g);
1686
1687   theCommands.Add("compare",
1688                   "Compare shapes. Usage: compare shape1 shape2",
1689                   __FILE__,
1690                   compareshapes, g);
1691
1692   theCommands.Add("issubshape",
1693                   "issubshape subshape shape\n"
1694                   "\t\tCheck if the shape is sub-shape of other shape and get its index in the shape.",
1695                   __FILE__,
1696                   issubshape, g);
1697   theCommands.Add("purgeloc",
1698     "purgeloc res shape ",
1699     __FILE__,
1700     purgeloc, g);
1701
1702   theCommands.Add("checkloc",
1703     "checkloc shape ",
1704     __FILE__,
1705     checkloc, g);
1706 }