// Created on: 1999-03-09 // Created by: data exchange team // Copyright (c) 1999-1999 Matra Datavision // Copyright (c) 1999-2014 OPEN CASCADE SAS // // This file is part of Open CASCADE Technology software library. // // This library is free software; you can redistribute it and/or modify it under // the terms of the GNU Lesser General Public License version 2.1 as published // by the Free Software Foundation, with special exception defined in the file // OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT // distribution for complete text of the license and disclaimer of any warranty. // // Alternatively, this file may be used under the terms of Open CASCADE // commercial license or contractual agreement. // sln 19.11.2001. Bug 2: Correction of output of 'statshape' draw function. #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include static Standard_Integer tolerance (Draw_Interpretor& di, Standard_Integer argc, const char** argv) { if (argc < 2) { di<<"myshape : analyses a shape\n" << "myshape [mode] valmin : sub-shapes over valmin\n" <<"myshape [mode] valmin valmax : between valmin and valmax\n" <<"myshape [mode] 0 valmax : below valmax\n" <<" more : all shapes(D) v vertices e edges f faces c combined(faces)\n"; return (argc < 2 ? 0 : 1 /* Error */); } Standard_CString arg1 = argv[1]; TopoDS_Shape Shape = DBRep::Get(arg1); if (Shape.IsNull()) { di<<"Shape unknown : "<Length(); switch (type) { case TopAbs_VERTEX : di<<"Analysing Vertices gives "; break; case TopAbs_EDGE : di<<"Analysing Edges gives "; break; case TopAbs_FACE : di<<"Analysing Faces gives "; break; case TopAbs_SHELL : di<<"Analysing Shells,Faces+content gives "; break; default : di<<"Analysing all sub-shapes gives "; } if (tol1 == 0) di< 1) di<<" , named tol_1 to tol_"<Value(i)); } } return 0; } static Standard_Integer projface (Draw_Interpretor& di, Standard_Integer argc, const char** argv) { if (argc < 4) { di<<"Give FACE name and X Y [Z]\n"; return 1 /* Error */; } Standard_CString arg1 = argv[1]; TopoDS_Shape Shape = DBRep::Get(arg1); if (Shape.IsNull()) { di<<"Shape unknown : "< 4) { Z = Draw::Atof (argv[4]); gp_Pnt P3D (X,Y,Z); di<<" Point 3D X = "<Bounds(uf, ul, vf, vl); if (Precision::IsInfinite(uf)) uf = -1000; if (Precision::IsInfinite(ul)) ul = 1000; if (Precision::IsInfinite(vf)) vf = -1000; if (Precision::IsInfinite(vl)) vl = 1000; Standard_Real du = Abs(ul-uf)/10; Standard_Real dv = Abs(vl-vf)/10; GeomAPI_ProjectPointOnSurf proj(P3D, thesurf, uf-du, ul+du, vf-dv, vl+dv); Standard_Integer sol, nPSurf = proj.NbPoints(); di<<" Found "<Value (U,V); di<<" => reproj X = "<ValueOfUV (P3D,BRep_Tool::Tolerance(F)); suval.Coord(U,V); di<<"** ShapeAnalysis_Surface gives U = "<Value(U,V); di<<" => reproj X = "<Value(U,V); di<<" => proj X = "<FirstParameter(); cl = C->LastParameter(); if (argc >= 7) { cf = Draw::Atof (argv[2]); cl = Draw::Atof (argv[3]); i0 = 2; } di<<"Curve 3D "< TopoDS_Iterator (it is the same) for (; it.More(); it.Next()) { TopoDS_Edge Edge = TopoDS::Edge (it.Value()); di<<"Wire "<D0 (fuv.X(),fuv.Y(),fxyz); surface->D0 (luv.X(),luv.Y(),lxyz); df3d = fp.Distance (fxyz); maxp3d = Max (maxp3d,df3d); dl3d = lp.Distance (lxyz); maxp3d = Max (maxp3d,dl3d); if (nbe > 1) duv = finuv.Distance (fuv); maxuv = Max (maxuv, duv); // et les min-max u1 = Min (fuv.X(),luv.X()); u2 = Max (fuv.X(),luv.X()); v1 = Min (fuv.Y(),luv.Y()); v2 = Max (fuv.Y(),luv.Y()); if (nbe == 1) { umin = u1; umax = u2; vmin = v1; vmax = v2; } else { umin = Min(umin,u1); umax = Max(umax,u2); vmin = Min(vmin,v1); vmax = Max(vmax,v2); } // et la classification directe if (nbe == 1) { baseuv = fuv.XY(); totcross = 0; } else { gp_XY buv1 = fuv.XY() - baseuv; gp_XY buv2 = luv.XY() - baseuv; totcross += buv2.Crossed(buv1); } } // Resultats ... if (nbe == 1) { debut = fxyz; debuv = fuv; } else { duv = finuv.Distance (fuv); maxuv = Max (maxuv, duv); dvtx = fin.Distance (fxyz); maxvtx = Max (maxvtx,dvtx); di<<" Fin("< 0) di<<"GProps:Mass Out\n"; else di<<"GProps:Mass In\n"; /// return (G.Mass() > 0); BRepTopAdaptor_FClass2d fcl (Face,BRep_Tool::Tolerance(Face)); if (fcl.PerformInfinitePoint () == TopAbs_OUT) di<<"Classifier Infinite : Out\n"; else di<<"Classifier Infinite : In\n"; gp_Pnt2d pcl; pcl.SetCoord(umin-difu,vmin-difv); if (fcl.Perform (pcl) == TopAbs_OUT) di<<"Classifier UMin-VMin : Out\n"; pcl.SetCoord(umin-difu,vmax+difv); if (fcl.Perform (pcl) == TopAbs_OUT) di<<"Classifier UMin-VMax : Out\n"; pcl.SetCoord(umax+difu,vmin-difv); if (fcl.Perform (pcl) == TopAbs_OUT) di<<"Classifier UMax-VMin : Out\n"; pcl.SetCoord(umax+difu,vmax+difv); if (fcl.Perform (pcl) == TopAbs_OUT) di<<"Classifier UMax-VMax : Out\n"; } } if (ShapeAnalysis::IsOuterBound (Face)) di<<"ShapeAnalysis: Outer Bound\n"; else di<<"ShapeAnalysis: Not Outer Bound\n"; di<<" Total "< 2) arg2 = argv[2]; if (argc > 3) arg3 = argv[3]; TopoDS_Shape Shape = DBRep::Get(arg1); if (Shape.IsNull()) { di<<"Shape unknown : "< 3) { analyzer.ModifyBigSplineMode()=(strstr("bigspl",arg3)!=NULL); analyzer.ModifyIndirectMode()=(strstr("indsur",arg3)!=NULL); analyzer.ModifyOffestSurfaceMode()=(strstr("ofsur",arg3)!=NULL); analyzer.ModifyTrimmed3dMode()=(strstr("trc3d",arg3)!=NULL); analyzer.ModifyOffsetCurveMode()=(strstr("ofcur",arg3)!=NULL); analyzer.ModifyTrimmed2dMode()=(strstr("trc2d",arg3)!=NULL); } analyzer.Perform(Shape); di<<"Count Item\n----- ----\n"; nb = analyzer.NbEdges(); if(nb>0) di<0) di<0) di<0) di<0) di<0) di<0) di<0) di<0) di<0) di<0) di<0) di<0) di<0) di<0) di<0) di<0) di< 8192 poles\n"; nb = analyzer.NbBezierSurf(); if(nb>0) di<0) di<0) di<0) di<0) di<0) di<0) di<0) di<0) di<0) di<Length(); i++) { Sprintf(nompart,"%s_bigspl_%d",arg2,i); DBRep::Set (nompart,sec->Value(i)); } } if(analyzer.ModifyIndirectMode()) { sec = analyzer.IndirectSec(); for(Standard_Integer i = 1; i <= sec->Length(); i++) { Sprintf(nompart,"%s_indsur_%d",arg2,i); DBRep::Set (nompart,sec->Value(i)); } } if(analyzer.ModifyOffestSurfaceMode()) { sec = analyzer.OffsetSurfaceSec(); for(Standard_Integer i = 1; i <= sec->Length(); i++) { Sprintf(nompart,"%s_ofsur_%d",arg2,i); DBRep::Set (nompart,sec->Value(i)); } } if(analyzer.ModifyTrimmed3dMode()) { sec = analyzer.Trimmed3dSec(); for(Standard_Integer i = 1; i <= sec->Length(); i++) { Sprintf(nompart,"%s_trc3d_%d",arg2,i); DBRep::Set (nompart,sec->Value(i)); } } if(analyzer.ModifyOffsetCurveMode()) { sec = analyzer.OffsetCurveSec(); for(Standard_Integer i = 1; i <= sec->Length(); i++) { Sprintf(nompart,"%s_ofcur_%d",arg2,i); DBRep::Set (nompart,sec->Value(i)); } } if(analyzer.ModifyTrimmed2dMode()) { sec = analyzer.Trimmed2dSec(); for(Standard_Integer i = 1; i <= sec->Length(); i++) { Sprintf(nompart,"%s_trc2d_%d",arg2,i); DBRep::Set (nompart,sec->Value(i)); } } return 0; } static Standard_Integer XSHAPE_comptoledge (Draw_Interpretor& di, Standard_Integer argc, const char** argv) { if ( argc <2 ) { di << "Use:\n" "> comptol shape [nbpoints=371] [prefix]\n\n" "Computes real tolerance of edges in the shape \n" "as maximal deviation of 3d curve and pcurves.\n" "Deviation is computed by nbpoints sample points (default is 371).\n" "Gives the max, min and average value on all edges in the shape\n" "If prefix is defined, edges with maximal real tolerance and\n" "relation (and corresponding faces) will be saved with such names\n\n"; return 0; } TopoDS_Shape shape = DBRep::Get(argv[1]); if (shape.IsNull()) { di << "Shape name \"" << argv[1] << "\" is invalid\n"; return 1; } Standard_Integer nbpnts = 371; Standard_CString prefix = 0; if ( argc >2 ) { if ( IsDigit(argv[2][0]) ) { nbpnts = Draw::Atoi(argv[2]); if ( nbpnts <2 ) nbpnts = 2; if ( argc >3 ) prefix = argv[3]; } else prefix = argv[2]; } Standard_Integer num = 0; Standard_Real max=0, min=0, ave=0.; Standard_Real relmax=0, relmin=0, relave=0.; ShapeAnalysis_Edge sae; TopoDS_Edge edmax, edmaxrel; for ( TopExp_Explorer exp(shape,TopAbs_EDGE); exp.More(); exp.Next() ) { Standard_Real tol; TopoDS_Edge edge = TopoDS::Edge(exp.Current()); sae.CheckSameParameter ( edge, tol, nbpnts ); Standard_Real t = BRep_Tool::Tolerance(edge); Standard_Real rel = tol / ( t > Precision::Confusion() ? t : Precision::Confusion() ); ave += tol; relave += rel; if ( ! num ) { max = min = tol; relmax = relmin = rel; edmax = edmaxrel = edge; } else { if ( max < tol ) { max = tol; edmax = edge; } if ( min > tol ) min = tol; if ( relmax < rel ) { relmax = rel; edmaxrel = edge; } if ( relmin > rel ) relmin = rel; } num++; } if ( ! num ) { di << "No edges found in the shape\n"; return 1; } di << "Edges tolerance computed by " << nbpnts << " points: \n" "MAX=" << max << " AVG=" << ave/num << " MIN=" << min << "\n"; di << "Relation real tolerance / tolerance set in edge\n" "MAX=" << relmax << " AVG=" << relave/num << " MIN=" << relmin << "\n"; if ( prefix && prefix[0] ) { char name[21]; Sprintf ( name, "%.10s_edge_tol", prefix ); DBRep::Set (name,edmax); di << "Edge with max tolerance saved to " << name; if ( edmax.IsSame ( edmaxrel ) ) di << "\n"; else { Sprintf ( name, "%.10s_edge_rel", prefix ); DBRep::Set (name,edmaxrel); di << "; edge with max relation saved to " << name << "\n"; } Standard_Integer num1=0; for ( TopExp_Explorer fac(shape,TopAbs_FACE); fac.More(); fac.Next() ) { TopoDS_Face face = TopoDS::Face ( fac.Current() ); for ( TopExp_Explorer ed(face,TopAbs_EDGE); ed.More(); ed.Next() ) { TopoDS_Edge edge = TopoDS::Edge ( ed.Current() ); if ( edge.IsSame ( edmax ) || edge.IsSame ( edmaxrel ) ) { if ( ! num1 ) di << "Concerned faces saved to shapes "; Sprintf ( name, "%.10s_%d", prefix, num1+1 ); DBRep::Set (name,face); //cout << ( num1 ? ", " : "" ) << name; if (num1 == 0) { di << "" << name; } else { di << ", " << name; } num1++; break; } } } if ( num1 >0 ) di << "\n"; } return 0; } //======================================================================= //function : freebounds //purpose : //======================================================================= static Standard_Integer freebounds (Draw_Interpretor& di, Standard_Integer n, const char** a) { if ((n < 3) || (n > 5)) return 1; TopoDS_Shape shape = DBRep::Get(a[1]); if (shape.IsNull()) return 1; Standard_Real toler = Draw::Atof (a[2]); Standard_Boolean splitclosed = Standard_False, splitopen = Standard_False; if ( n > 3) splitclosed = Draw::Atoi (a[3]); if ( n > 4) splitopen = Draw::Atoi (a[4]); ShapeAnalysis_FreeBounds F; if (toler <= 0) F = ShapeAnalysis_FreeBounds (shape, splitclosed, splitopen); else F = ShapeAnalysis_FreeBounds (shape, toler, splitclosed, splitopen); char name[100]; TopoDS_Shape wires = F.GetClosedWires(); Sprintf (name, "%s_c", a[1]); DBRep::Set (name, wires); di << name << " - closed wires\n"; wires = F.GetOpenWires(); Sprintf (name, "%s_o", a[1]); DBRep::Set (name, wires); di << name << " - open wires\n"; return 0; } //======================================================================= //function : PrintProps //purpose : auxilary for FreeBoundsProps //======================================================================= static void PrintProps(Standard_Integer i, const Handle(ShapeAnalysis_FreeBoundData)& fbd, Draw_Interpretor& di) { char str[100]; Standard_Real area = fbd->Area(); Standard_Real perimeter = fbd->Perimeter(); Standard_Real ratio = fbd->Ratio(); Standard_Real width = fbd->Width(); Standard_Integer notch = fbd->NbNotches(); Sprintf(str," %d\t%12.5f\t%12.5f\t%12.5f\t%12.5f\t%d", i, area, perimeter, ratio, width, notch); di< 5) ) { di<<"Usage : freeprops shapename [tolerance [splitclosed [splitopen]]]\n"; return 1; } TopoDS_Shape source = DBRep::Get(a[1]); if (source.IsNull()) { di<<"Error : unknown shape "< 2) toler = Draw::Atof(a[2]); if (n > 3) splitclosed = Draw::Atoi(a[3]); if (n > 4) splitopen = Draw::Atoi(a[4]); ShapeAnalysis_FreeBoundsProperties analyzer; if (toler > 0) analyzer.Init(source, toler, splitclosed, splitopen); else analyzer.Init(source, splitclosed, splitopen); analyzer.Perform(); TopoDS_Compound closed, open; BRep_Builder B; Standard_Integer nb = analyzer.NbClosedFreeBounds(); di<<"\n"; di<<" \tArea mm2\tLength mm\tRatio L/W\tWidth mm\tNb noth\n"; B.MakeCompound(closed); if (nb) { di<<"Closed bounds properties\n"; for (Standard_Integer i=1; i <= nb; i++) { Handle(ShapeAnalysis_FreeBoundData) fbd = analyzer.ClosedFreeBound(i); PrintProps(i, fbd, di); B.Add(closed,fbd->FreeBound()); } } nb = analyzer.NbOpenFreeBounds(); B.MakeCompound(open); if (nb) { di<<"Open bounds properties\n"; for (Standard_Integer i=1; i <= nb; i++) { Handle(ShapeAnalysis_FreeBoundData) fbd = analyzer.OpenFreeBound(i); PrintProps(i, fbd, di); B.Add(open,fbd->FreeBound()); } } char name[100]; Sprintf (name, "%s_c",a[1]); di << name << " - closed wires, "; DBRep::Set(name, closed); Sprintf (name, "%s_o",a[1]); di << name << " - closed wires \n"; DBRep::Set(name, open); return 0; } //======================================================================= //function : closefreebounds //purpose : //======================================================================= static Standard_Integer closefreebounds (Draw_Interpretor& di, Standard_Integer n, const char** a) { if ((n < 4) || (n > 6)) return 1; TopoDS_Shape shape = DBRep::Get(a[1]); if (shape.IsNull()) return 1; Standard_Real sewtoler = Draw::Atof (a[2]), closetoler = Draw::Atof (a[3]); Standard_Boolean splitclosed = Standard_False, splitopen = Standard_False; if ( n > 4) splitclosed = Draw::Atoi (a[3]); if ( n > 5) splitopen = Draw::Atoi (a[4]); ShapeFix_FreeBounds F; if (sewtoler <= 0) F = ShapeFix_FreeBounds (shape, closetoler, splitclosed, splitopen); else F = ShapeFix_FreeBounds (shape, sewtoler, closetoler, splitclosed, splitopen); char name[100]; TopoDS_Shape wires = F.GetClosedWires(); Sprintf (name, "%s_c", a[1]); DBRep::Set (name, wires); di << name << " - closed wires\n"; wires = F.GetOpenWires(); Sprintf (name, "%s_o", a[1]); DBRep::Set (name, wires); di << name << " - open wires\n"; return 0; } //======================================================================= //function : MyVISEDG //purpose : //======================================================================= static Standard_Integer MyVISEDG (Draw_Interpretor& /*di*/, Standard_Integer n, const char** a) { if (n >4) return 1; TopoDS_Shape MaListe = DBRep::Get(a[1]); if (MaListe.IsNull()) return 1; TopoDS_Compound TheList = TopoDS::Compound(MaListe); if (TheList.IsNull()) return 1; Standard_Real toler = 0.001; int create = 0; if ( n >= 3) toler = Draw::Atof(a[2]); if (n == 4 && !strcmp(a[3],"C")) create = 1; ShapeAnalysis_FreeBounds F(TheList,toler); // // // char name[100]; char num[5]; if (!create) { TopoDS_Compound Wires = F.GetClosedWires(); TopoDS_Iterator S(Wires); Standard_Integer iwire = 0; while (S.More()) { Sprintf (num,"%d",iwire); name[0] = 'w'; name[1] = '\0'; strncat(name,num,strlen(num)); name[strlen(name)] = '\0'; DBRep::Set(name,S.Value()); S.Next(); iwire++; } iwire = 0; TopoDS_Compound Edges = F.GetOpenWires(); S.Initialize(Edges); iwire = 0; while (S.More()) { Sprintf (num,"%d",iwire); name[0] = 'E'; name[1] = '\0'; strncat(name,num,strlen(num)); name[strlen(name)] = '\0'; DBRep::Set(name,S.Value()); S.Next(); iwire++; } } else { } return 0; } static Standard_Integer getareacontour (Draw_Interpretor& di, Standard_Integer n, const char** a) { if (n < 2) return 1; TopoDS_Shape shape = DBRep::Get(a[1]); if (shape.IsNull()) { di<<"Shape is not defined\n"; return 1; } if(shape.ShapeType() != TopAbs_WIRE) { di<<"invalid type of argument\n"; return 1; } //Handle(ShapeExtend_WireData) asewd = new ShapeExtend_WireData(TopoDS::Wire(shape)); Standard_Real anArea = ShapeAnalysis::ContourArea(TopoDS::Wire(shape)); di<<"Area = "< 2) { const char* arg2 = argv[2]; face = DBRep::Get(arg2); if (face.IsNull() || face.ShapeType() != TopAbs_FACE) { di<<"A null shape or not a face is used.\n"; return 3; } } // If the face is null, make a plane inside the wire. if (face.IsNull()) { BRepBuilderAPI_MakeFace mkFace(TopoDS::Wire(wire), true); if (mkFace.IsDone()) face = mkFace.Face(); else { di<<"Can't make a face for the wire. Provide please a face for analysis.\n"; return 4; } } ShapeAnalysis_Wire analyser(TopoDS::Wire(wire), TopoDS::Face(face), Precision::Confusion()); Standard_Boolean result = analyser.CheckSelfIntersection(); if (result == Standard_True) di<<"A self-intersecting wire.\n"; else di<<"Not self-intersecting wire.\n"; return 0; } static Standard_Integer checkedge(Draw_Interpretor& di, Standard_Integer argc, const char** argv) { if (argc < 2) { di<<"Call please \"checkedge edge [face]\"\n"; return 1; } // Get edge. const char* arg1 = argv[1]; TopoDS_Shape edge = DBRep::Get(arg1); if (edge.IsNull() || edge.ShapeType() != TopAbs_EDGE) { di<<"A null shape or not an edge is used.\n"; return 2; } // Get face. TopoDS_Shape face; if (argc == 3) { const char* arg2 = argv[2]; face = DBRep::Get(arg2); if (face.IsNull() || face.ShapeType() != TopAbs_FACE) { di<<"A null shape or not a face is used.\n"; return 3; } } // Analysis of the edge. ShapeAnalysis_Edge analyser; Standard_Boolean isOk(Standard_True); // Curve 3D. if (analyser.HasCurve3d(TopoDS::Edge(edge))) { // Check vertices. if (analyser.CheckVerticesWithCurve3d(TopoDS::Edge(edge))) { isOk = Standard_False; di<<"Vertices of the edge don't coincide with start/end points of 3d-curve (using tolerance of the vertices).\n"; } } else { isOk = Standard_False; di<<"Edge doesn't have a 3d-curve\n"; } if (!face.IsNull()) { // Curve 2D. if (analyser.HasPCurve(TopoDS::Edge(edge), TopoDS::Face(face))) { // Check vertices. if (analyser.CheckVerticesWithPCurve(TopoDS::Edge(edge), TopoDS::Face(face))) { isOk = Standard_False; di<<"Vertices of the edge don't coincide with start/end points of 2d-curve (using tolerance of the vertices).\n"; } } else { isOk = Standard_False; di<<"Edge doesn't have a 2d-curve on this face\n"; } } if (isOk) di<<"Edge seems OK.\n"; return 0; } //======================================================================= //function : InitCommands //purpose : //======================================================================= void SWDRAW_ShapeAnalysis::InitCommands(Draw_Interpretor& theCommands) { static Standard_Integer initactor = 0; if (initactor) return; initactor = 1; Standard_CString g = SWDRAW::GroupName(); theCommands.Add ("tolerance","shape [tolmin tolmax:real]", __FILE__,tolerance,g); theCommands.Add ("projface","nom_face X Y [Z]", __FILE__,projface,g); theCommands.Add ("projcurve","nom_edge | curve3d | curve3d first last + X Y Z", __FILE__,projcurve,g); theCommands.Add ("anaface","nomface",__FILE__,anaface,g); theCommands.Add ("statshape","shape [particul] : stats/particularites", __FILE__,XSHAPE_statshape,g); theCommands.Add ("comptol","shape [nbpoints]",__FILE__,XSHAPE_comptoledge,g); theCommands.Add("freebounds", "shp toler [splitclosed [splitopen]] - free bounds; toler <= 0 for shells (no sewing call)", __FILE__, freebounds, g); const char* groupold="DE: old"; theCommands.Add("fbprops", "shp [toler [splitclosed [splitopen]]] - free bounds properties; toler <= 0 or not specified - for shells (no sewing call)", __FILE__, FreeBoundsProps, groupold); theCommands.Add("fbclose", "shp sewtoler closetoler [splitclosed [splitopen]] - closes free bounds; use sewtoler <= 0 for shells (no sewing call)", __FILE__, closefreebounds, groupold); theCommands.Add("K_VISEDG", "K_VISEDG Visu of free edge of a compound of faces.", __FILE__, MyVISEDG, groupold); theCommands.Add("getareacontour","wire ",__FILE__, getareacontour, groupold); theCommands.Add ("checkselfintersection","wire [face]", __FILE__,checkselfintersection,g); theCommands.Add ("checkedge","edge [face]", __FILE__,checkedge,g); }