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