1 // Created on: 1999-03-09
2 // Created by: data exchange team
3 // Copyright (c) 1999-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.
17 // sln 19.11.2001. Bug 2: Correction of output of 'statshape' draw function.
19 #include <SWDRAW_ShapeAnalysis.ixx>
23 #include <DrawTrSurf.hxx>
25 #include <Precision.hxx>
26 #include <gp_Pnt2d.hxx>
28 #include <Geom_Curve.hxx>
29 #include <Geom_Surface.hxx>
30 #include <GeomAPI_ProjectPointOnSurf.hxx>
32 #include <TopoDS_Shape.hxx>
33 #include <TopoDS_Edge.hxx>
34 #include <TopoDS_Face.hxx>
35 #include <TopTools_HSequenceOfShape.hxx>
36 #include <BRep_Tool.hxx>
37 #include <BRepBuilderAPI.hxx>
38 #include <ShapeAnalysis.hxx>
39 #include <ShapeAnalysis_ShapeTolerance.hxx>
40 #include <ShapeAnalysis_Curve.hxx>
41 #include <ShapeAnalysis_Surface.hxx>
42 #include <ShapeAnalysis_Edge.hxx>
43 #include <TopExp_Explorer.hxx>
44 #include <TopoDS_Wire.hxx>
46 #include <gp_Pnt2d.hxx>
47 #include <TopoDS_Vertex.hxx>
48 #include <TopoDS_Iterator.hxx>
49 #include <TopoDS_Edge.hxx>
50 #include <Geom_Curve.hxx>
51 #include <Geom2d_Curve.hxx>
52 #include <BRep_Tool.hxx>
54 #include <GProp_GProps.hxx>
55 #include <BRepGProp.hxx>
56 #include <BRepTopAdaptor_FClass2d.hxx>
57 #include <ShapeAnalysis_ShapeContents.hxx>
58 #include <BRepBuilderAPI_MakeFace.hxx>
60 #include <TopoDS_Compound.hxx>
61 #include <BRep_Builder.hxx>
62 #include <TColStd_MapOfInteger.hxx>
63 #include <TCollection_AsciiString.hxx>
65 #include <ShapeAnalysis_FreeBounds.hxx>
66 #include <ShapeAnalysis_FreeBoundsProperties.hxx>
67 #include <ShapeAnalysis_FreeBoundData.hxx>
68 #include <ShapeFix_FreeBounds.hxx>
70 #include <ShapeExtend_WireData.hxx>
71 #include <ShapeAnalysis_Wire.hxx>
73 static Standard_Integer tolerance
74 (Draw_Interpretor& di, Standard_Integer argc, const char** argv)
76 if (argc < 2) { di<<"myshape : analyses a shape\n"
77 << "myshape [mode] valmin : sub-shapes over valmin\n"
78 <<"myshape [mode] valmin valmax : between valmin and valmax\n"
79 <<"myshape [mode] 0 valmax : below valmax\n"
80 <<" more : all shapes(D) v vertices e edges f faces c combined(faces)"<<"\n";
81 return (argc < 2 ? 0 : 1 /* Error */); }
82 Standard_CString arg1 = argv[1];
83 TopoDS_Shape Shape = DBRep::Get(arg1);
84 if (Shape.IsNull()) { di<<"Shape unknown : "<<arg1<<"\n"; return 1 /* Error */; }
86 ShapeAnalysis_ShapeTolerance sat;
89 sat.AddTolerance (Shape);
90 di<<"Tolerance MAX="<<sat.GlobalTolerance(1)<<" AVG="<<sat.GlobalTolerance(0)<<" MIN="<<sat.GlobalTolerance(-1)<<"\n";
92 sat.AddTolerance (Shape,TopAbs_FACE);
93 di<<"FACE : MAX="<<sat.GlobalTolerance(1)<<" AVG="<<sat.GlobalTolerance(0)<<" MIN="<<sat.GlobalTolerance(-1)<<"\n";
95 sat.AddTolerance (Shape,TopAbs_EDGE);
96 di<<"EDGE : MAX="<<sat.GlobalTolerance(1)<<" AVG="<<sat.GlobalTolerance(0)<<" MIN="<<sat.GlobalTolerance(-1)<<"\n";
98 sat.AddTolerance (Shape,TopAbs_VERTEX);
99 di<<"VERTEX : MAX="<<sat.GlobalTolerance(1)<<" AVG="<<sat.GlobalTolerance(0)<<" MIN="<<sat.GlobalTolerance(-1)<<"\n";
101 // Analyse plus fouillee
102 Standard_Integer nextarg = 2;
103 char opt = argv[2][0];
104 TopAbs_ShapeEnum type = TopAbs_SHAPE;
105 if (opt == 'a') nextarg = 3;
106 else if (opt == 'c') { nextarg = 3; type = TopAbs_SHELL; }
107 else if (opt == 'e') { nextarg = 3; type = TopAbs_EDGE; }
108 else if (opt == 'f') { nextarg = 3; type = TopAbs_FACE; }
109 else if (opt == 'v') { nextarg = 3; type = TopAbs_VERTEX; }
110 if (nextarg < 3) opt = 'a';
112 Standard_Real tol1= 0., tol2= 0.;
113 if (nextarg < argc) tol1 = Draw::Atof (argv[nextarg]);
114 if (nextarg < argc-1) tol2 = Draw::Atof (argv[nextarg+1]);
115 // Standard_Real tol = Draw::Atof (argv[2]);
116 Handle(TopTools_HSequenceOfShape) list = sat.InTolerance (Shape,tol1,tol2,type);
117 Standard_Integer i, nb = list->Length();
119 case TopAbs_VERTEX : di<<"Analysing Vertices gives "; break;
120 case TopAbs_EDGE : di<<"Analysing Edges gives "; break;
121 case TopAbs_FACE : di<<"Analysing Faces gives "; break;
122 case TopAbs_SHELL : di<<"Analysing Shells,Faces+content gives "; break;
123 default : di<<"Analysing all sub-shapes gives ";
125 if (tol1 == 0) di<<nb<<" Shapes below tol="<<tol2;
126 else if (tol2 == 0) di<<nb<<" Shapes over tol="<<tol1;
127 else di<<nb<<" Shapes between tol1="<<tol1<<" and tol2="<<tol2;
128 if (nb == 1) di<<" , named tol_1";
129 if (nb > 1) di<<" , named tol_1 to tol_"<<nb;
132 for (i = 1; i <= nb; i ++) {
133 Sprintf (nomsh,"tol_%d",i);
134 DBRep::Set (nomsh,list->Value(i));
140 static Standard_Integer projface
141 (Draw_Interpretor& di, Standard_Integer argc, const char** argv)
143 if (argc < 4) { di<<"Give FACE name and X Y [Z]"<<"\n"; return 1 /* Error */; }
144 Standard_CString arg1 = argv[1];
145 TopoDS_Shape Shape = DBRep::Get(arg1);
146 if (Shape.IsNull()) { di<<"Shape unknown : "<<arg1<<"\n"; return 1 /* Error */; }
147 if (Shape.ShapeType() != TopAbs_FACE) { di<<"Not a face"<<"\n"; return 1 /* Error */; }
148 TopoDS_Face F = TopoDS::Face (Shape);
149 Handle(Geom_Surface) thesurf = BRep_Tool::Surface (F); // pas locface
151 Standard_Real X,Y,Z,U,V;
152 X = U = Draw::Atof (argv[2]);
153 Y = V = Draw::Atof (argv[3]);
155 Z = Draw::Atof (argv[4]);
157 di<<" Point 3D X = "<<X<<" Y = "<<Y<<" Z = "<<Z<<"\n";
158 Standard_Real uf, ul, vf, vl;
159 thesurf->Bounds(uf, ul, vf, vl);
161 if (Precision::IsInfinite(uf)) uf = -1000;
162 if (Precision::IsInfinite(ul)) ul = 1000;
163 if (Precision::IsInfinite(vf)) vf = -1000;
164 if (Precision::IsInfinite(vl)) vl = 1000;
165 Standard_Real du = Abs(ul-uf)/10; Standard_Real dv = Abs(vl-vf)/10;
167 GeomAPI_ProjectPointOnSurf proj(P3D, thesurf, uf-du, ul+du, vf-dv, vl+dv);
168 Standard_Integer sol, nPSurf = proj.NbPoints();
169 di<<" Found "<<nPSurf<<" Points"<<"\n";
170 for (sol = 1; sol <= nPSurf; sol ++) {
171 di<<"n0 "<<sol<<" Distance "<<proj.Distance(sol);
172 proj.Parameters(sol, U,V);
173 di<<" U = "<<U<<" V = "<<V<<"\n";
175 P3D = thesurf->Value (U,V);
176 di<<" => reproj X = "<<P3D.X()<<" Y = "<<P3D.Y()<<" Z = "<<P3D.Z()<<"\n";
178 // Que donne ShapeTool ?
179 P3D.SetCoord (X,Y,Z);
180 Handle(ShapeAnalysis_Surface) su = new ShapeAnalysis_Surface(thesurf);
181 gp_Pnt2d suval = su->ValueOfUV (P3D,BRep_Tool::Tolerance(F));
183 di<<"** ShapeAnalysis_Surface gives U = "<<U<<" V = "<<V<<"\n";
184 P3D = thesurf->Value(U,V);
185 di<<" => reproj X = "<<P3D.X()<<" Y = "<<P3D.Y()<<" Z = "<<P3D.Z()<<"\n";
188 di<<" Point UV U = "<<U<<" V = "<<V<<"\n";
189 gp_Pnt P3D = thesurf->Value(U,V);
190 di<<" => proj X = "<<P3D.X()<<" Y = "<<P3D.Y()<<" Z = "<<P3D.Z()<<"\n";
195 static Standard_Integer projcurve
196 (Draw_Interpretor& di, Standard_Integer argc, const char** argv)
198 // admet une EDGE ou une CURVE
199 if (argc < 5) { di<<"Give : EDGE X Y Z or CURVE3D X Y Z or CURVE3D first last X Y Z"<<"\n"; return 1 /* Error */; }
200 const char * arg1 = argv[1];
201 Standard_Integer i0 = 0;
202 TopoDS_Shape Shape = DBRep::Get(arg1);
204 Handle(Geom_Curve) C; Standard_Real cf,cl;
205 if (!Shape.IsNull()) {
206 if (Shape.ShapeType() == TopAbs_EDGE) {
207 TopoDS_Edge E = TopoDS::Edge(Shape);
208 C = BRep_Tool::Curve (E,cf,cl);
209 di<<"Edge "<<arg1<<" Params from "<<cf<<" to "<<cl<<"\n";
211 di<<"SHAPE "<<arg1<<" Not an EDGE"<<"\n"; return 1 /* Error */;
214 const char* a1 = arg1;
215 C = DrawTrSurf::GetCurve (a1);
217 { di<<arg1<<" neither EDGE nor CURVE 3D"<<"\n"; return 1 /* Error */; }
218 cf = C->FirstParameter(); cl = C->LastParameter();
219 if (argc >= 7) { cf = Draw::Atof (argv[2]); cl = Draw::Atof (argv[3]); i0 = 2; }
220 di<<"Curve 3D "<<arg1<<" Params from "<<cf<<" to "<<cl<<"\n";
224 X = Draw::Atof (argv[2+i0]);
225 Y = Draw::Atof (argv[3+i0]);
226 Z = Draw::Atof (argv[4+i0]);
227 di<<"Precision (BRepBuilderAPI) : "<<BRepBuilderAPI::Precision()
228 <<" Projection : "<<X<<" "<<Y<<" "<<Z<<"\n";
231 gp_Pnt res; Standard_Real param,dist;
233 dist = ShapeAnalysis_Curve().Project (C,P3D,BRepBuilderAPI::Precision(),res,param, cf,cl);
235 di<<"Result : "<<X<<" "<<Y<<" "<<Z<<"\n"<<"Param = "<<param<<" Gap = "<<dist<<"\n";
239 static Standard_Integer anaface
240 (Draw_Interpretor& di, Standard_Integer argc, const char** argv)
242 if (argc < 2) { di<<"donner un nom de face"<<"\n"; return 1 /* Error */; }
243 Standard_CString arg1 = argv[1];
244 TopoDS_Shape Shape = DBRep::Get(arg1);
245 if (Shape.IsNull()) { di<<arg1<<" inconnu"<<"\n"; return 1 /* Error */; }
246 // if (Shape.ShapeType() != TopAbs_FACE) { di<<"Pas une FACE"<<"\n"; return 1 /* Error */; }
248 // On regarde les wires, sont-ils bien fermes
249 Standard_Integer nbw = 0, nbe = 0;
250 Handle(Geom_Surface) surface;
252 if (Shape.ShapeType() == TopAbs_FACE) {
253 Face = TopoDS::Face(Shape);
254 surface = BRep_Tool::Surface (Face); // pas locface
255 // TopLoc_Location locface;
256 di<<"Face, surface type = "<<surface->DynamicType()->Name()<<" Tol="<<BRep_Tool::Tolerance(Face);
257 if (Face.Orientation() == TopAbs_REVERSED) {
259 // Face.Orientation(TopAbs_FORWARD);
263 else { di<<"Analyse Wires, Ignore Faces"<<"\n"; }
264 Standard_Boolean iasurf = !surface.IsNull();
265 //:sw if (!Face.IsNull()) STW.SetFace (Face);
266 //:sw else STW.SetPrecision (BRepBuilderAPI::Precision());
268 for (TopExp_Explorer exp(Shape,TopAbs_WIRE); exp.More(); exp.Next()) {
269 TopoDS_Wire Wire = TopoDS::Wire (exp.Current()); nbw ++; nbe = 0;
271 if (Wire.Orientation() == TopAbs_FORWARD) di<<" (FWD)"<<"\n";
272 else di<<" (REV)"<<"\n";
274 gp_Pnt2d finuv,debuv; gp_XY baseuv;
276 Standard_Real maxp3d = 0., maxuv = 0., maxvtx = 0.;
277 Standard_Real df3d= 0.,dl3d= 0.,dvtx= 0.,duv= 0.;
278 Standard_Boolean iaw2d = iasurf;
279 Standard_Real u1= 0.,u2= 0.,v1= 0.,v2= 0.,umin= 0.,umax= 0.,vmin= 0.,vmax= 0., totcross= 0.;
281 //:sw STW.ClearWire(); STW.Load (Wire);
282 // if (STW.Reorder()) di<<"Wire reordered to explore"<<"\n";
283 // for (TopExp_Explorer exe(Wire.Oriented(TopAbs_FORWARD),TopAbs_EDGE); exe.More(); exe.Next()) {
284 // TopoDS_Edge Edge = TopoDS::Edge (exe.Current()); nbe ++;
285 //:sw for (nbe = 1; nbe <= STW.NbEdges(); nbe ++) {
286 //:sw TopoDS_Edge Edge = STW.Edge(nbe);
287 TopoDS_Iterator it (Wire); //:sw: ShapeTool_Wire -> TopoDS_Iterator (it is the same)
288 for (; it.More(); it.Next()) {
289 TopoDS_Edge Edge = TopoDS::Edge (it.Value());
291 di<<"Wire "<<nbw<<", Edge "<<nbe;
292 if (Edge.Orientation() == TopAbs_FORWARD) di<<" (FWD";
294 di<<" , Tol= "<<BRep_Tool::Tolerance (Edge)<<" )"<<"\n";
295 Standard_Real f3d,l3d,f2d,l2d;
296 Handle(Geom_Curve) curve3d = BRep_Tool::Curve (Edge,f3d,l3d);
297 Handle(Geom2d_Curve) curve2d;
298 if (iasurf) curve2d = BRep_Tool::CurveOnSurface(Edge,Face,f2d,l2d);
299 Standard_Boolean ia2d = !curve2d.IsNull(); iaw2d |= ia2d;
300 if (!ia2d) di<<"-- No PCurve"<<"\n";
301 if (curve3d.IsNull()) di<<"-- no Curve 3d"<<"\n";
303 // On va tacher de calculer les positions et les comparer
305 if (Edge.Orientation() == TopAbs_FORWARD)
306 { TopExp::Vertices (Edge,fv,lv);
307 if (ia2d) BRep_Tool::UVPoints (Edge,Face,fuv,luv); }
309 { TopExp::Vertices (Edge,lv,fv);
310 if (ia2d) BRep_Tool::UVPoints (Edge,Face,luv,fuv); }
311 gp_Pnt fp = BRep_Tool::Pnt (fv);
312 gp_Pnt lp = BRep_Tool::Pnt (lv);
315 surface->D0 (fuv.X(),fuv.Y(),fxyz);
316 surface->D0 (luv.X(),luv.Y(),lxyz);
317 df3d = fp.Distance (fxyz); maxp3d = Max (maxp3d,df3d);
318 dl3d = lp.Distance (lxyz); maxp3d = Max (maxp3d,dl3d);
319 if (nbe > 1) duv = finuv.Distance (fuv); maxuv = Max (maxuv, duv);
321 u1 = Min (fuv.X(),luv.X()); u2 = Max (fuv.X(),luv.X());
322 v1 = Min (fuv.Y(),luv.Y()); v2 = Max (fuv.Y(),luv.Y());
323 if (nbe == 1) { umin = u1; umax = u2; vmin = v1; vmax = v2; }
324 else { umin = Min(umin,u1); umax = Max(umax,u2); vmin = Min(vmin,v1); vmax = Max(vmax,v2); }
325 // et la classification directe
326 if (nbe == 1) { baseuv = fuv.XY(); totcross = 0; }
328 gp_XY buv1 = fuv.XY() - baseuv;
329 gp_XY buv2 = luv.XY() - baseuv;
330 totcross += buv2.Crossed(buv1);
335 if (nbe == 1) { debut = fxyz; debuv = fuv; }
337 duv = finuv.Distance (fuv); maxuv = Max (maxuv, duv);
338 dvtx = fin.Distance (fxyz); maxvtx = Max (maxvtx,dvtx);
339 di<<" Fin("<<nbe-1<<")-Debut("<<nbe<<"): DISTANCE="<<dvtx;
340 if (ia2d) di<<" DeltaUV="<<duv;
341 di<<" Tol(Fin)="<<BRep_Tool::Tolerance(lv)<<"\n";
343 fin = lxyz; finuv = luv;
345 di<<"-- Deb : VTX="<<fp.X()<<" , "<<fp.Y()<<" , "<<fp.Z()
346 <<"\n XYZ="<<fxyz.X()<<" , "<<fxyz.Y()<<" , "<<fxyz.Z()
347 <<"\n UV="<<fuv.X()<<" , "<<fuv.Y()<<" -- D.UV/3D="<<df3d<<"\n";
348 di<<"-- Fin : VTX="<<lp.X()<<" , "<<lp.Y()<<" , "<<lp.Z()
349 <<"\n XYZ="<<lxyz.X()<<" , "<<lxyz.Y()<<" , "<<lxyz.Z()
350 <<"\n UV="<<luv.X()<<" , "<<luv.Y()<<" -- D.UV/3D="<<dl3d<<"\n";
352 dvtx = fin.Distance (debut); maxvtx = Max (maxvtx,dvtx);
353 if (iaw2d) { duv = finuv.Distance (debuv); maxuv = Max (maxuv, duv); }
354 di<<" Fin("<<nbe<<")-Debut(1): DISTANCE="<<dvtx;
355 if (iaw2d) di <<" DeltaUV="<<duv;
356 di<<" Tol(Fin)="<<BRep_Tool::Tolerance(lv)<<"\n";
358 di<<" Wire "<<nbw<<" Max : Dist.Vertex="<<maxvtx;
359 if (iaw2d) di<<" Ecart UV/3D="<<maxp3d<<" DeltaUV="<<maxuv;
363 di<<"TotCross="<<totcross;
364 di<<" UMin-Max:"<<umin<<" , "<<umax<<" VMin-Max:"<<vmin<<" , "<<vmax<<"\n";
365 Standard_Real difu = umax - umin, difv = vmax - vmin;
367 BRepGProp::SurfaceProperties(Face,G);
368 if (G.Mass() > 0) di<<"GProps:Mass Out"<<"\n";
369 else di<<"GProps:Mass In"<<"\n";
370 /// return (G.Mass() > 0);
371 BRepTopAdaptor_FClass2d fcl (Face,BRep_Tool::Tolerance(Face));
372 if (fcl.PerformInfinitePoint () == TopAbs_OUT) di<<"Classifier Infinite : Out"<<"\n";
373 else di<<"Classifier Infinite : In"<<"\n";
375 pcl.SetCoord(umin-difu,vmin-difv);
376 if (fcl.Perform (pcl) == TopAbs_OUT) di<<"Classifier UMin-VMin : Out"<<"\n";
377 pcl.SetCoord(umin-difu,vmax+difv);
378 if (fcl.Perform (pcl) == TopAbs_OUT) di<<"Classifier UMin-VMax : Out"<<"\n";
379 pcl.SetCoord(umax+difu,vmin-difv);
380 if (fcl.Perform (pcl) == TopAbs_OUT) di<<"Classifier UMax-VMin : Out"<<"\n";
381 pcl.SetCoord(umax+difu,vmax+difv);
382 if (fcl.Perform (pcl) == TopAbs_OUT) di<<"Classifier UMax-VMax : Out"<<"\n";
385 if (ShapeAnalysis::IsOuterBound (Face)) di<<"ShapeAnalysis: Outer Bound"<<"\n";
386 else di<<"ShapeAnalysis: Not Outer Bound"<<"\n";
387 di<<" Total "<<nbw<<" Wire(s)"<<"\n";
391 static Standard_Integer XSHAPE_statshape(Draw_Interpretor& di, Standard_Integer argc, const char** argv)
393 if (argc < 2) { di<<"ShapeName; + options : prefix for particular cases : what to get"<<"\n"; return 1 /* Error */; }
394 Standard_CString arg1 = argv[1];
395 Standard_CString arg2 = NULL;
396 Standard_CString arg3 = NULL;
397 if (argc > 2) arg2 = argv[2];
398 if (argc > 3) arg3 = argv[3];
399 TopoDS_Shape Shape = DBRep::Get(arg1);
400 if (Shape.IsNull()) { di<<"Shape unknown : "<<arg1<<"\n"; return 1 /* Error */; }
404 ShapeAnalysis_ShapeContents analyzer;
406 analyzer.ModifyBigSplineMode()=(strstr("bigspl",arg3)!=NULL);
407 analyzer.ModifyIndirectMode()=(strstr("indsur",arg3)!=NULL);
408 analyzer.ModifyOffestSurfaceMode()=(strstr("ofsur",arg3)!=NULL);
409 analyzer.ModifyTrimmed3dMode()=(strstr("trc3d",arg3)!=NULL);
410 analyzer.ModifyOffsetCurveMode()=(strstr("ofcur",arg3)!=NULL);
411 analyzer.ModifyTrimmed2dMode()=(strstr("trc2d",arg3)!=NULL);
413 analyzer.Perform(Shape);
415 di<<"Count Item\n----- ----"<<"\n";
416 nb = analyzer.NbEdges();
417 if(nb>0) di<<nb<<" "<<" EDGE (Oriented)"<<"\n";
418 nb = analyzer.NbSharedEdges();
419 if(nb>0) di<<nb<<" "<<" EDGE (Shared)"<<"\n";
420 nb = analyzer.NbFreeEdges();
421 if(nb>0) di<<nb<<" "<<" EDGE (Free)"<<"\n";
422 nb = analyzer.NbFaces();
423 if(nb>0) di<<nb<<" "<<" FACE"<<"\n";
424 nb = analyzer.NbFreeFaces();
425 if(nb>0) di<<nb<<" "<<" FACE (Free)"<<"\n";
426 nb = analyzer.NbFreeWires();
427 if(nb>0) di<<nb<<" "<<" WIRE (Free)"<<"\n";
428 nb = analyzer.NbShells();
429 if(nb>0) di<<nb<<" "<<" SHELL"<<"\n";
430 nb = analyzer.NbSolids();
431 if(nb>0) di<<nb<<" "<<" SOLID"<<"\n";
432 nb = analyzer.NbVertices();
433 if(nb>0) di<<nb<<" "<<" VERTEX (Oriented)"<<"\n";
434 nb = analyzer.NbSharedVertices();
435 if(nb>0) di<<nb<<" "<<" VERTEX (Shared)"<<"\n";
436 nb = analyzer.NbWires();
437 if(nb>0) di<<nb<<" "<<" WIRE"<<"\n";
438 nb = analyzer.NbFaceWithSevWires();
439 if(nb>0) di<<nb<<" "<<"Face with more than one wire"<<"\n";
440 nb = analyzer.NbNoPCurve();
441 if(nb>0) di<<nb<<" "<<"No pcurve"<<"\n";
442 nb = analyzer.NbSolidsWithVoids();
443 if(nb>0) di<<nb<<" "<<"SOLID with voids"<<"\n";
444 nb = analyzer.NbWireWitnSeam();
445 if(nb>0) di<<nb<<" "<<"Wire(s) with one seam edge"<<"\n";
446 nb = analyzer.NbWireWithSevSeams();
447 if(nb>0) di<<nb<<" "<<"Wire(s) with several seam edges"<<"\n";
448 nb = analyzer.NbBigSplines();
449 if(nb>0) di<<nb<<" "<<"bigspl : BSpline > 8192 poles"<<"\n";
450 nb = analyzer.NbBezierSurf();
451 if(nb>0) di<<nb<<" "<<"bezsur : BezierSurface"<<"\n";
452 nb = analyzer.NbBSplibeSurf();
453 if(nb>0) di<<nb<<" "<<"bspsur : BSplineSurface"<<"\n";
454 nb = analyzer.NbC0Curves();
455 if(nb>0) di<<nb<<" "<<"c0curv : Curve Only C0"<<"\n";
456 nb = analyzer.NbC0Surfaces();
457 if(nb>0) di<<nb<<" "<<"c0surf : Surface Only C0"<<"\n";
458 nb = analyzer.NbIndirectSurf();
459 if(nb>0) di<<nb<<" "<<"indsur : Indirect Surface"<<"\n";
460 nb = analyzer.NbOffsetCurves();
461 if(nb>0) di<<nb<<" "<<"ofcur : Offset Curve(s)"<<"\n";
462 nb = analyzer.NbOffsetSurf();
463 if(nb>0) di<<nb<<" "<<"ofsur : Offset Surface"<<"\n";
464 nb = analyzer.NbTrimmedCurve2d();
465 if(nb>0) di<<nb<<" "<<"trc2d : Trimmed Curve2d"<<"\n";
466 nb = analyzer.NbTrimmedCurve3d();
467 if(nb>0) di<<nb<<" "<<"trc3d : Trimmed Curve3d"<<"\n";
468 nb = analyzer.NbTrimSurf();
469 if(nb>0) di<<nb<<" "<<"trimsu : RectangularTrimmedSurface"<<"\n";
471 if(arg3 ==NULL) return 0;
473 Handle(TopTools_HSequenceOfShape) sec;
474 if(analyzer.ModifyBigSplineMode()) {
475 sec = analyzer.BigSplineSec();
476 for(Standard_Integer i = 1; i <= sec->Length(); i++) {
477 Sprintf(nompart,"%s_bigspl_%d",arg2,i);
478 DBRep::Set (nompart,sec->Value(i));
481 if(analyzer.ModifyIndirectMode()) {
482 sec = analyzer.IndirectSec();
483 for(Standard_Integer i = 1; i <= sec->Length(); i++) {
484 Sprintf(nompart,"%s_indsur_%d",arg2,i);
485 DBRep::Set (nompart,sec->Value(i));
488 if(analyzer.ModifyOffestSurfaceMode()) {
489 sec = analyzer.OffsetSurfaceSec();
490 for(Standard_Integer i = 1; i <= sec->Length(); i++) {
491 Sprintf(nompart,"%s_ofsur_%d",arg2,i);
492 DBRep::Set (nompart,sec->Value(i));
495 if(analyzer.ModifyTrimmed3dMode()) {
496 sec = analyzer.Trimmed3dSec();
497 for(Standard_Integer i = 1; i <= sec->Length(); i++) {
498 Sprintf(nompart,"%s_trc3d_%d",arg2,i);
499 DBRep::Set (nompart,sec->Value(i));
502 if(analyzer.ModifyOffsetCurveMode()) {
503 sec = analyzer.OffsetCurveSec();
504 for(Standard_Integer i = 1; i <= sec->Length(); i++) {
505 Sprintf(nompart,"%s_ofcur_%d",arg2,i);
506 DBRep::Set (nompart,sec->Value(i));
509 if(analyzer.ModifyTrimmed2dMode()) {
510 sec = analyzer.Trimmed2dSec();
511 for(Standard_Integer i = 1; i <= sec->Length(); i++) {
512 Sprintf(nompart,"%s_trc2d_%d",arg2,i);
513 DBRep::Set (nompart,sec->Value(i));
519 static Standard_Integer XSHAPE_comptoledge
520 (Draw_Interpretor& di, Standard_Integer argc, const char** argv)
524 "> comptol shape [nbpoints=371] [prefix]\n\n"
525 "Computes real tolerance of edges in the shape \n"
526 "as maximal deviation of 3d curve and pcurves.\n"
527 "Deviation is computed by nbpoints sample points (default is 371).\n"
528 "Gives the max, min and average value on all edges in the shape\n"
529 "If prefix is defined, edges with maximal real tolerance and\n"
530 "relation (and corresponding faces) will be saved with such names\n" << "\n";
534 TopoDS_Shape shape = DBRep::Get(argv[1]);
535 if (shape.IsNull()) { di << "Shape name \"" << argv[1] << "\" is invalid" << "\n"; return 1; }
536 Standard_Integer nbpnts = 371;
537 Standard_CString prefix = 0;
539 if ( IsDigit(argv[2][0]) ) {
540 nbpnts = Draw::Atoi(argv[2]);
541 if ( nbpnts <2 ) nbpnts = 2;
542 if ( argc >3 ) prefix = argv[3];
544 else prefix = argv[2];
547 Standard_Integer num = 0;
548 Standard_Real max=0, min=0, ave=0.;
549 Standard_Real relmax=0, relmin=0, relave=0.;
550 ShapeAnalysis_Edge sae;
551 TopoDS_Edge edmax, edmaxrel;
552 for ( TopExp_Explorer exp(shape,TopAbs_EDGE); exp.More(); exp.Next() ) {
554 TopoDS_Edge edge = TopoDS::Edge(exp.Current());
555 sae.CheckSameParameter ( edge, tol, nbpnts );
556 Standard_Real t = BRep_Tool::Tolerance(edge);
557 Standard_Real rel = tol / ( t > Precision::Confusion() ? t : Precision::Confusion() );
560 if ( ! num ) { max = min = tol; relmax = relmin = rel; edmax = edmaxrel = edge; }
562 if ( max < tol ) { max = tol; edmax = edge; }
563 if ( min > tol ) min = tol;
564 if ( relmax < rel ) { relmax = rel; edmaxrel = edge; }
565 if ( relmin > rel ) relmin = rel;
569 if ( ! num ) { di << "No edges found in the shape" << "\n"; return 1; }
571 di << "Edges tolerance computed by " << nbpnts << " points: \n"
572 "MAX=" << max << " AVG=" << ave/num << " MIN=" << min << "\n";
573 di << "Relation real tolerance / tolerance set in edge\n"
574 "MAX=" << relmax << " AVG=" << relave/num << " MIN=" << relmin << "\n";
575 if ( prefix && prefix[0] ) {
577 Sprintf ( name, "%.10s_edge_tol", prefix );
578 DBRep::Set (name,edmax);
579 di << "Edge with max tolerance saved to " << name;
580 if ( edmax.IsSame ( edmaxrel ) ) di << "\n";
582 Sprintf ( name, "%.10s_edge_rel", prefix );
583 DBRep::Set (name,edmaxrel);
584 di << "; edge with max relation saved to " << name << "\n";
586 Standard_Integer num1=0;
587 for ( TopExp_Explorer fac(shape,TopAbs_FACE); fac.More(); fac.Next() ) {
588 TopoDS_Face face = TopoDS::Face ( fac.Current() );
589 for ( TopExp_Explorer ed(face,TopAbs_EDGE); ed.More(); ed.Next() ) {
590 TopoDS_Edge edge = TopoDS::Edge ( ed.Current() );
591 if ( edge.IsSame ( edmax ) || edge.IsSame ( edmaxrel ) ) {
592 if ( ! num1 ) di << "Concerned faces saved to shapes ";
593 Sprintf ( name, "%.10s_%d", prefix, num1+1 );
594 DBRep::Set (name,face);
595 //cout << ( num1 ? ", " : "" ) << name;
606 if ( num1 >0 ) di << "\n";
612 //=======================================================================
613 //function : freebounds
615 //=======================================================================
616 static Standard_Integer freebounds (Draw_Interpretor& di,
617 Standard_Integer n, const char** a)
619 if ((n < 3) || (n > 5)) return 1;
620 TopoDS_Shape shape = DBRep::Get(a[1]);
621 if (shape.IsNull()) return 1;
622 Standard_Real toler = Draw::Atof (a[2]);
623 Standard_Boolean splitclosed = Standard_False, splitopen = Standard_False;
624 if ( n > 3) splitclosed = Draw::Atoi (a[3]);
625 if ( n > 4) splitopen = Draw::Atoi (a[4]);
627 ShapeAnalysis_FreeBounds F;
629 F = ShapeAnalysis_FreeBounds (shape, splitclosed, splitopen);
631 F = ShapeAnalysis_FreeBounds (shape, toler, splitclosed, splitopen);
634 TopoDS_Shape wires = F.GetClosedWires();
635 Sprintf (name, "%s_c", a[1]);
636 DBRep::Set (name, wires);
637 di << name << " - closed wires" << "\n";
638 wires = F.GetOpenWires();
639 Sprintf (name, "%s_o", a[1]);
640 DBRep::Set (name, wires);
641 di << name << " - open wires" << "\n";
647 //=======================================================================
648 //function : PrintProps
649 //purpose : auxilary for FreeBoundsProps
650 //=======================================================================
651 static void PrintProps(Standard_Integer i,
652 const Handle(ShapeAnalysis_FreeBoundData)& fbd,
653 Draw_Interpretor& di)
657 Standard_Real area = fbd->Area();
658 Standard_Real perimeter = fbd->Perimeter();
659 Standard_Real ratio = fbd->Ratio();
660 Standard_Real width = fbd->Width();
661 Standard_Integer notch = fbd->NbNotches();
662 Sprintf(str," %d\t%12.5f\t%12.5f\t%12.5f\t%12.5f\t%d", i, area, perimeter, ratio, width, notch);
667 //=======================================================================
668 //function : FreeBoundsProps
670 //=======================================================================
671 static Standard_Integer FreeBoundsProps(Draw_Interpretor& di,
672 Standard_Integer n, const char** a)
674 if ( (n < 2)||(n > 5) ) {
675 di<<"Usage : freeprops shapename [tolerance [splitclosed [splitopen]]]"<<"\n";
679 TopoDS_Shape source = DBRep::Get(a[1]);
680 if (source.IsNull()) {
681 di<<"Error : unknown shape "<<a[1]<<"\n";
685 Standard_Real toler = 0.;
686 Standard_Boolean splitclosed = Standard_False, splitopen = Standard_False;
687 if (n > 2) toler = Draw::Atof(a[2]);
688 if (n > 3) splitclosed = Draw::Atoi(a[3]);
689 if (n > 4) splitopen = Draw::Atoi(a[4]);
690 ShapeAnalysis_FreeBoundsProperties analyzer;
692 analyzer.Init(source, toler, splitclosed, splitopen);
694 analyzer.Init(source, splitclosed, splitopen);
696 TopoDS_Compound closed, open;
699 Standard_Integer nb = analyzer.NbClosedFreeBounds();
701 di<<" \t"<<"Area mm2"<<"\t"<<"Length mm"<<"\t"<<"Ratio L/W"<<"\t"<<"Width mm"<<"\t"<<"Nb noth"<<"\n";
702 B.MakeCompound(closed);
704 di<<"Closed bounds properties"<<"\n";
705 for (Standard_Integer i=1; i <= nb; i++) {
706 Handle(ShapeAnalysis_FreeBoundData) fbd = analyzer.ClosedFreeBound(i);
707 PrintProps(i, fbd, di);
708 B.Add(closed,fbd->FreeBound());
712 nb = analyzer.NbOpenFreeBounds();
713 B.MakeCompound(open);
715 di<<"Open bounds properties"<<"\n";
716 for (Standard_Integer i=1; i <= nb; i++) {
717 Handle(ShapeAnalysis_FreeBoundData) fbd = analyzer.OpenFreeBound(i);
718 PrintProps(i, fbd, di);
719 B.Add(open,fbd->FreeBound());
724 Sprintf (name, "%s_c",a[1]);
725 di << name << " - closed wires, ";
726 DBRep::Set(name, closed);
727 Sprintf (name, "%s_o",a[1]);
728 di << name << " - closed wires " << "\n";
729 DBRep::Set(name, open);
734 //=======================================================================
735 //function : closefreebounds
737 //=======================================================================
738 static Standard_Integer closefreebounds (Draw_Interpretor& di,
739 Standard_Integer n, const char** a)
741 if ((n < 4) || (n > 6)) return 1;
742 TopoDS_Shape shape = DBRep::Get(a[1]);
743 if (shape.IsNull()) return 1;
744 Standard_Real sewtoler = Draw::Atof (a[2]), closetoler = Draw::Atof (a[3]);
745 Standard_Boolean splitclosed = Standard_False, splitopen = Standard_False;
746 if ( n > 4) splitclosed = Draw::Atoi (a[3]);
747 if ( n > 5) splitopen = Draw::Atoi (a[4]);
749 ShapeFix_FreeBounds F;
751 F = ShapeFix_FreeBounds (shape, closetoler, splitclosed, splitopen);
753 F = ShapeFix_FreeBounds (shape, sewtoler, closetoler, splitclosed, splitopen);
756 TopoDS_Shape wires = F.GetClosedWires();
757 Sprintf (name, "%s_c", a[1]);
758 DBRep::Set (name, wires);
759 di << name << " - closed wires" << "\n";
760 wires = F.GetOpenWires();
761 Sprintf (name, "%s_o", a[1]);
762 DBRep::Set (name, wires);
763 di << name << " - open wires" << "\n";
769 //=======================================================================
770 //function : MyVISEDG
772 //=======================================================================
773 static Standard_Integer MyVISEDG (Draw_Interpretor& /*di*/,
774 Standard_Integer n, const char** a)
777 TopoDS_Shape MaListe = DBRep::Get(a[1]);
778 if (MaListe.IsNull()) return 1;
779 TopoDS_Compound TheList = TopoDS::Compound(MaListe);
780 if (TheList.IsNull()) return 1;
781 Standard_Real toler = 0.001;
783 if ( n >= 3) toler = Draw::Atof(a[2]);
784 if (n == 4 && !strcmp(a[3],"C")) create = 1;
785 ShapeAnalysis_FreeBounds F(TheList,toler);
793 TopoDS_Compound Wires = F.GetClosedWires();
794 TopoDS_Iterator S(Wires);
795 Standard_Integer iwire = 0;
798 Sprintf (num,"%d",iwire);
801 strncat(name,num,strlen(num));
802 name[strlen(name)] = '\0';
803 DBRep::Set(name,S.Value());
808 TopoDS_Compound Edges = F.GetOpenWires();
813 Sprintf (num,"%d",iwire);
816 strncat(name,num,strlen(num));
817 name[strlen(name)] = '\0';
818 DBRep::Set(name,S.Value());
829 static Standard_Integer getareacontour (Draw_Interpretor& di,
830 Standard_Integer n, const char** a)
833 TopoDS_Shape shape = DBRep::Get(a[1]);
834 if (shape.IsNull()) {
835 di<<"Shape is not defined"<<"\n";
838 if(shape.ShapeType() != TopAbs_WIRE) {
839 di<<"invalid type of argument"<<"\n";
842 //Handle(ShapeExtend_WireData) asewd = new ShapeExtend_WireData(TopoDS::Wire(shape));
843 Standard_Real anArea = ShapeAnalysis::ContourArea(TopoDS::Wire(shape));
844 di<<"Area = "<<anArea<<"\n";
849 static Standard_Integer checkselfintersection
850 (Draw_Interpretor& di, Standard_Integer argc, const char** argv)
854 di<<"Call please \"checkselfintersection wire [face]\""<<"\n";
859 const char* arg1 = argv[1];
860 TopoDS_Shape wire = DBRep::Get(arg1);
861 if (wire.IsNull() || wire.ShapeType() != TopAbs_WIRE)
863 di<<"A null shape or not a wire is used."<<"\n";
867 // Get face if the user provided us with a face.
871 const char* arg2 = argv[2];
872 face = DBRep::Get(arg2);
873 if (face.IsNull() || face.ShapeType() != TopAbs_FACE)
875 di<<"A null shape or not a face is used."<<"\n";
880 // If the face is null, make a plane inside the wire.
883 BRepBuilderAPI_MakeFace mkFace(TopoDS::Wire(wire), true);
885 face = mkFace.Face();
888 di<<"Can't make a face for the wire. Provide please a face for analysis."<<"\n";
893 ShapeAnalysis_Wire analyser(TopoDS::Wire(wire), TopoDS::Face(face), Precision::Confusion());
894 Standard_Boolean result = analyser.CheckSelfIntersection();
896 if (result == Standard_True)
897 di<<"A self-intersecting wire."<<"\n";
899 di<<"Not self-intersecting wire."<<"\n";
903 static Standard_Integer checkedge(Draw_Interpretor& di, Standard_Integer argc, const char** argv)
907 di<<"Call please \"checkedge edge [face]\""<<"\n";
912 const char* arg1 = argv[1];
913 TopoDS_Shape edge = DBRep::Get(arg1);
914 if (edge.IsNull() || edge.ShapeType() != TopAbs_EDGE)
916 di<<"A null shape or not an edge is used."<<"\n";
924 const char* arg2 = argv[2];
925 face = DBRep::Get(arg2);
926 if (face.IsNull() || face.ShapeType() != TopAbs_FACE)
928 di<<"A null shape or not a face is used."<<"\n";
933 // Analysis of the edge.
934 ShapeAnalysis_Edge analyser;
935 Standard_Boolean isOk(Standard_True);
938 if (analyser.HasCurve3d(TopoDS::Edge(edge)))
941 if (analyser.CheckVerticesWithCurve3d(TopoDS::Edge(edge)))
943 isOk = Standard_False;
944 di<<"Vertices of the edge don't coincide with start/end points of 3d-curve (using tolerance of the vertices).\n";
949 isOk = Standard_False;
950 di<<"Edge doesn't have a 3d-curve\n";
956 if (analyser.HasPCurve(TopoDS::Edge(edge), TopoDS::Face(face)))
959 if (analyser.CheckVerticesWithPCurve(TopoDS::Edge(edge), TopoDS::Face(face)))
961 isOk = Standard_False;
962 di<<"Vertices of the edge don't coincide with start/end points of 2d-curve (using tolerance of the vertices).\n";
967 isOk = Standard_False;
968 di<<"Edge doesn't have a 2d-curve on this face\n";
973 di<<"Edge seems OK.\n";
978 //=======================================================================
979 //function : InitCommands
981 //=======================================================================
983 void SWDRAW_ShapeAnalysis::InitCommands(Draw_Interpretor& theCommands)
985 static Standard_Integer initactor = 0;
986 if (initactor) return; initactor = 1;
988 Standard_CString g = SWDRAW::GroupName();
990 theCommands.Add ("tolerance","shape [tolmin tolmax:real]", __FILE__,tolerance,g);
991 theCommands.Add ("projface","nom_face X Y [Z]", __FILE__,projface,g);
992 theCommands.Add ("projcurve","nom_edge | curve3d | curve3d first last + X Y Z",
993 __FILE__,projcurve,g);
994 theCommands.Add ("anaface","nomface",__FILE__,anaface,g);
995 theCommands.Add ("statshape","shape [particul] : stats/particularites",
996 __FILE__,XSHAPE_statshape,g);
997 theCommands.Add ("comptol","shape [nbpoints]",__FILE__,XSHAPE_comptoledge,g);
998 theCommands.Add("freebounds",
999 "shp toler [splitclosed [splitopen]] - free bounds; toler <= 0 for shells (no sewing call)",
1000 __FILE__, freebounds, g);
1002 const char* groupold="DE: old";
1003 theCommands.Add("fbprops",
1004 "shp [toler [splitclosed [splitopen]]] - free bounds properties; toler <= 0 or not specified - for shells (no sewing call)",
1005 __FILE__, FreeBoundsProps, groupold);
1006 theCommands.Add("fbclose",
1007 "shp sewtoler closetoler [splitclosed [splitopen]] - closes free bounds; use sewtoler <= 0 for shells (no sewing call)",
1008 __FILE__, closefreebounds, groupold);
1009 theCommands.Add("K_VISEDG",
1010 "K_VISEDG Visu of free edge of a compound of faces.",
1011 __FILE__, MyVISEDG, groupold);
1013 theCommands.Add("getareacontour","wire ",__FILE__, getareacontour, groupold);
1014 theCommands.Add ("checkselfintersection","wire [face]", __FILE__,checkselfintersection,g);
1015 theCommands.Add ("checkedge","edge [face]", __FILE__,checkedge,g);