0026687: SIGSEGV in BRepBuilderAPI_MakeFace
[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& theDI, 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   BRepBuilderAPI_MakeFace aMF(TopoDS::Wire(S), OnlyPlane);
196
197   switch(aMF.Error())
198   {
199   case BRepBuilderAPI_FaceDone:
200     DBRep::Set(a[1],aMF.Face());
201     break;
202   case BRepLib_NoFace:
203     theDI << "Error. mkplane has been finished with \"No Face\" status.\n";
204     break;
205   case BRepLib_NotPlanar:
206     theDI << "Error. mkplane has been finished with \"Not Planar\" status.\n";
207     break;
208   case BRepLib_CurveProjectionFailed:
209     theDI << "Error. mkplane has been finished with \"Fail in projection curve\" status.\n";
210     break;
211   case BRepLib_ParametersOutOfRange:
212     theDI << "Error. mkplane has been finished with \"Parameters are out of range\" status.\n";
213     break;
214   default:
215     theDI << "Error. Undefined status. Please check the code.\n";
216     break;
217   }
218
219   return 0;
220 }
221
222 //=======================================================================
223 // pcurve
224 //=======================================================================
225 Standard_IMPORT Draw_Color DrawTrSurf_CurveColor(const Draw_Color col);
226 Standard_IMPORT void DBRep_WriteColorOrientation ();
227 Standard_IMPORT Draw_Color DBRep_ColorOrientation (const TopAbs_Orientation Or);
228
229 static Standard_Integer pcurve(Draw_Interpretor& , Standard_Integer n, const char** a)
230 {
231   Standard_Boolean mute = Standard_False;
232   for(Standard_Integer ia=1;ia<n;ia++) {
233     if (!strcasecmp(a[ia],"-mute")) {
234       suppressarg(n,a,ia);
235       mute = Standard_True;
236     }
237   }
238
239   if (n == 2) {
240     // pcurves of a face
241     TopoDS_Shape S = DBRep::Get(a[1],TopAbs_FACE);
242     if (S.IsNull()) return 1;
243
244     if (!mute) DBRep_WriteColorOrientation();
245     Draw_Color col, savecol = DrawTrSurf_CurveColor(Draw_rouge);
246
247     char* name = new char[100];
248     Standard_Real f,l;
249     S.Orientation(TopAbs_FORWARD);
250     TopExp_Explorer ex(S,TopAbs_EDGE);
251     for (Standard_Integer i=1; ex.More(); ex.Next(), i++) {
252       const Handle(Geom2d_Curve) c = BRep_Tool::CurveOnSurface
253         (TopoDS::Edge(ex.Current()),TopoDS::Face(S),f,l);
254       if ( c.IsNull() ) {
255         cout << "Error: Edge " << i << " does not have pcurve" << endl;
256         continue;
257       }
258       col = DBRep_ColorOrientation(ex.Current().Orientation());
259       DrawTrSurf_CurveColor(col);
260
261       Sprintf(name,"%s_%d",a[1],i);
262       DrawTrSurf::Set(name,new Geom2d_TrimmedCurve(c,f,l));
263     }
264     DrawTrSurf_CurveColor(savecol);
265
266   }
267   else if (n >= 4) {
268     TopoDS_Shape SE = DBRep::Get(a[2],TopAbs_EDGE);
269     if (SE.IsNull()) return 1;
270     TopoDS_Shape SF = DBRep::Get(a[3],TopAbs_FACE);
271     if (SF.IsNull()) return 1;
272
273     Draw_Color col, savecol = DrawTrSurf_CurveColor(Draw_rouge);
274     Standard_Real f,l;
275     const Handle(Geom2d_Curve) c = BRep_Tool::CurveOnSurface
276       (TopoDS::Edge(SE),TopoDS::Face(SF),f,l);
277
278     col = DBRep_ColorOrientation(SE.Orientation());
279     DrawTrSurf_CurveColor(col);
280     DrawTrSurf::Set(a[1],new Geom2d_TrimmedCurve(c,f,l));
281     DrawTrSurf_CurveColor(savecol);
282   }
283   else { 
284     return 1;
285   }
286     
287   return 0;
288 }
289
290 //=======================================================================
291 // sewing
292 //=======================================================================
293
294 static Standard_Integer sewing (Draw_Interpretor& theDi, 
295                                 Standard_Integer theArgc, const char** theArgv)
296 {
297   BRepBuilderAPI_Sewing aSewing;
298   Standard_Integer aPar = 1;
299   TopTools_SequenceOfShape aSeq;
300
301   Standard_Real aTol = 1.0e-06;
302   Standard_Boolean aSewingMode = Standard_True;
303   Standard_Boolean anAnalysisMode = Standard_True;
304   Standard_Boolean aCuttingMode = Standard_True;
305   Standard_Boolean aNonManifoldMode = Standard_False;
306   Standard_Boolean aSameParameterMode = Standard_True;
307   Standard_Boolean aFloatingEdgesMode = Standard_False;
308   Standard_Boolean aFaceMode = Standard_True;
309   Standard_Boolean aSetMinTol = Standard_False;
310   Standard_Real aMinTol = 0.;
311   Standard_Real aMaxTol = Precision::Infinite();
312
313   for (Standard_Integer i = 2; i < theArgc; i++)
314   {
315     if (theArgv[i][0] == '-' || theArgv[i][0] == '+')
316     {
317       Standard_Boolean aVal = (theArgv[i][0] == '+' ? Standard_True : Standard_False);
318       switch (tolower(theArgv[i][1]))
319       {
320       case 'm':
321         {
322           if (tolower(theArgv[i][2]) == 'i' && i+1 < theArgc)
323           {
324             if (Draw::Atof (theArgv[i+1]))
325             {
326               aMinTol = Draw::Atof (theArgv[++i]);
327               aSetMinTol = Standard_True;
328             }
329             else
330             {
331               theDi << "Error! min tolerance can't possess the null value" << "\n";
332               return (1);
333             }
334           }
335           if (tolower(theArgv[i][2]) == 'a' && i+1 < theArgc)
336           {
337             if (Draw::Atof (theArgv[i+1]))
338               aMaxTol = Draw::Atof (theArgv[++i]);
339             else
340             {
341               theDi << "Error! max tolerance can't possess the null value" << "\n";
342               return (1);
343             }
344           }
345         }
346         break;
347       case 's': aSewingMode = aVal; break;
348       case 'a': anAnalysisMode = aVal; break;
349       case 'c': aCuttingMode = aVal; break;
350       case 'n': aNonManifoldMode = aVal; break;
351       case 'p': aSameParameterMode = aVal; break;
352       case 'e': aFloatingEdgesMode = aVal; break;
353       case 'f': aFaceMode = aVal; break;
354       }
355     }
356     else
357     {
358       TopoDS_Shape aShape = DBRep::Get (theArgv[i]);
359       if (!aShape.IsNull())
360       {
361         aSeq.Append (aShape);
362         aPar++;
363       }
364       else
365       {
366         if (Draw::Atof (theArgv[i]))
367           aTol = Draw::Atof (theArgv[i]);
368       }
369     }
370   }
371    
372   if (aPar < 2)
373   {
374     theDi << "Use: " << theArgv[0] << " result [tolerance] shape1 shape2 ... [min tolerance] [max tolerance] [switches]" << "\n";
375     theDi << "To set user's value of min/max tolerances the following syntax is used: +<parameter> <value>" << "\n";
376     theDi << "- parameters are identified by letters:" << "\n";
377     theDi << "  mint - min tolerance" << "\n";
378     theDi << "  maxt - max tolerance" << "\n";
379     theDi << "Switches allow to tune other parameters of Sewing" << "\n";
380     theDi << "The following syntax is used: <symbol><parameter>" << "\n";
381     theDi << "- symbol may be - to set parameter off, + to set on" << "\n";
382     theDi << "- parameters are identified by letters:" << "\n";
383     theDi << "  s - mode for creating sewed shape" << "\n";
384     theDi << "  a - mode for analysis of input shapes" << "\n";
385     theDi << "  c - mode for cutting of free edges" << "\n";
386     theDi << "  n - mode for non manifold processing" << "\n";
387     theDi << "  p - mode for same parameter processing for edges" << "\n";
388     theDi << "  e - mode for sewing floating edges" << "\n";
389     theDi << "  f - mode for sewing faces" << "\n";
390     return (1);
391   }
392     
393   if (!aSetMinTol)
394     aMinTol = aTol*1e-4;
395   if (aTol < Precision::Confusion())
396     aTol = Precision::Confusion();
397   if (aMinTol < Precision::Confusion())
398     aMinTol = Precision::Confusion();
399   if (aMinTol > aTol)
400   {
401     theDi << "Error! min tolerance can't exceed working tolerance" << "\n";
402     return (1);
403   }
404   if (aMaxTol < aTol)
405   {
406     theDi << "Error! max tolerance can't be less than working tolerance" << "\n";
407     return (1);
408   }
409
410   aSewing.Init (aTol, aSewingMode, anAnalysisMode, aCuttingMode, aNonManifoldMode);
411   aSewing.SetSameParameterMode (aSameParameterMode);
412   aSewing.SetFloatingEdgesMode (aFloatingEdgesMode);
413   aSewing.SetFaceMode (aFaceMode);
414   aSewing.SetMinTolerance (aMinTol);
415   aSewing.SetMaxTolerance (aMaxTol);
416
417   for (Standard_Integer i = 1; i <= aSeq.Length(); i++)
418     aSewing.Add(aSeq.Value(i));
419   
420   Handle(Draw_ProgressIndicator) aProgress = new Draw_ProgressIndicator (theDi, 1);
421   aSewing.Perform (aProgress);
422   aSewing.Dump();
423
424   const TopoDS_Shape& aRes = aSewing.SewedShape();
425   if (!aRes.IsNull())
426     DBRep::Set(theArgv[1], aRes);
427   return 0;
428 }
429
430 //=======================================================================
431 //function : fastsewing
432 //purpose  : 
433 //=======================================================================
434 Standard_Integer fastsewing (Draw_Interpretor& theDI, 
435                             Standard_Integer theNArg, 
436                             const char** theArgVal)
437 {
438   if(theNArg < 3)
439   {
440     //                0         1       2     3         4
441     theDI << "Use: fastsewing result [-tol <value>] <list_of_faces>\n";
442     return 1;
443   }
444
445   BRepBuilderAPI_FastSewing aFS;
446
447   Standard_Integer aStartIndex = 2;
448
449   if(!strcmp(theArgVal[aStartIndex], "-tol"))
450   {
451     aFS.SetTolerance(Draw::Atof (theArgVal[aStartIndex+1]));
452     aStartIndex = 4;
453   }
454
455   for(Standard_Integer i = aStartIndex; i < theNArg; i++)
456   {
457     TopoDS_Shape aS = DBRep::Get(theArgVal[i]);
458     
459     if(!aFS.Add(aS))
460     {
461       theDI << "Face is not added. See statuses.\n";
462     }
463   }
464
465   BRepBuilderAPI_FastSewing::FS_VARStatuses aStatus = aFS.GetStatuses();
466
467   if(aStatus)
468   {
469     theDI << "Error: There are some problems while adding (" <<
470                         (static_cast<Standard_Integer>(aStatus)) << ")\n";
471     aFS.GetStatuses(&cout);
472   }
473
474   aFS.Perform();
475
476   aStatus = aFS.GetStatuses();
477
478   if(aStatus)
479   {
480     theDI << "Error: There are some problems while performing (" <<
481                         (static_cast<Standard_Integer>(aStatus)) << ")\n";
482     aFS.GetStatuses(&cout);
483   }
484
485   DBRep::Set(theArgVal[1], aFS.GetResult());
486
487   return 0;
488 }
489
490 //=======================================================================
491 // continuity
492 //=======================================================================
493
494 static Standard_Integer continuity (Draw_Interpretor& , 
495                                     Standard_Integer n, const char** a)
496 {
497   if (n < 2) return (1);
498
499   BRepOffsetAPI_FindContigousEdges aFind;
500
501   TopoDS_Shape sh = DBRep::Get(a[1]);
502   Standard_Integer i=1;
503   if (sh.IsNull()) {
504     if (n < 3) return (1);
505     Standard_Real tol = Draw::Atof(a[1]);
506     aFind.Init(tol, Standard_False);
507     i = 2;
508   }
509   
510   while (i < n) {
511     sh = DBRep::Get(a[i]);
512     aFind.Add(sh);
513     i++;
514   }
515
516   aFind.Perform();
517   aFind.Dump();
518
519   return 0;
520 }
521
522 //=======================================================================
523 // encoderegularity
524 //=======================================================================
525 static Standard_Integer encoderegularity (Draw_Interpretor& , 
526                                           Standard_Integer n, const char** a)
527
528 {
529   if (n < 2) return 1;
530   TopoDS_Shape sh = DBRep::Get(a[1]);
531   if (sh.IsNull()) return 1;
532   if (n==2) 
533     BRepLib::EncodeRegularity(sh);
534   else {
535     Standard_Real Tol = Draw::Atof(a[2]);
536     Tol *= M_PI/180.;
537     BRepLib::EncodeRegularity(sh, Tol);
538   }
539   return 0;
540 }
541
542
543 //=======================================================================
544 //function : SurfaceCommands
545 //purpose  : 
546 //=======================================================================
547
548 void  BRepTest::SurfaceCommands(Draw_Interpretor& theCommands)
549 {
550   static Standard_Boolean done = Standard_False;
551   if (done) return;
552   done = Standard_True;
553
554   DBRep::BasicCommands(theCommands);
555   GeometryTest::SurfaceCommands(theCommands);
556
557   const char* g = "Surface topology commands";
558
559   theCommands.Add("mkface",
560                   "mkface facename surfacename [ufirst ulast vfirst vlast] [wire [norient]]",
561                   __FILE__,mkface,g);
562
563   theCommands.Add("mkshell",
564                   "mkshell shellname surfacename [ufirst ulast vfirst vlast] [segment 0/1]",
565                   __FILE__,mkface,g);
566
567   theCommands.Add("quilt",
568                   "quilt compoundname shape1 edgeshape2  edgeshape1... shape2  edgeshape3 edgeshape1or2 ... shape3 ...",
569                   __FILE__,quilt,g);
570   
571   theCommands.Add("mksurface",
572                   "mksurface surfacename facename",
573                   __FILE__,mksurface,g);
574
575   theCommands.Add("mkplane",
576                   "mkplane facename wirename [OnlyPlane 0/1]",
577                   __FILE__,mkplane,g);
578
579   theCommands.Add("pcurve",
580                   "pcurve [name edgename] facename",
581                   __FILE__,pcurve,g);
582
583   theCommands.Add("sewing",
584                   "sewing result [tolerance] shape1 shape2 ... [min tolerance] [max tolerance] [switches]",
585                   __FILE__,sewing, g);
586
587   theCommands.Add("continuity", 
588                   "continuity [tolerance] shape1 shape2 ...",
589                   __FILE__,continuity, g);
590
591   theCommands.Add("encoderegularity", 
592                   "encoderegularity shape [tolerance (in degree)]",
593                   __FILE__,encoderegularity, g);
594
595   theCommands.Add ("fastsewing", "fastsewing result [-tol <value>] <list_of_faces>", 
596                                                 __FILE__, fastsewing, g);
597 }
598