0026261: Create a tool to remove tails from any wire
[occt.git] / src / SWDRAW / SWDRAW_ShapeFix.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 #include <SWDRAW_ShapeFix.ixx>
18
19 #include <Draw.hxx>
20 #include <DBRep.hxx>
21 #include <BRep_Tool.hxx>
22 #include <SWDRAW.hxx>
23 #include <gp_XYZ.hxx>
24 #include <gp_Pnt2d.hxx>
25 #include <TopoDS.hxx>
26 #include <TopoDS_Shape.hxx>
27 #include <TopoDS_Edge.hxx>
28 #include <TopoDS_Wire.hxx>
29 #include <TopoDS_Face.hxx>
30 #include <TopoDS_Iterator.hxx>
31 #include <TopExp_Explorer.hxx>
32 #include <BRep_Tool.hxx>
33 #include <BRep_Builder.hxx>
34 #include <BRepBuilderAPI.hxx>
35 #include <BRepTopAdaptor_FClass2d.hxx>
36
37 #include <ShapeBuild_ReShape.hxx>
38 #include <ShapeAnalysis_Edge.hxx>
39 #include <ShapeAnalysis_WireOrder.hxx>
40 #include <ShapeAnalysis_WireVertex.hxx>
41 #include <ShapeAnalysis_Wire.hxx>
42 #include <ShapeExtend_WireData.hxx>
43 #include <ShapeFix.hxx>
44 #include <ShapeFix_ShapeTolerance.hxx>
45 #include <ShapeFix_Wire.hxx>
46 #include <ShapeFix_WireVertex.hxx>
47 #include <ShapeFix_Wireframe.hxx>
48 #include <ShapeFix_Face.hxx>
49 #include <ShapeFix_Shape.hxx>
50 #include <Precision.hxx>
51 #include <ShapeExtend_DataMapOfShapeListOfMsg.hxx>
52 #include <ShapeExtend_MsgRegistrator.hxx>
53 #include <ShapeExtend_DataMapIteratorOfDataMapOfShapeListOfMsg.hxx>
54 #include <Message_ListIteratorOfListOfMsg.hxx>
55 #include <Message_Msg.hxx>
56 #include <TCollection_AsciiString.hxx>
57 #include <TColStd_DataMapIteratorOfDataMapOfAsciiStringInteger.hxx>
58 #include <TColStd_DataMapOfAsciiStringInteger.hxx>
59 #include <TopTools_MapOfShape.hxx>
60 #include <TopTools_DataMapOfShapeListOfShape.hxx>
61 #include <TopAbs_State.hxx>
62
63 #include <Draw_ProgressIndicator.hxx>
64 #include <ShapeAnalysis_FreeBounds.hxx>
65 #include <TopTools_HSequenceOfShape.hxx>
66 #include <BRep_Builder.hxx>
67 #include <TopTools_IndexedMapOfShape.hxx>
68 #include <TopExp.hxx>
69
70 #ifdef AIX
71 #include <strings.h>
72 #endif
73 #include <stdio.h>
74 #include <ShapeExtend_WireData.hxx>
75
76 //=======================================================================
77 //function : edgesameparam
78 //purpose  : 
79 //=======================================================================
80
81 static Standard_Integer edgesameparam (Draw_Interpretor& di, Standard_Integer argc, const char** argv)
82 {
83 //  const Standard_CString arg1 = argv[1];
84   const Standard_CString arg2 (argc > 2 ? argv[2] : NULL);
85 //        ****    Edge:SameParameter         ****
86   if (argc < 2) { di<<"shapename ,  option f to force, else only Edges not-SameParameter are computed"<<"\n"; return 1 /* Error */; }
87   TopoDS_Shape Shape = DBRep::Get(argv[1]);
88
89   if (!ShapeFix::SameParameter(Shape, (argc > 2 && arg2[0] == 'f') , BRepBuilderAPI::Precision()) )
90     di<<"Some edges were not processed"<<"\n";
91   di<<"\n";
92   return 0; // Done
93 }
94
95 //=======================================================================
96 //function : settolerance
97 //purpose  : 
98 //=======================================================================
99
100 static Standard_Integer settolerance (Draw_Interpretor& di, Standard_Integer argc, const char** argv)
101 {
102   if (argc < 3) {
103     di<<    "myshape val   : forces tolerances at <val>"<<"\n"
104       <<      "myshape < max : sets maximum tolerance to <max>"<<"\n"
105         <<    "myshape > min : sets minimum tolerance to <min>"<<"\n"
106           <<  "myshape min max : bounds tolerances between <min> and <max>"<<"\n"
107             <<"myshape mode=v-e-f other args : idem but only on vertex-edge-face"<<"\n";
108     return (argc < 2 ? 0 : 1 /* Error */);
109   }
110   Standard_CString arg1 = argv[1];
111   Standard_CString arg2 = argv[2];
112   TopoDS_Shape Shape = DBRep::Get(arg1);
113   if (Shape.IsNull()) { di<<"Shape unknown : "<<arg1<<"\n"; return 1 /* Error */; }
114   char mod2 = arg2[0];
115   Standard_Integer premarg = 2;
116   TopAbs_ShapeEnum styp = TopAbs_SHAPE;
117   if (mod2 == 'v') { styp = TopAbs_VERTEX; premarg = 3; }
118   if (mod2 == 'e') { styp = TopAbs_EDGE;   premarg = 3; }
119   if (mod2 == 'w') { styp = TopAbs_WIRE;   premarg = 3; }
120   if (mod2 == 'f') { styp = TopAbs_FACE;   premarg = 3; }
121   if (mod2 == 'a') { styp = TopAbs_SHAPE;  premarg = 3; }
122
123   Standard_Real tmin,tmax;
124   mod2 = argv[premarg][0];
125   if (mod2 == '=') tmin = tmax = Draw::Atof (argv[argc-1]);
126   else if (mod2 == '<') { tmin = 0; tmax = Draw::Atof (argv[argc-1]); }
127   else if (mod2 == '>') { tmin = Draw::Atof (argv[argc-1]); tmax = 0; }
128   else { tmin = Draw::Atof (argv[premarg]);  tmax = Draw::Atof (argv[argc-1]); }
129
130   if (argc == premarg + 1 || tmin == tmax) di<<"Setting Tolerance to "<<tmin<<"\n";
131   else if (tmax < tmin) di<<"Minimum Tolerance to "<<tmin<<"\n";
132   else if (tmin <= 0)   di<<"Maximum Tolerance to "<<tmax<<"\n";
133   else                  di<<"Tolerance Limited between "<<tmin<<" and "<<tmax<<"\n";
134   ShapeFix_ShapeTolerance sat;
135   sat.LimitTolerance (Shape,tmin,tmax,styp);
136   return 0; // Done
137 }
138
139 //=======================================================================
140 //function : stwire
141 //purpose  : 
142 //=======================================================================
143
144 static Standard_Integer stwire (Draw_Interpretor& di, Standard_Integer argc, const char** argv)
145 {
146   if (argc < 2) { // help
147     di<<"Donner nom shape depart + nom shape resultat + option"<<"\n";
148     di<<"Options de chargement :  x add connected  (sinon add simple)\n"
149       <<  "Options de traitement :  l fix little/BRepBuilderAPI\n"
150       <<"Options de sortie : aucune make simple\n"
151       <<"  m MakeAPI r avec reorder  v vertex\n"
152       <<"Autres (se cumulent) :  q quid(stats)"<<"\n";
153     return 0;
154   }
155   if (argc < 4) { di<<"stwire tout court pour help"<<"\n"; return 1 /* Error */; }
156   Standard_CString arg1 = argv[1];
157   Standard_CString arg2 = argv[2];
158
159 //  Options
160   Standard_Integer i;  int ox,ol,om,orint,oq,ov;  ox=ol=om=orint=oq=ov=0;
161   for (i = 3; i < argc; i ++) {
162     int valopt = 1;
163     char opt = argv[i][0];
164     if (opt == '+')   opt = argv[i][1];
165     if (opt == '-') { opt = argv[i][1]; valopt = 0; }
166     switch (opt) {
167     case 'l' : ol = valopt; break;
168     case 'm' : om = valopt; break;
169     case 'q' : oq = valopt; break;
170     case 'r' : orint = valopt; break;
171     case 'v' : ov = valopt; break;
172     case 'x' : ox = valopt; break;
173     default : break;
174     }
175   }
176   TopoDS_Shape Shape = DBRep::Get(arg1);
177   if (Shape.IsNull()) { di<<arg1<<" inconnu"<<"\n"; return 1 /* Error */; }
178
179 //  On y va
180   Handle(ShapeExtend_WireData) sbwd = new ShapeExtend_WireData;
181   Handle(ShapeAnalysis_Wire) saw = new ShapeAnalysis_Wire;
182   saw->Load ( sbwd );
183   
184   TopoDS_Shape awire;  // en principe un Wire
185   if (Shape.ShapeType() == TopAbs_WIRE) {
186     awire = Shape;
187   } else if (Shape.ShapeType() == TopAbs_FACE) {
188     saw->SetFace (TopoDS::Face(Shape));
189     TopExp_Explorer expw(Shape,TopAbs_WIRE);
190     if (expw.More()) awire = expw.Current();
191     saw->SetPrecision (BRepBuilderAPI::Precision());
192   }
193   if (awire.IsNull()) {
194     di<<"Neither FACE nor WIRE : "<<arg1<<"\n";
195     di<<"Considering as list of edges ..."<<"\n";
196     awire = Shape;
197 //    return 1 /* Error */;
198   }
199
200 // Chargement : normal ou par connected(oriented)
201 //  if (ox) {
202     for (TopExp_Explorer exp(Shape,TopAbs_EDGE); exp.More(); exp.Next()) {
203       TopoDS_Edge E = TopoDS::Edge (exp.Current());
204       Standard_Integer orient = saw->CheckShapeConnect (E);
205       di<<"Orientation : "<<orient<<" LowerDist : "<< saw->MinDistance3d() << "\n";
206       if (ox) sbwd->AddOriented (E,orient);
207       else sbwd->Add (E);
208     }
209 //  }
210 //  else sbwd->Init (awire);
211   
212   Handle(ShapeFix_Wire) sfw = new ShapeFix_Wire;
213   sfw->Init ( saw );
214
215 //   Traitement en cours
216   if (ol) {
217     Standard_Integer nb = sfw->NbEdges();
218     for (i = 1; i <= nb; i ++) {
219       Standard_Boolean stat = sfw->FixSmall (i, Standard_True, 0.0);
220       //cout<<"FixSmall for"<<i<<(stat ? " done" : " not done"); //:sw <<" StatusFix="<<STW.StatusFix()<<"\n";
221       di<<"FixSmall for"<<i;
222       if (!stat) {
223         di<<" not done";
224       } else {
225         di<<" done";
226       }
227       if ( sfw->LastFixStatus ( ShapeExtend_FAIL ) ) di << " (failed)";
228       di << "\n";
229     }
230   }
231
232 //  Traitement
233   if (orint) {  // reorder ?
234     ShapeAnalysis_WireOrder WO ( (Shape.ShapeType() != TopAbs_FACE), BRepBuilderAPI::Precision());
235
236     Standard_Integer stwo = saw->CheckOrder (WO);
237     Standard_Integer nb = WO.NbEdges();
238     di<<"Reorder status : "<<stwo<<"  NbEdges="<<nb<<"\n";
239     for (i = 1; i <= nb; i ++) {
240       Standard_Integer iord = WO.Ordered(i);
241       di<<"Edge n0 "<<i;
242       if ( sbwd->Edge(iord).Orientation() == TopAbs_REVERSED) di<<" REV";
243       else di<<" FWD";
244       di<<" ordered to "<<iord<<" Gap="<<WO.Gap(i)<<"\n";
245     }
246     di<<"Reorder not yet done"<<"\n";
247     sfw->FixReorder (WO);
248 //   Mais on n execute pas
249   }
250
251 //  Statistiques
252   if (oq) {
253     ShapeAnalysis_Edge sae;
254     Standard_Integer nb = sbwd->NbEdges();
255     di<<"NbEdges : "<<nb<<"\n";
256     for (i = 1; i <= nb; i ++) {
257       TopoDS_Edge E = sbwd->Edge(i);
258       di<<"Edge "<<i;
259       if (E.Orientation() == TopAbs_REVERSED) di<<" REV";
260       else di<<" FWD";
261       if (BRep_Tool::Degenerated(E)) di<<" DGNR";
262       if (sbwd->IsSeam(i))        di<<" SEAM_WIRE";
263       if (Shape.ShapeType() == TopAbs_FACE &&
264           sae.IsSeam(E,TopoDS::Face(Shape)))  di<<" SEAM_FACE";
265       if (Shape.ShapeType() == TopAbs_FACE ) {
266         if (sae.HasPCurve(E,TopoDS::Face(Shape)))     di<<" PCU";
267         else di<<" NO_PCU";
268       }
269       if (sae.HasCurve3d(E))    di<<" C3D";
270       else di<<" NO_C3D";
271       if (sae.IsClosed3d(E))  di<<" CLOSED";
272       di<<"\n";
273     }
274   }
275
276 //  Resultat
277   TopoDS_Wire result;
278   if (ov) {
279     ShapeAnalysis_WireVertex sawv;
280     sawv.Init ( sbwd, saw->Precision() );
281     sawv.Analyze();
282     Standard_Integer nb = sbwd->NbEdges();
283     di<<"Nb(End)Vertex : "<<nb<<"\n";
284     for (i = 1; i <= nb; i ++) {
285       gp_XYZ pos; Standard_Real upre,ufol;
286       Standard_Integer stat = sawv.Data (i,pos,upre,ufol);
287       di<<i<<" : ";
288       switch (stat) {
289       case 0 : di<<"Same Vertex"<<"\n"; break;
290       case 1 : di<<"Same Coords with recorded precisions (but not Same Vertex)"<<"\n"; break;
291       case 2 : di<<"Close (with preci="<< saw->Precision()<<")"<<"\n"; break;
292       case 3 : di<<"End of "<<i<<" OK, Start of "<<(i == nb ? 1 : i+1)<<" at U="<<ufol; break;
293       case 4 : di<<"End of "<<i<<" at U="<<upre<<", Start of "<<(i == nb ? 1 : i+1)<<" OK"; break;
294       case 5 : di<<"Intersection, End of "<<i<<" at U="<<upre<<", Start of "<<(i == nb ? 1 : i+1)<<" at U="<<ufol; break;
295         default : di<<"Disjoined"<<"\n";
296       }
297       if (stat >= 3 && stat <= 5) di<<"\n   - Position : "<<pos.X()<<"  "<<pos.Y()<<"  "<<pos.Z()<<"\n";
298     }
299     ShapeFix_WireVertex sfwv;
300     sfwv.Init ( sawv );
301     di<<"Nb Fixed Vertex : "<< sfwv.Fix() <<"\n";
302   }
303   /*
304   if (oc) {
305     if ( Shape.ShapeType() == TopAbs_FACE ) {
306       Correct_Wire CW ( TopoDS::Face(Shape) );
307       Standard_Integer i, nb = sbwd->NbEdges();
308       Standard_Integer num = 1;
309       for (i = 1; i <= nb; i ++)  CW.Add (sbwd->Edge(i));
310       CW.Perform ( saw->Precision() );
311       nb = CW.NbWires();
312       if (nb != 1) {
313         //  On prend celui qui a le plus d edges
314         Standard_Integer nbe, maxe = 0;
315         for (i = 1; i <= nb; i ++) {
316           TopoDS_Wire wir = CW.Wire(i);
317           nbe = 0;
318           for (TopoDS_Iterator ite(wir); ite.More(); ite.Next()) nbe ++;
319           if (nbe > maxe) { num = i; maxe = nbe; }
320         }
321         di<<"Correct_Wire produced "<<nb<<" Wires, taken n0 "<<num<<"\n";
322       }
323       result = CW.Wire (num);
324     }
325     else di << "Cannot apply Correct_Wire: face not defined" << "\n";
326   }
327   */
328   else if (om) result = sbwd->WireAPIMake();
329   else         result = sbwd->Wire();
330   if (result.IsNull()) {
331     di<<"Pas de resultat, desole"<<"\n";
332     return 1;  // Fail
333   }
334   DBRep::Set (arg2,result);
335   return 0; // Done
336 }
337
338 //=======================================================================
339 //function : reface
340 //purpose  : 
341 //=======================================================================
342
343 static Standard_Integer reface (Draw_Interpretor& di, Standard_Integer argc, const char** argv)
344 {
345   if (argc < 3) { di<<"Donner un nom de SHAPE (SHELL ou FACE) + un nom de RESULTAT"<<"\n"; return 1 /* Error */; }
346   Standard_CString arg1 = argv[1];
347   Standard_CString arg2 = argv[2];
348   TopoDS_Shape Shape = DBRep::Get(arg1);
349   if (Shape.IsNull()) { di<<"Shape unknown : "<<arg1<<"\n"; return 1 /* Error */; }
350
351   Standard_Boolean rebuild = Standard_False;
352
353   Handle(ShapeFix_Face) STF = new ShapeFix_Face;
354 //  Options ?
355   Standard_Integer i; // svv Jan11 2000 : porting on DEC
356   for (i = 3; i < argc; i ++) {
357     Standard_Boolean valopt = Standard_True;
358     char opt = argv[i][0];
359     if (opt == '+')   opt = argv[i][1];
360     if (opt == '-') { opt = argv[i][1]; valopt = Standard_False; }
361     //cout<<(valopt ? ".." : ".. NO");
362     if (!valopt) {
363       di<<".. NO";
364     } else {
365       di<<"..";
366     }
367
368     if (opt == 'R') { di<<" REBUILD-ANYWAY .."; rebuild = valopt; }
369     if (opt == 'd') { di<<" fix-dgnr .."; STF->FixWireTool()->FixDegeneratedMode() = valopt; }
370     if (opt == 'r') { di<<" fix-reorder-wire .."; STF->FixWireTool()->FixReorderMode()    = valopt; }
371     if (opt == 'k') {
372     }
373   }
374
375   TopoDS_Face  face;
376   ShapeBuild_ReShape resh;
377
378   Standard_Integer nbf = 0, nbfc = 0;
379   for (TopExp_Explorer EF (Shape,TopAbs_FACE); EF.More(); EF.Next()) {
380     TopoDS_Face F = TopoDS::Face (EF.Current());    face = F;
381     nbf ++;
382     Standard_Boolean newface = Standard_False;
383 //    on va voir si ShapeTool_Face trouve qqchose a redire
384 //:sw    ShapeTool_Wire STW;
385 //:sw    STW.SetFace (F);
386
387     STF->Init (F);  // qui fait tout
388     STF->Perform();
389     face = STF->Face();
390     newface = STF->Status(ShapeExtend_DONE) || rebuild;
391     if (newface) { nbfc ++; resh.Replace (F,face); }
392   }
393   if (nbfc > 0) {
394     di<<"Faces reprises par ShapeFix_Face : "<<nbfc<<"\n";
395     DBRep::Set (arg2,resh.Apply (Shape,TopAbs_FACE,2));
396     return 0; // Done
397   }
398   else di<<"ShapeFix_Face n a rien trouve a redire"<<"\n";
399   return 0;
400 }
401
402
403 //=======================================================================
404 //function : fixshape
405 //purpose  : 
406 //=======================================================================
407
408 static Standard_Integer fixshape (Draw_Interpretor& di, Standard_Integer argc, const char** argv)
409 {
410   Handle(ShapeExtend_MsgRegistrator) msg = new ShapeExtend_MsgRegistrator;
411   Handle(ShapeFix_Shape) sfs = new ShapeFix_Shape;
412   sfs->SetMsgRegistrator ( msg );
413   
414   Standard_CString res = 0;
415   Standard_Integer par = 0, mess=0;
416   for ( Standard_Integer i=1; i < argc; i++ )
417   {
418     if (strlen(argv[i]) == 2 &&
419       (argv[i][0] == '-' || argv[i][0] == '+' || argv[i][0] == '*'))
420     {
421       Standard_Integer val = ( argv[i][0] == '-' ? 0 : argv[i][0] == '+' ? 1 : -1 );
422       switch ( argv[i][1] ) {
423       case 'l': sfs->FixWireTool()->FixLackingMode()          = val; break;
424       case 'o': sfs->FixFaceTool()->FixOrientationMode()      = val; break;
425       case 'h': sfs->FixWireTool()->FixShiftedMode()          = val; break;
426       case 'm': sfs->FixFaceTool()->FixMissingSeamMode()      = val; break;
427       case 'd': sfs->FixWireTool()->FixDegeneratedMode()      = val; break;
428       case 's': sfs->FixWireTool()->FixSmallMode()            = val; break;
429       case 'i': sfs->FixWireTool()->FixSelfIntersectionMode() = val; break;
430       case 'n': sfs->FixWireTool()->FixNotchedEdgesMode()     = val; break;
431       case '?': mess                                          = val; break;
432       }
433       continue;
434     }
435     else if (!strcmp(argv[i], "-maxtaila"))
436     {
437       if (++i >= argc)
438       {
439         break;
440       }
441
442       sfs->FixWireTool()->SetMaxTailAngle(Draw::Atof(argv[i]) * (M_PI / 180));
443     }
444     else if (!strcmp(argv[i], "-maxtailw"))
445     {
446       if (++i >= argc)
447       {
448         break;
449       }
450
451       sfs->FixWireTool()->SetMaxTailWidth(Draw::Atof(argv[i]));
452       sfs->FixWireTool()->FixTailMode() = 1;
453     }
454     else
455     {
456       switch ( par ) {
457       case 0: res = argv[i];                       break;
458       case 1: {
459         TopoDS_Shape initShape =  DBRep::Get(argv[i]);
460         if(initShape.IsNull()) continue;
461         sfs->Init ( initShape );
462       } break;
463       case 2: sfs->SetPrecision   (Draw::Atof(argv[i])); break;
464       case 3: sfs->SetMaxTolerance(Draw::Atof(argv[i])); break;
465       }
466     }
467     par++;
468   }
469
470   if ( par <2 ) {
471     di << "Use: " << argv[0] << " result shape [tolerance [max_tolerance]] [switches]\n"
472       "[-maxtaila <degrees>] [-maxtailw <width>]" << "\n";
473     di << "Switches allow to tune parameters of ShapeFix" << "\n"; 
474     di << "The following syntax is used: <symbol><parameter>" << "\n"; 
475     di << "- symbol may be - to set parameter off, + to set on or * to set default" << "\n"; 
476     di << "- parameters are identified by letters:" << "\n"; 
477     di << "  l - FixLackingMode" << "\n"; 
478     di << "  o - FixOrientationMode" << "\n"; 
479     di << "  h - FixShiftedMode" << "\n"; 
480     di << "  m - FixMissingSeamMode" << "\n"; 
481     di << "  d - FixDegeneratedMode" << "\n"; 
482     di << "  s - FixSmallMode" << "\n"; 
483     di << "  i - FixSelfIntersectionMode" << "\n"; 
484     di << "  n - FixNotchedEdgesMode" << "\n"; 
485     di << "For enhanced message output, use switch '+?'" << "\n"; 
486     return 1;
487   }
488
489   Handle(Draw_ProgressIndicator) aProgress = new Draw_ProgressIndicator (di, 1);
490   sfs->Perform (aProgress);
491   DBRep::Set (res,sfs->Shape());
492
493   if ( mess ) 
494   {
495     TColStd_DataMapOfAsciiStringInteger aMapOfNumberOfFixes;
496     Standard_SStream aSStream;
497     TopoDS_Compound aCompound;
498     BRep_Builder aBuilder;
499     aBuilder.MakeCompound (aCompound);
500     const ShapeExtend_DataMapOfShapeListOfMsg &map = msg->MapShape();
501     // Counting the number of each type of fixes. If the switch '*?' store all modified shapes in compound.
502     for ( ShapeExtend_DataMapIteratorOfDataMapOfShapeListOfMsg it ( map ); it.More(); it.Next() )
503     {
504       for ( Message_ListIteratorOfListOfMsg iter ( it.Value() ); iter.More(); iter.Next() )
505       {
506         if ( aMapOfNumberOfFixes.IsBound ( iter.Value().Value() ) )
507         {
508           aMapOfNumberOfFixes ( iter.Value().Value() )++;
509         }
510         else
511         {
512           aMapOfNumberOfFixes.Bind ( iter.Value().Value(), 1 );
513         }
514       }
515       if ( mess < 0 )
516       {
517         aBuilder.Add ( aCompound, it.Key() );
518       }
519     }
520     
521     aSStream << " Fix" << setw (58) << "Count\n";
522     aSStream << " ------------------------------------------------------------\n";
523     for ( TColStd_DataMapIteratorOfDataMapOfAsciiStringInteger anIter ( aMapOfNumberOfFixes ); anIter.More(); anIter.Next() )
524     {
525       aSStream << " " << anIter.Key() << setw ( 60 - anIter.Key().Length() ) << anIter.Value() << "\n";
526     }
527     aSStream << " ------------------------------------------------------------\n";
528     di << aSStream;
529
530     if ( mess < 0 )
531     {
532       char buff[256];
533       Sprintf ( buff, "%s_%s", res, "m" );
534       di << " Modified shapes saved in compound: " << buff;
535       DBRep::Set (buff, aCompound);
536     }
537   }
538   
539   return 0; // Done
540 }
541
542 //=======================================================================
543 //function : fixgaps
544 //purpose  : 
545 //=======================================================================
546
547 Standard_Integer fixgaps(Draw_Interpretor& di, Standard_Integer n, const char** a)
548 {
549   if (n < 3) return 1;
550   
551   TopoDS_Shape S = DBRep::Get(a[2]);
552   if (S.IsNull()) {
553     di << " Shape is null" << "\n";
554     return 1;
555   }
556
557   Handle(ShapeFix_Wireframe) SFWF = new ShapeFix_Wireframe(S);
558   Standard_Real prec = ( n >3 ? Draw::Atof(a[3]) : 0. );
559   SFWF->SetPrecision(prec);
560   if ( SFWF->FixWireGaps() ) {
561     DBRep::Set(a[1],SFWF->Shape());
562     di<<" Wireframe gaps fixed on shape"<<"\n";
563   }
564
565   return 0;
566 }
567
568 //=======================================================================
569 //function : fixsmall
570 //purpose  : 
571 //=======================================================================
572
573 Standard_Integer fixsmall(Draw_Interpretor& di, Standard_Integer n, const char** a)
574 {
575   if (n < 3) return 1;
576   
577   TopoDS_Shape S = DBRep::Get(a[2]);
578   if (S.IsNull()) {
579     di << " Shape is null" << "\n";
580     return 1;
581   }
582
583   Standard_Real prec = (n == 4)? Draw::Atof(a[3]) : 1.;
584   ShapeFix_Wireframe SFWF(S);
585   SFWF.SetPrecision(prec);
586   
587   if (SFWF.FixSmallEdges()) {
588     DBRep::Set(a[1],SFWF.Shape());
589     di<<" Small edges fixed on shape"<<"\n";
590   }
591
592   return 0;
593 }
594
595 //=======================================================================
596 //function : fixsmalledges
597 //purpose  : 
598 //=======================================================================
599
600 static Standard_Integer fixsmalledges(Draw_Interpretor& di, Standard_Integer n, const char** a)
601 {
602   if( n < 3) {
603     di<<"Invalid number of arguments"<<"\n";
604     return 1;
605   }
606   TopoDS_Shape Sh = DBRep::Get(a[2]);
607  
608   Standard_Integer k = 3;
609   Standard_Real tol = 100000;
610   Standard_Integer mode = 2;
611   Standard_Real tolang = M_PI/2;
612   if(n > k) 
613     tol = Draw::Atof(a[k++]);
614   
615   if(n > k) 
616     mode=  Draw::Atoi(a[k++]);
617    
618   if(n > k) 
619     tolang = Draw::Atof(a[k++]);
620      
621   Handle(ShapeFix_Wireframe) aSfwr = new ShapeFix_Wireframe();
622   Handle(ShapeBuild_ReShape) aReShape = new ShapeBuild_ReShape;
623   aSfwr->SetContext(aReShape);
624   aSfwr->Load(Sh);
625   aSfwr->SetPrecision(tol);
626   Standard_Boolean aModeDrop = Standard_True;
627   if(mode == 2) 
628     aModeDrop = Standard_False;
629    
630   TopTools_MapOfShape theSmallEdges, theMultyEdges;
631   TopTools_DataMapOfShapeListOfShape theEdgeToFaces,theFaceWithSmall;
632   aSfwr->CheckSmallEdges(theSmallEdges,theEdgeToFaces,theFaceWithSmall, theMultyEdges);
633   aSfwr->MergeSmallEdges (theSmallEdges,theEdgeToFaces,theFaceWithSmall, theMultyEdges, aModeDrop,tolang);
634    //aSfwr->FixSmallEdges(); 
635   TopoDS_Shape resShape =  aSfwr->Shape();;
636   DBRep::Set ( a[1], resShape );
637   return 0;
638 }
639
640 //=======================================================================
641 //function : checkoverlapedges
642 //purpose  : 
643 //=======================================================================
644
645 static Standard_Integer checkoverlapedges(Draw_Interpretor& di, Standard_Integer n, const char** a)
646 {
647    if( n < 3) {
648      di<<"Invalid number of arguments"<<"\n";
649      return 1;
650    }
651    TopoDS_Shape Sh1 = DBRep::Get(a[1]);
652    TopoDS_Shape Sh2 = DBRep::Get(a[2]);
653    if(Sh1.IsNull() || Sh2.IsNull()) {
654      di<<"Invalid arguments"<<"\n";
655      return 1;
656    }
657    TopoDS_Edge e1 = TopoDS::Edge(Sh1);
658    TopoDS_Edge e2 = TopoDS::Edge(Sh2);
659    if(e1.IsNull() || e2.IsNull()) {
660      di<<"Invalid type of arguments"<<"\n";
661      return 1;
662    }
663
664    if (BRep_Tool::Degenerated(e1))
665    {
666      di << a[1] << " is degenerated\n";
667      return 1;
668    }
669
670    if (BRep_Tool::Degenerated(e2))
671    {
672      di << a[2] << " is degenerated\n";
673      return 1;
674    }
675
676    Standard_Real aTol = Precision::Confusion();
677    Standard_Real aDistDomain = 0.0;
678    Standard_Integer k = 3;
679    if(k < n)
680      aTol = Draw::Atof(a[k++]);
681    if(k < n)
682      aDistDomain = Draw::Atof(a[k++]);
683    
684    ShapeAnalysis_Edge sae;
685    if(sae.CheckOverlapping(e1,e2,aTol,aDistDomain)) {
686      if(aDistDomain ==0.0)
687        di<<"Edges is overlaping comletly"<<"\n";
688      else {
689         di<<"Edges is overlaped"<<"\n";
690         di<<"with tolerance = "<<aTol<<"\n";
691         di<<"on segment length = "<<aDistDomain<<"\n";
692      }
693    }
694    else di<<"Edges is not overlaped"<<"\n";
695    return 0;
696 }
697
698 //=======================================================================
699 //function : checkfclass2d
700 //purpose  : 
701 //=======================================================================
702
703 static Standard_Integer checkfclass2d(Draw_Interpretor& di, Standard_Integer n, const char** a)
704 {
705   if( n < 4) {
706     di<<"Invalid number of arguments"<<"\n";
707     return 1;
708   }
709   TopoDS_Shape Sh1 = DBRep::Get(a[1]);
710   Standard_Real ucoord = Draw::Atof(a[2]);
711   Standard_Real vcoord = Draw::Atof(a[3]);
712   if(Sh1.IsNull() || Sh1.ShapeType()!= TopAbs_FACE) {
713     di<<"Invalid arguments"<<"\n";
714     return 1;
715   }
716   TopoDS_Face aFace = TopoDS::Face(Sh1);
717   gp_Pnt2d p2d(ucoord,vcoord);
718   BRepTopAdaptor_FClass2d f2d(aFace,Precision::Confusion());
719   TopAbs_State stat = f2d.Perform(p2d);
720   if(stat == TopAbs_OUT)
721     di<<"Point is OUT"<<"\n";
722   else if(stat == TopAbs_IN)
723     di<<"Point is IN"<<"\n";
724   else if(stat == TopAbs_ON)
725     di<<"Point is ON"<<"\n";
726   else
727     di<<"Point is UNKNOWN"<<"\n";
728   return 0;
729 }
730
731 static Standard_Integer connectedges(Draw_Interpretor& di, Standard_Integer n, const char** a)
732 {
733   if( n < 3) {
734     di<<"Invalid number of arguments. Should be : result shape [toler shared]"<<"\n";
735     return 1;
736   }
737   TopoDS_Shape aSh1 = DBRep::Get(a[2]);
738   if(aSh1.IsNull()) {
739     di<<"Shape is null"<<"\n";
740     return 1;
741   }
742   Standard_Real aTol = Precision::Confusion();
743   if( n > 3)
744     aTol = Draw::Atof(a[3]);
745   
746   Standard_Boolean shared = Standard_True;
747   if( n > 4)
748     shared = (Draw::Atoi(a[4]) == 1);
749   TopExp_Explorer aExpE(aSh1,TopAbs_EDGE);
750   Handle(TopTools_HSequenceOfShape) aSeqEdges = new TopTools_HSequenceOfShape;
751   Handle(TopTools_HSequenceOfShape) aSeqWires = new TopTools_HSequenceOfShape;
752   TopTools_IndexedMapOfShape aMapEdges;
753   for( ; aExpE.More(); aExpE.Next())
754   {
755     aSeqEdges->Append(aExpE.Current());
756     aMapEdges.Add(aExpE.Current());
757   }
758   
759   ShapeAnalysis_FreeBounds::ConnectEdgesToWires(aSeqEdges,aTol,shared,aSeqWires );
760   TopoDS_Compound aComp;
761   BRep_Builder aB;
762   aB.MakeCompound(aComp);
763   Standard_Integer i = 1;
764   for( ; i <= aSeqWires->Length() ; i++)
765   {
766     TopoDS_Shape aW = aSeqWires->Value(i);
767     di<<"Wire - "<<i<<" : "<<"\n";
768     
769     TopExp_Explorer aExp1(aW, TopAbs_EDGE);
770     for( ; aExp1.More(); aExp1.Next())
771     {
772       if(shared)
773       {
774         Standard_Integer ind = aMapEdges.FindIndex(aExp1.Current());
775         di<<ind<<" ";
776       }
777        else
778       {
779         TopoDS_Vertex aV1, aV2;
780         TopExp::Vertices(TopoDS::Edge(aExp1.Current()), aV1,aV2);
781         gp_Pnt aP = BRep_Tool::Pnt(aV1);
782         di<<aP.X()<<" "<<aP.Y()<<" "<<aP.Z()<<"\n";
783       }
784     }
785    
786     di<<"\n";
787     aB.Add( aComp,aSeqWires->Value(i));
788   }
789   DBRep::Set(a[1],aComp);
790   return 0;
791   
792 }
793
794 //=======================================================================
795 //function : InitCommands
796 //purpose  : 
797 //=======================================================================
798
799  void SWDRAW_ShapeFix::InitCommands(Draw_Interpretor& theCommands) 
800 {
801   static Standard_Integer initactor = 0;
802   if (initactor) return;  initactor = 1;
803   
804   Standard_CString g = SWDRAW::GroupName();
805   
806   theCommands.Add ("edgesameparam","nom shape draw ou * [+ option force]",
807                    __FILE__,edgesameparam,g);
808   theCommands.Add ("settolerance","shape [mode=v-e-f-a] val(fix value) or tolmin tolmax",
809                    __FILE__,settolerance,g);
810   theCommands.Add ("stwire","stwire tout court pour help complet",
811                    __FILE__,stwire,g);
812   theCommands.Add ("reface","shape result : controle sens wire",
813                    __FILE__,reface,g);
814   theCommands.Add ("fixshape",
815 "res shape [preci [maxpreci]] [{switches}]\n"
816 "  [-maxtaila <degrees>] [-maxtailw <width>]",
817                    __FILE__,fixshape,g);
818 //  theCommands.Add ("testfill","result edge1 edge2",
819 //                 __FILE__,XSHAPE_testfill,g);
820   theCommands.Add ("fixwgaps","result shape [toler=0]",
821                    __FILE__,fixgaps,g);
822   theCommands.Add ("fixsmall","result shape [toler=1.]",
823                    __FILE__,fixsmall,g);
824   theCommands.Add ("fixsmalledges","result shape [toler mode amxangle]",
825                    __FILE__,fixsmalledges,g);
826   theCommands.Add ("checkoverlapedges","edge1 edge2 [toler domaindist]",
827                    __FILE__,checkoverlapedges,g);
828   theCommands.Add ("checkfclass2d","face ucoord vcoord",
829                    __FILE__,checkfclass2d,g);
830   theCommands.Add ("connectedges","res shape [toler shared]",
831                    __FILE__,connectedges,g);
832   
833 }
834