694ea0330af34bd324c0cb6c6dd713eb4a042b32
[occt.git] / src / TestTopOpe / TestTopOpe_CORCommands.cxx
1 // Created on: 1997-07-24
2 // Created by: Xuan PHAM PHU
3 // Copyright (c) 1997-1999 Matra Datavision
4 // Copyright (c) 1999-2012 OPEN CASCADE SAS
5 //
6 // The content of this file is subject to the Open CASCADE Technology Public
7 // License Version 6.5 (the "License"). You may not use the content of this file
8 // except in compliance with the License. Please obtain a copy of the License
9 // at http://www.opencascade.org and read it completely before using this file.
10 //
11 // The Initial Developer of the Original Code is Open CASCADE S.A.S., having its
12 // main offices at: 1, place des Freres Montgolfier, 78280 Guyancourt, France.
13 //
14 // The Original Code and all software distributed under the License is
15 // distributed on an "AS IS" basis, without warranty of any kind, and the
16 // Initial Developer hereby disclaims all such warranties, including without
17 // limitation, any warranties of merchantability, fitness for a particular
18 // purpose or non-infringement. Please see the License for the specific terms
19 // and conditions governing the rights and limitations under the License.
20
21
22 #include <TestTopOpe.hxx>
23 #include <TopOpeBRepTool_2d.hxx>
24 #include <TopOpeBRepTool_C2DF.hxx>
25 #include <TopOpeBRepTool_CORRISO.hxx>
26 #include <TopOpeBRepTool_TOOL.hxx>
27 #include <TopOpeBRepTool_REGUS.hxx>
28 #include <TopOpeBRepTool_CLASSI.hxx>
29 #include <TopOpeBRepTool_TOOL.hxx>
30 #include <TopOpeBRepBuild_define.hxx>
31
32 #include <gp_Pnt2d.hxx>
33 #include <gp_Trsf2d.hxx>
34 #include <gp_Pnt2d.hxx>
35 #include <gp_Dir2d.hxx>
36 #include <gp_Vec2d.hxx>
37 #include <BRepAdaptor_Curve2d.hxx>
38 #include <BndLib_Add2dCurve.hxx>
39 #include <BRepLProp_SLProps.hxx>
40 #include <Geom_Curve.hxx>
41 #include <Geom2dAdaptor_Curve.hxx>
42 #include <Geom2d_Line.hxx>
43 #include <Geom2d_Curve.hxx>
44 #include <Geom2d_TrimmedCurve.hxx>
45 #include <Geom_Line.hxx>
46 #include <Geom_Surface.hxx>
47 #include <GeomAPI_IntCS.hxx>
48 #include <TopoDS.hxx>
49 #include <TopoDS_Solid.hxx>
50 #include <TopoDS_Wire.hxx>
51 #include <TopoDS_Compound.hxx>
52 #include <TopExp.hxx>
53 #include <TopExp_Explorer.hxx>
54 #include <BRep_Tool.hxx>
55 #include <BRep_Builder.hxx>
56 #include <Precision.hxx>
57 #include <Bnd_Box2d.hxx>
58 #include <Bnd_Array1OfBox2d.hxx>
59 #include <BRepClass3d_SolidClassifier.hxx>
60
61 #include <TopOpeBRepTool.hxx>
62 #include <TopOpeBRepDS.hxx>
63 #include <TopOpeBRepBuild_FaceBuilder.hxx>
64 #include <TopOpeBRepBuild_ShellToSolid.hxx>
65 #include <TopOpeBRepTool_EXPORT.hxx>
66 #include <TopOpeBRepTool_SolidClassifier.hxx>
67 #include <TopOpeBRepTool_ShapeClassifier.hxx>
68 #include <TopOpeBRepDS_EXPORT.hxx>
69
70 #include <Draw.hxx>
71 #include <Draw_Interpretor.hxx>
72 #include <DrawTrSurf.hxx>
73 #include <Draw_Color.hxx>
74 #include <DBRep.hxx>
75
76 #include <Extrema_ExtFlag.hxx>
77 #include <Extrema_ExtAlgo.hxx>
78
79 #ifdef DRAW
80 #include <TopOpeBRepTool_DRAW.hxx>
81 #endif
82
83 Standard_IMPORT Draw_Color DrawTrSurf_CurveColor(const Draw_Color col);
84 Standard_IMPORT void DBRep_WriteColorOrientation ();
85 Standard_IMPORT Draw_Color DBRep_ColorOrientation (const TopAbs_Orientation Or);
86
87 Standard_IMPORT Draw_Color DrawTrSurf_CurveColor(const Draw_Color col);
88 Standard_IMPORT void DBRep_WriteColorOrientation ();
89 Standard_IMPORT Draw_Color DBRep_ColorOrientation (const TopAbs_Orientation Or);
90 Standard_EXPORT void FUN_tool_mkBnd2d(const TopoDS_Shape& W, const TopoDS_Shape& F,Bnd_Box2d& B2d);
91 Standard_EXPORT void FUN_tool_UpdateBnd2d(Bnd_Box2d& B2d, const Bnd_Box2d& newB2d);
92 Standard_IMPORT Standard_Integer FUN_tool_classiBnd2d(const Bnd_Array1OfBox2d& B,const Standard_Boolean chklarge = Standard_True);
93 Standard_IMPORT Standard_Boolean FUN_tool_chkp2dFORinE(const gp_Pnt2d& p2d,const TopoDS_Edge& E, 
94                                           const TopoDS_Face& F, Standard_Real& tol2d);
95 Standard_IMPORT TopoDS_Vertex FUN_tool_getv(const Standard_Integer Index,const TopoDS_Edge& E);
96
97
98 #define SAME     (-1)
99 #define DIFF     (-2)
100 #define UNKNOWN  ( 0)
101 #define oneINtwo ( 1)
102 #define twoINone ( 2)
103
104 #ifdef DEB
105 static void FUN_coutsta(const Standard_Integer& sta, const Standard_Integer& i1, const Standard_Integer& i2, Draw_Interpretor& di)
106 {
107   switch (sta) {
108   case SAME:
109     di<<i1<<" gives SAME bnd with "<<i2<<"\n"; break;
110   case DIFF:
111     di<<i1<<" gives  OUT bnd with "<<i2<<"\n"; break;
112   case oneINtwo:
113     di<<i1<<" is IN "<<i2<<"\n"; break;
114   case twoINone:
115     di<<i2<<" is IN "<<i1<<"\n"; break;
116   }
117 }
118 #endif
119
120 static void FUN_test_draw(TCollection_AsciiString aa,
121                           const TopoDS_Edge& E, const TopoDS_Face& F,
122                           const Standard_Integer ie,
123                           Draw_Interpretor& di)
124 {  
125   if (E.IsNull())  {di<<"************* null edge\n"; return;} 
126   Standard_Real f,l; const Handle(Geom2d_Curve)& PC = BRep_Tool::CurveOnSurface(E,F,f,l);  
127   if (PC.IsNull()) {di<<"************* no curv on surf\n"; return;}
128   TCollection_AsciiString bb(aa); bb += TCollection_AsciiString(ie);  
129   char* aaa = (char *)bb.ToCString();
130   
131   Standard_Boolean coldef = Standard_False;
132   TopExp_Explorer ex(F,TopAbs_EDGE);
133   Draw_Color col;
134 #ifdef DEB
135   Draw_Color savecol =
136 #endif
137                        DrawTrSurf_CurveColor(Draw_Color(Draw_rouge));
138   for (; ex.More(); ex.Next()) 
139     if (E.IsEqual(ex.Current())) 
140       {col = DBRep_ColorOrientation(ex.Current().Orientation()); 
141        coldef = Standard_True;
142        break;}
143   if (!coldef) col = DBRep_ColorOrientation(E.Orientation());
144   
145   DrawTrSurf_CurveColor(col);  
146   DrawTrSurf::Set(aaa,new Geom2d_TrimmedCurve(PC,f,l));
147 }
148
149 void FUN_draw(const TCollection_AsciiString aa,const TopoDS_Shape& s)
150 {char* aaa = (char *)aa.ToCString(); DBRep::Set(aaa,s);}
151
152 void FUN_cout(const gp_Pnt2d& p2d, Draw_Interpretor& di)
153 {di <<" = ("<<p2d.X()<<" "<<p2d.Y()<<") ";}
154
155 #ifdef DEB
156 Standard_IMPORT void FUN_tool_coutsta(const Standard_Integer& sta, const Standard_Integer& i1, const Standard_Integer& i2);
157 #endif
158
159
160 Standard_Integer regularize(Draw_Interpretor& di, Standard_Integer n, const char** a)
161 {
162   if (n < 2) return 1;
163   TopoDS_Shape aLocalShape = DBRep::Get(a[1]);
164   TopoDS_Face fa = TopoDS::Face(aLocalShape);
165 //  TopoDS_Face fa = TopoDS::Face(DBRep::Get(a[1]));
166   if (fa.IsNull()) {di<<"null face"<<"\n"; return 1;}
167   
168   TopTools_DataMapOfShapeListOfShape ESplits;
169   TopTools_ListOfShape lof;  
170   TopOpeBRepTool::Regularize(fa, lof, ESplits);  
171   Standard_Integer nfa = lof.Extent();
172   di<<"face gives "<<nfa<<" newfaces"<<"\n";
173   
174   Standard_Integer i = 0;
175   TopTools_ListIteratorOfListOfShape itlof(lof) ;
176   for ( ; itlof.More(); itlof.Next()) {
177     i++;
178     TCollection_AsciiString aa = TCollection_AsciiString("fa_");
179     aa += TCollection_AsciiString(i);
180     FUN_draw(aa,itlof.Value());        
181   }
182   BRep_Builder BB;
183   TopoDS_Compound CC; BB.MakeCompound(CC);
184   for (itlof.Initialize(lof); itlof.More(); itlof.Next()) BB.Add(CC, itlof.Value());
185   di<<"resulting compound is cmp"<<"\n";
186   TCollection_AsciiString aa = TCollection_AsciiString("cmp");
187   FUN_draw(aa,CC);  
188   
189   return 0;
190 }
191
192 static Standard_Integer splitF(Draw_Interpretor& di, Standard_Integer n, const char** a)
193 {
194   if (n < 2) return 1;
195   TopoDS_Shape aLocalShape = DBRep::Get(a[1]);
196   const TopoDS_Face& fa = TopoDS::Face(aLocalShape);
197 //  const TopoDS_Face& fa = TopoDS::Face(DBRep::Get(a[1]));
198   if (fa.IsNull()) {di<<"null face"<<"\n"; return 1;}
199   
200   TopTools_ListOfShape fsplits;
201 //  Standard_Boolean splitok = FUN_tool_SplitF(fa,fsplits);
202   Standard_Boolean splitok = TopOpeBRepTool_REGUS::SplitF(fa,fsplits);
203   
204   if (!splitok) {di<<"no splits"<<"\n"; return 0;}
205   di<<"fa gives "<<fsplits.Extent()<<" splits"<<"\n";
206   
207   BRep_Builder BB;
208   TopoDS_Compound CC; BB.MakeCompound(CC);
209   for (TopTools_ListIteratorOfListOfShape it(fsplits); it.More(); it.Next()) BB.Add(CC, it.Value());
210   
211   di<<"resulting compound is cmp"<<"\n";
212   TCollection_AsciiString aa = TCollection_AsciiString("cmp");
213   FUN_draw(aa,CC); 
214   return 0;
215 }
216
217
218 static Standard_Integer regush(Draw_Interpretor& di, Standard_Integer n, const char** a)
219 {
220   if (n < 2) return 1;
221   const TopoDS_Shape& sha = DBRep::Get(a[1]);
222   if (sha.IsNull()) {di<<"null shape"<<"\n"; return 1;}
223   TopExp_Explorer ex(sha, TopAbs_SOLID);
224   const TopoDS_Solid& so = TopoDS::Solid(ex.Current());
225   if (so.IsNull()) {di<<"no solid"<<"\n"; return 1;}
226   
227   TopTools_DataMapOfShapeListOfShape FSplits;
228   TopTools_DataMapOfShapeListOfShape OldSheNewShe;
229   
230   BRep_Builder BB;
231   TopoDS_Compound CC; BB.MakeCompound(CC);
232   Standard_Integer nshe = 0;
233   Standard_Boolean regu = TopOpeBRepTool::RegularizeShells(so,OldSheNewShe,FSplits);
234   if (!regu) {di<<"solid gives no new shell"<<"\n";}
235   else {  
236     Standard_Integer noldshe = OldSheNewShe.Extent();
237     TopTools_DataMapIteratorOfDataMapOfShapeListOfShape ite(OldSheNewShe);
238     for (; ite.More(); ite.Next()){
239       const TopoDS_Shape& oldshe = ite.Key();
240       const TopTools_ListOfShape& newshells =  ite.Value();
241       if (newshells.IsEmpty()) {BB.Add(CC,oldshe); nshe++;}
242       else {
243         for (TopTools_ListIteratorOfListOfShape it(newshells); it.More(); it.Next()){
244           BB.Add(CC,it.Value()); nshe++;
245         }
246       }
247     } // i = 1..noldshe
248     di <<"noldshe = "<<noldshe<<" gives nshe = "<<nshe<<"\n";
249     di<<"resulting compound is cmp"<<"\n";
250     TCollection_AsciiString aa = TCollection_AsciiString("cmp");
251     FUN_draw(aa,CC);  
252   }
253   return 0;
254 }
255
256 Standard_Integer reguso(Draw_Interpretor& di, Standard_Integer n, const char** a)
257 {
258   if (n < 2) return 1;
259   const TopoDS_Shape& sha = DBRep::Get(a[1]);
260   if (sha.IsNull()) {di<<"null shape"<<"\n"; return 1;}
261   TopExp_Explorer ex(sha, TopAbs_SOLID);
262   const TopoDS_Solid& so = TopoDS::Solid(ex.Current());
263   if (so.IsNull()) {di<<"no solid"<<"\n"; return 1;}
264   
265   TopTools_DataMapOfShapeListOfShape FSplits;
266   TopTools_DataMapOfShapeListOfShape OldSheNewShe;
267   
268   BRep_Builder BB;
269   TopoDS_Compound CC; BB.MakeCompound(CC);
270 //  Standard_Integer nshe = 0;
271   Standard_Boolean regu = TopOpeBRepTool::RegularizeShells(so,OldSheNewShe,FSplits);
272   if (!regu) {di<<"solid gives no new shell"<<"\n";}
273   else {  
274     TopTools_DataMapIteratorOfDataMapOfShapeListOfShape itm(OldSheNewShe);
275     
276     TopOpeBRepBuild_ShellToSolid SheToSo;      
277     for (; itm.More(); itm.Next()) {
278       const TopTools_ListOfShape& lns = itm.Value();
279       TopTools_ListIteratorOfListOfShape itsh(lns);
280       for (; itsh.More(); itsh.Next()) {
281         const TopoDS_Shell& she = TopoDS::Shell(itsh.Value());
282         SheToSo.AddShell(she);
283       }
284     }
285     TopTools_ListOfShape splits; 
286     SheToSo.MakeSolids(so,splits);
287     
288     BRep_Builder BB;
289     TopoDS_Compound CC; BB.MakeCompound(CC);
290     Standard_Integer nSo = 0;
291     TopTools_ListIteratorOfListOfShape itSo(splits);
292     for (; itSo.More(); itSo.Next()) {
293       const TopoDS_Shape& spli = itSo.Value();
294       BB.Add(CC,spli);
295       nSo++;
296     } 
297     di<<"so gives "<<nSo<<" new solids"<<"\n";
298     di<<"resulting compound is cmp"<<"\n";
299     TCollection_AsciiString aa = TCollection_AsciiString("cmp");
300     FUN_draw(aa,CC);  
301   }
302   return 0;
303 }
304
305 static Standard_Integer purge(Draw_Interpretor& di, Standard_Integer n, const char** a)
306 {  
307
308   if (n < 2) return 1;
309   TopoDS_Shape aLocalShape = DBRep::Get(a[1]);
310   TopoDS_Face fa = TopoDS::Face(aLocalShape);
311 //  TopoDS_Face fa = TopoDS::Face(DBRep::Get(a[1]));
312   if (fa.IsNull()) return 1;
313     TopOpeBRepTool_CORRISO CORRISO(fa); 
314   Standard_Real tolF = BRep_Tool::Tolerance(fa);
315   Standard_Real uperiod; Standard_Boolean uclosed = CORRISO.Refclosed(1,uperiod);
316   Standard_Real vperiod; Standard_Boolean vclosed = CORRISO.Refclosed(2,vperiod);
317   if (!uclosed && !vclosed) return 1;
318   Standard_Boolean inU = uclosed ? Standard_True : Standard_False;  
319   Standard_Real xmin = inU ? (CORRISO.GASref().FirstUParameter()) : (CORRISO.GASref().LastUParameter());
320   Standard_Real xper = inU ? uperiod : vperiod;
321   Standard_Real tolx = inU ? (CORRISO.Tol(1,tolF)) : (CORRISO.Tol(2,tolF));
322
323   BRep_Builder BB; 
324   TopTools_ListOfShape lWs; Standard_Boolean hasnew = Standard_False;
325   TopExp_Explorer exw(fa, TopAbs_WIRE);
326   for (; exw.More(); exw.Next()){
327     const TopoDS_Shape& W = exw.Current();
328
329     CORRISO.Init(W);
330     Standard_Boolean ok = CORRISO.UVClosed();
331     if (ok) {lWs.Append(W); continue;}
332
333     TopTools_ListOfShape cEds; 
334     TopTools_ListIteratorOfListOfShape ite(CORRISO.Eds());
335     for (; ite.More(); ite.Next()){
336       const TopoDS_Edge& E = TopoDS::Edge(ite.Value());
337       Standard_Boolean closing = BRep_Tool::IsClosed(E,fa); 
338       if (!closing) {// xpu231198 : pcurve modified, the information is lost
339         TopOpeBRepTool_C2DF C2DF; Standard_Boolean isb = CORRISO.UVRep(E,C2DF);
340         if (!isb) return 1;//NYIRAISE
341         Standard_Boolean onclo = TopOpeBRepTool_TOOL::IsonCLO(C2DF,inU,xmin,xper,tolx);
342         if (onclo) closing=Standard_True;
343       }
344       if (closing) cEds.Append(E);
345     }          
346     Standard_Integer ncE = cEds.Extent();
347     Standard_Boolean nopurge = (ncE <= 1);
348     if (nopurge) {lWs.Append(W); continue;}
349     
350     // Checking <W>
351     TopTools_ListOfShape lfyE; Standard_Boolean topurge = CORRISO.PurgeFyClosingE(cEds,lfyE);
352     if (!topurge) {lWs.Append(W); continue;}
353     
354     TopoDS_Wire Wi; BB.MakeWire(Wi); // Add une TShape
355     Wi.Free(Standard_True);
356     ite.Initialize(CORRISO.Eds());
357     for (; ite.More(); ite.Next()) {
358       const TopoDS_Edge& ed = TopoDS::Edge(ite.Value());
359       Standard_Boolean equ = Standard_False;
360       for (TopTools_ListIteratorOfListOfShape itlfyE(lfyE);itlfyE.More();itlfyE.Next()) {
361         const TopoDS_Shape& fyE = itlfyE.Value();
362         if (ed.IsEqual(fyE)) {
363           equ = Standard_True; 
364           break;
365         }
366       }
367       if (equ) {
368         continue;
369       }
370       BB.Add(Wi,ed);
371     }
372     lWs.Append(Wi);
373   } // exw
374   
375   if (!hasnew) return 1;
376
377   // Building up the new face :
378   aLocalShape = fa.EmptyCopied();
379   TopoDS_Face newF = TopoDS::Face(aLocalShape);
380 //  TopoDS_Face newF = TopoDS::Face(fa.EmptyCopied());
381   TopTools_ListIteratorOfListOfShape itw(lWs);  
382   for (; itw.More(); itw.Next()) BB.Add(newF, TopoDS::Wire(itw.Value()));
383
384   di <<"New face built is newF"<<"\n";
385   TCollection_AsciiString aa("newF");
386   FUN_draw(aa, newF);
387   return 0;  
388 }
389
390
391 Standard_Integer correctONISO(Draw_Interpretor& di, Standard_Integer n, const char** a)
392 {
393   if (n < 3) return 1;
394   TopoDS_Shape aLocalShape = DBRep::Get(a[1]);
395   TopoDS_Face F   = TopoDS::Face(aLocalShape);
396   aLocalShape = DBRep::Get(a[2]);
397   TopoDS_Face Fsp = TopoDS::Face(aLocalShape);
398 //  TopoDS_Face F   = TopoDS::Face(DBRep::Get(a[1]));
399 //  TopoDS_Face Fsp = TopoDS::Face(DBRep::Get(a[2]));
400
401   FC2D_Prepare(F,F);
402
403   if (F.IsNull() || Fsp.IsNull()) {di<<"NULL shape(s)"<<"\n";return 1;}
404
405   TopOpeBRepTool::CorrectONUVISO(F,Fsp);
406   TCollection_AsciiString aa("newFsp");
407   FUN_draw(aa,Fsp);
408   di<<"-> newFsp"<<"\n";
409   
410   return 0;  
411 }
412
413 // ======================================================================
414 //                useful commands :
415 // ======================================================================
416
417 static Standard_Integer isclosingE(Draw_Interpretor& di, Standard_Integer n, const char** a)
418 {
419   if (n < 3) return 1;
420   TopoDS_Shape aLocalShape = DBRep::Get(a[1]) ;
421   TopoDS_Edge ed = TopoDS::Edge(aLocalShape);
422   aLocalShape = DBRep::Get(a[2]);
423   TopoDS_Face fa = TopoDS::Face(aLocalShape);
424 //  TopoDS_Edge ed = TopoDS::Edge(DBRep::Get(a[1]));
425 //  TopoDS_Face fa = TopoDS::Face(DBRep::Get(a[2]));
426   Standard_Boolean isclosing = BRep_Tool::IsClosed(ed,fa);
427   TopAbs_Orientation oriE = ed.Orientation();
428   if (isclosing) {di <<"edge is ";
429                   //TopAbs::Print(oriE,cout);
430                   Standard_SStream aSStream;
431                   TopAbs::Print(oriE,aSStream);
432                   di << aSStream;
433                   di<<" closing edge"<<"\n";}
434   else di <<"edge is NOT closing edge"<<"\n";
435   return 0;
436 }
437
438 static Standard_Integer compareshsh(Draw_Interpretor& di, Standard_Integer n, const char** a)
439 {
440   if (n < 3) return 1;
441   TopoDS_Shape sh1 = DBRep::Get(a[1]);
442   TopoDS_Shape sh2 = DBRep::Get(a[2]);
443   Standard_Boolean issame = sh1.IsSame(sh2); 
444   if (issame) di<<" same shapes"<<"\n";
445   else        di <<" shapes are not same"<<"\n";
446   Standard_Boolean isequal = sh1.IsEqual(sh2); if (isequal) di<<" equal shapes"<<"\n";
447   return 0;
448 }
449 static Standard_Integer pcurveedgeonface(Draw_Interpretor& di, Standard_Integer n, const char** a)
450 {
451   if (n < 3) return 1;
452   TopoDS_Shape ed = DBRep::Get(a[1]);
453   TopoDS_Shape fa = DBRep::Get(a[2]);
454   TCollection_AsciiString aa("edonfa_");
455   FUN_test_draw(aa,TopoDS::Edge(ed),TopoDS::Face(fa),0,di);
456   return 0;
457 }
458
459 static Standard_Integer pcurvesonface(Draw_Interpretor& di, Standard_Integer n, const char** a)
460 {
461   if (n < 3) return 1;
462   TopoDS_Shape sh = DBRep::Get(a[2]);
463   TopoDS_Shape fa = DBRep::Get(a[3]);
464   TopExp_Explorer exe(sh, TopAbs_EDGE);
465   Standard_Integer i = 0;
466   for (; exe.More(); exe.Next()){
467     i++;
468     TCollection_AsciiString aa(a[1]);
469     FUN_test_draw(aa,TopoDS::Edge(exe.Current()),TopoDS::Face(fa),i,di);    
470   }
471   return 0;
472 }
473
474 static Standard_Integer orivine(Draw_Interpretor& di, Standard_Integer n, const char** a)
475 {
476   if (n < 3) return 1;
477   TopoDS_Shape aLocalShape = DBRep::Get(a[1]);
478   TopoDS_Vertex v = TopoDS::Vertex(aLocalShape);
479   aLocalShape = DBRep::Get(a[2]);
480   TopoDS_Edge ed = TopoDS::Edge(aLocalShape);
481 //  TopoDS_Vertex v = TopoDS::Vertex(DBRep::Get(a[1]));
482 //  TopoDS_Edge ed = TopoDS::Edge(DBRep::Get(a[2]));
483
484   Standard_Integer ori = TopOpeBRepTool_TOOL::OriinSor(v,ed);
485   if      (ori==0) di<<"v not in ed"<<"\n";
486   else if (ori==1)  di<<"v FORWARD in ed"<<"\n";
487   else if (ori==2)  di<<"v REVERSED in ed"<<"\n";
488   else if (ori==3)  di<<"v INTERNAL in ed"<<"\n";
489   else if (ori==4)  di<<"v EXTERNAL in ed"<<"\n";
490   else if (ori==5)  di<<"v CLOSING in ed"<<"\n";
491   return 0;
492 }
493
494 static Standard_Integer vine(Draw_Interpretor& di, Standard_Integer n, const char** a)
495 {
496   if (n < 4) return 1;
497   TopoDS_Shape aLocalShape = DBRep::Get(a[1]);
498   TopoDS_Vertex v = TopoDS::Vertex(aLocalShape);
499   aLocalShape = DBRep::Get(a[2]);
500   TopoDS_Edge ed = TopoDS::Edge(aLocalShape);
501   aLocalShape = DBRep::Get(a[3]);
502   TopoDS_Face fa = TopoDS::Face(aLocalShape);
503 //  TopoDS_Vertex v = TopoDS::Vertex(DBRep::Get(a[1]));
504 //  TopoDS_Edge ed = TopoDS::Edge(DBRep::Get(a[2]));
505 //  TopoDS_Face fa = TopoDS::Face(DBRep::Get(a[3]));
506   
507   Standard_Real pf,pl;
508   const Handle(Geom2d_Curve) PC = BRep_Tool::CurveOnSurface(ed,fa,pf,pl);
509   gp_Pnt2d p2df, p2dl; PC->D0(pf,p2df); PC->D0(pl,p2dl);
510   di << "p2df";FUN_cout(p2df,di); di << "p2dl";FUN_cout(p2dl,di);di<<"\n";  
511   
512   Standard_Integer ori = TopOpeBRepTool_TOOL::OriinSor(v,ed);
513   if      (ori==0)  {di<<"v not in ed"<<"\n"; return 0;}
514   else if (ori==1)  di<<"v FORWARD in ed"<<"\n";
515   else if (ori==2)  di<<"v REVERSED in ed"<<"\n";
516   else if (ori==3)  di<<"v INTERNAL in ed"<<"\n";
517   else if (ori==4)  di<<"v EXTERNAL in ed"<<"\n";
518   else if (ori==5)  di<<"v CLOSING in ed"<<"\n";
519
520   if ((ori == 1) || (ori == 2)) {
521     Standard_Real par = TopOpeBRepTool_TOOL::ParE(ori,ed);//FUN_tool_parOnE(ind,ed,fa);
522     gp_Pnt2d p2d; PC->D0(par,p2d);
523     di <<"p2d : with TopOpeBRepTool_TOOL::ParE";FUN_cout(p2d,di);di<<"\n"; 
524   }
525   
526   Standard_Real par = BRep_Tool::Parameter(v,ed,fa);
527   gp_Pnt2d pp2d; PC->D0(par,pp2d);
528   di <<"p2d computed with BRep_Tool::Parameter";FUN_cout(pp2d,di);di<<"\n";
529   
530   return 0;
531 }
532
533 static Standard_Integer issubshape(Draw_Interpretor& di, Standard_Integer n, const char** a)
534 {  
535   if (n < 3) return 1;
536   TopoDS_Shape subshape = DBRep::Get(a[1]);
537   TopoDS_Shape shape    = DBRep::Get(a[2]);
538   TopExp_Explorer ex(shape, subshape.ShapeType());
539   Standard_Boolean issubs = Standard_False;
540   for (; ex.More(); ex.Next())
541     if (ex.Current().IsSame(subshape)) {issubs = Standard_True; break;}
542   
543   if (issubs) di<<" is subshape"<<"\n";
544   else        di<<" is NOT subshape"<<"\n";
545   return 0;
546 }
547
548 void FUN_mkBnd2dBREP(const TopoDS_Shape& W, const TopoDS_Shape& F,Bnd_Box2d& B2d,const Standard_Integer& i)
549 {
550   // greater <B> with <W>'s UV representation on <F>
551   Standard_Real tol = 1.e-8;  
552   TopExp_Explorer ex;
553   for (ex.Init(W, TopAbs_EDGE); ex.More(); ex.Next()) {
554 //  for (TopExp_Explorer ex(W, TopAbs_EDGE); ex.More(); ex.Next()) {
555     if (i == 0) {
556       FUN_tool_mkBnd2d(W,F,B2d);
557     }
558     if (i == 1) {
559       BRepAdaptor_Curve2d BC2d(TopoDS::Edge(ex.Current()), TopoDS::Face(F));
560       BndLib_Add2dCurve::Add(BC2d, tol, B2d);
561     }
562     if (i == 2) {
563       Standard_Real f,l;
564       Handle(Geom2d_Curve) PC = BRep_Tool::CurveOnSurface(TopoDS::Edge(ex.Current()),TopoDS::Face(F),f,l);
565       Geom2dAdaptor_Curve GC2d(PC);
566       BndLib_Add2dCurve::Add(GC2d, tol, B2d);
567     }
568     if (i == 3) {
569       TopLoc_Location L; Standard_Real f,l;
570       const Handle(Geom_Surface)& S = BRep_Tool::Surface(TopoDS::Face(F),L);
571       const Handle(Geom2d_Curve)& PC = BRep_Tool::CurveOnSurface(TopoDS::Edge(ex.Current()),S,L,f,l); 
572       Geom2dAdaptor_Curve GC2d(PC);
573       BndLib_Add2dCurve::Add(GC2d, tol, B2d);
574     }
575     
576   } //ex(W,EDGE)
577 }
578
579 static Standard_Integer drawbnd2d(Draw_Interpretor& , Standard_Integer n, const char** a)
580 {
581   if (n < 5) return 1;
582   Standard_Integer i = Draw::Atoi(a[4]);
583   TopoDS_Shape W = DBRep::Get(a[2]);
584   TopoDS_Shape F = DBRep::Get(a[3]);
585   if (W.IsNull() || F.IsNull()) return 1;
586   Bnd_Box2d B2d;
587   Standard_Real umin,vmin,umax,vmax;
588   FUN_mkBnd2dBREP(W,F,B2d,i);
589   B2d.Get(umin,vmin,umax,vmax);
590   
591   Handle(Geom2d_Line) cx = new Geom2d_Line(gp_Pnt2d(umin,vmin),gp_Dir2d(1.,0.));
592   Handle(Geom2d_Line) cy = new Geom2d_Line(gp_Pnt2d(umin,vmin),gp_Dir2d(0.,1.));
593   gp_Trsf2d tx; gp_Vec2d vx(umax-umin,0.); tx.SetTranslation(vx);
594   gp_Trsf2d ty; gp_Vec2d vy(0.,vmax-vmin); ty.SetTranslation(vy);
595   
596   Handle(Geom2d_TrimmedCurve) tcx = new Geom2d_TrimmedCurve(cx,0.,umax-umin);
597   Handle(Geom2d_TrimmedCurve) tcy = new Geom2d_TrimmedCurve(cy,0.,vmax-vmin);
598   Handle(Geom2d_TrimmedCurve) tccx = Handle(Geom2d_TrimmedCurve)::DownCast(tcx->Copy()); tccx->Transform(ty);
599   Handle(Geom2d_TrimmedCurve) tccy = Handle(Geom2d_TrimmedCurve)::DownCast(tcy->Copy()); tccy->Transform(tx);
600   
601   Draw_Color col(Draw_blanc);
602   DrawTrSurf_CurveColor(col);
603   
604   TCollection_AsciiString aa3 = TCollection_AsciiString(a[1]); aa3 += TCollection_AsciiString(3);
605   TCollection_AsciiString aa4 = TCollection_AsciiString(a[1]); aa4 += TCollection_AsciiString(4);
606   
607   TCollection_AsciiString aa;
608   aa=TCollection_AsciiString(a[1]); aa+=TCollection_AsciiString(1); char* aaa = (char *)aa.ToCString(); DrawTrSurf::Set(aaa,tcx);
609   aa=TCollection_AsciiString(a[1]); aa+=TCollection_AsciiString(2); aaa=(char *)aa.ToCString();         DrawTrSurf::Set(aaa,tcy);
610   aa=TCollection_AsciiString(a[1]); aa+=TCollection_AsciiString(3); aaa=(char *)aa.ToCString();         DrawTrSurf::Set(aaa,tccx);
611   aa=TCollection_AsciiString(a[1]); aa+=TCollection_AsciiString(4); aaa=(char *)aa.ToCString();         DrawTrSurf::Set(aaa,tccy);
612   return 0;
613 }
614
615 static Standard_Integer classifBnd2d(Draw_Interpretor& di, Standard_Integer n, const char** a)
616 {
617   if (n < 5) return 1;
618   TopoDS_Shape W1 = DBRep::Get(a[1]);
619   TopoDS_Shape W2 = DBRep::Get(a[2]);
620   TopoDS_Shape F = DBRep::Get(a[3]);
621   
622   TopoDS_Wire w1 = TopoDS::Wire(W1);
623   TopoDS_Wire w2 = TopoDS::Wire(W2);
624   TopoDS_Face Fref = TopoDS::Face(F);
625
626   TopOpeBRepTool_CLASSI classi; classi.Init2d(Fref);
627   Standard_Real tolF = BRep_Tool::Tolerance(Fref);
628   Standard_Real toluv = TopOpeBRepTool_TOOL::TolUV(Fref,tolF);
629
630   if (w1.IsNull() || w2.IsNull() || Fref.IsNull()) return 1;
631
632   Standard_Integer sta = classi.ClassiBnd2d(w1,w2,toluv,Standard_True);
633   di <<"wires classification : checklarge=true ";
634 #ifdef DEB
635   FUN_tool_coutsta(sta,1,2);
636 #endif
637
638   sta = classi.ClassiBnd2d(w1,w2,toluv,Standard_False);
639   di <<"wires classification : checklarge=false ";
640 #ifdef DEB
641   FUN_tool_coutsta(sta,1,2);
642 #endif
643   
644   return 0;
645 }
646
647 static Standard_Integer pntonc(Draw_Interpretor& di, Standard_Integer n, const char** a)
648 {
649   if (n < 3) return 1;
650   Standard_Real x = Draw::Atof(a[1]);
651   Handle(Geom_Curve) C = DrawTrSurf::GetCurve(a[2]);
652   if (C.IsNull()) {di<<"null curve"<<"\n"; return 1;}
653   gp_Pnt p = C->Value(x);
654   di<<"point on curve of parameter "<<x<<" =("<<p.X()<<",";
655   di<<p.Y()<<","<<p.Z()<<")"<<"\n";
656   return 0;
657 }
658
659 static Standard_Integer pntonc2d(Draw_Interpretor& di, Standard_Integer n, const char** a)
660 {
661   if (n < 4) return 1;
662   Standard_Real x = Draw::Atof(a[1]);
663   Handle(Geom2d_Curve) C2d = DrawTrSurf::GetCurve2d(a[2]);
664   if (C2d.IsNull()) {di<<"null curve"<<"\n"; return 1;}
665   Handle(Geom_Surface) S   = DrawTrSurf::GetSurface(a[3]);
666   if (S.IsNull()) {di<<"null surface"<<"\n"; return 1;}
667   gp_Pnt2d p2d = C2d->Value(x);
668   di<<"point on curve of parameter "<<x<<" =("<<p2d.X()<<","<<p2d.Y()<<")"<<"\n";
669   gp_Pnt p = S->Value(p2d.X(),p2d.Y());
670   di<<"point on curve of parameter "<<x<<" =("<<p.X()<<",";
671   di<<p.Y()<<","<<p.Z()<<")"<<"\n";     
672   return 0;                                                       
673 }
674
675 static Standard_Integer projponf(Draw_Interpretor& di, Standard_Integer n, const char** a)
676 {
677   if (n < 3) {
678     di << "projponf f pnt [extrema flag: -min/-max/-minmax] [extrema algo: -g(grad)/-t(tree)]\n";
679     return 1;
680   }
681   //
682   TopoDS_Shape aLocalShape = DBRep::Get(a[1]);
683   TopoDS_Face f = TopoDS::Face(aLocalShape);
684   //
685   if (f.IsNull()) {
686     di<<"null shape"<<"\n";
687     return 1;
688   }
689   //
690   Standard_Real dist=0.;
691   Standard_Boolean ok;
692   gp_Pnt2d uv;
693   gp_Pnt p, pproj; 
694   Extrema_ExtAlgo aExtAlgo = Extrema_ExtAlgo_Grad;
695   Extrema_ExtFlag aExtFlag = Extrema_ExtFlag_MINMAX;
696   //
697   DrawTrSurf::GetPoint(a[2], p);
698   //
699   if (n > 3) {
700     const char* key1 = a[3];
701     const char* key2 = (n > 4) ? a[4] : NULL;
702     if (key1) {
703       if (!strcasecmp(key1,"-min")) {
704         aExtFlag = Extrema_ExtFlag_MIN;
705       } else if (!strcasecmp(key1,"-max")) {
706         aExtFlag = Extrema_ExtFlag_MAX;
707       } else {
708         aExtAlgo = (!strcasecmp(key1,"-t")) ? Extrema_ExtAlgo_Tree : aExtAlgo;
709       }
710     }
711     if (key2) {
712       aExtAlgo = (!strcasecmp(key2,"-t")) ? Extrema_ExtAlgo_Tree : aExtAlgo;
713     }
714   }
715   ok = FUN_tool_projPonF(p, f, uv, dist, aExtFlag, aExtAlgo);
716   //
717   if (!ok) {
718     di<<"projection failed"<<"\n"; 
719     return 1;
720   }
721   //
722   ok = FUN_tool_value(uv,f,pproj);
723   if (!ok) {
724     di<<"projection failed"<<"\n"; 
725     return 1;
726   }
727   //
728   di<<"proj dist = "<<dist<<" uvproj = ("<<uv.X()<<" "<<uv.Y();
729   di<<"); pproj = ("<<pproj.X()<<" "<<pproj.Y()<<" "<<pproj.Z()<<")"<<"\n";
730   return 0;
731 }  
732
733 static Standard_Integer tolmax(Draw_Interpretor& di, Standard_Integer n, const char** a)
734 {
735   if (n < 2) return 1;
736   TopoDS_Shape s = DBRep::Get(a[1]);
737   if (s.IsNull()) {di<<"null shape"<<"\n"; return 1;}  
738   Standard_Real tol = FUN_tool_maxtol(s);
739   di<<"max tol = "<<tol<<"\n";
740   return 0;
741 }
742
743 static Standard_Integer solidclassifier(Draw_Interpretor& di, Standard_Integer n, const char** a)
744 {
745   if (n < 4) return 1;
746   TopoDS_Shape s = DBRep::Get(a[1]);
747   if (s.IsNull()) {di<<"null shape"<<"\n";return 1;}
748   gp_Pnt p; DrawTrSurf::GetPoint(a[2], p);
749   Standard_Real tol = Draw::Atof(a[3]);
750   
751   TopOpeBRepTool_SolidClassifier soclassi;
752   TopAbs_State sta = TopAbs_UNKNOWN;
753   if      (s.ShapeType() == TopAbs_SOLID) soclassi.Classify(TopoDS::Solid(s),p,tol);
754   else if (s.ShapeType() == TopAbs_SHELL) soclassi.Classify(TopoDS::Shell(s),p,tol);
755   else {di<<"shape is not a solid nor a shell => KO"<<"\n"; return 1;}
756   
757   sta = soclassi.State();
758   di<<"point is ";
759   //TopAbs::Print(sta,cout);
760   Standard_SStream aSStream;
761   TopAbs::Print(sta,aSStream);
762   di << aSStream;
763   di<<" shape s"<<"\n";
764   return 0;
765 }
766
767 static Standard_Integer class3dclassifier(Draw_Interpretor& di, Standard_Integer n, const char** a)
768 {
769   if (n < 4) return 1;
770   TopoDS_Shape s = DBRep::Get(a[1]);
771   if (s.IsNull()) {di<<"null shape"<<"\n";return 1;}
772   gp_Pnt p; DrawTrSurf::GetPoint(a[2], p);
773   Standard_Real tol = Draw::Atof(a[3]);
774   
775   BRepClass3d_SolidClassifier soclassi(s);
776   TopAbs_State sta = TopAbs_UNKNOWN;
777   soclassi.Perform(p,tol);
778   
779   sta = soclassi.State();
780   di<<"point is ";
781   //TopAbs::Print(sta,cout);
782   Standard_SStream aSStream;
783   TopAbs::Print(sta,aSStream);
784   di << aSStream;
785   di<<" shape s"<<"\n";
786   return 0;
787 }
788 static Standard_Integer shapeclassifier(Draw_Interpretor& di, Standard_Integer n, const char** a)
789 {
790   if (n < 3) return 1;
791   TopoDS_Shape sh = DBRep::Get(a[1]);
792   if (sh.IsNull()) {di<<"null shape"<<"\n";return 1;}
793   TopoDS_Shape shref = DBRep::Get(a[2]);
794   if (shref.IsNull()) {di<<"null reference shape"<<"\n";return 1;}
795   Standard_Boolean hastoavoid = (n > 3);
796   TopTools_ListOfShape toavoid;
797   if (hastoavoid) {
798     for (Standard_Integer i=3; i<=n; i++) {
799       TopoDS_Shape shtoavoid = DBRep::Get(a[i]); 
800       if (shtoavoid.IsNull()) {di<<"null toavoid shape"<<"\n";return 1;}    
801       toavoid.Append(shtoavoid);
802     }
803   }
804   
805   TopOpeBRepTool_ShapeClassifier shclassi;
806   TopAbs_State sta = TopAbs_UNKNOWN;
807   if (hastoavoid) sta = shclassi.StateShapeShape(sh,shref);
808   else if (toavoid.Extent() == 1) sta = shclassi.StateShapeShape(sh,toavoid.First(),shref);
809   else sta = shclassi.StateShapeShape(sh,toavoid,shref);
810   
811   di<<"shape is ";
812   //TopAbs::Print(sta,cout);
813   Standard_SStream aSStream;
814   TopAbs::Print(sta,aSStream);
815   di << aSStream;
816   di<<" shape ref"<<"\n";
817   return 0;
818 }
819
820
821 // normals ..
822 static Standard_Integer normal(Draw_Interpretor& di, Standard_Integer n, const char** a)
823 {
824   if (n < 3) return 1;
825   TopoDS_Shape aLocalShape = DBRep::Get(a[1]);
826   TopoDS_Face f = TopoDS::Face(aLocalShape);
827 //  TopoDS_Face f = TopoDS::Face(DBRep::Get(a[1]));
828   if (f.IsNull()) {di<<"null shape"<<"\n";return 1;}
829   gp_Pnt p; DrawTrSurf::GetPoint(a[2], p);
830 #ifdef DEB
831   Standard_Real length = Draw::Atof(a[3]);
832 #endif
833   Standard_Real dist=0.; gp_Pnt2d uv; Standard_Boolean ok = FUN_tool_projPonF(p,f,uv,dist);
834   if (!ok) {di<<"projection failed"<<"\n"; return 1;}
835 #ifdef DEB
836   gp_Vec ngf =
837 #endif
838                FUN_tool_nggeomF(uv,f);
839   TCollection_AsciiString aa("ngS"); 
840 #ifdef DRAW
841   FUN_tool_draw(aa,p,ngf,length);
842 #endif
843   return 0;
844 }  
845
846 static Standard_Integer curvature(Draw_Interpretor& di, Standard_Integer n, const char** a)
847 {
848   if (n < 5) return 1;
849   TopoDS_Shape aLocalShape = DBRep::Get(a[1]);
850   TopoDS_Face f = TopoDS::Face(aLocalShape);
851 //  TopoDS_Face f = TopoDS::Face(DBRep::Get(a[1]));
852   if (f.IsNull()) {di<<"null shape"<<"\n";return 1;}
853   Standard_Real x = Draw::Atof(a[2]);
854   Standard_Real y = Draw::Atof(a[3]);
855   Standard_Real z = Draw::Atof(a[4]);
856   Handle(Geom_Line) line = new Geom_Line(gp_Ax1(gp_Pnt(0.,0.,0.), gp_Dir(x,y,z)));
857   BRepAdaptor_Surface BS(f);
858   Handle(Geom_Surface) su = BRep_Tool::Surface(f);
859   GeomAPI_IntCS intcs(line,su);
860   Standard_Boolean done = intcs.IsDone();
861   if (!done) {di<<"intersection point on surface not found"<<"\n"; return 1;}
862   Standard_Integer npnts = intcs.NbPoints();
863   if (npnts < 1) {di<<"intersection point on surface not found"<<"\n"; return 1;}
864   
865   Standard_Real tol = Precision::Confusion();
866   BRepLProp_SLProps props(BS,2,tol);
867   Standard_Real Cur1=0., Cur2=0.;
868   gp_Dir Norm,D1,D2;  
869   for (Standard_Integer i = 1; i <= npnts; i++) {
870     gp_Pnt p = intcs.Point(i);
871     Standard_Real u,v,w; intcs.Parameters(i,u,v,w);
872     di<<"point("<<i<<") = { ("<<p.X()<<" "<<p.Y()<<" "<<p.Z()<<"), ("<<u<<" "<<v<<") }"<<"\n"; 
873     props.SetParameters(u,v);
874     Standard_Boolean curdef = props.IsCurvatureDefined();
875     if (!curdef) {di<<"!IsCurvatureDefined"<<"\n"; continue;}
876     Standard_Boolean umbilic = props.IsUmbilic();
877     if (umbilic) { 
878       Cur1 = Cur2 = props.MeanCurvature();
879       D1 = gp_Dir(0,0,1);
880       D2 = gp_Dir(0,1,0);   
881       di<<"umbilic";
882     }
883     else {
884       Cur1 = props.MaxCurvature();
885       Cur2 = props.MinCurvature();
886       props.CurvatureDirections(D1,D2);
887     }
888     Norm = gp_Dir(D1^D2); 
889     di<<"D1  = ("<<D1.X()<<" "<<D1.Y()<<" "<<D1.Z()<<" "<<")"<<"\n";
890     di<<"D2  = ("<<D2.X()<<" "<<D2.Y()<<" "<<D2.Z()<<" "<<")"<<"\n";
891     di<<"Norm  = ("<<Norm.X()<<" "<<Norm.Y()<<" "<<Norm.Z()<<" "<<")"<<"\n";
892   } // i
893   return 0;
894 }
895
896 void TestTopOpe::CORCommands(Draw_Interpretor& theCommands)
897 {
898   static Standard_Boolean done = Standard_False;
899   if (done) return; done = Standard_True;
900   const char* g = "TestTopOpe CORCommands";
901   // purge, regularization commands :
902   theCommands.Add("purge",   "purge f",                  __FILE__, purge, g);
903   theCommands.Add("corrISO", "corrISO f Fsp",            __FILE__, correctONISO, g);
904   theCommands.Add("regufa",  "regufa f",                 __FILE__, regularize, g);
905   theCommands.Add("splitf",  "splitf f",                 __FILE__, splitF, g);
906   theCommands.Add("regush",  "regush so",                __FILE__, regush, g);
907   theCommands.Add("reguso",  "reguso so",                __FILE__, reguso, g);
908   // builder commands :
909   theCommands.Add("soclass",  "soclass sh pnt tol",         __FILE__, solidclassifier, g);
910   theCommands.Add("shclass",  "shclass sh shref <toavoid>", __FILE__, shapeclassifier, g);
911   theCommands.Add("clclass",  "clclass sh shref <toavoid>", __FILE__, class3dclassifier, g);
912   
913   // useful commands :
914   theCommands.Add("cled",       "cled ed f",                __FILE__, isclosingE, g);
915   theCommands.Add("compare",    "compare s1 s2",            __FILE__, compareshsh, g);
916   theCommands.Add("edonfa",     "edonfa ed f",              __FILE__, pcurveedgeonface, g);
917   theCommands.Add("pconfa",     "pconfa name s f",          __FILE__, pcurvesonface, g);
918   theCommands.Add("orivine",    "orivine v ed",             __FILE__, orivine, g);
919   theCommands.Add("vine",       "vine v ed fa",             __FILE__, vine, g);
920   theCommands.Add("issubsh",    "issubsh subsh sh",         __FILE__, issubshape, g);
921   theCommands.Add("bnd2d",      "bnd2d name W F i",         __FILE__, drawbnd2d, g);
922   theCommands.Add("classibnd2d","classibnd2d W1 W2 F i",    __FILE__, classifBnd2d, g);
923   theCommands.Add("pntonc",     "pntonc par C3d",           __FILE__, pntonc, g);
924   theCommands.Add("pntonc2d",   "pntonc2d par C2d S",       __FILE__, pntonc2d, g);
925   theCommands.Add("projponf",   
926                   "projponf f pnt [extrema flag: -min/-max/-minmax] [extrema algo: -g(grad)/-t(tree)]",
927                                                             __FILE__, projponf, g);
928   theCommands.Add("tolmax",     "tolmax s",                 __FILE__, tolmax, g);
929   theCommands.Add("normal",     "normal f p3d length",      __FILE__, normal, g);
930   theCommands.Add("curvature",  "curvature f x y z",        __FILE__, curvature , g);
931   
932 }