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
6 // This file is part of Open CASCADE Technology software library.
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.
14 // Alternatively, this file may be used under the terms of Open CASCADE
15 // commercial license or contractual agreement.
18 #include <BRepTest.hxx>
19 #include <GeometryTest.hxx>
21 #include <DrawTrSurf.hxx>
23 #include <Draw_Interpretor.hxx>
24 #include <Draw_Appli.hxx>
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>
38 #include <TopoDS_Face.hxx>
39 #include <TCollection_AsciiString.hxx>
40 #include <Geom_Surface.hxx>
41 #include <Geom2d_TrimmedCurve.hxx>
42 #include <TopTools_ListOfShape.hxx>
43 #include <TopTools_SequenceOfShape.hxx>
44 #include <Precision.hxx>
45 #include <Draw_ProgressIndicator.hxx>
46 #include <NCollection_Vector.hxx>
47 #include <BRepBuilderAPI_FastSewing.hxx>
49 #include <GeomAPI_ProjectPointOnSurf.hxx>
50 #include <Message.hxx>
53 //#define strcasecmp strcmp Already defined
57 //-----------------------------------------------------------------------
58 // suppressarg : suppress a[d],modifie na--
59 //-----------------------------------------------------------------------
60 static void suppressarg(Standard_Integer& na,const char** a,const Standard_Integer d)
62 for(Standard_Integer i=d;i<na;i++) {
70 //=======================================================================
72 //=======================================================================
74 static Standard_Integer mkface(Draw_Interpretor& , Standard_Integer n, const char** a)
78 Handle(Geom_Surface) S = DrawTrSurf::GetSurface(a[2]);
80 Message::SendFail() << a[2] << " is not a surface";
84 Standard_Boolean mkface = a[0][2] == 'f';
87 Standard_Boolean Segment = Standard_False;
88 if ( !mkface && (n == 4 || n == 8)) {
89 Segment = !strcmp(a[n-1],"1");
95 res = BRepBuilderAPI_MakeFace(S, Precision::Confusion());
97 res = BRepBuilderAPI_MakeShell(S,Segment);
100 if (!mkface) return 1;
101 Standard_Boolean orient = (n == 4);
102 TopoDS_Shape W = DBRep::Get(a[3],TopAbs_WIRE);
103 if (W.IsNull()) return 1;
104 res = BRepBuilderAPI_MakeFace(S,TopoDS::Wire(W),orient);
108 res = BRepBuilderAPI_MakeFace(S,Draw::Atof(a[3]),Draw::Atof(a[4]),Draw::Atof(a[5]),Draw::Atof(a[6]),Precision::Confusion());
110 res = BRepBuilderAPI_MakeShell(S,Draw::Atof(a[3]),Draw::Atof(a[4]),Draw::Atof(a[5]),Draw::Atof(a[6]),
114 DBRep::Set(a[1],res);
118 //=======================================================================
120 //=======================================================================
122 static Standard_Integer quilt(Draw_Interpretor& , Standard_Integer n, const char** a)
127 Standard_Integer i = 2;
129 TopoDS_Shape S = DBRep::Get(a[i]);
131 if (S.ShapeType() == TopAbs_EDGE) {
133 TopoDS_Shape E = DBRep::Get(a[i+1]);
135 if (E.ShapeType() == TopAbs_EDGE) {
137 Q.Bind(TopoDS::Edge(S),TopoDS::Edge(E));
142 if (S.ShapeType() == TopAbs_VERTEX) {
144 TopoDS_Shape E = DBRep::Get(a[i+1]);
146 if (E.ShapeType() == TopAbs_VERTEX) {
148 Q.Bind(TopoDS::Vertex(S),TopoDS::Vertex(E));
160 DBRep::Set(a[1],Q.Shells());
165 //=======================================================================
167 //=======================================================================
169 static Standard_Integer mksurface(Draw_Interpretor& , Standard_Integer n, const char** a)
173 TopoDS_Shape S = DBRep::Get(a[2],TopAbs_FACE);
174 if (S.IsNull()) return 1;
176 Handle(Geom_Surface) C = BRep_Tool::Surface(TopoDS::Face(S),L);
179 DrawTrSurf::Set(a[1],C->Transformed(L.Transformation()));
183 //=======================================================================
185 //=======================================================================
187 static Standard_Integer mkplane(Draw_Interpretor& theDI, Standard_Integer n, const char** a)
191 TopoDS_Shape S = DBRep::Get(a[2],TopAbs_WIRE);
192 if (S.IsNull()) return 1;
194 Standard_Boolean OnlyPlane = Standard_False;
196 OnlyPlane = !strcmp(a[3],"1");
199 BRepBuilderAPI_MakeFace aMF(TopoDS::Wire(S), OnlyPlane);
203 case BRepBuilderAPI_FaceDone:
204 DBRep::Set(a[1],aMF.Face());
206 case BRepBuilderAPI_NoFace:
207 theDI << "Error. mkplane has been finished with \"No Face\" status.\n";
209 case BRepBuilderAPI_NotPlanar:
210 theDI << "Error. mkplane has been finished with \"Not Planar\" status.\n";
212 case BRepBuilderAPI_CurveProjectionFailed:
213 theDI << "Error. mkplane has been finished with \"Fail in projection curve\" status.\n";
215 case BRepBuilderAPI_ParametersOutOfRange:
216 theDI << "Error. mkplane has been finished with \"Parameters are out of range\" status.\n";
219 theDI << "Error. Undefined status. Please check the code.\n";
226 //=======================================================================
228 //=======================================================================
229 Standard_IMPORT Draw_Color DrawTrSurf_CurveColor(const Draw_Color col);
230 Standard_IMPORT void DBRep_WriteColorOrientation ();
231 Standard_IMPORT Draw_Color DBRep_ColorOrientation (const TopAbs_Orientation Or);
233 static Standard_Integer pcurve(Draw_Interpretor& , Standard_Integer n, const char** a)
235 Standard_Boolean mute = Standard_False;
236 for(Standard_Integer ia=1;ia<n;ia++) {
237 if (!strcasecmp(a[ia],"-mute")) {
239 mute = Standard_True;
245 TopoDS_Shape S = DBRep::Get(a[1],TopAbs_FACE);
246 if (S.IsNull()) return 1;
248 if (!mute) DBRep_WriteColorOrientation();
249 Draw_Color col, savecol = DrawTrSurf_CurveColor(Draw_rouge);
251 char* name = new char[100];
253 S.Orientation(TopAbs_FORWARD);
254 TopExp_Explorer ex(S,TopAbs_EDGE);
255 for (Standard_Integer i=1; ex.More(); ex.Next(), i++) {
256 const Handle(Geom2d_Curve) c = BRep_Tool::CurveOnSurface
257 (TopoDS::Edge(ex.Current()),TopoDS::Face(S),f,l);
259 std::cout << "Error: Edge " << i << " does not have pcurve" << std::endl;
262 col = DBRep_ColorOrientation(ex.Current().Orientation());
263 DrawTrSurf_CurveColor(col);
265 Sprintf(name,"%s_%d",a[1],i);
266 Standard_Real fr = c->FirstParameter(), lr = c->LastParameter();
267 Standard_Boolean IsPeriodic = c->IsPeriodic();
268 if (c->DynamicType() == STANDARD_TYPE(Geom2d_TrimmedCurve))
270 const Handle(Geom2d_Curve)& aC = Handle(Geom2d_TrimmedCurve)::DownCast (c)->BasisCurve();
271 IsPeriodic = aC->IsPeriodic();
272 fr = aC->FirstParameter();
273 lr = aC->LastParameter();
276 ((fr - f > Precision::PConfusion()) || (l - lr > Precision::PConfusion())))
278 DrawTrSurf::Set(name, c);
282 DrawTrSurf::Set(name,new Geom2d_TrimmedCurve(c,f,l));
285 DrawTrSurf_CurveColor(savecol);
289 TopoDS_Shape SE = DBRep::Get(a[2],TopAbs_EDGE);
290 if (SE.IsNull()) return 1;
291 TopoDS_Shape SF = DBRep::Get(a[3],TopAbs_FACE);
292 if (SF.IsNull()) return 1;
294 Draw_Color col, savecol = DrawTrSurf_CurveColor(Draw_rouge);
296 const Handle(Geom2d_Curve) c = BRep_Tool::CurveOnSurface
297 (TopoDS::Edge(SE),TopoDS::Face(SF),f,l);
298 Standard_Real fr = c->FirstParameter(), lr = c->LastParameter();
299 Standard_Boolean IsPeriodic = c->IsPeriodic();
300 if (c->DynamicType() == STANDARD_TYPE(Geom2d_TrimmedCurve))
302 const Handle(Geom2d_Curve)& aC = Handle(Geom2d_TrimmedCurve)::DownCast (c)->BasisCurve();
303 IsPeriodic = aC->IsPeriodic();
304 fr = aC->FirstParameter();
305 lr = aC->LastParameter();
308 col = DBRep_ColorOrientation(SE.Orientation());
309 DrawTrSurf_CurveColor(col);
311 ((fr - f > Precision::PConfusion()) || (l - lr > Precision::PConfusion())))
313 DrawTrSurf::Set(a[1], c);
317 DrawTrSurf::Set(a[1],new Geom2d_TrimmedCurve(c,f,l));
319 DrawTrSurf_CurveColor(savecol);
328 //=======================================================================
330 //=======================================================================
332 static Standard_Integer sewing (Draw_Interpretor& theDi,
333 Standard_Integer theArgc, const char** theArgv)
335 BRepBuilderAPI_Sewing aSewing;
336 Standard_Integer aPar = 1;
337 TopTools_SequenceOfShape aSeq;
339 Standard_Real aTol = 1.0e-06;
340 Standard_Boolean aSewingMode = Standard_True;
341 Standard_Boolean anAnalysisMode = Standard_True;
342 Standard_Boolean aCuttingMode = Standard_True;
343 Standard_Boolean aNonManifoldMode = Standard_False;
344 Standard_Boolean aSameParameterMode = Standard_True;
345 Standard_Boolean aFloatingEdgesMode = Standard_False;
346 Standard_Boolean aFaceMode = Standard_True;
347 Standard_Boolean aSetMinTol = Standard_False;
348 Standard_Real aMinTol = 0.;
349 Standard_Real aMaxTol = Precision::Infinite();
351 for (Standard_Integer i = 2; i < theArgc; i++)
353 if (theArgv[i][0] == '-' || theArgv[i][0] == '+')
355 Standard_Boolean aVal = (theArgv[i][0] == '+' ? Standard_True : Standard_False);
356 switch (tolower(theArgv[i][1]))
360 if (tolower(theArgv[i][2]) == 'i' && i+1 < theArgc)
362 if (Draw::Atof (theArgv[i+1]))
364 aMinTol = Draw::Atof (theArgv[++i]);
365 aSetMinTol = Standard_True;
369 theDi << "Error! min tolerance can't possess the null value\n";
373 if (tolower(theArgv[i][2]) == 'a' && i+1 < theArgc)
375 if (Draw::Atof (theArgv[i+1]))
376 aMaxTol = Draw::Atof (theArgv[++i]);
379 theDi << "Error! max tolerance can't possess the null value\n";
385 case 's': aSewingMode = aVal; break;
386 case 'a': anAnalysisMode = aVal; break;
387 case 'c': aCuttingMode = aVal; break;
388 case 'n': aNonManifoldMode = aVal; break;
389 case 'p': aSameParameterMode = aVal; break;
390 case 'e': aFloatingEdgesMode = aVal; break;
391 case 'f': aFaceMode = aVal; break;
396 TopoDS_Shape aShape = DBRep::Get (theArgv[i]);
397 if (!aShape.IsNull())
399 aSeq.Append (aShape);
404 if (Draw::Atof (theArgv[i]))
405 aTol = Draw::Atof (theArgv[i]);
412 theDi << "Use: " << theArgv[0] << " result [tolerance] shape1 shape2 ... [min tolerance] [max tolerance] [switches]\n";
413 theDi << "To set user's value of min/max tolerances the following syntax is used: +<parameter> <value>\n";
414 theDi << "- parameters are identified by letters:\n";
415 theDi << " mint - min tolerance\n";
416 theDi << " maxt - max tolerance\n";
417 theDi << "Switches allow to tune other parameters of Sewing\n";
418 theDi << "The following syntax is used: <symbol><parameter>\n";
419 theDi << "- symbol may be - to set parameter off, + to set on\n";
420 theDi << "- parameters are identified by letters:\n";
421 theDi << " s - mode for creating sewed shape\n";
422 theDi << " a - mode for analysis of input shapes\n";
423 theDi << " c - mode for cutting of free edges\n";
424 theDi << " n - mode for non manifold processing\n";
425 theDi << " p - mode for same parameter processing for edges\n";
426 theDi << " e - mode for sewing floating edges\n";
427 theDi << " f - mode for sewing faces\n";
433 if (aTol < Precision::Confusion())
434 aTol = Precision::Confusion();
435 if (aMinTol < Precision::Confusion())
436 aMinTol = Precision::Confusion();
439 theDi << "Error! min tolerance can't exceed working tolerance\n";
444 theDi << "Error! max tolerance can't be less than working tolerance\n";
448 aSewing.Init (aTol, aSewingMode, anAnalysisMode, aCuttingMode, aNonManifoldMode);
449 aSewing.SetSameParameterMode (aSameParameterMode);
450 aSewing.SetFloatingEdgesMode (aFloatingEdgesMode);
451 aSewing.SetFaceMode (aFaceMode);
452 aSewing.SetMinTolerance (aMinTol);
453 aSewing.SetMaxTolerance (aMaxTol);
455 for (Standard_Integer i = 1; i <= aSeq.Length(); i++)
456 aSewing.Add(aSeq.Value(i));
458 Handle(Draw_ProgressIndicator) aProgress = new Draw_ProgressIndicator (theDi, 1);
459 aSewing.Perform (aProgress->Start());
462 const TopoDS_Shape& aRes = aSewing.SewedShape();
464 DBRep::Set(theArgv[1], aRes);
468 //=======================================================================
469 //function : fastsewing
471 //=======================================================================
472 Standard_Integer fastsewing (Draw_Interpretor& theDI,
473 Standard_Integer theNArg,
474 const char** theArgVal)
479 theDI << "Use: fastsewing result [-tol <value>] <list_of_faces>\n";
483 BRepBuilderAPI_FastSewing aFS;
485 Standard_Integer aStartIndex = 2;
487 if(!strcmp(theArgVal[aStartIndex], "-tol"))
489 aFS.SetTolerance(Draw::Atof (theArgVal[aStartIndex+1]));
493 for(Standard_Integer i = aStartIndex; i < theNArg; i++)
495 TopoDS_Shape aS = DBRep::Get(theArgVal[i]);
499 theDI << "Face is not added. See statuses.\n";
503 BRepBuilderAPI_FastSewing::FS_VARStatuses aStatus = aFS.GetStatuses();
507 theDI << "Error: There are some problems while adding (" <<
508 (static_cast<Standard_Integer>(aStatus)) << ")\n";
509 aFS.GetStatuses(&std::cout);
514 aStatus = aFS.GetStatuses();
518 theDI << "Error: There are some problems while performing (" <<
519 (static_cast<Standard_Integer>(aStatus)) << ")\n";
520 aFS.GetStatuses(&std::cout);
523 DBRep::Set(theArgVal[1], aFS.GetResult());
528 //=======================================================================
530 //=======================================================================
532 static Standard_Integer continuity (Draw_Interpretor& ,
533 Standard_Integer n, const char** a)
535 if (n < 2) return (1);
537 BRepOffsetAPI_FindContigousEdges aFind;
539 TopoDS_Shape sh = DBRep::Get(a[1]);
540 Standard_Integer i=1;
542 if (n < 3) return (1);
543 Standard_Real tol = Draw::Atof(a[1]);
544 aFind.Init(tol, Standard_False);
549 sh = DBRep::Get(a[i]);
560 //=======================================================================
562 //=======================================================================
563 static Standard_Integer encoderegularity (Draw_Interpretor& ,
564 Standard_Integer n, const char** a)
568 TopoDS_Shape sh = DBRep::Get(a[1]);
569 if (sh.IsNull()) return 1;
571 BRepLib::EncodeRegularity(sh);
573 Standard_Real Tol = Draw::Atof(a[2]);
575 BRepLib::EncodeRegularity(sh, Tol);
580 static Standard_Integer getedgeregul
581 (Draw_Interpretor& di, Standard_Integer argc, const char** argv)
585 Message::SendFail() << "Invalid number of arguments. Should be: checkedgeregularity edge face1 [face2]";
589 TopoDS_Shape anEdge = DBRep::Get(argv[1],TopAbs_EDGE);
590 TopoDS_Shape aFace1 = DBRep::Get(argv[2],TopAbs_FACE);
591 TopoDS_Shape aFace2 = (argc > 3 ? DBRep::Get(argv[3],TopAbs_FACE) : aFace1);
592 if( anEdge.IsNull() || aFace1.IsNull() || aFace2.IsNull())
594 Message::SendFail() << "Invalid number of arguments. Should be: getedgeregularity edge face1 [face2]";
598 GeomAbs_Shape aRegularity = BRep_Tool::Continuity(TopoDS::Edge(anEdge), TopoDS::Face(aFace1), TopoDS::Face(aFace2));
599 TCollection_AsciiString aStrReg("Regularity of edge : ");
603 case GeomAbs_C0 : aStrReg += "C0"; break;
604 case GeomAbs_G1 : aStrReg += "G1"; break;
605 case GeomAbs_C1 : aStrReg += "C1"; break;
606 case GeomAbs_G2 : aStrReg += "G2"; break;
607 case GeomAbs_C2 : aStrReg += "C2"; break;
608 case GeomAbs_C3 : aStrReg += "C3"; break;
609 case GeomAbs_CN : aStrReg += "CN"; break;
612 di<<aStrReg.ToCString()<<"\n";
616 //=======================================================================
617 //function : projponf
619 //=======================================================================
620 static Standard_Integer projponf(Draw_Interpretor& di, Standard_Integer n, const char** a)
622 if (n < 3 || n > 5) {
623 di << "Project point on the face.\n";
624 di << "Usage: projponf face pnt [extrema flag: -min/-max/-minmax] [extrema algo: -g(grad)/-t(tree)]\n";
628 TopoDS_Shape aS = DBRep::Get(a[1]);
630 di << "the face is a null shape\n";
634 if (aS.ShapeType() != TopAbs_FACE) {
635 di << "not a face\n";
639 const TopoDS_Face& aFace = *(TopoDS_Face*)&aS;
643 DrawTrSurf::GetPoint(a[2], aP);
645 // get projection options
647 Extrema_ExtAlgo anExtAlgo = Extrema_ExtAlgo_Grad;
648 Extrema_ExtFlag anExtFlag = Extrema_ExtFlag_MINMAX;
650 for (Standard_Integer i = 3; i < n; ++i) {
651 if (!strcasecmp(a[i], "-min")) {
652 anExtFlag = Extrema_ExtFlag_MIN;
654 else if (!strcasecmp(a[i], "-max")) {
655 anExtFlag = Extrema_ExtFlag_MAX;
657 else if (!strcasecmp(a[i], "-minmax")) {
658 anExtFlag = Extrema_ExtFlag_MINMAX;
660 else if (!strcasecmp(a[i], "-t")) {
661 anExtAlgo = Extrema_ExtAlgo_Tree;
663 else if (!strcasecmp(a[i], "-g")) {
664 anExtAlgo = Extrema_ExtAlgo_Grad;
669 TopLoc_Location aLoc;
670 const Handle(Geom_Surface)& aSurf = BRep_Tool::Surface(aFace, aLoc);
671 // move point to surface location
672 aP.Transform(aLoc.Transformation().Inverted());
674 // get bounds of the surface
675 Standard_Real aUMin, aUMax, aVMin, aVMax;
676 aSurf->Bounds(aUMin, aUMax, aVMin, aVMax);
678 // initialize projector
679 GeomAPI_ProjectPointOnSurf aProjPS;
680 aProjPS.Init(aSurf, aUMin, aUMax, aVMin, aVMax);
682 aProjPS.SetExtremaAlgo(anExtAlgo);
683 aProjPS.SetExtremaFlag(anExtFlag);
684 // perform projection
687 if (aProjPS.NbPoints()) {
689 Standard_Real aDist = aProjPS.LowerDistance();
690 // lower distance parameters
692 aProjPS.LowerDistanceParameters(U, V);
694 gp_Pnt aPProj = aProjPS.NearestPoint();
695 // translate projection point to face location
696 aPProj.Transform(aLoc.Transformation());
698 // print the projection values
699 di << "proj dist = " << aDist << "\n";
700 di << "uvproj = " << U << " " << V << "\n";
701 di << "pproj = " << aPProj.X() << " " << aPProj.Y() << " " << aPProj.Z() << "\n";
704 if (!aProjPS.IsDone()) {
705 di << "projection failed\n";
708 di << "no projection found\n";
714 //=======================================================================
715 //function : SurfaceCommands
717 //=======================================================================
719 void BRepTest::SurfaceCommands(Draw_Interpretor& theCommands)
721 static Standard_Boolean done = Standard_False;
723 done = Standard_True;
725 DBRep::BasicCommands(theCommands);
726 GeometryTest::SurfaceCommands(theCommands);
728 const char* g = "Surface topology commands";
730 theCommands.Add("mkface",
731 "mkface facename surfacename [ufirst ulast vfirst vlast] [wire [norient]]",
734 theCommands.Add("mkshell",
735 "mkshell shellname surfacename [ufirst ulast vfirst vlast] [segment 0/1]",
738 theCommands.Add("quilt",
739 "quilt compoundname shape1 edgeshape2 edgeshape1... shape2 edgeshape3 edgeshape1or2 ... shape3 ...",
742 theCommands.Add("mksurface",
743 "mksurface surfacename facename",
744 __FILE__,mksurface,g);
746 theCommands.Add("mkplane",
747 "mkplane facename wirename [OnlyPlane 0/1]",
750 theCommands.Add("pcurve",
751 "pcurve [name edgename] facename",
754 theCommands.Add("sewing",
755 "sewing result [tolerance] shape1 shape2 ... [min tolerance] [max tolerance] [switches]",
758 theCommands.Add("continuity",
759 "continuity [tolerance] shape1 shape2 ...",
760 __FILE__,continuity, g);
762 theCommands.Add("encoderegularity",
763 "encoderegularity shape [tolerance (in degree)]",
764 __FILE__,encoderegularity, g);
766 theCommands.Add ("fastsewing", "fastsewing result [-tol <value>] <list_of_faces>",
767 __FILE__, fastsewing, g);
768 theCommands.Add ("getedgeregularity", "getedgeregularity edge face1 [face2]", __FILE__,getedgeregul,g);
770 theCommands.Add ("projponf",
771 "projponf face pnt [extrema flag: -min/-max/-minmax] [extrema algo: -g(grad)/-t(tree)]\n"
772 "\t\tProject point on the face.",
773 __FILE__, projponf, g);