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