0026570: Crash on attempt to rotate a shape.
[occt.git] / src / BRepTest / BRepTest_SurfaceCommands.cxx
1 // Created on: 1993-07-22
2 // Created by: Remi LEQUETTE
3 // Copyright (c) 1993-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 <stdio.h>
18 #include <BRepTest.hxx>
19 #include <GeometryTest.hxx>
20
21 #include <DrawTrSurf.hxx>
22 #include <DBRep.hxx>
23 #include <Draw_Interpretor.hxx>
24 #include <Draw_Appli.hxx>
25
26 #include <BRep_Builder.hxx>
27 #include <BRep_Tool.hxx>
28 #include <BRepLib.hxx>
29 #include <BRepTools_Quilt.hxx>
30 #include <BRepAdaptor_Curve.hxx>
31 #include <BRepBuilderAPI_MakeFace.hxx>
32 #include <BRepBuilderAPI_MakeShell.hxx>
33 #include <BRepBuilderAPI.hxx>
34 #include <BRepBuilderAPI_Sewing.hxx>
35 #include <BRepOffsetAPI_FindContigousEdges.hxx>
36 #include <TopExp_Explorer.hxx>
37 #include <TopoDS.hxx>
38 #include <TopoDS_Face.hxx>
39 #include <Geom_Surface.hxx>
40 #include <Geom2d_TrimmedCurve.hxx>
41 #include <TopTools_ListOfShape.hxx>
42 #include <TopTools_SequenceOfShape.hxx>
43 #include <Precision.hxx>
44 #include <Draw_ProgressIndicator.hxx>
45 #include <NCollection_Vector.hxx>
46 #include <BRepBuilderAPI_FastSewing.hxx>
47
48 #include <GeomAPI_ProjectPointOnSurf.hxx>
49
50 #ifdef _WIN32
51 //#define strcasecmp strcmp Already defined
52 #include <stdio.h>
53 #endif
54
55 //-----------------------------------------------------------------------
56 // suppressarg : suppress a[d],modifie na--
57 //-----------------------------------------------------------------------
58 static void suppressarg(Standard_Integer& na,const char** a,const Standard_Integer d) 
59 {
60   for(Standard_Integer i=d;i<na;i++) {
61     a[i]=a[i+1];
62     a[i+1]=NULL;
63   }
64   na--;
65 }
66
67
68 //=======================================================================
69 // mkface
70 //=======================================================================
71
72 static Standard_Integer mkface(Draw_Interpretor& , Standard_Integer n, const char** a)
73 {
74   if (n < 3) return 1;
75   
76   Handle(Geom_Surface) S = DrawTrSurf::GetSurface(a[2]);
77   if (S.IsNull()) {
78     cout << a[2] << " is not a surface" << endl;
79     return 1;
80   }
81   
82   Standard_Boolean mkface = a[0][2] == 'f';
83   TopoDS_Shape res;
84
85   Standard_Boolean Segment = Standard_False;
86   if ( !mkface && (n == 4 || n == 8)) {
87     Segment = !strcmp(a[n-1],"1");
88     n--;
89   }
90
91   if (n == 3) {
92     if (mkface)
93       res = BRepBuilderAPI_MakeFace(S, Precision::Confusion());
94     else
95       res = BRepBuilderAPI_MakeShell(S,Segment);
96   }
97   else if (n <= 5) {
98     if (!mkface) return 1;
99     Standard_Boolean orient = (n  == 4);
100     TopoDS_Shape W = DBRep::Get(a[3],TopAbs_WIRE);
101     if (W.IsNull()) return 1;
102     res = BRepBuilderAPI_MakeFace(S,TopoDS::Wire(W),orient);
103   }
104   else {
105     if (mkface)
106       res = BRepBuilderAPI_MakeFace(S,Draw::Atof(a[3]),Draw::Atof(a[4]),Draw::Atof(a[5]),Draw::Atof(a[6]),Precision::Confusion());
107     else
108       res = BRepBuilderAPI_MakeShell(S,Draw::Atof(a[3]),Draw::Atof(a[4]),Draw::Atof(a[5]),Draw::Atof(a[6]),
109                               Segment);
110   }
111   
112   DBRep::Set(a[1],res);
113   return 0;
114 }
115
116 //=======================================================================
117 // quilt
118 //=======================================================================
119
120 static Standard_Integer quilt(Draw_Interpretor& , Standard_Integer n, const char** a)
121 {
122   if (n < 4) return 1;
123   BRepTools_Quilt Q;
124
125   Standard_Integer i = 2;
126   while (i < n) {
127     TopoDS_Shape S = DBRep::Get(a[i]);
128     if (!S.IsNull()) {
129       if (S.ShapeType() == TopAbs_EDGE) {
130         if (i+1 < n) {
131           TopoDS_Shape E = DBRep::Get(a[i+1]);
132           if (!E.IsNull()) {
133             if (E.ShapeType() == TopAbs_EDGE) {
134               i++;
135               Q.Bind(TopoDS::Edge(S),TopoDS::Edge(E));
136             }
137           }
138         }
139       }
140       if (S.ShapeType() == TopAbs_VERTEX) {
141         if (i+1 < n) {
142           TopoDS_Shape E = DBRep::Get(a[i+1]);
143           if (!E.IsNull()) {
144             if (E.ShapeType() == TopAbs_VERTEX) {
145               i++;
146               Q.Bind(TopoDS::Vertex(S),TopoDS::Vertex(E));
147             }
148           }
149         }
150       }
151       else {
152         Q.Add(S);
153       }
154     }
155     i++;
156   }
157
158   DBRep::Set(a[1],Q.Shells());
159   return 0;
160 }
161
162
163 //=======================================================================
164 // mksurface
165 //=======================================================================
166
167 static Standard_Integer mksurface(Draw_Interpretor& , Standard_Integer n, const char** a)
168 {
169   if (n < 3) return 1;
170
171   TopoDS_Shape S = DBRep::Get(a[2],TopAbs_FACE);
172   if (S.IsNull()) return 1;
173   TopLoc_Location L;
174   Handle(Geom_Surface) C = BRep_Tool::Surface(TopoDS::Face(S),L);
175
176
177   DrawTrSurf::Set(a[1],C->Transformed(L.Transformation()));
178   return 0;
179 }
180
181 //=======================================================================
182 // mkplane
183 //=======================================================================
184
185 static Standard_Integer mkplane(Draw_Interpretor& theDI, Standard_Integer n, const char** a)
186 {
187   if (n < 3) return 1;
188
189   TopoDS_Shape S = DBRep::Get(a[2],TopAbs_WIRE);
190   if (S.IsNull()) return 1;
191
192   Standard_Boolean OnlyPlane = Standard_False;
193   if ( n == 4) {
194     OnlyPlane =  !strcmp(a[3],"1");
195   }
196
197   BRepBuilderAPI_MakeFace aMF(TopoDS::Wire(S), OnlyPlane);
198
199   switch(aMF.Error())
200   {
201   case BRepBuilderAPI_FaceDone:
202     DBRep::Set(a[1],aMF.Face());
203     break;
204   case BRepLib_NoFace:
205     theDI << "Error. mkplane has been finished with \"No Face\" status.\n";
206     break;
207   case BRepLib_NotPlanar:
208     theDI << "Error. mkplane has been finished with \"Not Planar\" status.\n";
209     break;
210   case BRepLib_CurveProjectionFailed:
211     theDI << "Error. mkplane has been finished with \"Fail in projection curve\" status.\n";
212     break;
213   case BRepLib_ParametersOutOfRange:
214     theDI << "Error. mkplane has been finished with \"Parameters are out of range\" status.\n";
215     break;
216   default:
217     theDI << "Error. Undefined status. Please check the code.\n";
218     break;
219   }
220
221   return 0;
222 }
223
224 //=======================================================================
225 // pcurve
226 //=======================================================================
227 Standard_IMPORT Draw_Color DrawTrSurf_CurveColor(const Draw_Color col);
228 Standard_IMPORT void DBRep_WriteColorOrientation ();
229 Standard_IMPORT Draw_Color DBRep_ColorOrientation (const TopAbs_Orientation Or);
230
231 static Standard_Integer pcurve(Draw_Interpretor& , Standard_Integer n, const char** a)
232 {
233   Standard_Boolean mute = Standard_False;
234   for(Standard_Integer ia=1;ia<n;ia++) {
235     if (!strcasecmp(a[ia],"-mute")) {
236       suppressarg(n,a,ia);
237       mute = Standard_True;
238     }
239   }
240
241   if (n == 2) {
242     // pcurves of a face
243     TopoDS_Shape S = DBRep::Get(a[1],TopAbs_FACE);
244     if (S.IsNull()) return 1;
245
246     if (!mute) DBRep_WriteColorOrientation();
247     Draw_Color col, savecol = DrawTrSurf_CurveColor(Draw_rouge);
248
249     char* name = new char[100];
250     Standard_Real f,l;
251     S.Orientation(TopAbs_FORWARD);
252     TopExp_Explorer ex(S,TopAbs_EDGE);
253     for (Standard_Integer i=1; ex.More(); ex.Next(), i++) {
254       const Handle(Geom2d_Curve) c = BRep_Tool::CurveOnSurface
255         (TopoDS::Edge(ex.Current()),TopoDS::Face(S),f,l);
256       if ( c.IsNull() ) {
257         cout << "Error: Edge " << i << " does not have pcurve" << endl;
258         continue;
259       }
260       col = DBRep_ColorOrientation(ex.Current().Orientation());
261       DrawTrSurf_CurveColor(col);
262
263       Sprintf(name,"%s_%d",a[1],i);
264       Standard_Real fr = c->FirstParameter(), lr = c->LastParameter();
265       Standard_Boolean IsPeriodic = c->IsPeriodic();
266       if (c->DynamicType() == STANDARD_TYPE(Geom2d_TrimmedCurve))
267       {
268         const Handle(Geom2d_Curve)& aC = Handle(Geom2d_TrimmedCurve)::DownCast (c)->BasisCurve(); 
269         IsPeriodic = aC->IsPeriodic();
270         fr = aC->FirstParameter();
271         lr = aC->LastParameter();
272       }
273       if(!IsPeriodic && 
274         ((fr - f > Precision::PConfusion()) || (l - lr > Precision::PConfusion())))
275       {
276         DrawTrSurf::Set(name, c);
277       }
278       else
279       {
280         DrawTrSurf::Set(name,new Geom2d_TrimmedCurve(c,f,l));
281       }
282     }
283     DrawTrSurf_CurveColor(savecol);
284
285   }
286   else if (n >= 4) {
287     TopoDS_Shape SE = DBRep::Get(a[2],TopAbs_EDGE);
288     if (SE.IsNull()) return 1;
289     TopoDS_Shape SF = DBRep::Get(a[3],TopAbs_FACE);
290     if (SF.IsNull()) return 1;
291
292     Draw_Color col, savecol = DrawTrSurf_CurveColor(Draw_rouge);
293     Standard_Real f,l;
294     const Handle(Geom2d_Curve) c = BRep_Tool::CurveOnSurface
295       (TopoDS::Edge(SE),TopoDS::Face(SF),f,l);
296     Standard_Real fr = c->FirstParameter(), lr = c->LastParameter();
297     Standard_Boolean IsPeriodic = c->IsPeriodic();
298     if (c->DynamicType() == STANDARD_TYPE(Geom2d_TrimmedCurve))
299     {
300       const Handle(Geom2d_Curve)& aC = Handle(Geom2d_TrimmedCurve)::DownCast (c)->BasisCurve(); 
301       IsPeriodic = aC->IsPeriodic();
302       fr = aC->FirstParameter();
303       lr = aC->LastParameter();
304     }
305
306     col = DBRep_ColorOrientation(SE.Orientation());
307     DrawTrSurf_CurveColor(col);
308     if(!IsPeriodic && 
309       ((fr - f > Precision::PConfusion()) || (l - lr > Precision::PConfusion())))
310     {
311       DrawTrSurf::Set(a[1], c);
312     }
313     else
314     {
315       DrawTrSurf::Set(a[1],new Geom2d_TrimmedCurve(c,f,l));
316     }
317     DrawTrSurf_CurveColor(savecol);
318   }
319   else { 
320     return 1;
321   }
322     
323   return 0;
324 }
325
326 //=======================================================================
327 // sewing
328 //=======================================================================
329
330 static Standard_Integer sewing (Draw_Interpretor& theDi, 
331                                 Standard_Integer theArgc, const char** theArgv)
332 {
333   BRepBuilderAPI_Sewing aSewing;
334   Standard_Integer aPar = 1;
335   TopTools_SequenceOfShape aSeq;
336
337   Standard_Real aTol = 1.0e-06;
338   Standard_Boolean aSewingMode = Standard_True;
339   Standard_Boolean anAnalysisMode = Standard_True;
340   Standard_Boolean aCuttingMode = Standard_True;
341   Standard_Boolean aNonManifoldMode = Standard_False;
342   Standard_Boolean aSameParameterMode = Standard_True;
343   Standard_Boolean aFloatingEdgesMode = Standard_False;
344   Standard_Boolean aFaceMode = Standard_True;
345   Standard_Boolean aSetMinTol = Standard_False;
346   Standard_Real aMinTol = 0.;
347   Standard_Real aMaxTol = Precision::Infinite();
348
349   for (Standard_Integer i = 2; i < theArgc; i++)
350   {
351     if (theArgv[i][0] == '-' || theArgv[i][0] == '+')
352     {
353       Standard_Boolean aVal = (theArgv[i][0] == '+' ? Standard_True : Standard_False);
354       switch (tolower(theArgv[i][1]))
355       {
356       case 'm':
357         {
358           if (tolower(theArgv[i][2]) == 'i' && i+1 < theArgc)
359           {
360             if (Draw::Atof (theArgv[i+1]))
361             {
362               aMinTol = Draw::Atof (theArgv[++i]);
363               aSetMinTol = Standard_True;
364             }
365             else
366             {
367               theDi << "Error! min tolerance can't possess the null value\n";
368               return (1);
369             }
370           }
371           if (tolower(theArgv[i][2]) == 'a' && i+1 < theArgc)
372           {
373             if (Draw::Atof (theArgv[i+1]))
374               aMaxTol = Draw::Atof (theArgv[++i]);
375             else
376             {
377               theDi << "Error! max tolerance can't possess the null value\n";
378               return (1);
379             }
380           }
381         }
382         break;
383       case 's': aSewingMode = aVal; break;
384       case 'a': anAnalysisMode = aVal; break;
385       case 'c': aCuttingMode = aVal; break;
386       case 'n': aNonManifoldMode = aVal; break;
387       case 'p': aSameParameterMode = aVal; break;
388       case 'e': aFloatingEdgesMode = aVal; break;
389       case 'f': aFaceMode = aVal; break;
390       }
391     }
392     else
393     {
394       TopoDS_Shape aShape = DBRep::Get (theArgv[i]);
395       if (!aShape.IsNull())
396       {
397         aSeq.Append (aShape);
398         aPar++;
399       }
400       else
401       {
402         if (Draw::Atof (theArgv[i]))
403           aTol = Draw::Atof (theArgv[i]);
404       }
405     }
406   }
407    
408   if (aPar < 2)
409   {
410     theDi << "Use: " << theArgv[0] << " result [tolerance] shape1 shape2 ... [min tolerance] [max tolerance] [switches]\n";
411     theDi << "To set user's value of min/max tolerances the following syntax is used: +<parameter> <value>\n";
412     theDi << "- parameters are identified by letters:\n";
413     theDi << "  mint - min tolerance\n";
414     theDi << "  maxt - max tolerance\n";
415     theDi << "Switches allow to tune other parameters of Sewing\n";
416     theDi << "The following syntax is used: <symbol><parameter>\n";
417     theDi << "- symbol may be - to set parameter off, + to set on\n";
418     theDi << "- parameters are identified by letters:\n";
419     theDi << "  s - mode for creating sewed shape\n";
420     theDi << "  a - mode for analysis of input shapes\n";
421     theDi << "  c - mode for cutting of free edges\n";
422     theDi << "  n - mode for non manifold processing\n";
423     theDi << "  p - mode for same parameter processing for edges\n";
424     theDi << "  e - mode for sewing floating edges\n";
425     theDi << "  f - mode for sewing faces\n";
426     return (1);
427   }
428     
429   if (!aSetMinTol)
430     aMinTol = aTol*1e-4;
431   if (aTol < Precision::Confusion())
432     aTol = Precision::Confusion();
433   if (aMinTol < Precision::Confusion())
434     aMinTol = Precision::Confusion();
435   if (aMinTol > aTol)
436   {
437     theDi << "Error! min tolerance can't exceed working tolerance\n";
438     return (1);
439   }
440   if (aMaxTol < aTol)
441   {
442     theDi << "Error! max tolerance can't be less than working tolerance\n";
443     return (1);
444   }
445
446   aSewing.Init (aTol, aSewingMode, anAnalysisMode, aCuttingMode, aNonManifoldMode);
447   aSewing.SetSameParameterMode (aSameParameterMode);
448   aSewing.SetFloatingEdgesMode (aFloatingEdgesMode);
449   aSewing.SetFaceMode (aFaceMode);
450   aSewing.SetMinTolerance (aMinTol);
451   aSewing.SetMaxTolerance (aMaxTol);
452
453   for (Standard_Integer i = 1; i <= aSeq.Length(); i++)
454     aSewing.Add(aSeq.Value(i));
455   
456   Handle(Draw_ProgressIndicator) aProgress = new Draw_ProgressIndicator (theDi, 1);
457   aSewing.Perform (aProgress);
458   aSewing.Dump();
459
460   const TopoDS_Shape& aRes = aSewing.SewedShape();
461   if (!aRes.IsNull())
462     DBRep::Set(theArgv[1], aRes);
463   return 0;
464 }
465
466 //=======================================================================
467 //function : fastsewing
468 //purpose  : 
469 //=======================================================================
470 Standard_Integer fastsewing (Draw_Interpretor& theDI, 
471                             Standard_Integer theNArg, 
472                             const char** theArgVal)
473 {
474   if(theNArg < 3)
475   {
476     //                0         1       2     3         4
477     theDI << "Use: fastsewing result [-tol <value>] <list_of_faces>\n";
478     return 1;
479   }
480
481   BRepBuilderAPI_FastSewing aFS;
482
483   Standard_Integer aStartIndex = 2;
484
485   if(!strcmp(theArgVal[aStartIndex], "-tol"))
486   {
487     aFS.SetTolerance(Draw::Atof (theArgVal[aStartIndex+1]));
488     aStartIndex = 4;
489   }
490
491   for(Standard_Integer i = aStartIndex; i < theNArg; i++)
492   {
493     TopoDS_Shape aS = DBRep::Get(theArgVal[i]);
494     
495     if(!aFS.Add(aS))
496     {
497       theDI << "Face is not added. See statuses.\n";
498     }
499   }
500
501   BRepBuilderAPI_FastSewing::FS_VARStatuses aStatus = aFS.GetStatuses();
502
503   if(aStatus)
504   {
505     theDI << "Error: There are some problems while adding (" <<
506                         (static_cast<Standard_Integer>(aStatus)) << ")\n";
507     aFS.GetStatuses(&cout);
508   }
509
510   aFS.Perform();
511
512   aStatus = aFS.GetStatuses();
513
514   if(aStatus)
515   {
516     theDI << "Error: There are some problems while performing (" <<
517                         (static_cast<Standard_Integer>(aStatus)) << ")\n";
518     aFS.GetStatuses(&cout);
519   }
520
521   DBRep::Set(theArgVal[1], aFS.GetResult());
522
523   return 0;
524 }
525
526 //=======================================================================
527 // continuity
528 //=======================================================================
529
530 static Standard_Integer continuity (Draw_Interpretor& , 
531                                     Standard_Integer n, const char** a)
532 {
533   if (n < 2) return (1);
534
535   BRepOffsetAPI_FindContigousEdges aFind;
536
537   TopoDS_Shape sh = DBRep::Get(a[1]);
538   Standard_Integer i=1;
539   if (sh.IsNull()) {
540     if (n < 3) return (1);
541     Standard_Real tol = Draw::Atof(a[1]);
542     aFind.Init(tol, Standard_False);
543     i = 2;
544   }
545   
546   while (i < n) {
547     sh = DBRep::Get(a[i]);
548     aFind.Add(sh);
549     i++;
550   }
551
552   aFind.Perform();
553   aFind.Dump();
554
555   return 0;
556 }
557
558 //=======================================================================
559 // encoderegularity
560 //=======================================================================
561 static Standard_Integer encoderegularity (Draw_Interpretor& , 
562                                           Standard_Integer n, const char** a)
563
564 {
565   if (n < 2) return 1;
566   TopoDS_Shape sh = DBRep::Get(a[1]);
567   if (sh.IsNull()) return 1;
568   if (n==2) 
569     BRepLib::EncodeRegularity(sh);
570   else {
571     Standard_Real Tol = Draw::Atof(a[2]);
572     Tol *= M_PI/180.;
573     BRepLib::EncodeRegularity(sh, Tol);
574   }
575   return 0;
576 }
577
578 static Standard_Integer getedgeregul
579   (Draw_Interpretor& di, Standard_Integer argc, const char** argv)
580 {
581   if( argc < 3)
582   {
583     cout<<"Invalid number of arguments. Should be: checkedgeregularity edge face1 [face2]"<<endl;
584     return 1;
585   }
586   
587   TopoDS_Shape anEdge =  DBRep::Get(argv[1],TopAbs_EDGE);
588   TopoDS_Shape aFace1 = DBRep::Get(argv[2],TopAbs_FACE);
589   TopoDS_Shape aFace2 = (argc > 3  ? DBRep::Get(argv[3],TopAbs_FACE) : aFace1);
590   if( anEdge.IsNull() || aFace1.IsNull() || aFace2.IsNull())
591   {
592     cout<<"Invalid number of arguments. Should be: getedgeregularity edge face1 [face2]"<<endl;
593     return 1;
594   }
595  
596   GeomAbs_Shape aRegularity = BRep_Tool::Continuity(TopoDS::Edge(anEdge), TopoDS::Face(aFace1),  TopoDS::Face(aFace2));
597   TCollection_AsciiString aStrReg("Regularity of edge : ");
598   switch( aRegularity)
599   {
600     default:
601     case GeomAbs_C0 : aStrReg += "C0"; break;
602     case GeomAbs_G1 : aStrReg += "G1"; break;
603     case GeomAbs_C1 : aStrReg += "C1"; break;
604     case GeomAbs_G2 : aStrReg += "G2"; break;
605     case GeomAbs_C2 : aStrReg += "C2"; break;
606     case GeomAbs_C3 : aStrReg += "C3"; break;
607     case GeomAbs_CN : aStrReg += "CN"; break;
608   };
609
610   di<<aStrReg.ToCString()<<"\n";
611   return 0; // Done
612 }
613
614 //=======================================================================
615 //function : projponf
616 //purpose  : 
617 //=======================================================================
618 static Standard_Integer projponf(Draw_Interpretor& di, Standard_Integer n, const char** a)
619 {
620   if (n < 3 || n > 5) {
621     di << "Project point on the face.\n";
622     di << "Usage: projponf face pnt [extrema flag: -min/-max/-minmax] [extrema algo: -g(grad)/-t(tree)]\n";
623     return 1;
624   }
625   // get face
626   TopoDS_Shape aS = DBRep::Get(a[1]);
627   if (aS.IsNull()) {
628     di << "the face is a null shape\n";
629     return 0;
630   }
631   //
632   if (aS.ShapeType() != TopAbs_FACE) {
633     di << "not a face\n";
634     return 0;
635   }
636   //
637   const TopoDS_Face& aFace = *(TopoDS_Face*)&aS;
638   //
639   // get point
640   gp_Pnt aP;
641   DrawTrSurf::GetPoint(a[2], aP);
642   //
643   // get projection options
644   // default values;
645   Extrema_ExtAlgo anExtAlgo = Extrema_ExtAlgo_Grad;
646   Extrema_ExtFlag anExtFlag = Extrema_ExtFlag_MINMAX;
647   //
648   for (Standard_Integer i = 3; i < n; ++i) {
649     if (!strcasecmp(a[i], "-min")) {
650       anExtFlag = Extrema_ExtFlag_MIN;
651     }
652     else if (!strcasecmp(a[i], "-max")) {
653       anExtFlag = Extrema_ExtFlag_MAX;
654     }
655     else if (!strcasecmp(a[i], "-minmax")) {
656       anExtFlag = Extrema_ExtFlag_MINMAX;
657     }
658     else if (!strcasecmp(a[i], "-t")) {
659       anExtAlgo = Extrema_ExtAlgo_Tree;
660     }
661     else if (!strcasecmp(a[i], "-g")) {
662       anExtAlgo = Extrema_ExtAlgo_Grad;
663     }
664   }
665   //
666   // get surface
667   TopLoc_Location aLoc;
668   const Handle(Geom_Surface)& aSurf = BRep_Tool::Surface(aFace, aLoc);
669   // move point to surface location
670   aP.Transform(aLoc.Transformation().Inverted());
671   //
672   // get bounds of the surface
673   Standard_Real aUMin, aUMax, aVMin, aVMax;
674   aSurf->Bounds(aUMin, aUMax, aVMin, aVMax);
675   //
676   // initialize projector
677   GeomAPI_ProjectPointOnSurf aProjPS;
678   aProjPS.Init(aSurf, aUMin, aUMax, aVMin, aVMax);
679   // set the options
680   aProjPS.SetExtremaAlgo(anExtAlgo);
681   aProjPS.SetExtremaFlag(anExtFlag);
682   // perform projection
683   aProjPS.Perform(aP);
684   //
685   if (aProjPS.NbPoints()) {
686     // lower distance
687     Standard_Real aDist = aProjPS.LowerDistance();
688     // lower distance parameters
689     Standard_Real U, V;
690     aProjPS.LowerDistanceParameters(U, V);
691     // nearest point
692     gp_Pnt aPProj = aProjPS.NearestPoint();
693     // translate projection point to face location
694     aPProj.Transform(aLoc.Transformation());
695     //
696     // print the projection values
697     di << "proj dist = " << aDist << "\n";
698     di << "uvproj = " << U << " " << V << "\n";
699     di << "pproj = " << aPProj.X() << " " << aPProj.Y() << " " << aPProj.Z() << "\n";
700   }
701   else {
702     if (!aProjPS.IsDone()) {
703       di << "projection failed\n";
704     }
705     else {
706       di << "no projection found\n";
707     }
708   }
709   return 0;
710 }
711
712 //=======================================================================
713 //function : SurfaceCommands
714 //purpose  : 
715 //=======================================================================
716
717 void  BRepTest::SurfaceCommands(Draw_Interpretor& theCommands)
718 {
719   static Standard_Boolean done = Standard_False;
720   if (done) return;
721   done = Standard_True;
722
723   DBRep::BasicCommands(theCommands);
724   GeometryTest::SurfaceCommands(theCommands);
725
726   const char* g = "Surface topology commands";
727
728   theCommands.Add("mkface",
729                   "mkface facename surfacename [ufirst ulast vfirst vlast] [wire [norient]]",
730                   __FILE__,mkface,g);
731
732   theCommands.Add("mkshell",
733                   "mkshell shellname surfacename [ufirst ulast vfirst vlast] [segment 0/1]",
734                   __FILE__,mkface,g);
735
736   theCommands.Add("quilt",
737                   "quilt compoundname shape1 edgeshape2  edgeshape1... shape2  edgeshape3 edgeshape1or2 ... shape3 ...",
738                   __FILE__,quilt,g);
739   
740   theCommands.Add("mksurface",
741                   "mksurface surfacename facename",
742                   __FILE__,mksurface,g);
743
744   theCommands.Add("mkplane",
745                   "mkplane facename wirename [OnlyPlane 0/1]",
746                   __FILE__,mkplane,g);
747
748   theCommands.Add("pcurve",
749                   "pcurve [name edgename] facename",
750                   __FILE__,pcurve,g);
751
752   theCommands.Add("sewing",
753                   "sewing result [tolerance] shape1 shape2 ... [min tolerance] [max tolerance] [switches]",
754                   __FILE__,sewing, g);
755
756   theCommands.Add("continuity", 
757                   "continuity [tolerance] shape1 shape2 ...",
758                   __FILE__,continuity, g);
759
760   theCommands.Add("encoderegularity", 
761                   "encoderegularity shape [tolerance (in degree)]",
762                   __FILE__,encoderegularity, g);
763
764   theCommands.Add ("fastsewing", "fastsewing result [-tol <value>] <list_of_faces>", 
765                                                 __FILE__, fastsewing, g);
766   theCommands.Add ("getedgeregularity", "getedgeregularity edge face1 [face2]",  __FILE__,getedgeregul,g);
767
768   theCommands.Add ("projponf",
769                    "projponf face pnt [extrema flag: -min/-max/-minmax] [extrema algo: -g(grad)/-t(tree)]\n"
770                    "\t\tProject point on the face.",
771                    __FILE__, projponf, g);
772 }
773