0030346: Modeling Algorithms - BRepPrimAPI_MakeRevol throws "BRepSweep_Translation...
[occt.git] / src / BRepTest / BRepTest_SurfaceCommands.cxx
old mode 100755 (executable)
new mode 100644 (file)
index 04868d3..3c55eaa
@@ -1,11 +1,19 @@
-// File:       DBRep_4.cxx
-// Created:    Thu Jul 22 16:39:43 1993
-// Author:     Remi LEQUETTE
-//             <rle@nonox>
+// Created on: 1993-07-22
+// Created by: Remi LEQUETTE
+// Copyright (c) 1993-1999 Matra Datavision
+// Copyright (c) 1999-2014 OPEN CASCADE SAS
+//
+// This file is part of Open CASCADE Technology software library.
+//
+// This library is free software; you can redistribute it and/or modify it under
+// the terms of the GNU Lesser General Public License version 2.1 as published
+// by the Free Software Foundation, with special exception defined in the file
+// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
+// distribution for complete text of the license and disclaimer of any warranty.
+//
+// Alternatively, this file may be used under the terms of Open CASCADE
+// commercial license or contractual agreement.
 
-#ifdef HAVE_CONFIG_H
-# include <config.h>
-#endif
 #include <stdio.h>
 #include <BRepTest.hxx>
 #include <GeometryTest.hxx>
 #include <Geom_Surface.hxx>
 #include <Geom2d_TrimmedCurve.hxx>
 #include <TopTools_ListOfShape.hxx>
+#include <TopTools_SequenceOfShape.hxx>
 #include <Precision.hxx>
+#include <Draw_ProgressIndicator.hxx>
+#include <NCollection_Vector.hxx>
+#include <BRepBuilderAPI_FastSewing.hxx>
+
+#include <GeomAPI_ProjectPointOnSurf.hxx>
 
-#ifdef WNT
+#ifdef _WIN32
 //#define strcasecmp strcmp Already defined
 #include <stdio.h>
 #endif
-#ifdef HAVE_STRINGS_H
-# include <strings.h>
-#endif
 
 //-----------------------------------------------------------------------
 // suppressarg : suppress a[d],modifie na--
