6d3ebcded9a62a030f6f611a2fe58571a1050eef
[occt.git] / src / SWDRAW / SWDRAW_ShapeAnalysis.cxx
1 // Created on: 1999-03-09
2 // Created by: data exchange team
3 // Copyright (c) 1999-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 // sln 19.11.2001. Bug 2: Correction of output of 'statshape' draw function.
18
19 #include <BRep_Builder.hxx>
20 #include <BRep_Tool.hxx>
21 #include <BRepBuilderAPI.hxx>
22 #include <BRepBuilderAPI_MakeFace.hxx>
23 #include <BRepGProp.hxx>
24 #include <BRepTopAdaptor_FClass2d.hxx>
25 #include <DBRep.hxx>
26 #include <Draw.hxx>
27 #include <DrawTrSurf.hxx>
28 #include <Geom2d_Curve.hxx>
29 #include <Geom_Curve.hxx>
30 #include <Geom_Surface.hxx>
31 #include <GeomAPI_ProjectPointOnSurf.hxx>
32 #include <gp_Pnt.hxx>
33 #include <gp_Pnt2d.hxx>
34 #include <GProp_GProps.hxx>
35 #include <Precision.hxx>
36 #include <ShapeAnalysis.hxx>
37 #include <ShapeAnalysis_Curve.hxx>
38 #include <ShapeAnalysis_Edge.hxx>
39 #include <ShapeAnalysis_FreeBoundData.hxx>
40 #include <ShapeAnalysis_FreeBounds.hxx>
41 #include <ShapeAnalysis_FreeBoundsProperties.hxx>
42 #include <ShapeAnalysis_ShapeContents.hxx>
43 #include <ShapeAnalysis_ShapeTolerance.hxx>
44 #include <ShapeAnalysis_Surface.hxx>
45 #include <ShapeAnalysis_Wire.hxx>
46 #include <ShapeExtend_WireData.hxx>
47 #include <ShapeFix_FreeBounds.hxx>
48 #include <SWDRAW.hxx>
49 #include <SWDRAW_ShapeAnalysis.hxx>
50 #include <TCollection_AsciiString.hxx>
51 #include <TColStd_MapOfInteger.hxx>
52 #include <TopExp.hxx>
53 #include <TopExp_Explorer.hxx>
54 #include <TopoDS.hxx>
55 #include <TopoDS_Compound.hxx>
56 #include <TopoDS_Edge.hxx>
57 #include <TopoDS_Face.hxx>
58 #include <TopoDS_Iterator.hxx>
59 #include <TopoDS_Shape.hxx>
60 #include <TopoDS_Vertex.hxx>
61 #include <TopoDS_Wire.hxx>
62 #include <TopTools_HSequenceOfShape.hxx>
63 #include <Adaptor3d_CurveOnSurface.hxx>
64 #include <BRepAdaptor_HCurve2d.hxx>
65 #include <BRepAdaptor_HSurface.hxx>
66
67 #include <stdio.h>
68 static Standard_Integer tolerance
69   (Draw_Interpretor& di, Standard_Integer argc, const char** argv)
70 {
71   if (argc < 2) { di<<"myshape  : analyses a shape\n"
72                     <<  "myshape [mode] valmin : sub-shapes over valmin\n"
73                       <<"myshape [mode] valmin valmax : between valmin and valmax\n"
74                         <<"myshape [mode] 0 valmax : below valmax\n"
75                           <<"  more : all shapes(D)  v vertices  e edges  f faces  c combined(faces)\n";
76                   return (argc < 2 ? 0 : 1 /* Error */);  }
77   Standard_CString arg1 = argv[1];
78   TopoDS_Shape Shape = DBRep::Get(arg1);
79   if (Shape.IsNull()) { di<<"Shape unknown : "<<arg1<<"\n"; return 1 /* Error */; }
80
81   ShapeAnalysis_ShapeTolerance sat;
82   if (argc == 2) {
83     sat.InitTolerance();
84     sat.AddTolerance (Shape);
85     di<<"Tolerance MAX="<<sat.GlobalTolerance(1)<<" AVG="<<sat.GlobalTolerance(0)<<" MIN="<<sat.GlobalTolerance(-1)<<"\n";
86     sat.InitTolerance();
87     sat.AddTolerance (Shape,TopAbs_FACE);
88     di<<"FACE    : MAX="<<sat.GlobalTolerance(1)<<" AVG="<<sat.GlobalTolerance(0)<<" MIN="<<sat.GlobalTolerance(-1)<<"\n";
89     sat.InitTolerance();
90     sat.AddTolerance (Shape,TopAbs_EDGE);
91     di<<"EDGE    : MAX="<<sat.GlobalTolerance(1)<<" AVG="<<sat.GlobalTolerance(0)<<" MIN="<<sat.GlobalTolerance(-1)<<"\n";
92     sat.InitTolerance();
93     sat.AddTolerance (Shape,TopAbs_VERTEX);
94     di<<"VERTEX  : MAX="<<sat.GlobalTolerance(1)<<" AVG="<<sat.GlobalTolerance(0)<<" MIN="<<sat.GlobalTolerance(-1)<<"\n";
95   } else {
96 //  Analyse plus fouillee
97     Standard_Integer nextarg = 2;
98     char opt = argv[2][0];
99     TopAbs_ShapeEnum type = TopAbs_SHAPE;
100     if (opt == 'a')  nextarg = 3;
101     else if (opt == 'c') { nextarg = 3; type = TopAbs_SHELL;  }
102     else if (opt == 'e') { nextarg = 3; type = TopAbs_EDGE;   }
103     else if (opt == 'f') { nextarg = 3; type = TopAbs_FACE;   }
104     else if (opt == 'v') { nextarg = 3; type = TopAbs_VERTEX; }
105     if (nextarg < 3) opt = 'a';
106
107     Standard_Real tol1= 0., tol2= 0.;
108     if (nextarg < argc)   tol1 = Draw::Atof (argv[nextarg]);
109     if (nextarg < argc-1) tol2 = Draw::Atof (argv[nextarg+1]);
110 //    Standard_Real tol = Draw::Atof (argv[2]);
111     Handle(TopTools_HSequenceOfShape) list = sat.InTolerance (Shape,tol1,tol2,type);
112     Standard_Integer i, nb = list->Length();
113     switch (type) {
114     case TopAbs_VERTEX : di<<"Analysing Vertices gives "; break;
115     case TopAbs_EDGE   : di<<"Analysing Edges gives "; break;
116     case TopAbs_FACE   : di<<"Analysing Faces gives "; break;
117     case TopAbs_SHELL  : di<<"Analysing Shells,Faces+content gives "; break;
118       default : di<<"Analysing all sub-shapes gives ";
119     }
120     if (tol1 == 0) di<<nb<<" Shapes below tol="<<tol2;
121     else if (tol2 == 0) di<<nb<<" Shapes over tol="<<tol1;
122     else di<<nb<<" Shapes between tol1="<<tol1<<" and tol2="<<tol2;
123     if (nb == 1) di<<" , named tol_1";
124     if (nb > 1) di<<" , named tol_1 to tol_"<<nb;
125     di<<"\n";
126     char nomsh[30];
127     for (i = 1; i <= nb; i ++) {
128       Sprintf (nomsh,"tol_%d",i);
129       DBRep::Set (nomsh,list->Value(i));
130     }
131   }
132   return 0;
133 }
134
135 static Standard_Integer projface
136   (Draw_Interpretor& di, Standard_Integer argc, const char** argv)
137 {
138   if (argc < 4) { di<<"Give FACE name and X Y [Z]\n"; return 1 /* Error */; }
139   Standard_CString arg1 = argv[1];
140   TopoDS_Shape Shape = DBRep::Get(arg1);
141   if (Shape.IsNull()) { di<<"Shape unknown : "<<arg1<<"\n"; return 1 /* Error */; }
142   if (Shape.ShapeType() != TopAbs_FACE) { di<<"Not a face\n"; return 1 /* Error */; }
143   TopoDS_Face F = TopoDS::Face (Shape);
144   Handle(Geom_Surface) thesurf = BRep_Tool::Surface (F);  // pas locface
145 //  On y va
146   Standard_Real X,Y,Z,U,V;
147   X = U = Draw::Atof (argv[2]);
148   Y = V = Draw::Atof (argv[3]);
149   if (argc > 4) {
150     Z = Draw::Atof (argv[4]);
151     gp_Pnt P3D (X,Y,Z);
152     di<<" Point 3D X = "<<X<<"  Y = "<<Y<<"  Z = "<<Z<<"\n";
153     Standard_Real uf, ul, vf, vl;
154     thesurf->Bounds(uf, ul, vf, vl);
155
156     if (Precision::IsInfinite(uf)) uf = -1000;
157     if (Precision::IsInfinite(ul)) ul = 1000;
158     if (Precision::IsInfinite(vf)) vf = -1000;
159     if (Precision::IsInfinite(vl)) vl = 1000;
160     Standard_Real du = Abs(ul-uf)/10;  Standard_Real dv = Abs(vl-vf)/10;
161
162     GeomAPI_ProjectPointOnSurf proj(P3D, thesurf, uf-du, ul+du, vf-dv, vl+dv);
163     Standard_Integer sol, nPSurf = proj.NbPoints();
164     di<<" Found "<<nPSurf<<" Points\n";
165     for (sol = 1; sol <= nPSurf; sol ++) {
166       di<<"n0 "<<sol<<" Distance "<<proj.Distance(sol);
167       proj.Parameters(sol, U,V);
168       di<<"  U = "<<U<<"  V = "<<V<<"\n";
169 //  reprojection
170       P3D = thesurf->Value (U,V);
171       di<<"  => reproj  X = "<<P3D.X()<<"  Y = "<<P3D.Y()<<"  Z = "<<P3D.Z()<<"\n";
172     }
173 //    Que donne ShapeTool ?
174     P3D.SetCoord (X,Y,Z);
175     Handle(ShapeAnalysis_Surface) su = new ShapeAnalysis_Surface(thesurf);
176     gp_Pnt2d suval = su->ValueOfUV (P3D,BRep_Tool::Tolerance(F));
177     suval.Coord(U,V);
178     di<<"**  ShapeAnalysis_Surface gives  U = "<<U<<"  V = "<<V<<"\n";
179     P3D = thesurf->Value(U,V);
180       di<<"  => reproj  X = "<<P3D.X()<<"  Y = "<<P3D.Y()<<"  Z = "<<P3D.Z()<<"\n";
181
182   } else {
183     di<<" Point UV  U = "<<U<<"  V = "<<V<<"\n";
184     gp_Pnt P3D = thesurf->Value(U,V);
185       di<<"  =>   proj  X = "<<P3D.X()<<"  Y = "<<P3D.Y()<<"  Z = "<<P3D.Z()<<"\n";
186   }
187   return 0;
188 }
189
190 static Standard_Integer projcurve
191   (Draw_Interpretor& di, Standard_Integer argc, const char** argv)
192 {
193 //  admet une EDGE ou une CURVE
194   if (argc < 5) { di<<"Give : EDGE X Y Z  or  CURVE3D X Y Z  or  CURVE3D first last X Y Z\n";  return 1 /* Error */; }
195   const char * arg1 = argv[1];
196   Standard_Integer i0 = 0;
197   TopoDS_Shape Shape = DBRep::Get(arg1);
198
199   Handle(Geom_Curve) C;  Standard_Real cf,cl;
200   if (!Shape.IsNull()) {
201     if (Shape.ShapeType() == TopAbs_EDGE) {
202       TopoDS_Edge E = TopoDS::Edge(Shape);
203       C = BRep_Tool::Curve (E,cf,cl);
204       di<<"Edge "<<arg1<<" Params from "<<cf<<" to "<<cl<<"\n";
205     } else {
206       di<<"SHAPE "<<arg1<<" Not an EDGE\n"; return 1 /* Error */;
207     }
208   } else {
209     const char* a1 = arg1;
210     C = DrawTrSurf::GetCurve (a1);
211     if (C.IsNull())
212       {  di<<arg1<<" neither EDGE nor CURVE 3D\n"; return 1 /* Error */;  }
213     cf = C->FirstParameter();  cl = C->LastParameter();
214     if (argc >= 7) { cf = Draw::Atof (argv[2]);  cl = Draw::Atof (argv[3]); i0 = 2; }
215     di<<"Curve 3D "<<arg1<<" Params from "<<cf<<" to "<<cl<<"\n";
216   }
217
218   Standard_Real X,Y,Z;
219   X = Draw::Atof (argv[2+i0]);
220   Y = Draw::Atof (argv[3+i0]);
221   Z = Draw::Atof (argv[4+i0]);
222   di<<"Precision (BRepBuilderAPI) : "<<BRepBuilderAPI::Precision()
223     <<"  Projection : "<<X<<"  "<<Y<<"  "<<Z<<"\n";
224
225   gp_Pnt P3D (X,Y,Z);
226   gp_Pnt res; Standard_Real param,dist;
227
228   dist = ShapeAnalysis_Curve().Project (C,P3D,BRepBuilderAPI::Precision(),res,param, cf,cl);
229   res.Coord(X,Y,Z);
230   di<<"Result : "<<X<<"  "<<Y<<"  "<<Z<<"\nParam = "<<param<<"  Gap = "<<dist<<"\n";
231   return 0;
232 }
233 static Standard_Integer projpcurve
234 (Draw_Interpretor& di, Standard_Integer argc, const char** argv)
235 {
236   //  admet une EDGE ou une CURVE
237   if (argc < 7)
238   {
239     di << "Give : projpcurve edge face tol X Y Z [start_param]\n";
240     return 1;
241   }
242
243   TopoDS_Edge aEdge = TopoDS::Edge(DBRep::Get(argv[1]));
244   if (aEdge.IsNull())
245   {
246     di << "SHAPE " << argv[1] << " is not an EDGE\n"; return 1 /* Error */;
247   }
248   TopoDS_Face aFace = TopoDS::Face(DBRep::Get(argv[2]));
249   if (aFace.IsNull())
250   {
251     di << "SHAPE " << argv[2] << " is not a FACE\n"; return 1 /* Error */;
252   }
253
254   Standard_Real aTol = Draw::Atof(argv[3]);
255
256
257   Standard_Real X = Draw::Atof(argv[4]);
258   Standard_Real Y = Draw::Atof(argv[5]);
259   Standard_Real Z = Draw::Atof(argv[6]);
260
261   gp_Pnt aP3D(X, Y, Z);
262
263   Standard_Boolean IsStartPoint = Standard_False;
264   Standard_Real startpar = 0.;
265   if (argc > 7)
266   {
267     startpar = Draw::Atof(argv[7]);
268     IsStartPoint = Standard_True;
269   }
270
271   Adaptor3d_CurveOnSurface aCOnS =
272     Adaptor3d_CurveOnSurface(new BRepAdaptor_HCurve2d(BRepAdaptor_Curve2d(aEdge, aFace)),
273     new BRepAdaptor_HSurface(BRepAdaptor_Surface(aFace, Standard_False)));
274
275   gp_Pnt aPnt;
276   Standard_Real aParam;
277   ShapeAnalysis_Curve aTool;
278   Standard_Real aDist = RealLast();
279   if (IsStartPoint)
280   {
281     aDist = aTool.NextProject(startpar, aCOnS, aP3D, aTol, aPnt, aParam);
282   }
283   else
284   {
285     aDist = aTool.Project(aCOnS, aP3D, aTol, aPnt, aParam, Standard_False);
286   }
287
288   di << "Point:" << "\n" << aPnt.X() << " " << aPnt.Y() << " " << aPnt.Z() << "\n";
289   di << "Param: " << aParam << "\n";
290   di << "Dist: " << aDist << "\n";
291   return 0;
292 }
293
294 static Standard_Integer anaface
295   (Draw_Interpretor& di, Standard_Integer argc, const char** argv)
296 {
297   if (argc < 2) { di<<"donner un nom de face\n"; return 1 /* Error */; }
298   Standard_CString arg1 = argv[1];
299   TopoDS_Shape Shape = DBRep::Get(arg1);
300   if (Shape.IsNull()) { di<<arg1<<" inconnu\n"; return 1 /* Error */; }
301 //  if (Shape.ShapeType() != TopAbs_FACE) { di<<"Pas une FACE\n"; return 1 /* Error */; }
302
303 //  On regarde les wires, sont-ils bien fermes
304   Standard_Integer nbw = 0, nbe = 0;
305   Handle(Geom_Surface) surface;
306   TopoDS_Face Face;
307   if (Shape.ShapeType() == TopAbs_FACE) {
308     Face = TopoDS::Face(Shape);
309     surface = BRep_Tool::Surface (Face);  // pas locface
310 //    TopLoc_Location locface;
311     di<<"Face, surface type = "<<surface->DynamicType()->Name()<<" Tol="<<BRep_Tool::Tolerance(Face);
312     if (Face.Orientation() == TopAbs_REVERSED) {
313       di<<" (REV)";
314 //      Face.Orientation(TopAbs_FORWARD);
315     }
316     di<<"\n";
317   }
318   else { di<<"Analyse Wires, Ignore Faces\n"; }
319   Standard_Boolean iasurf = !surface.IsNull();
320 //:sw  if (!Face.IsNull()) STW.SetFace (Face);
321 //:sw  else STW.SetPrecision (BRepBuilderAPI::Precision());
322
323   for (TopExp_Explorer exp(Shape,TopAbs_WIRE); exp.More(); exp.Next()) {
324     TopoDS_Wire Wire = TopoDS::Wire   (exp.Current());  nbw ++;  nbe = 0;
325     di<<"WIRE "<<nbw;
326     if (Wire.Orientation() == TopAbs_FORWARD) di<<" (FWD)\n";
327     else di<<" (REV)\n";
328     gp_Pnt   fin,debut;
329     gp_Pnt2d finuv,debuv;  gp_XY baseuv;
330     TopoDS_Vertex fv,lv;
331     Standard_Real maxp3d = 0., maxuv = 0., maxvtx = 0.;
332     Standard_Real df3d= 0.,dl3d= 0.,dvtx= 0.,duv= 0.;
333     Standard_Boolean iaw2d = iasurf;
334     Standard_Real u1= 0.,u2= 0.,v1= 0.,v2= 0.,umin= 0.,umax= 0.,vmin= 0.,vmax= 0., totcross= 0.;
335
336 //:sw    STW.ClearWire();  STW.Load (Wire);
337 //    if (STW.Reorder()) di<<"Wire reordered to explore\n";
338 //    for (TopExp_Explorer exe(Wire.Oriented(TopAbs_FORWARD),TopAbs_EDGE); exe.More(); exe.Next()) {
339 //      TopoDS_Edge Edge = TopoDS::Edge (exe.Current());  nbe ++;
340 //:sw    for (nbe = 1; nbe <= STW.NbEdges(); nbe ++) {
341 //:sw      TopoDS_Edge Edge = STW.Edge(nbe);
342     TopoDS_Iterator it (Wire); //:sw: ShapeTool_Wire -> TopoDS_Iterator (it is the same)
343     for (; it.More(); it.Next()) {
344       TopoDS_Edge Edge = TopoDS::Edge (it.Value());
345
346       di<<"Wire "<<nbw<<", Edge "<<nbe;
347       if (Edge.Orientation() == TopAbs_FORWARD) di<<" (FWD";
348       else di<<" (REV";
349       di<<" , Tol= "<<BRep_Tool::Tolerance (Edge)<<" )\n";
350       Standard_Real f3d,l3d,f2d,l2d;
351       Handle(Geom_Curve) curve3d = BRep_Tool::Curve (Edge,f3d,l3d);
352       Handle(Geom2d_Curve) curve2d;
353       if (iasurf) curve2d = BRep_Tool::CurveOnSurface(Edge,Face,f2d,l2d);
354       Standard_Boolean ia2d = !curve2d.IsNull(); iaw2d |= ia2d;
355       if (!ia2d) di<<"--  No PCurve\n";
356       if (curve3d.IsNull()) di<<"-- no Curve 3d\n";
357
358 //      On va tacher de calculer les positions et les comparer
359       gp_Pnt2d fuv,luv;
360       if (Edge.Orientation() == TopAbs_FORWARD)
361       {
362         TopExp::Vertices (Edge, fv, lv);
363         if (ia2d) BRep_Tool::UVPoints (Edge, Face, fuv, luv);
364       }
365       else
366       {
367         TopExp::Vertices (Edge, lv, fv);
368         if (ia2d) BRep_Tool::UVPoints (Edge, Face, luv, fuv);
369       }
370       gp_Pnt fp = BRep_Tool::Pnt (fv);
371       gp_Pnt lp = BRep_Tool::Pnt (lv);
372       gp_Pnt fxyz, lxyz;
373       if (ia2d)
374       {
375         surface->D0 (fuv.X(),fuv.Y(),fxyz);
376         surface->D0 (luv.X(),luv.Y(),lxyz);
377         df3d = fp.Distance    (fxyz); maxp3d = Max (maxp3d,df3d);
378         dl3d = lp.Distance    (lxyz); maxp3d = Max (maxp3d,dl3d);
379         if (nbe > 1)
380         {
381           duv = finuv.Distance (fuv);
382           maxuv = Max (maxuv, duv);
383         }
384 // et les min-max
385         u1 = Min (fuv.X(),luv.X());  u2 = Max (fuv.X(),luv.X());
386         v1 = Min (fuv.Y(),luv.Y());  v2 = Max (fuv.Y(),luv.Y());
387         if (nbe == 1) { umin = u1; umax = u2; vmin = v1; vmax = v2; }
388         else { umin = Min(umin,u1); umax = Max(umax,u2); vmin = Min(vmin,v1); vmax = Max(vmax,v2); }
389 // et la classification directe
390         if (nbe == 1) { baseuv = fuv.XY(); totcross = 0; }
391         else {
392           gp_XY buv1 = fuv.XY() - baseuv;
393           gp_XY buv2 = luv.XY() - baseuv;
394           totcross += buv2.Crossed(buv1);
395         }
396       }
397
398 //  Resultats ...
399       if (nbe == 1)  {  debut = fxyz; debuv = fuv;  }
400       else {
401         duv  = finuv.Distance (fuv);  maxuv  = Max (maxuv, duv);
402         dvtx = fin.Distance   (fxyz); maxvtx = Max (maxvtx,dvtx);
403         di<<"   Fin("<<nbe-1<<")-Debut("<<nbe<<"): DISTANCE="<<dvtx;
404         if (ia2d) di<<" DeltaUV="<<duv;
405         di<<" Tol(Fin)="<<BRep_Tool::Tolerance(lv)<<"\n";
406       }
407       fin = lxyz;  finuv = luv;
408
409       di<<"-- Deb : VTX="<<fp.X()<<" , "<<fp.Y()<<" , "<<fp.Z()
410         <<"\n         XYZ="<<fxyz.X()<<" , "<<fxyz.Y()<<" , "<<fxyz.Z()
411         <<"\n         UV="<<fuv.X()<<" , "<<fuv.Y()<<"  -- D.UV/3D="<<df3d<<"\n";
412       di<<"-- Fin : VTX="<<lp.X()<<" , "<<lp.Y()<<" , "<<lp.Z()
413         <<"\n         XYZ="<<lxyz.X()<<" , "<<lxyz.Y()<<" , "<<lxyz.Z()
414         <<"\n         UV="<<luv.X()<<" , "<<luv.Y()<<"  -- D.UV/3D="<<dl3d<<"\n";
415     }
416     dvtx = fin.Distance   (debut); maxvtx = Max (maxvtx,dvtx);
417     if (iaw2d)  {  duv  = finuv.Distance (debuv); maxuv  = Max (maxuv, duv);  }
418     di<<"   Fin("<<nbe<<")-Debut(1): DISTANCE="<<dvtx;
419     if (iaw2d) di <<" DeltaUV="<<duv;
420     di<<" Tol(Fin)="<<BRep_Tool::Tolerance(lv)<<"\n";
421
422     di<<"   Wire "<<nbw<<" Max :  Dist.Vertex="<<maxvtx;
423     if (iaw2d) di<<"  Ecart UV/3D="<<maxp3d<<"  DeltaUV="<<maxuv;
424     di<<"\n";
425 //  Min Max
426     if (iaw2d) {
427       di<<"TotCross="<<totcross;
428       di<<"  UMin-Max:"<<umin<<" , "<<umax<<"  VMin-Max:"<<vmin<<" , "<<vmax<<"\n";
429       Standard_Real difu = umax - umin, difv = vmax - vmin;
430       GProp_GProps G;
431       BRepGProp::SurfaceProperties(Face,G);
432       if (G.Mass() > 0) di<<"GProps:Mass Out\n";
433       else di<<"GProps:Mass In\n";
434 ///  return (G.Mass() > 0);
435       BRepTopAdaptor_FClass2d fcl (Face,BRep_Tool::Tolerance(Face));
436       if (fcl.PerformInfinitePoint () == TopAbs_OUT) di<<"Classifier Infinite : Out\n";
437       else di<<"Classifier Infinite : In\n";
438       gp_Pnt2d pcl;
439       pcl.SetCoord(umin-difu,vmin-difv);
440       if (fcl.Perform (pcl) == TopAbs_OUT) di<<"Classifier UMin-VMin : Out\n";
441       pcl.SetCoord(umin-difu,vmax+difv);
442       if (fcl.Perform (pcl) == TopAbs_OUT) di<<"Classifier UMin-VMax : Out\n";
443       pcl.SetCoord(umax+difu,vmin-difv);
444       if (fcl.Perform (pcl) == TopAbs_OUT) di<<"Classifier UMax-VMin : Out\n";
445       pcl.SetCoord(umax+difu,vmax+difv);
446       if (fcl.Perform (pcl) == TopAbs_OUT) di<<"Classifier UMax-VMax : Out\n";
447     }
448   }
449   if (ShapeAnalysis::IsOuterBound (Face)) di<<"ShapeAnalysis: Outer Bound\n";
450   else di<<"ShapeAnalysis: Not Outer Bound\n";
451   di<<" Total "<<nbw<<" Wire(s)\n";
452   return 0;
453 }
454
455 static Standard_Integer XSHAPE_statshape(Draw_Interpretor& di, Standard_Integer argc, const char** argv)
456 {
457   if (argc < 2) { di<<"ShapeName; + options : prefix for particular cases : what to get\n"; return 1 /* Error */; }
458   Standard_CString arg1 = argv[1];
459   Standard_CString arg2 = NULL;
460   Standard_CString arg3 = NULL;
461   if (argc > 2) arg2 = argv[2];
462   if (argc > 3) arg3 = argv[3];
463   TopoDS_Shape Shape = DBRep::Get(arg1);
464   if (Shape.IsNull()) { di<<"Shape unknown : "<<arg1<<"\n"; return 1 /* Error */; }
465   char nompart[100];
466   Standard_Integer nb;
467
468   ShapeAnalysis_ShapeContents analyzer;
469   if(argc > 3) {
470     analyzer.ModifyBigSplineMode()=(strstr("bigspl",arg3)!=NULL);
471     analyzer.ModifyIndirectMode()=(strstr("indsur",arg3)!=NULL);
472     analyzer.ModifyOffestSurfaceMode()=(strstr("ofsur",arg3)!=NULL);
473     analyzer.ModifyTrimmed3dMode()=(strstr("trc3d",arg3)!=NULL);
474     analyzer.ModifyOffsetCurveMode()=(strstr("ofcur",arg3)!=NULL);
475     analyzer.ModifyTrimmed2dMode()=(strstr("trc2d",arg3)!=NULL);
476   }
477   analyzer.Perform(Shape);
478   
479   di<<"Count    Item\n-----    ----\n";
480   nb = analyzer.NbEdges();
481   if(nb>0) di<<nb<<"     EDGE (Oriented)\n";
482   nb = analyzer.NbSharedEdges();
483   if(nb>0) di<<nb<<"     EDGE (Shared)\n";
484   nb = analyzer.NbFreeEdges();
485   if(nb>0) di<<nb<<"     EDGE (Free)\n";
486   nb = analyzer.NbFaces();
487   if(nb>0) di<<nb<<"     FACE\n";
488   nb = analyzer.NbFreeFaces();
489   if(nb>0) di<<nb<<"     FACE (Free)\n";
490   nb = analyzer.NbFreeWires();
491   if(nb>0) di<<nb<<"     WIRE (Free)\n";
492   nb = analyzer.NbShells();
493   if(nb>0) di<<nb<<"     SHELL\n";
494   nb = analyzer.NbSolids();
495   if(nb>0) di<<nb<<"     SOLID\n";
496   nb = analyzer.NbVertices();
497   if(nb>0) di<<nb<<"     VERTEX (Oriented)\n";
498   nb = analyzer.NbSharedVertices();
499   if(nb>0) di<<nb<<"     VERTEX (Shared)\n";
500   nb = analyzer.NbWires();
501   if(nb>0) di<<nb<<"     WIRE\n";
502   nb = analyzer.NbFaceWithSevWires();
503   if(nb>0) di<<nb<<"    Face with more than one wire\n";
504   nb = analyzer.NbNoPCurve();
505   if(nb>0) di<<nb<<"    No pcurve\n";
506   nb = analyzer.NbSolidsWithVoids();
507   if(nb>0) di<<nb<<"    SOLID with voids\n";
508   nb = analyzer.NbWireWitnSeam();
509   if(nb>0) di<<nb<<"    Wire(s) with one seam edge\n";
510   nb = analyzer.NbWireWithSevSeams();
511   if(nb>0) di<<nb<<"    Wire(s) with several seam edges\n";
512   nb = analyzer.NbBigSplines();
513   if(nb>0) di<<nb<<"    bigspl : BSpline > 8192 poles\n";
514   nb = analyzer.NbBezierSurf();
515   if(nb>0) di<<nb<<"    bezsur : BezierSurface\n";
516   nb = analyzer.NbBSplibeSurf();
517   if(nb>0) di<<nb<<"    bspsur : BSplineSurface\n";
518   nb = analyzer.NbC0Curves();
519   if(nb>0) di<<nb<<"    c0curv : Curve Only C0\n";
520   nb = analyzer.NbC0Surfaces();
521   if(nb>0) di<<nb<<"    c0surf : Surface Only C0\n";
522   nb = analyzer.NbIndirectSurf();
523   if(nb>0) di<<nb<<"    indsur : Indirect Surface\n";
524   nb = analyzer.NbOffsetCurves();
525   if(nb>0) di<<nb<<"    ofcur  : Offset Curve(s)\n";
526   nb = analyzer.NbOffsetSurf();
527   if(nb>0) di<<nb<<"    ofsur  : Offset Surface\n";
528   nb = analyzer.NbTrimmedCurve2d();
529   if(nb>0) di<<nb<<"    trc2d  : Trimmed Curve2d\n";
530   nb = analyzer.NbTrimmedCurve3d();
531   if(nb>0) di<<nb<<"    trc3d  : Trimmed Curve3d\n";
532   nb = analyzer.NbTrimSurf();
533   if(nb>0) di<<nb<<"    trimsu : RectangularTrimmedSurface\n";
534   
535   if(arg3 ==NULL) return 0;
536   
537   Handle(TopTools_HSequenceOfShape) sec;
538   if(analyzer.ModifyBigSplineMode()) {
539     sec = analyzer.BigSplineSec();
540     for(Standard_Integer i = 1; i <= sec->Length(); i++) {
541       Sprintf(nompart,"%s_bigspl_%d",arg2,i);
542       DBRep::Set (nompart,sec->Value(i));
543     }
544   }
545   if(analyzer.ModifyIndirectMode()) {
546     sec = analyzer.IndirectSec();
547     for(Standard_Integer i = 1; i <= sec->Length(); i++) {
548       Sprintf(nompart,"%s_indsur_%d",arg2,i);
549       DBRep::Set (nompart,sec->Value(i));
550     }
551   }
552   if(analyzer.ModifyOffestSurfaceMode()) {
553     sec = analyzer.OffsetSurfaceSec();
554     for(Standard_Integer i = 1; i <= sec->Length(); i++) {
555       Sprintf(nompart,"%s_ofsur_%d",arg2,i);
556       DBRep::Set (nompart,sec->Value(i));
557     }
558   }
559   if(analyzer.ModifyTrimmed3dMode()) {
560     sec = analyzer.Trimmed3dSec();
561     for(Standard_Integer i = 1; i <= sec->Length(); i++) {
562       Sprintf(nompart,"%s_trc3d_%d",arg2,i);
563       DBRep::Set (nompart,sec->Value(i));
564     }
565   }
566   if(analyzer.ModifyOffsetCurveMode()) {
567     sec = analyzer.OffsetCurveSec();
568     for(Standard_Integer i = 1; i <= sec->Length(); i++) {
569       Sprintf(nompart,"%s_ofcur_%d",arg2,i);
570       DBRep::Set (nompart,sec->Value(i));
571     }
572   }
573   if(analyzer.ModifyTrimmed2dMode()) {
574     sec = analyzer.Trimmed2dSec();
575     for(Standard_Integer i = 1; i <= sec->Length(); i++) {
576       Sprintf(nompart,"%s_trc2d_%d",arg2,i);
577       DBRep::Set (nompart,sec->Value(i));
578     }
579   }
580   return 0;
581 }
582     
583 static Standard_Integer XSHAPE_comptoledge
584   (Draw_Interpretor& di, Standard_Integer argc, const char** argv)
585 {
586   if ( argc <2 ) {
587     di << "Use:\n"
588             "> comptol shape [nbpoints=371] [prefix]\n\n" 
589             "Computes real tolerance of edges in the shape \n"
590             "as maximal deviation of 3d curve and pcurves.\n"
591             "Deviation is computed by nbpoints sample points (default is 371).\n"
592             "Gives the max, min and average value on all edges in the shape\n"
593             "If prefix is defined, edges with maximal real tolerance and\n"
594             "relation (and corresponding faces) will be saved with such names\n\n"; 
595     return 0; 
596   }
597
598   TopoDS_Shape shape = DBRep::Get(argv[1]);
599   if (shape.IsNull()) { di << "Shape name \"" << argv[1] << "\" is invalid\n"; return 1; }
600   Standard_Integer nbpnts = 371;
601   Standard_CString prefix = 0;
602   if ( argc >2 ) {
603     if ( IsDigit(argv[2][0]) ) {
604       nbpnts = Draw::Atoi(argv[2]);
605       if ( nbpnts <2 ) nbpnts = 2;
606       if ( argc >3 ) prefix = argv[3];
607     }
608     else prefix = argv[2];
609   }
610   
611   Standard_Integer num = 0;
612   Standard_Real max=0, min=0, ave=0.;
613   Standard_Real relmax=0, relmin=0, relave=0.;
614   ShapeAnalysis_Edge sae;
615   TopoDS_Edge edmax, edmaxrel;
616   for ( TopExp_Explorer exp(shape,TopAbs_EDGE); exp.More(); exp.Next() ) {
617     Standard_Real tol;
618     TopoDS_Edge edge = TopoDS::Edge(exp.Current());
619     sae.CheckSameParameter ( edge, tol, nbpnts );
620     Standard_Real t = BRep_Tool::Tolerance(edge);
621     Standard_Real rel = tol / ( t > Precision::Confusion() ? t : Precision::Confusion() );
622     ave += tol;
623     relave += rel;
624     if ( ! num ) { max = min = tol; relmax = relmin = rel; edmax = edmaxrel = edge; }
625     else {
626       if ( max < tol ) { max = tol; edmax = edge; }
627       if ( min > tol ) min = tol;
628       if ( relmax < rel ) { relmax = rel; edmaxrel = edge; }
629       if ( relmin > rel ) relmin = rel;
630     }
631     num++;
632   }
633   if ( ! num ) { di << "No edges found in the shape\n"; return 1; }
634   
635   di << "Edges tolerance computed by " << nbpnts << " points: \n"
636           "MAX=" << max << " AVG=" << ave/num << " MIN=" << min << "\n"; 
637   di << "Relation real tolerance / tolerance set in edge\n"
638           "MAX=" << relmax << " AVG=" << relave/num << " MIN=" << relmin << "\n"; 
639   if ( prefix && prefix[0] ) {
640     char name[21];
641     Sprintf ( name, "%.10s_edge_tol", prefix );
642     DBRep::Set (name,edmax);
643     di << "Edge with max tolerance saved to " << name;
644     if ( edmax.IsSame ( edmaxrel ) ) di << "\n";
645     else {
646       Sprintf ( name, "%.10s_edge_rel", prefix );
647       DBRep::Set (name,edmaxrel);
648       di << "; edge with max relation saved to " << name << "\n";
649     }
650     Standard_Integer num1=0;
651     for ( TopExp_Explorer fac(shape,TopAbs_FACE); fac.More(); fac.Next() ) {
652       TopoDS_Face face = TopoDS::Face ( fac.Current() );
653       for ( TopExp_Explorer ed(face,TopAbs_EDGE); ed.More(); ed.Next() ) {
654         TopoDS_Edge edge = TopoDS::Edge ( ed.Current() );
655         if ( edge.IsSame ( edmax ) || edge.IsSame ( edmaxrel ) ) {
656           if ( ! num1 ) di << "Concerned faces saved to shapes ";
657           Sprintf ( name, "%.10s_%d", prefix, num1+1 );
658           DBRep::Set (name,face);
659           //std::cout << ( num1 ? ", " : "" ) << name;
660           if (num1 == 0) {
661             di << "" << name;
662           } else {
663             di << ", " << name;
664           }
665           num1++;
666           break;
667         }
668       }
669     }
670     if ( num1 >0 ) di << "\n";
671   }
672   return 0;
673 }
674
675
676 //=======================================================================
677 //function : freebounds
678 //purpose  : 
679 //=======================================================================
680 static Standard_Integer freebounds (Draw_Interpretor& di,
681                                     Standard_Integer n, const char** a)
682 {
683   if ((n < 3) || (n > 5)) return 1;
684   TopoDS_Shape shape = DBRep::Get(a[1]);
685   if (shape.IsNull()) return 1;
686   Standard_Real toler = Draw::Atof (a[2]);
687   Standard_Boolean splitclosed = Standard_False, splitopen = Standard_False;
688   if ( n > 3) splitclosed = Draw::Atoi (a[3]) != 0;
689   if ( n > 4) splitopen   = Draw::Atoi (a[4]) != 0;
690
691   ShapeAnalysis_FreeBounds F;
692   if (toler <= 0)
693     F = ShapeAnalysis_FreeBounds (shape, splitclosed, splitopen);
694   else
695     F = ShapeAnalysis_FreeBounds (shape, toler,  splitclosed, splitopen);
696
697   char name[100];
698   TopoDS_Shape wires = F.GetClosedWires();
699   Sprintf (name, "%s_c", a[1]);
700   DBRep::Set (name, wires);
701   di << name << " - closed wires\n";
702   wires = F.GetOpenWires();
703   Sprintf (name, "%s_o", a[1]);
704   DBRep::Set (name, wires);
705   di << name << " - open wires\n";
706
707   return 0;
708 }
709
710
711 //=======================================================================
712 //function : PrintProps
713 //purpose  : auxilary for FreeBoundsProps
714 //=======================================================================
715 static void PrintProps(Standard_Integer i,
716                        const Handle(ShapeAnalysis_FreeBoundData)& fbd,
717                        Draw_Interpretor& di)
718 {
719   char str[100];
720
721   Standard_Real area = fbd->Area();
722   Standard_Real perimeter = fbd->Perimeter();
723   Standard_Real ratio = fbd->Ratio();
724   Standard_Real width = fbd->Width();
725   Standard_Integer notch = fbd->NbNotches();
726   Sprintf(str," %d\t%12.5f\t%12.5f\t%12.5f\t%12.5f\t%d", i, area, perimeter, ratio, width, notch);
727   di<<str<<"\n";
728 }
729
730
731 //=======================================================================
732 //function : FreeBoundsProps
733 //purpose  : 
734 //=======================================================================
735 static Standard_Integer FreeBoundsProps(Draw_Interpretor& di,
736                                         Standard_Integer n, const char** a)
737 {
738   if ( (n < 2)||(n > 5) ) {
739     di<<"Usage : freeprops shapename [tolerance [splitclosed [splitopen]]]\n";
740     return 1;
741   }
742
743   TopoDS_Shape source = DBRep::Get(a[1]);
744   if (source.IsNull()) {
745     di<<"Error : unknown shape "<<a[1]<<"\n";
746     return 1;
747   }
748
749   Standard_Real toler = 0.;
750   Standard_Boolean splitclosed = Standard_False, splitopen = Standard_False;
751   if (n > 2) toler =  Draw::Atof(a[2]);
752   if (n > 3) splitclosed = Draw::Atoi(a[3]) != 0;
753   if (n > 4) splitopen   = Draw::Atoi(a[4]) != 0;
754   ShapeAnalysis_FreeBoundsProperties analyzer;
755   if (toler > 0)
756     analyzer.Init(source, toler, splitclosed, splitopen);
757   else
758     analyzer.Init(source, splitclosed, splitopen);
759   analyzer.Perform();
760   TopoDS_Compound closed, open;
761   BRep_Builder B;
762
763   Standard_Integer nb = analyzer.NbClosedFreeBounds();
764   di<<"\n";
765   di<<" \tArea mm2\tLength mm\tRatio L/W\tWidth mm\tNb noth\n";
766   B.MakeCompound(closed);
767   if (nb) {
768     di<<"Closed bounds properties\n";
769     for (Standard_Integer i=1; i <= nb; i++) {
770       Handle(ShapeAnalysis_FreeBoundData) fbd = analyzer.ClosedFreeBound(i);
771       PrintProps(i, fbd, di);
772       B.Add(closed,fbd->FreeBound());
773     }
774   }
775
776   nb = analyzer.NbOpenFreeBounds();
777   B.MakeCompound(open);
778   if (nb) {
779     di<<"Open bounds properties\n";
780     for (Standard_Integer i=1; i <= nb; i++) {
781       Handle(ShapeAnalysis_FreeBoundData) fbd = analyzer.OpenFreeBound(i);
782       PrintProps(i, fbd, di);
783       B.Add(open,fbd->FreeBound());
784     }
785   }
786
787   char name[100];
788   Sprintf (name, "%s_c",a[1]);
789   di << name << " - closed wires,  ";
790   DBRep::Set(name, closed);
791   Sprintf (name, "%s_o",a[1]);
792   di << name << " - closed wires \n";
793   DBRep::Set(name, open);
794   return 0;
795 }
796
797
798 //=======================================================================
799 //function : closefreebounds
800 //purpose  : 
801 //=======================================================================
802 static Standard_Integer closefreebounds (Draw_Interpretor& di,
803                                          Standard_Integer n, const char** a)
804 {
805   if ((n < 4) || (n > 6)) return 1;
806   TopoDS_Shape shape = DBRep::Get(a[1]);
807   if (shape.IsNull()) return 1;
808   Standard_Real sewtoler = Draw::Atof (a[2]), closetoler = Draw::Atof (a[3]);
809   Standard_Boolean splitclosed = Standard_False, splitopen = Standard_False;
810   if ( n > 4) splitclosed = Draw::Atoi (a[3]) != 0;
811   if ( n > 5) splitopen   = Draw::Atoi (a[4]) != 0;
812
813   ShapeFix_FreeBounds F;
814   if (sewtoler <= 0)
815     F = ShapeFix_FreeBounds (shape, closetoler, splitclosed, splitopen);
816   else
817     F = ShapeFix_FreeBounds (shape, sewtoler, closetoler, splitclosed, splitopen);
818
819   char name[100];
820   TopoDS_Shape wires = F.GetClosedWires();
821   Sprintf (name, "%s_c", a[1]);
822   DBRep::Set (name, wires);
823   di << name << " - closed wires\n";
824   wires = F.GetOpenWires();
825   Sprintf (name, "%s_o", a[1]);
826   DBRep::Set (name, wires);
827   di << name << " - open wires\n";
828
829   return 0;
830 }
831
832
833 static Standard_Integer getareacontour (Draw_Interpretor& di,
834                                          Standard_Integer n, const char** a)
835 {
836   if (n < 2) return 1;
837   TopoDS_Shape shape = DBRep::Get(a[1]);
838   if (shape.IsNull()) {
839     di<<"Shape is not defined\n";
840     return 1;
841   }
842   if(shape.ShapeType() != TopAbs_WIRE) {
843     di<<"invalid type of argument\n";
844     return 1;
845   }
846   //Handle(ShapeExtend_WireData) asewd = new ShapeExtend_WireData(TopoDS::Wire(shape));
847   Standard_Real anArea = ShapeAnalysis::ContourArea(TopoDS::Wire(shape));
848   di<<"Area = "<<anArea<<"\n";
849   return 0;
850 }
851
852
853 static Standard_Integer checkselfintersection
854   (Draw_Interpretor& di, Standard_Integer argc, const char** argv)
855 {
856   if (argc < 2) 
857   { 
858       di<<"Call please \"checkselfintersection wire [face]\"\n";  
859       return 1; 
860   }
861
862   // Get wire.
863   const char* arg1 = argv[1];
864   TopoDS_Shape wire = DBRep::Get(arg1);
865   if (wire.IsNull() || wire.ShapeType() != TopAbs_WIRE)
866   { 
867       di<<"A null shape or not a wire is used.\n";  
868       return 2; 
869   }
870
871   // Get face if the user provided us with a face.
872   TopoDS_Shape face;
873   if (argc > 2)
874   {
875       const char* arg2 = argv[2];
876       face = DBRep::Get(arg2);
877       if (face.IsNull() || face.ShapeType() != TopAbs_FACE)
878       { 
879           di<<"A null shape or not a face is used.\n";  
880           return 3; 
881       }
882   }
883
884   // If the face is null, make a plane inside the wire.
885   if (face.IsNull())
886   {
887       BRepBuilderAPI_MakeFace mkFace(TopoDS::Wire(wire), true);
888       if (mkFace.IsDone())
889           face = mkFace.Face();
890       else
891       { 
892           di<<"Can't make a face for the wire. Provide please a face for analysis.\n";  
893           return 4; 
894       }
895   }
896
897   ShapeAnalysis_Wire analyser(TopoDS::Wire(wire), TopoDS::Face(face), Precision::Confusion());
898   Standard_Boolean result = analyser.CheckSelfIntersection();
899
900   if (result == Standard_True)
901       di<<"A self-intersecting wire.\n";
902   else
903       di<<"Not self-intersecting wire.\n";
904   return 0;
905 }
906
907 static Standard_Integer checkedge(Draw_Interpretor& di, Standard_Integer argc, const char** argv)
908 {
909   if (argc < 2) 
910   { 
911     di<<"Call please \"checkedge edge [face]\"\n";  
912     return 1;
913   }
914
915   // Get edge.
916   const char* arg1 = argv[1];
917   TopoDS_Shape edge = DBRep::Get(arg1);
918   if (edge.IsNull() || edge.ShapeType() != TopAbs_EDGE)
919   { 
920     di<<"A null shape or not an edge is used.\n";  
921     return 2;
922   }
923
924   // Get face.
925   TopoDS_Shape face;
926   if (argc == 3)
927   {
928     const char* arg2 = argv[2];
929     face = DBRep::Get(arg2);
930     if (face.IsNull() || face.ShapeType() != TopAbs_FACE)
931     { 
932       di<<"A null shape or not a face is used.\n";  
933       return 3;
934     }
935   }
936
937   // Analysis of the edge.
938   ShapeAnalysis_Edge analyser;
939   Standard_Boolean isOk(Standard_True);
940
941   // Curve 3D.
942   if (analyser.HasCurve3d(TopoDS::Edge(edge)))
943   {
944     // Check vertices.
945     if (analyser.CheckVerticesWithCurve3d(TopoDS::Edge(edge)))
946     {
947       isOk = Standard_False;
948       di<<"Vertices of the edge don't coincide with start/end points of 3d-curve (using tolerance of the vertices).\n";
949     }
950   }
951   else
952   {
953     isOk = Standard_False;
954     di<<"Edge doesn't have a 3d-curve\n";
955   }
956
957   if (!face.IsNull())
958   {
959       // Curve 2D.
960       if (analyser.HasPCurve(TopoDS::Edge(edge), TopoDS::Face(face)))
961       {
962         // Check vertices.
963         if (analyser.CheckVerticesWithPCurve(TopoDS::Edge(edge), TopoDS::Face(face)))
964         {
965           isOk = Standard_False;
966           di<<"Vertices of the edge don't coincide with start/end points of 2d-curve (using tolerance of the vertices).\n";
967         }
968       }
969       else
970       {
971         isOk = Standard_False;
972         di<<"Edge doesn't have a 2d-curve on this face\n";
973       }
974   }
975
976   if (isOk)
977     di<<"Edge seems OK.\n";
978
979   return 0;
980 }
981
982 //=======================================================================
983 //function : InitCommands
984 //purpose  : 
985 //=======================================================================
986
987  void SWDRAW_ShapeAnalysis::InitCommands(Draw_Interpretor& theCommands) 
988 {
989   static Standard_Integer initactor = 0;
990   if (initactor)
991   {
992     return;
993   }
994   initactor = 1;
995
996   Standard_CString g = SWDRAW::GroupName();
997
998   theCommands.Add ("tolerance","shape [tolmin tolmax:real]", __FILE__,tolerance,g);
999   theCommands.Add ("projface","nom_face X Y [Z]", __FILE__,projface,g);
1000   theCommands.Add ("projcurve","nom_edge | curve3d | curve3d first last + X Y Z",
1001                    __FILE__,projcurve,g);
1002   theCommands.Add("projpcurve", "edge face tol x y z [start_param]",
1003     __FILE__, projpcurve, g);
1004   theCommands.Add("anaface", "nomface", __FILE__, anaface, g);
1005   theCommands.Add ("statshape","shape [particul] : stats/particularites",
1006                    __FILE__,XSHAPE_statshape,g);
1007   theCommands.Add ("comptol","shape [nbpoints]",__FILE__,XSHAPE_comptoledge,g);
1008   theCommands.Add("freebounds",
1009                   "shp toler [splitclosed [splitopen]] - free bounds; toler <= 0 for shells (no sewing call)",
1010                   __FILE__, freebounds, g);
1011
1012   const char* groupold="DE: old";
1013   theCommands.Add("fbprops",
1014                   "shp [toler [splitclosed [splitopen]]] - free bounds properties; toler <= 0 or not specified - for shells (no sewing call)",
1015                   __FILE__, FreeBoundsProps, groupold);
1016   theCommands.Add("fbclose",
1017                   "shp sewtoler closetoler [splitclosed [splitopen]] - closes free bounds; use sewtoler <= 0 for shells (no sewing call)",
1018                   __FILE__, closefreebounds, groupold);
1019     
1020   theCommands.Add("getareacontour","wire ",__FILE__, getareacontour, groupold);
1021   theCommands.Add ("checkselfintersection","wire [face]", __FILE__,checkselfintersection,g);
1022   theCommands.Add ("checkedge","edge [face]", __FILE__,checkedge,g);
1023 }