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