@@ -92,9 +103,9 @@ static Standard_Integer mkface(Draw_Interpretor& , Standard_Integer n, const cha
   }
   else {
     if (mkface)
-      res = BRepBuilderAPI_MakeFace(S,atof(a[3]),atof(a[4]),atof(a[5]),atof(a[6]),Precision::Confusion());
+      res = BRepBuilderAPI_MakeFace(S,Draw::Atof(a[3]),Draw::Atof(a[4]),Draw::Atof(a[5]),Draw::Atof(a[6]),Precision::Confusion());
     else
-      res = BRepBuilderAPI_MakeShell(S,atof(a[3]),atof(a[4]),atof(a[5]),atof(a[6]),
+      res = BRepBuilderAPI_MakeShell(S,Draw::Atof(a[3]),Draw::Atof(a[4]),Draw::Atof(a[5]),Draw::Atof(a[6]),
                              Segment);
   }
   
@@ -171,7 +182,7 @@ static Standard_Integer mksurface(Draw_Interpretor& , Standard_Integer n, const
 // mkplane
 //=======================================================================
 
-static Standard_Integer mkplane(Draw_Interpretor& , Standard_Integer n, const char** a)
+static Standard_Integer mkplane(Draw_Interpretor& theDI, Standard_Integer n, const char** a)
 {
   if (n < 3) return 1;
 
@@ -183,9 +194,30 @@ static Standard_Integer mkplane(Draw_Interpretor& , Standard_Integer n, const ch
     OnlyPlane =  !strcmp(a[3],"1");
   }
 
-  TopoDS_Face F = BRepBuilderAPI_MakeFace(TopoDS::Wire(S), OnlyPlane);
+  BRepBuilderAPI_MakeFace aMF(TopoDS::Wire(S), OnlyPlane);
+
+  switch(aMF.Error())
+  {
+  case BRepBuilderAPI_FaceDone:
+    DBRep::Set(a[1],aMF.Face());
+    break;
+  case BRepBuilderAPI_NoFace:
+    theDI << "Error. mkplane has been finished with \"No Face\" status.\n";
+    break;
+  case BRepBuilderAPI_NotPlanar:
+    theDI << "Error. mkplane has been finished with \"Not Planar\" status.\n";
+    break;
+  case BRepBuilderAPI_CurveProjectionFailed:
+    theDI << "Error. mkplane has been finished with \"Fail in projection curve\" status.\n";
+    break;
+  case BRepBuilderAPI_ParametersOutOfRange:
+    theDI << "Error. mkplane has been finished with \"Parameters are out of range\" status.\n";
+    break;
+  default:
+    theDI << "Error. Undefined status. Please check the code.\n";
+    break;
+  }
 
-  DBRep::Set(a[1],F);
   return 0;
 }
 
@@ -228,8 +260,25 @@ static Standard_Integer pcurve(Draw_Interpretor& , Standard_Integer n, const cha
       col = DBRep_ColorOrientation(ex.Current().Orientation());
       DrawTrSurf_CurveColor(col);
 
-      sprintf(name,"%s_%d",a[1],i);
-      DrawTrSurf::Set(name,new Geom2d_TrimmedCurve(c,f,l));
+      Sprintf(name,"%s_%d",a[1],i);
+      Standard_Real fr = c->FirstParameter(), lr = c->LastParameter();
+      Standard_Boolean IsPeriodic = c->IsPeriodic();
+      if (c->DynamicType() == STANDARD_TYPE(Geom2d_TrimmedCurve))
+      {
+        const Handle(Geom2d_Curve)& aC = Handle(Geom2d_TrimmedCurve)::DownCast (c)->BasisCurve(); 
+        IsPeriodic = aC->IsPeriodic();
+        fr = aC->FirstParameter();
+        lr = aC->LastParameter();
+      }
+      if(!IsPeriodic && 
+        ((fr - f > Precision::PConfusion()) || (l - lr > Precision::PConfusion())))
+      {
+        DrawTrSurf::Set(name, c);
+      }
+      else
+      {
+        DrawTrSurf::Set(name,new Geom2d_TrimmedCurve(c,f,l));
+      }
     }
     DrawTrSurf_CurveColor(savecol);
 
@@ -244,10 +293,27 @@ static Standard_Integer pcurve(Draw_Interpretor& , Standard_Integer n, const cha
     Standard_Real f,l;
     const Handle(Geom2d_Curve) c = BRep_Tool::CurveOnSurface
       (TopoDS::Edge(SE),TopoDS::Face(SF),f,l);
+    Standard_Real fr = c->FirstParameter(), lr = c->LastParameter();
+    Standard_Boolean IsPeriodic = c->IsPeriodic();
+    if (c->DynamicType() == STANDARD_TYPE(Geom2d_TrimmedCurve))
+    {
+      const Handle(Geom2d_Curve)& aC = Handle(Geom2d_TrimmedCurve)::DownCast (c)->BasisCurve(); 
+      IsPeriodic = aC->IsPeriodic();
+      fr = aC->FirstParameter();
+      lr = aC->LastParameter();
+    }
 
     col = DBRep_ColorOrientation(SE.Orientation());
     DrawTrSurf_CurveColor(col);
-    DrawTrSurf::Set(a[1],new Geom2d_TrimmedCurve(c,f,l));
+    if(!IsPeriodic && 
+      ((fr - f > Precision::PConfusion()) || (l - lr > Precision::PConfusion())))
+    {
+      DrawTrSurf::Set(a[1], c);
+    }
+    else
+    {
+      DrawTrSurf::Set(a[1],new Geom2d_TrimmedCurve(c,f,l));
+    }
     DrawTrSurf_CurveColor(savecol);
   }
   else { 
@@ -261,50 +327,199 @@ static Standard_Integer pcurve(Draw_Interpretor& , Standard_Integer n, const cha
 // sewing
 //=======================================================================
 
-static Standard_Integer sewing (Draw_Interpretor& , 
-                               Standard_Integer n, const char** a)
+static Standard_Integer sewing (Draw_Interpretor& theDi
+                               Standard_Integer theArgc, const char** theArgv)
 {
-  if (n < 3) return (1);
-
   BRepBuilderAPI_Sewing aSewing;
-  Standard_Integer ntmp = n;
+  Standard_Integer aPar = 1;
+  TopTools_SequenceOfShape aSeq;
+
+  Standard_Real aTol = 1.0e-06;
+  Standard_Boolean aSewingMode = Standard_True;
+  Standard_Boolean anAnalysisMode = Standard_True;
+  Standard_Boolean aCuttingMode = Standard_True;
+  Standard_Boolean aNonManifoldMode = Standard_False;
+  Standard_Boolean aSameParameterMode = Standard_True;
+  Standard_Boolean aFloatingEdgesMode = Standard_False;
+  Standard_Boolean aFaceMode = Standard_True;
+  Standard_Boolean aSetMinTol = Standard_False;
+  Standard_Real aMinTol = 0.;
+  Standard_Real aMaxTol = Precision::Infinite();
+
+  for (Standard_Integer i = 2; i < theArgc; i++)
+  {
+    if (theArgv[i][0] == '-' || theArgv[i][0] == '+')
+    {
+      Standard_Boolean aVal = (theArgv[i][0] == '+' ? Standard_True : Standard_False);
+      switch (tolower(theArgv[i][1]))
+      {
+      case 'm':
+        {
+          if (tolower(theArgv[i][2]) == 'i' && i+1 < theArgc)
+          {
+            if (Draw::Atof (theArgv[i+1]))
+            {
+              aMinTol = Draw::Atof (theArgv[++i]);
+              aSetMinTol = Standard_True;
+            }
+            else
+            {
+              theDi << "Error! min tolerance can't possess the null value\n";
+              return (1);
+            }
+          }
+          if (tolower(theArgv[i][2]) == 'a' && i+1 < theArgc)
+          {
+            if (Draw::Atof (theArgv[i+1]))
+              aMaxTol = Draw::Atof (theArgv[++i]);
+            else
+            {
+              theDi << "Error! max tolerance can't possess the null value\n";
+              return (1);
+            }
+          }
+        }
+        break;
+      case 's': aSewingMode = aVal; break;
+      case 'a': anAnalysisMode = aVal; break;
+      case 'c': aCuttingMode = aVal; break;
+      case 'n': aNonManifoldMode = aVal; break;
+      case 'p': aSameParameterMode = aVal; break;
+      case 'e': aFloatingEdgesMode = aVal; break;
+      case 'f': aFaceMode = aVal; break;
+      }
+    }
+    else
+    {
+      TopoDS_Shape aShape = DBRep::Get (theArgv[i]);
+      if (!aShape.IsNull())
+      {
+        aSeq.Append (aShape);
+        aPar++;
+      }
+      else
+      {
+        if (Draw::Atof (theArgv[i]))
+          aTol = Draw::Atof (theArgv[i]);
+      }
+    }
+  }
+   
+  if (aPar < 2)
+  {
+    theDi << "Use: " << theArgv[0] << " result [tolerance] shape1 shape2 ... [min tolerance] [max tolerance] [switches]\n";
+    theDi << "To set user's value of min/max tolerances the following syntax is used: +<parameter> <value>\n";
+    theDi << "- parameters are identified by letters:\n";
+    theDi << "  mint - min tolerance\n";
+    theDi << "  maxt - max tolerance\n";
+    theDi << "Switches allow to tune other parameters of Sewing\n";
+    theDi << "The following syntax is used: <symbol><parameter>\n";
+    theDi << "- symbol may be - to set parameter off, + to set on\n";
+    theDi << "- parameters are identified by letters:\n";
+    theDi << "  s - mode for creating sewed shape\n";
+    theDi << "  a - mode for analysis of input shapes\n";
+    theDi << "  c - mode for cutting of free edges\n";
+    theDi << "  n - mode for non manifold processing\n";
+    theDi << "  p - mode for same parameter processing for edges\n";
+    theDi << "  e - mode for sewing floating edges\n";
+    theDi << "  f - mode for sewing faces\n";
+    return (1);
+  }
+    
+  if (!aSetMinTol)
+    aMinTol = aTol*1e-4;
+  if (aTol < Precision::Confusion())
+    aTol = Precision::Confusion();
+  if (aMinTol < Precision::Confusion())
+    aMinTol = Precision::Confusion();
+  if (aMinTol > aTol)
+  {
+    theDi << "Error! min tolerance can't exceed working tolerance\n";
+    return (1);
+  }
+  if (aMaxTol < aTol)
+  {
+    theDi << "Error! max tolerance can't be less than working tolerance\n";
+    return (1);
+  }
 
-  TopoDS_Shape sh = DBRep::Get(a[2]);
-  Standard_Integer i=2;
-  Standard_Real tol = 1.0e-06;
-  if (sh.IsNull()) {
-    if (n < 4) return (1);
-    tol = atof(a[2]);
-    //Standard_Real tol = atof(a[2]);
-    //aSewing.Init(tol, Standard_True,Standard_True,Standard_True,Standard_False);
-    i = 3;
+  aSewing.Init (aTol, aSewingMode, anAnalysisMode, aCuttingMode, aNonManifoldMode);
+  aSewing.SetSameParameterMode (aSameParameterMode);
+  aSewing.SetFloatingEdgesMode (aFloatingEdgesMode);
+  aSewing.SetFaceMode (aFaceMode);
+  aSewing.SetMinTolerance (aMinTol);
+  aSewing.SetMaxTolerance (aMaxTol);
+
+  for (Standard_Integer i = 1; i <= aSeq.Length(); i++)
+    aSewing.Add(aSeq.Value(i));
+  
+  Handle(Draw_ProgressIndicator) aProgress = new Draw_ProgressIndicator (theDi, 1);
+  aSewing.Perform (aProgress);
+  aSewing.Dump();
+
+  const TopoDS_Shape& aRes = aSewing.SewedShape();
+  if (!aRes.IsNull())
+    DBRep::Set(theArgv[1], aRes);
+  return 0;
+}
+
+//=======================================================================
+//function : fastsewing
+//purpose  : 
+//=======================================================================
+Standard_Integer fastsewing (Draw_Interpretor& theDI, 
+                            Standard_Integer theNArg, 
+                            const char** theArgVal)
+{
+  if(theNArg < 3)
+  {
+    //                0         1       2     3         4
+    theDI << "Use: fastsewing result [-tol <value>] <list_of_faces>\n";
+    return 1;
   }
 
-  Standard_Boolean NonManifoldMode = Standard_False;
-  sh = DBRep::Get(a[n-1]);
-  if (sh.IsNull()) {
-    // read non manifold mode
-    Standard_Integer nmm = atoi(a[n-1]);
-    if(nmm==1)
-      NonManifoldMode = Standard_True;
-    ntmp--;
+  BRepBuilderAPI_FastSewing aFS;
+
+  Standard_Integer aStartIndex = 2;
+
+  if(!strcmp(theArgVal[aStartIndex], "-tol"))
+  {
+    aFS.SetTolerance(Draw::Atof (theArgVal[aStartIndex+1]));
+    aStartIndex = 4;
   }
 
-  aSewing.Init(tol, Standard_True,Standard_True,Standard_True,NonManifoldMode);
-  
-  while (i < ntmp) {
-    sh = DBRep::Get(a[i]);
-    aSewing.Add(sh);
-    i++;
+  for(Standard_Integer i = aStartIndex; i < theNArg; i++)
+  {
+    TopoDS_Shape aS = DBRep::Get(theArgVal[i]);
+    
+    if(!aFS.Add(aS))
+    {
+      theDI << "Face is not added. See statuses.\n";
+    }
   }
 
-  aSewing.Perform();
-  aSewing.Dump();
+  BRepBuilderAPI_FastSewing::FS_VARStatuses aStatus = aFS.GetStatuses();
+
+  if(aStatus)
+  {
+    theDI << "Error: There are some problems while adding (" <<
+                        (static_cast<Standard_Integer>(aStatus)) << ")\n";
+    aFS.GetStatuses(&cout);
+  }
 
-  const TopoDS_Shape& sh2 = aSewing.SewedShape();
-  if (!sh2.IsNull()) {
-    DBRep::Set(a[1], sh2);
+  aFS.Perform();
+
+  aStatus = aFS.GetStatuses();
+
+  if(aStatus)
+  {
+    theDI << "Error: There are some problems while performing (" <<
+                        (static_cast<Standard_Integer>(aStatus)) << ")\n";
+    aFS.GetStatuses(&cout);
   }
+
+  DBRep::Set(theArgVal[1], aFS.GetResult());
+
   return 0;
 }
 
@@ -323,7 +538,7 @@ static Standard_Integer continuity (Draw_Interpretor& ,
   Standard_Integer i=1;
   if (sh.IsNull()) {
     if (n < 3) return (1);
-    Standard_Real tol = atof(a[1]);
+    Standard_Real tol = Draw::Atof(a[1]);
     aFind.Init(tol, Standard_False);
     i = 2;
   }
@@ -337,24 +552,6 @@ static Standard_Integer continuity (Draw_Interpretor& ,
   aFind.Perform();
   aFind.Dump();
 
-  for (i=1; i<=aFind.NbContigousEdges(); i++) {
-#ifdef DEB
-    const TopoDS_Edge& edge =
-#endif
-                              aFind.ContigousEdge(i);
-    const TopTools_ListOfShape& list = aFind.ContigousEdgeCouple(i);
-    const TopoDS_Edge& sec1 = TopoDS::Edge(list.First());
-    const TopoDS_Edge& sec2 = TopoDS::Edge(list.Last());
-#ifdef DEB
-    const TopoDS_Edge& bound1 =
-#endif
-                                aFind.SectionToBoundary(sec1);
-#ifdef DEB
-    const TopoDS_Edge& bound2 =
-#endif
-                                aFind.SectionToBoundary(sec2);
-  }
-
   return 0;
 }
 
@@ -371,13 +568,146 @@ static Standard_Integer encoderegularity (Draw_Interpretor& ,
   if (n==2) 
     BRepLib::EncodeRegularity(sh);
   else {
-    Standard_Real Tol = atof(a[2]);
-    Tol *= PI/180.;
+    Standard_Real Tol = Draw::Atof(a[2]);
+    Tol *= M_PI/180.;
     BRepLib::EncodeRegularity(sh, Tol);
   }
   return 0;
 }
 
+static Standard_Integer getedgeregul
+  (Draw_Interpretor& di, Standard_Integer argc, const char** argv)
+{
+  if( argc < 3)
+  {
+    cout<<"Invalid number of arguments. Should be: checkedgeregularity edge face1 [face2]"<<endl;
+    return 1;
+  }
+  
+  TopoDS_Shape anEdge =  DBRep::Get(argv[1],TopAbs_EDGE);
+  TopoDS_Shape aFace1 = DBRep::Get(argv[2],TopAbs_FACE);
+  TopoDS_Shape aFace2 = (argc > 3  ? DBRep::Get(argv[3],TopAbs_FACE) : aFace1);
+  if( anEdge.IsNull() || aFace1.IsNull() || aFace2.IsNull())
+  {
+    cout<<"Invalid number of arguments. Should be: getedgeregularity edge face1 [face2]"<<endl;
+    return 1;
+  }
+  GeomAbs_Shape aRegularity = BRep_Tool::Continuity(TopoDS::Edge(anEdge), TopoDS::Face(aFace1),  TopoDS::Face(aFace2));
+  TCollection_AsciiString aStrReg("Regularity of edge : ");
+  switch( aRegularity)
+  {
+    default:
+    case GeomAbs_C0 : aStrReg += "C0"; break;
+    case GeomAbs_G1 : aStrReg += "G1"; break;
+    case GeomAbs_C1 : aStrReg += "C1"; break;
+    case GeomAbs_G2 : aStrReg += "G2"; break;
+    case GeomAbs_C2 : aStrReg += "C2"; break;
+    case GeomAbs_C3 : aStrReg += "C3"; break;
+    case GeomAbs_CN : aStrReg += "CN"; break;
+  };
+
+  di<<aStrReg.ToCString()<<"\n";
+  return 0; // Done
+}
+
+//=======================================================================
+//function : projponf
+//purpose  : 
+//=======================================================================
+static Standard_Integer projponf(Draw_Interpretor& di, Standard_Integer n, const char** a)
+{
+  if (n < 3 || n > 5) {
+    di << "Project point on the face.\n";
+    di << "Usage: projponf face pnt [extrema flag: -min/-max/-minmax] [extrema algo: -g(grad)/-t(tree)]\n";
+    return 1;
+  }
+  // get face
+  TopoDS_Shape aS = DBRep::Get(a[1]);
+  if (aS.IsNull()) {
+    di << "the face is a null shape\n";
+    return 0;
+  }
+  //
+  if (aS.ShapeType() != TopAbs_FACE) {
+    di << "not a face\n";
+    return 0;
+  }
+  //
+  const TopoDS_Face& aFace = *(TopoDS_Face*)&aS;
+  //
+  // get point
+  gp_Pnt aP;
+  DrawTrSurf::GetPoint(a[2], aP);
+  //
+  // get projection options
+  // default values;
+  Extrema_ExtAlgo anExtAlgo = Extrema_ExtAlgo_Grad;
+  Extrema_ExtFlag anExtFlag = Extrema_ExtFlag_MINMAX;
+  //
+  for (Standard_Integer i = 3; i < n; ++i) {
+    if (!strcasecmp(a[i], "-min")) {
+      anExtFlag = Extrema_ExtFlag_MIN;
+    }
+    else if (!strcasecmp(a[i], "-max")) {
+      anExtFlag = Extrema_ExtFlag_MAX;
+    }
+    else if (!strcasecmp(a[i], "-minmax")) {
+      anExtFlag = Extrema_ExtFlag_MINMAX;
+    }
+    else if (!strcasecmp(a[i], "-t")) {
+      anExtAlgo = Extrema_ExtAlgo_Tree;
+    }
+    else if (!strcasecmp(a[i], "-g")) {
+      anExtAlgo = Extrema_ExtAlgo_Grad;
+    }
+  }
+  //
+  // get surface
+  TopLoc_Location aLoc;
+  const Handle(Geom_Surface)& aSurf = BRep_Tool::Surface(aFace, aLoc);
+  // move point to surface location
+  aP.Transform(aLoc.Transformation().Inverted());
+  //
+  // get bounds of the surface
+  Standard_Real aUMin, aUMax, aVMin, aVMax;
+  aSurf->Bounds(aUMin, aUMax, aVMin, aVMax);
+  //
+  // initialize projector
+  GeomAPI_ProjectPointOnSurf aProjPS;
+  aProjPS.Init(aSurf, aUMin, aUMax, aVMin, aVMax);
+  // set the options
+  aProjPS.SetExtremaAlgo(anExtAlgo);
+  aProjPS.SetExtremaFlag(anExtFlag);
+  // perform projection
+  aProjPS.Perform(aP);
+  //
+  if (aProjPS.NbPoints()) {
+    // lower distance
+    Standard_Real aDist = aProjPS.LowerDistance();
+    // lower distance parameters
+    Standard_Real U, V;
+    aProjPS.LowerDistanceParameters(U, V);
+    // nearest point
+    gp_Pnt aPProj = aProjPS.NearestPoint();
+    // translate projection point to face location
+    aPProj.Transform(aLoc.Transformation());
+    //
+    // print the projection values
+    di << "proj dist = " << aDist << "\n";
+    di << "uvproj = " << U << " " << V << "\n";
+    di << "pproj = " << aPProj.X() << " " << aPProj.Y() << " " << aPProj.Z() << "\n";
+  }
+  else {
+    if (!aProjPS.IsDone()) {
+      di << "projection failed\n";
+    }
+    else {
+      di << "no projection found\n";
+    }
+  }
+  return 0;
+}
 
 //=======================================================================
 //function : SurfaceCommands
@@ -420,7 +750,7 @@ void  BRepTest::SurfaceCommands(Draw_Interpretor& theCommands)
                  __FILE__,pcurve,g);
 
   theCommands.Add("sewing",
-                 "sewing result [tolerance] shape1 shape2 ...",
+                 "sewing result [tolerance] shape1 shape2 ... [min tolerance] [max tolerance] [switches]",
                  __FILE__,sewing, g);
 
   theCommands.Add("continuity", 
@@ -430,5 +760,14 @@ void  BRepTest::SurfaceCommands(Draw_Interpretor& theCommands)
   theCommands.Add("encoderegularity", 
                  "encoderegularity shape [tolerance (in degree)]",
                  __FILE__,encoderegularity, g);
+
+  theCommands.Add ("fastsewing", "fastsewing result [-tol <value>] <list_of_faces>", 
+                                                __FILE__, fastsewing, g);
+  theCommands.Add ("getedgeregularity", "getedgeregularity edge face1 [face2]",  __FILE__,getedgeregul,g);
+
+  theCommands.Add ("projponf",
+                   "projponf face pnt [extrema flag: -min/-max/-minmax] [extrema algo: -g(grad)/-t(tree)]\n"
+                   "\t\tProject point on the face.",
+                   __FILE__, projponf, g);
 }