0026118: Implement FastSewing algorithm
[occt.git] / src / BRepTest / BRepTest_SurfaceCommands.cxx
1 // Created on: 1993-07-22
2 // Created by: Remi LEQUETTE
3 // Copyright (c) 1993-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 <stdio.h>
18 #include <BRepTest.hxx>
19 #include <GeometryTest.hxx>
20
21 #include <DrawTrSurf.hxx>
22 #include <DBRep.hxx>
23 #include <Draw_Interpretor.hxx>
24 #include <Draw_Appli.hxx>
25
26 #include <BRep_Builder.hxx>
27 #include <BRep_Tool.hxx>
28 #include <BRepLib.hxx>
29 #include <BRepTools_Quilt.hxx>
30 #include <BRepAdaptor_Curve.hxx>
31 #include <BRepBuilderAPI_MakeFace.hxx>
32 #include <BRepBuilderAPI_MakeShell.hxx>
33 #include <BRepBuilderAPI.hxx>
34 #include <BRepBuilderAPI_Sewing.hxx>
35 #include <BRepOffsetAPI_FindContigousEdges.hxx>
36 #include <TopExp_Explorer.hxx>
37 #include <TopoDS.hxx>
38 #include <TopoDS_Face.hxx>
39 #include <Geom_Surface.hxx>
40 #include <Geom2d_TrimmedCurve.hxx>
41 #include <TopTools_ListOfShape.hxx>
42 #include <TopTools_SequenceOfShape.hxx>
43 #include <Precision.hxx>
44 #include <Draw_ProgressIndicator.hxx>
45 #include <NCollection_Vector.hxx>
46 #include <BRepBuilderAPI_FastSewing.hxx>
47
48 #ifdef _WIN32
49 //#define strcasecmp strcmp Already defined
50 #include <stdio.h>
51 #endif
52
53 //-----------------------------------------------------------------------
54 // suppressarg : suppress a[d],modifie na--
55 //-----------------------------------------------------------------------
56 static void suppressarg(Standard_Integer& na,const char** a,const Standard_Integer d) 
57 {
58   for(Standard_Integer i=d;i<na;i++) {
59     a[i]=a[i+1];
60     a[i+1]=NULL;
61   }
62   na--;
63 }
64
65
66 //=======================================================================
67 // mkface
68 //=======================================================================
69
70 static Standard_Integer mkface(Draw_Interpretor& , Standard_Integer n, const char** a)
71 {
72   if (n < 3) return 1;
73   
74   Handle(Geom_Surface) S = DrawTrSurf::GetSurface(a[2]);
75   if (S.IsNull()) {
76     cout << a[2] << " is not a surface" << endl;
77     return 1;
78   }
79   
80   Standard_Boolean mkface = a[0][2] == 'f';
81   TopoDS_Shape res;
82
83   Standard_Boolean Segment = Standard_False;
84   if ( !mkface && (n == 4 || n == 8)) {
85     Segment = !strcmp(a[n-1],"1");
86     n--;
87   }
88
89   if (n == 3) {
90     if (mkface)
91       res = BRepBuilderAPI_MakeFace(S, Precision::Confusion());
92     else
93       res = BRepBuilderAPI_MakeShell(S,Segment);
94   }
95   else if (n <= 5) {
96     if (!mkface) return 1;
97     Standard_Boolean orient = (n  == 4);
98     TopoDS_Shape W = DBRep::Get(a[3],TopAbs_WIRE);
99     if (W.IsNull()) return 1;
100     res = BRepBuilderAPI_MakeFace(S,TopoDS::Wire(W),orient);
101   }
102   else {
103     if (mkface)
104       res = BRepBuilderAPI_MakeFace(S,Draw::Atof(a[3]),Draw::Atof(a[4]),Draw::Atof(a[5]),Draw::Atof(a[6]),Precision::Confusion());
105     else
106       res = BRepBuilderAPI_MakeShell(S,Draw::Atof(a[3]),Draw::Atof(a[4]),Draw::Atof(a[5]),Draw::Atof(a[6]),
107                               Segment);
108   }
109   
110   DBRep::Set(a[1],res);
111   return 0;
112 }
113
114 //=======================================================================
115 // quilt
116 //=======================================================================
117
118 static Standard_Integer quilt(Draw_Interpretor& , Standard_Integer n, const char** a)
119 {
120   if (n < 4) return 1;
121   BRepTools_Quilt Q;
122
123   Standard_Integer i = 2;
124   while (i < n) {
125     TopoDS_Shape S = DBRep::Get(a[i]);
126     if (!S.IsNull()) {
127       if (S.ShapeType() == TopAbs_EDGE) {
128         if (i+1 < n) {
129           TopoDS_Shape E = DBRep::Get(a[i+1]);
130           if (!E.IsNull()) {
131             if (E.ShapeType() == TopAbs_EDGE) {
132               i++;
133               Q.Bind(TopoDS::Edge(S),TopoDS::Edge(E));
134             }
135           }
136         }
137       }
138       if (S.ShapeType() == TopAbs_VERTEX) {
139         if (i+1 < n) {
140           TopoDS_Shape E = DBRep::Get(a[i+1]);
141           if (!E.IsNull()) {
142             if (E.ShapeType() == TopAbs_VERTEX) {
143               i++;
144               Q.Bind(TopoDS::Vertex(S),TopoDS::Vertex(E));
145             }
146           }
147         }
148       }
149       else {
150         Q.Add(S);
151       }
152     }
153     i++;
154   }
155
156   DBRep::Set(a[1],Q.Shells());
157   return 0;
158 }
159
160
161 //=======================================================================
162 // mksurface
163 //=======================================================================
164
165 static Standard_Integer mksurface(Draw_Interpretor& , Standard_Integer n, const char** a)
166 {
167   if (n < 3) return 1;
168
169   TopoDS_Shape S = DBRep::Get(a[2],TopAbs_FACE);
170   if (S.IsNull()) return 1;
171   TopLoc_Location L;
172   Handle(Geom_Surface) C = BRep_Tool::Surface(TopoDS::Face(S),L);
173
174
175   DrawTrSurf::Set(a[1],C->Transformed(L.Transformation()));
176   return 0;
177 }
178
179 //=======================================================================
180 // mkplane
181 //=======================================================================
182
183 static Standard_Integer mkplane(Draw_Interpretor& , Standard_Integer n, const char** a)
184 {
185   if (n < 3) return 1;
186
187   TopoDS_Shape S = DBRep::Get(a[2],TopAbs_WIRE);
188   if (S.IsNull()) return 1;
189
190   Standard_Boolean OnlyPlane = Standard_False;
191   if ( n == 4) {
192     OnlyPlane =  !strcmp(a[3],"1");
193   }
194
195   TopoDS_Face F = BRepBuilderAPI_MakeFace(TopoDS::Wire(S), OnlyPlane);
196
197   DBRep::Set(a[1],F);
198   return 0;
199 }
200
201 //=======================================================================
202 // pcurve
203 //=======================================================================
204 Standard_IMPORT Draw_Color DrawTrSurf_CurveColor(const Draw_Color col);
205 Standard_IMPORT void DBRep_WriteColorOrientation ();
206 Standard_IMPORT Draw_Color DBRep_ColorOrientation (const TopAbs_Orientation Or);
207
208 static Standard_Integer pcurve(Draw_Interpretor& , Standard_Integer n, const char** a)
209 {
210   Standard_Boolean mute = Standard_False;
211   for(Standard_Integer ia=1;ia<n;ia++) {
212     if (!strcasecmp(a[ia],"-mute")) {
213       suppressarg(n,a,ia);
214       mute = Standard_True;
215     }
216   }
217
218   if (n == 2) {
219     // pcurves of a face
220     TopoDS_Shape S = DBRep::Get(a[1],TopAbs_FACE);
221     if (S.IsNull()) return 1;
222
223     if (!mute) DBRep_WriteColorOrientation();
224     Draw_Color col, savecol = DrawTrSurf_CurveColor(Draw_rouge);
225
226     char* name = new char[100];
227     Standard_Real f,l;
228     S.Orientation(TopAbs_FORWARD);
229     TopExp_Explorer ex(S,TopAbs_EDGE);
230     for (Standard_Integer i=1; ex.More(); ex.Next(), i++) {
231       const Handle(Geom2d_Curve) c = BRep_Tool::CurveOnSurface
232         (TopoDS::Edge(ex.Current()),TopoDS::Face(S),f,l);
233       if ( c.IsNull() ) {
234         cout << "Error: Edge " << i << " does not have pcurve" << endl;
235         continue;
236       }
237       col = DBRep_ColorOrientation(ex.Current().Orientation());
238       DrawTrSurf_CurveColor(col);
239
240       Sprintf(name,"%s_%d",a[1],i);
241       DrawTrSurf::Set(name,new Geom2d_TrimmedCurve(c,f,l));
242     }
243     DrawTrSurf_CurveColor(savecol);
244
245   }
246   else if (n >= 4) {
247     TopoDS_Shape SE = DBRep::Get(a[2],TopAbs_EDGE);
248     if (SE.IsNull()) return 1;
249     TopoDS_Shape SF = DBRep::Get(a[3],TopAbs_FACE);
250     if (SF.IsNull()) return 1;
251
252     Draw_Color col, savecol = DrawTrSurf_CurveColor(Draw_rouge);
253     Standard_Real f,l;
254     const Handle(Geom2d_Curve) c = BRep_Tool::CurveOnSurface
255       (TopoDS::Edge(SE),TopoDS::Face(SF),f,l);
256
257     col = DBRep_ColorOrientation(SE.Orientation());
258     DrawTrSurf_CurveColor(col);
259     DrawTrSurf::Set(a[1],new Geom2d_TrimmedCurve(c,f,l));
260     DrawTrSurf_CurveColor(savecol);
261   }
262   else { 
263     return 1;
264   }
265     
266   return 0;
267 }
268
269 //=======================================================================
270 // sewing
271 //=======================================================================
272
273 static Standard_Integer sewing (Draw_Interpretor& theDi, 
274                                 Standard_Integer theArgc, const char** theArgv)
275 {
276   BRepBuilderAPI_Sewing aSewing;
277   Standard_Integer aPar = 1;
278   TopTools_SequenceOfShape aSeq;
279
280   Standard_Real aTol = 1.0e-06;
281   Standard_Boolean aSewingMode = Standard_True;
282   Standard_Boolean anAnalysisMode = Standard_True;
283   Standard_Boolean aCuttingMode = Standard_True;
284   Standard_Boolean aNonManifoldMode = Standard_False;
285   Standard_Boolean aSameParameterMode = Standard_True;
286   Standard_Boolean aFloatingEdgesMode = Standard_False;
287   Standard_Boolean aFaceMode = Standard_True;
288   Standard_Boolean aSetMinTol = Standard_False;
289   Standard_Real aMinTol = 0.;
290   Standard_Real aMaxTol = Precision::Infinite();
291
292   for (Standard_Integer i = 2; i < theArgc; i++)
293   {
294     if (theArgv[i][0] == '-' || theArgv[i][0] == '+')
295     {
296       Standard_Boolean aVal = (theArgv[i][0] == '+' ? Standard_True : Standard_False);
297       switch (tolower(theArgv[i][1]))
298       {
299       case 'm':
300         {
301           if (tolower(theArgv[i][2]) == 'i' && i+1 < theArgc)
302           {
303             if (Draw::Atof (theArgv[i+1]))
304             {
305               aMinTol = Draw::Atof (theArgv[++i]);
306               aSetMinTol = Standard_True;
307             }
308             else
309             {
310               theDi << "Error! min tolerance can't possess the null value" << "\n";
311               return (1);
312             }
313           }
314           if (tolower(theArgv[i][2]) == 'a' && i+1 < theArgc)
315           {
316             if (Draw::Atof (theArgv[i+1]))
317               aMaxTol = Draw::Atof (theArgv[++i]);
318             else
319             {
320               theDi << "Error! max tolerance can't possess the null value" << "\n";
321               return (1);
322             }
323           }
324         }
325         break;
326       case 's': aSewingMode = aVal; break;
327       case 'a': anAnalysisMode = aVal; break;
328       case 'c': aCuttingMode = aVal; break;
329       case 'n': aNonManifoldMode = aVal; break;
330       case 'p': aSameParameterMode = aVal; break;
331       case 'e': aFloatingEdgesMode = aVal; break;
332       case 'f': aFaceMode = aVal; break;
333       }
334     }
335     else
336     {
337       TopoDS_Shape aShape = DBRep::Get (theArgv[i]);
338       if (!aShape.IsNull())
339       {
340         aSeq.Append (aShape);
341         aPar++;
342       }
343       else
344       {
345         if (Draw::Atof (theArgv[i]))
346           aTol = Draw::Atof (theArgv[i]);
347       }
348     }
349   }
350    
351   if (aPar < 2)
352   {
353     theDi << "Use: " << theArgv[0] << " result [tolerance] shape1 shape2 ... [min tolerance] [max tolerance] [switches]" << "\n";
354     theDi << "To set user's value of min/max tolerances the following syntax is used: +<parameter> <value>" << "\n";
355     theDi << "- parameters are identified by letters:" << "\n";
356     theDi << "  mint - min tolerance" << "\n";
357     theDi << "  maxt - max tolerance" << "\n";
358     theDi << "Switches allow to tune other parameters of Sewing" << "\n";
359     theDi << "The following syntax is used: <symbol><parameter>" << "\n";
360     theDi << "- symbol may be - to set parameter off, + to set on" << "\n";
361     theDi << "- parameters are identified by letters:" << "\n";
362     theDi << "  s - mode for creating sewed shape" << "\n";
363     theDi << "  a - mode for analysis of input shapes" << "\n";
364     theDi << "  c - mode for cutting of free edges" << "\n";
365     theDi << "  n - mode for non manifold processing" << "\n";
366     theDi << "  p - mode for same parameter processing for edges" << "\n";
367     theDi << "  e - mode for sewing floating edges" << "\n";
368     theDi << "  f - mode for sewing faces" << "\n";
369     return (1);
370   }
371     
372   if (!aSetMinTol)
373     aMinTol = aTol*1e-4;
374   if (aTol < Precision::Confusion())
375     aTol = Precision::Confusion();
376   if (aMinTol < Precision::Confusion())
377     aMinTol = Precision::Confusion();
378   if (aMinTol > aTol)
379   {
380     theDi << "Error! min tolerance can't exceed working tolerance" << "\n";
381     return (1);
382   }
383   if (aMaxTol < aTol)
384   {
385     theDi << "Error! max tolerance can't be less than working tolerance" << "\n";
386     return (1);
387   }
388
389   aSewing.Init (aTol, aSewingMode, anAnalysisMode, aCuttingMode, aNonManifoldMode);
390   aSewing.SetSameParameterMode (aSameParameterMode);
391   aSewing.SetFloatingEdgesMode (aFloatingEdgesMode);
392   aSewing.SetFaceMode (aFaceMode);
393   aSewing.SetMinTolerance (aMinTol);
394   aSewing.SetMaxTolerance (aMaxTol);
395
396   for (Standard_Integer i = 1; i <= aSeq.Length(); i++)
397     aSewing.Add(aSeq.Value(i));
398   
399   Handle(Draw_ProgressIndicator) aProgress = new Draw_ProgressIndicator (theDi, 1);
400   aSewing.Perform (aProgress);
401   aSewing.Dump();
402
403   const TopoDS_Shape& aRes = aSewing.SewedShape();
404   if (!aRes.IsNull())
405     DBRep::Set(theArgv[1], aRes);
406   return 0;
407 }
408
409 //=======================================================================
410 //function : fastsewing
411 //purpose  : 
412 //=======================================================================
413 Standard_Integer fastsewing (Draw_Interpretor& theDI, 
414                             Standard_Integer theNArg, 
415                             const char** theArgVal)
416 {
417   if(theNArg < 3)
418   {
419     //                0         1       2     3         4
420     theDI << "Use: fastsewing result [-tol <value>] <list_of_faces>\n";
421     return 1;
422   }
423
424   BRepBuilderAPI_FastSewing aFS;
425
426   Standard_Integer aStartIndex = 2;
427
428   if(!strcmp(theArgVal[aStartIndex], "-tol"))
429   {
430     aFS.SetTolerance(Draw::Atof (theArgVal[aStartIndex+1]));
431     aStartIndex = 4;
432   }
433
434   for(Standard_Integer i = aStartIndex; i < theNArg; i++)
435   {
436     TopoDS_Shape aS = DBRep::Get(theArgVal[i]);
437     
438     if(!aFS.Add(aS))
439     {
440       theDI << "Face is not added. See statuses.\n";
441     }
442   }
443
444   BRepBuilderAPI_FastSewing::FS_VARStatuses aStatus = aFS.GetStatuses();
445
446   if(aStatus)
447   {
448     theDI << "Error: There are some problems while adding (" <<
449                         (static_cast<Standard_Integer>(aStatus)) << ")\n";
450     aFS.GetStatuses(&cout);
451   }
452
453   aFS.Perform();
454
455   aStatus = aFS.GetStatuses();
456
457   if(aStatus)
458   {
459     theDI << "Error: There are some problems while performing (" <<
460                         (static_cast<Standard_Integer>(aStatus)) << ")\n";
461     aFS.GetStatuses(&cout);
462   }
463
464   DBRep::Set(theArgVal[1], aFS.GetResult());
465
466   return 0;
467 }
468
469 //=======================================================================
470 // continuity
471 //=======================================================================
472
473 static Standard_Integer continuity (Draw_Interpretor& , 
474                                     Standard_Integer n, const char** a)
475 {
476   if (n < 2) return (1);
477
478   BRepOffsetAPI_FindContigousEdges aFind;
479
480   TopoDS_Shape sh = DBRep::Get(a[1]);
481   Standard_Integer i=1;
482   if (sh.IsNull()) {
483     if (n < 3) return (1);
484     Standard_Real tol = Draw::Atof(a[1]);
485     aFind.Init(tol, Standard_False);
486     i = 2;
487   }
488   
489   while (i < n) {
490     sh = DBRep::Get(a[i]);
491     aFind.Add(sh);
492     i++;
493   }
494
495   aFind.Perform();
496   aFind.Dump();
497
498   return 0;
499 }
500
501 //=======================================================================
502 // encoderegularity
503 //=======================================================================
504 static Standard_Integer encoderegularity (Draw_Interpretor& , 
505                                           Standard_Integer n, const char** a)
506
507 {
508   if (n < 2) return 1;
509   TopoDS_Shape sh = DBRep::Get(a[1]);
510   if (sh.IsNull()) return 1;
511   if (n==2) 
512     BRepLib::EncodeRegularity(sh);
513   else {
514     Standard_Real Tol = Draw::Atof(a[2]);
515     Tol *= M_PI/180.;
516     BRepLib::EncodeRegularity(sh, Tol);
517   }
518   return 0;
519 }
520
521
522 //=======================================================================
523 //function : SurfaceCommands
524 //purpose  : 
525 //=======================================================================
526
527 void  BRepTest::SurfaceCommands(Draw_Interpretor& theCommands)
528 {
529   static Standard_Boolean done = Standard_False;
530   if (done) return;
531   done = Standard_True;
532
533   DBRep::BasicCommands(theCommands);
534   GeometryTest::SurfaceCommands(theCommands);
535
536   const char* g = "Surface topology commands";
537
538   theCommands.Add("mkface",
539                   "mkface facename surfacename [ufirst ulast vfirst vlast] [wire [norient]]",
540                   __FILE__,mkface,g);
541
542   theCommands.Add("mkshell",
543                   "mkshell shellname surfacename [ufirst ulast vfirst vlast] [segment 0/1]",
544                   __FILE__,mkface,g);
545
546   theCommands.Add("quilt",
547                   "quilt compoundname shape1 edgeshape2  edgeshape1... shape2  edgeshape3 edgeshape1or2 ... shape3 ...",
548                   __FILE__,quilt,g);
549   
550   theCommands.Add("mksurface",
551                   "mksurface surfacename facename",
552                   __FILE__,mksurface,g);
553
554   theCommands.Add("mkplane",
555                   "mkplane facename wirename [OnlyPlane 0/1]",
556                   __FILE__,mkplane,g);
557
558   theCommands.Add("pcurve",
559                   "pcurve [name edgename] facename",
560                   __FILE__,pcurve,g);
561
562   theCommands.Add("sewing",
563                   "sewing result [tolerance] shape1 shape2 ... [min tolerance] [max tolerance] [switches]",
564                   __FILE__,sewing, g);
565
566   theCommands.Add("continuity", 
567                   "continuity [tolerance] shape1 shape2 ...",
568                   __FILE__,continuity, g);
569
570   theCommands.Add("encoderegularity", 
571                   "encoderegularity shape [tolerance (in degree)]",
572                   __FILE__,encoderegularity, g);
573
574   theCommands.Add ("fastsewing", "fastsewing result [-tol <value>] <list_of_faces>", 
575                                                 __FILE__, fastsewing, g);
576 }
577