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 <BRep_Builder.hxx>
20 #include <BRep_Tool.hxx>
21 #include <BRepBuilderAPI.hxx>
22 #include <BRepBuilderAPI_MakeFace.hxx>
23 #include <BRepGProp.hxx>
24 #include <BRepTopAdaptor_FClass2d.hxx>
27 #include <DrawTrSurf.hxx>
28 #include <Geom2d_Curve.hxx>
29 #include <Geom_Curve.hxx>
30 #include <Geom_Surface.hxx>
31 #include <GeomAPI_ProjectPointOnSurf.hxx>
33 #include <gp_Pnt2d.hxx>
34 #include <GProp_GProps.hxx>
35 #include <Precision.hxx>
36 #include <ShapeAnalysis.hxx>
37 #include <ShapeAnalysis_Curve.hxx>
38 #include <ShapeAnalysis_Edge.hxx>
39 #include <ShapeAnalysis_FreeBoundData.hxx>
40 #include <ShapeAnalysis_FreeBounds.hxx>
41 #include <ShapeAnalysis_FreeBoundsProperties.hxx>
42 #include <ShapeAnalysis_ShapeContents.hxx>
43 #include <ShapeAnalysis_ShapeTolerance.hxx>
44 #include <ShapeAnalysis_Surface.hxx>
45 #include <ShapeAnalysis_Wire.hxx>
46 #include <ShapeExtend_WireData.hxx>
47 #include <ShapeFix_FreeBounds.hxx>
49 #include <SWDRAW_ShapeAnalysis.hxx>
50 #include <TCollection_AsciiString.hxx>
51 #include <TColStd_MapOfInteger.hxx>
53 #include <TopExp_Explorer.hxx>
55 #include <TopoDS_Compound.hxx>
56 #include <TopoDS_Edge.hxx>
57 #include <TopoDS_Face.hxx>
58 #include <TopoDS_Iterator.hxx>
59 #include <TopoDS_Shape.hxx>
60 #include <TopoDS_Vertex.hxx>
61 #include <TopoDS_Wire.hxx>
62 #include <TopTools_HSequenceOfShape.hxx>
63 #include <Adaptor3d_CurveOnSurface.hxx>
64 #include <BRepAdaptor_HCurve2d.hxx>
65 #include <BRepAdaptor_HSurface.hxx>
68 static Standard_Integer tolerance
69 (Draw_Interpretor& di, Standard_Integer argc, const char** argv)
71 if (argc < 2) { di<<"myshape : analyses a shape\n"
72 << "myshape [mode] valmin : sub-shapes over valmin\n"
73 <<"myshape [mode] valmin valmax : between valmin and valmax\n"
74 <<"myshape [mode] 0 valmax : below valmax\n"
75 <<" more : all shapes(D) v vertices e edges f faces c combined(faces)\n";
76 return (argc < 2 ? 0 : 1 /* Error */); }
77 Standard_CString arg1 = argv[1];
78 TopoDS_Shape Shape = DBRep::Get(arg1);
79 if (Shape.IsNull()) { di<<"Shape unknown : "<<arg1<<"\n"; return 1 /* Error */; }
81 ShapeAnalysis_ShapeTolerance sat;
84 sat.AddTolerance (Shape);
85 di<<"Tolerance MAX="<<sat.GlobalTolerance(1)<<" AVG="<<sat.GlobalTolerance(0)<<" MIN="<<sat.GlobalTolerance(-1)<<"\n";
87 sat.AddTolerance (Shape,TopAbs_FACE);
88 di<<"FACE : MAX="<<sat.GlobalTolerance(1)<<" AVG="<<sat.GlobalTolerance(0)<<" MIN="<<sat.GlobalTolerance(-1)<<"\n";
90 sat.AddTolerance (Shape,TopAbs_EDGE);
91 di<<"EDGE : MAX="<<sat.GlobalTolerance(1)<<" AVG="<<sat.GlobalTolerance(0)<<" MIN="<<sat.GlobalTolerance(-1)<<"\n";
93 sat.AddTolerance (Shape,TopAbs_VERTEX);
94 di<<"VERTEX : MAX="<<sat.GlobalTolerance(1)<<" AVG="<<sat.GlobalTolerance(0)<<" MIN="<<sat.GlobalTolerance(-1)<<"\n";
96 // Analyse plus fouillee
97 Standard_Integer nextarg = 2;
98 char opt = argv[2][0];
99 TopAbs_ShapeEnum type = TopAbs_SHAPE;
100 if (opt == 'a') nextarg = 3;
101 else if (opt == 'c') { nextarg = 3; type = TopAbs_SHELL; }
102 else if (opt == 'e') { nextarg = 3; type = TopAbs_EDGE; }
103 else if (opt == 'f') { nextarg = 3; type = TopAbs_FACE; }
104 else if (opt == 'v') { nextarg = 3; type = TopAbs_VERTEX; }
105 if (nextarg < 3) opt = 'a';
107 Standard_Real tol1= 0., tol2= 0.;
108 if (nextarg < argc) tol1 = Draw::Atof (argv[nextarg]);
109 if (nextarg < argc-1) tol2 = Draw::Atof (argv[nextarg+1]);
110 // Standard_Real tol = Draw::Atof (argv[2]);
111 Handle(TopTools_HSequenceOfShape) list = sat.InTolerance (Shape,tol1,tol2,type);
112 Standard_Integer i, nb = list->Length();
114 case TopAbs_VERTEX : di<<"Analysing Vertices gives "; break;
115 case TopAbs_EDGE : di<<"Analysing Edges gives "; break;
116 case TopAbs_FACE : di<<"Analysing Faces gives "; break;
117 case TopAbs_SHELL : di<<"Analysing Shells,Faces+content gives "; break;
118 default : di<<"Analysing all sub-shapes gives ";
120 if (tol1 == 0) di<<nb<<" Shapes below tol="<<tol2;
121 else if (tol2 == 0) di<<nb<<" Shapes over tol="<<tol1;
122 else di<<nb<<" Shapes between tol1="<<tol1<<" and tol2="<<tol2;
123 if (nb == 1) di<<" , named tol_1";
124 if (nb > 1) di<<" , named tol_1 to tol_"<<nb;
127 for (i = 1; i <= nb; i ++) {
128 Sprintf (nomsh,"tol_%d",i);
129 DBRep::Set (nomsh,list->Value(i));
135 static Standard_Integer projface
136 (Draw_Interpretor& di, Standard_Integer argc, const char** argv)
138 if (argc < 4) { di<<"Give FACE name and X Y [Z]\n"; return 1 /* Error */; }
139 Standard_CString arg1 = argv[1];
140 TopoDS_Shape Shape = DBRep::Get(arg1);
141 if (Shape.IsNull()) { di<<"Shape unknown : "<<arg1<<"\n"; return 1 /* Error */; }
142 if (Shape.ShapeType() != TopAbs_FACE) { di<<"Not a face\n"; return 1 /* Error */; }
143 TopoDS_Face F = TopoDS::Face (Shape);
144 Handle(Geom_Surface) thesurf = BRep_Tool::Surface (F); // pas locface
146 Standard_Real X,Y,Z,U,V;
147 X = U = Draw::Atof (argv[2]);
148 Y = V = Draw::Atof (argv[3]);
150 Z = Draw::Atof (argv[4]);
152 di<<" Point 3D X = "<<X<<" Y = "<<Y<<" Z = "<<Z<<"\n";
153 Standard_Real uf, ul, vf, vl;
154 thesurf->Bounds(uf, ul, vf, vl);
156 if (Precision::IsInfinite(uf)) uf = -1000;
157 if (Precision::IsInfinite(ul)) ul = 1000;
158 if (Precision::IsInfinite(vf)) vf = -1000;
159 if (Precision::IsInfinite(vl)) vl = 1000;
160 Standard_Real du = Abs(ul-uf)/10; Standard_Real dv = Abs(vl-vf)/10;
162 GeomAPI_ProjectPointOnSurf proj(P3D, thesurf, uf-du, ul+du, vf-dv, vl+dv);
163 Standard_Integer sol, nPSurf = proj.NbPoints();
164 di<<" Found "<<nPSurf<<" Points\n";
165 for (sol = 1; sol <= nPSurf; sol ++) {
166 di<<"n0 "<<sol<<" Distance "<<proj.Distance(sol);
167 proj.Parameters(sol, U,V);
168 di<<" U = "<<U<<" V = "<<V<<"\n";
170 P3D = thesurf->Value (U,V);
171 di<<" => reproj X = "<<P3D.X()<<" Y = "<<P3D.Y()<<" Z = "<<P3D.Z()<<"\n";
173 // Que donne ShapeTool ?
174 P3D.SetCoord (X,Y,Z);
175 Handle(ShapeAnalysis_Surface) su = new ShapeAnalysis_Surface(thesurf);
176 gp_Pnt2d suval = su->ValueOfUV (P3D,BRep_Tool::Tolerance(F));
178 di<<"** ShapeAnalysis_Surface gives U = "<<U<<" V = "<<V<<"\n";
179 P3D = thesurf->Value(U,V);
180 di<<" => reproj X = "<<P3D.X()<<" Y = "<<P3D.Y()<<" Z = "<<P3D.Z()<<"\n";
183 di<<" Point UV U = "<<U<<" V = "<<V<<"\n";
184 gp_Pnt P3D = thesurf->Value(U,V);
185 di<<" => proj X = "<<P3D.X()<<" Y = "<<P3D.Y()<<" Z = "<<P3D.Z()<<"\n";
190 static Standard_Integer projcurve
191 (Draw_Interpretor& di, Standard_Integer argc, const char** argv)
193 // admet une EDGE ou une CURVE
194 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 */; }
195 const char * arg1 = argv[1];
196 Standard_Integer i0 = 0;
197 TopoDS_Shape Shape = DBRep::Get(arg1);
199 Handle(Geom_Curve) C; Standard_Real cf,cl;
200 if (!Shape.IsNull()) {
201 if (Shape.ShapeType() == TopAbs_EDGE) {
202 TopoDS_Edge E = TopoDS::Edge(Shape);
203 C = BRep_Tool::Curve (E,cf,cl);
204 di<<"Edge "<<arg1<<" Params from "<<cf<<" to "<<cl<<"\n";
206 di<<"SHAPE "<<arg1<<" Not an EDGE\n"; return 1 /* Error */;
209 const char* a1 = arg1;
210 C = DrawTrSurf::GetCurve (a1);
212 { di<<arg1<<" neither EDGE nor CURVE 3D\n"; return 1 /* Error */; }
213 cf = C->FirstParameter(); cl = C->LastParameter();
214 if (argc >= 7) { cf = Draw::Atof (argv[2]); cl = Draw::Atof (argv[3]); i0 = 2; }
215 di<<"Curve 3D "<<arg1<<" Params from "<<cf<<" to "<<cl<<"\n";
219 X = Draw::Atof (argv[2+i0]);
220 Y = Draw::Atof (argv[3+i0]);
221 Z = Draw::Atof (argv[4+i0]);
222 di<<"Precision (BRepBuilderAPI) : "<<BRepBuilderAPI::Precision()
223 <<" Projection : "<<X<<" "<<Y<<" "<<Z<<"\n";
226 gp_Pnt res; Standard_Real param,dist;
228 dist = ShapeAnalysis_Curve().Project (C,P3D,BRepBuilderAPI::Precision(),res,param, cf,cl);
230 di<<"Result : "<<X<<" "<<Y<<" "<<Z<<"\nParam = "<<param<<" Gap = "<<dist<<"\n";
233 static Standard_Integer projpcurve
234 (Draw_Interpretor& di, Standard_Integer argc, const char** argv)
236 // admet une EDGE ou une CURVE
239 di << "Give : projpcurve edge face tol X Y Z [start_param]\n";
243 TopoDS_Edge aEdge = TopoDS::Edge(DBRep::Get(argv[1]));
246 di << "SHAPE " << argv[1] << " is not an EDGE\n"; return 1 /* Error */;
248 TopoDS_Face aFace = TopoDS::Face(DBRep::Get(argv[2]));
251 di << "SHAPE " << argv[2] << " is not a FACE\n"; return 1 /* Error */;
254 Standard_Real aTol = Draw::Atof(argv[3]);
257 Standard_Real X = Draw::Atof(argv[4]);
258 Standard_Real Y = Draw::Atof(argv[5]);
259 Standard_Real Z = Draw::Atof(argv[6]);
261 gp_Pnt aP3D(X, Y, Z);
263 Standard_Boolean IsStartPoint = Standard_False;
264 Standard_Real startpar = 0.;
267 startpar = Draw::Atof(argv[7]);
268 IsStartPoint = Standard_True;
271 Adaptor3d_CurveOnSurface aCOnS =
272 Adaptor3d_CurveOnSurface(new BRepAdaptor_HCurve2d(BRepAdaptor_Curve2d(aEdge, aFace)),
273 new BRepAdaptor_HSurface(BRepAdaptor_Surface(aFace, Standard_False)));
276 Standard_Real aParam;
277 ShapeAnalysis_Curve aTool;
278 Standard_Real aDist = RealLast();
281 aDist = aTool.NextProject(startpar, aCOnS, aP3D, aTol, aPnt, aParam);
285 aDist = aTool.Project(aCOnS, aP3D, aTol, aPnt, aParam, Standard_False);
288 di << "Point:" << "\n" << aPnt.X() << " " << aPnt.Y() << " " << aPnt.Z() << "\n";
289 di << "Param: " << aParam << "\n";
290 di << "Dist: " << aDist << "\n";
294 static Standard_Integer anaface
295 (Draw_Interpretor& di, Standard_Integer argc, const char** argv)
297 if (argc < 2) { di<<"donner un nom de face\n"; return 1 /* Error */; }
298 Standard_CString arg1 = argv[1];
299 TopoDS_Shape Shape = DBRep::Get(arg1);
300 if (Shape.IsNull()) { di<<arg1<<" inconnu\n"; return 1 /* Error */; }
301 // if (Shape.ShapeType() != TopAbs_FACE) { di<<"Pas une FACE\n"; return 1 /* Error */; }
303 // On regarde les wires, sont-ils bien fermes
304 Standard_Integer nbw = 0, nbe = 0;
305 Handle(Geom_Surface) surface;
307 if (Shape.ShapeType() == TopAbs_FACE) {
308 Face = TopoDS::Face(Shape);
309 surface = BRep_Tool::Surface (Face); // pas locface
310 // TopLoc_Location locface;
311 di<<"Face, surface type = "<<surface->DynamicType()->Name()<<" Tol="<<BRep_Tool::Tolerance(Face);
312 if (Face.Orientation() == TopAbs_REVERSED) {
314 // Face.Orientation(TopAbs_FORWARD);
318 else { di<<"Analyse Wires, Ignore Faces\n"; }
319 Standard_Boolean iasurf = !surface.IsNull();
320 //:sw if (!Face.IsNull()) STW.SetFace (Face);
321 //:sw else STW.SetPrecision (BRepBuilderAPI::Precision());
323 for (TopExp_Explorer exp(Shape,TopAbs_WIRE); exp.More(); exp.Next()) {
324 TopoDS_Wire Wire = TopoDS::Wire (exp.Current()); nbw ++; nbe = 0;
326 if (Wire.Orientation() == TopAbs_FORWARD) di<<" (FWD)\n";
329 gp_Pnt2d finuv,debuv; gp_XY baseuv;
331 Standard_Real maxp3d = 0., maxuv = 0., maxvtx = 0.;
332 Standard_Real df3d= 0.,dl3d= 0.,dvtx= 0.,duv= 0.;
333 Standard_Boolean iaw2d = iasurf;
334 Standard_Real u1= 0.,u2= 0.,v1= 0.,v2= 0.,umin= 0.,umax= 0.,vmin= 0.,vmax= 0., totcross= 0.;
336 //:sw STW.ClearWire(); STW.Load (Wire);
337 // if (STW.Reorder()) di<<"Wire reordered to explore\n";
338 // for (TopExp_Explorer exe(Wire.Oriented(TopAbs_FORWARD),TopAbs_EDGE); exe.More(); exe.Next()) {
339 // TopoDS_Edge Edge = TopoDS::Edge (exe.Current()); nbe ++;
340 //:sw for (nbe = 1; nbe <= STW.NbEdges(); nbe ++) {
341 //:sw TopoDS_Edge Edge = STW.Edge(nbe);
342 TopoDS_Iterator it (Wire); //:sw: ShapeTool_Wire -> TopoDS_Iterator (it is the same)
343 for (; it.More(); it.Next()) {
344 TopoDS_Edge Edge = TopoDS::Edge (it.Value());
346 di<<"Wire "<<nbw<<", Edge "<<nbe;
347 if (Edge.Orientation() == TopAbs_FORWARD) di<<" (FWD";
349 di<<" , Tol= "<<BRep_Tool::Tolerance (Edge)<<" )\n";
350 Standard_Real f3d,l3d,f2d,l2d;
351 Handle(Geom_Curve) curve3d = BRep_Tool::Curve (Edge,f3d,l3d);
352 Handle(Geom2d_Curve) curve2d;
353 if (iasurf) curve2d = BRep_Tool::CurveOnSurface(Edge,Face,f2d,l2d);
354 Standard_Boolean ia2d = !curve2d.IsNull(); iaw2d |= ia2d;
355 if (!ia2d) di<<"-- No PCurve\n";
356 if (curve3d.IsNull()) di<<"-- no Curve 3d\n";
358 // On va tacher de calculer les positions et les comparer
360 if (Edge.Orientation() == TopAbs_FORWARD)
362 TopExp::Vertices (Edge, fv, lv);
363 if (ia2d) BRep_Tool::UVPoints (Edge, Face, fuv, luv);
367 TopExp::Vertices (Edge, lv, fv);
368 if (ia2d) BRep_Tool::UVPoints (Edge, Face, luv, fuv);
370 gp_Pnt fp = BRep_Tool::Pnt (fv);
371 gp_Pnt lp = BRep_Tool::Pnt (lv);
375 surface->D0 (fuv.X(),fuv.Y(),fxyz);
376 surface->D0 (luv.X(),luv.Y(),lxyz);
377 df3d = fp.Distance (fxyz); maxp3d = Max (maxp3d,df3d);
378 dl3d = lp.Distance (lxyz); maxp3d = Max (maxp3d,dl3d);
381 duv = finuv.Distance (fuv);
382 maxuv = Max (maxuv, duv);
385 u1 = Min (fuv.X(),luv.X()); u2 = Max (fuv.X(),luv.X());
386 v1 = Min (fuv.Y(),luv.Y()); v2 = Max (fuv.Y(),luv.Y());
387 if (nbe == 1) { umin = u1; umax = u2; vmin = v1; vmax = v2; }
388 else { umin = Min(umin,u1); umax = Max(umax,u2); vmin = Min(vmin,v1); vmax = Max(vmax,v2); }
389 // et la classification directe
390 if (nbe == 1) { baseuv = fuv.XY(); totcross = 0; }
392 gp_XY buv1 = fuv.XY() - baseuv;
393 gp_XY buv2 = luv.XY() - baseuv;
394 totcross += buv2.Crossed(buv1);
399 if (nbe == 1) { debut = fxyz; debuv = fuv; }
401 duv = finuv.Distance (fuv); maxuv = Max (maxuv, duv);
402 dvtx = fin.Distance (fxyz); maxvtx = Max (maxvtx,dvtx);
403 di<<" Fin("<<nbe-1<<")-Debut("<<nbe<<"): DISTANCE="<<dvtx;
404 if (ia2d) di<<" DeltaUV="<<duv;
405 di<<" Tol(Fin)="<<BRep_Tool::Tolerance(lv)<<"\n";
407 fin = lxyz; finuv = luv;
409 di<<"-- Deb : VTX="<<fp.X()<<" , "<<fp.Y()<<" , "<<fp.Z()
410 <<"\n XYZ="<<fxyz.X()<<" , "<<fxyz.Y()<<" , "<<fxyz.Z()
411 <<"\n UV="<<fuv.X()<<" , "<<fuv.Y()<<" -- D.UV/3D="<<df3d<<"\n";
412 di<<"-- Fin : VTX="<<lp.X()<<" , "<<lp.Y()<<" , "<<lp.Z()
413 <<"\n XYZ="<<lxyz.X()<<" , "<<lxyz.Y()<<" , "<<lxyz.Z()
414 <<"\n UV="<<luv.X()<<" , "<<luv.Y()<<" -- D.UV/3D="<<dl3d<<"\n";
416 dvtx = fin.Distance (debut); maxvtx = Max (maxvtx,dvtx);
417 if (iaw2d) { duv = finuv.Distance (debuv); maxuv = Max (maxuv, duv); }
418 di<<" Fin("<<nbe<<")-Debut(1): DISTANCE="<<dvtx;
419 if (iaw2d) di <<" DeltaUV="<<duv;
420 di<<" Tol(Fin)="<<BRep_Tool::Tolerance(lv)<<"\n";
422 di<<" Wire "<<nbw<<" Max : Dist.Vertex="<<maxvtx;
423 if (iaw2d) di<<" Ecart UV/3D="<<maxp3d<<" DeltaUV="<<maxuv;
427 di<<"TotCross="<<totcross;
428 di<<" UMin-Max:"<<umin<<" , "<<umax<<" VMin-Max:"<<vmin<<" , "<<vmax<<"\n";
429 Standard_Real difu = umax - umin, difv = vmax - vmin;
431 BRepGProp::SurfaceProperties(Face,G);
432 if (G.Mass() > 0) di<<"GProps:Mass Out\n";
433 else di<<"GProps:Mass In\n";
434 /// return (G.Mass() > 0);
435 BRepTopAdaptor_FClass2d fcl (Face,BRep_Tool::Tolerance(Face));
436 if (fcl.PerformInfinitePoint () == TopAbs_OUT) di<<"Classifier Infinite : Out\n";
437 else di<<"Classifier Infinite : In\n";
439 pcl.SetCoord(umin-difu,vmin-difv);
440 if (fcl.Perform (pcl) == TopAbs_OUT) di<<"Classifier UMin-VMin : Out\n";
441 pcl.SetCoord(umin-difu,vmax+difv);
442 if (fcl.Perform (pcl) == TopAbs_OUT) di<<"Classifier UMin-VMax : Out\n";
443 pcl.SetCoord(umax+difu,vmin-difv);
444 if (fcl.Perform (pcl) == TopAbs_OUT) di<<"Classifier UMax-VMin : Out\n";
445 pcl.SetCoord(umax+difu,vmax+difv);
446 if (fcl.Perform (pcl) == TopAbs_OUT) di<<"Classifier UMax-VMax : Out\n";
449 if (ShapeAnalysis::IsOuterBound (Face)) di<<"ShapeAnalysis: Outer Bound\n";
450 else di<<"ShapeAnalysis: Not Outer Bound\n";
451 di<<" Total "<<nbw<<" Wire(s)\n";
455 static Standard_Integer XSHAPE_statshape(Draw_Interpretor& di, Standard_Integer argc, const char** argv)
457 if (argc < 2) { di<<"ShapeName; + options : prefix for particular cases : what to get\n"; return 1 /* Error */; }
458 Standard_CString arg1 = argv[1];
459 Standard_CString arg2 = NULL;
460 Standard_CString arg3 = NULL;
461 if (argc > 2) arg2 = argv[2];
462 if (argc > 3) arg3 = argv[3];
463 TopoDS_Shape Shape = DBRep::Get(arg1);
464 if (Shape.IsNull()) { di<<"Shape unknown : "<<arg1<<"\n"; return 1 /* Error */; }
468 ShapeAnalysis_ShapeContents analyzer;
470 analyzer.ModifyBigSplineMode()=(strstr("bigspl",arg3)!=NULL);
471 analyzer.ModifyIndirectMode()=(strstr("indsur",arg3)!=NULL);
472 analyzer.ModifyOffestSurfaceMode()=(strstr("ofsur",arg3)!=NULL);
473 analyzer.ModifyTrimmed3dMode()=(strstr("trc3d",arg3)!=NULL);
474 analyzer.ModifyOffsetCurveMode()=(strstr("ofcur",arg3)!=NULL);
475 analyzer.ModifyTrimmed2dMode()=(strstr("trc2d",arg3)!=NULL);
477 analyzer.Perform(Shape);
479 di<<"Count Item\n----- ----\n";
480 nb = analyzer.NbEdges();
481 if(nb>0) di<<nb<<" EDGE (Oriented)\n";
482 nb = analyzer.NbSharedEdges();
483 if(nb>0) di<<nb<<" EDGE (Shared)\n";
484 nb = analyzer.NbFreeEdges();
485 if(nb>0) di<<nb<<" EDGE (Free)\n";
486 nb = analyzer.NbFaces();
487 if(nb>0) di<<nb<<" FACE\n";
488 nb = analyzer.NbFreeFaces();
489 if(nb>0) di<<nb<<" FACE (Free)\n";
490 nb = analyzer.NbFreeWires();
491 if(nb>0) di<<nb<<" WIRE (Free)\n";
492 nb = analyzer.NbShells();
493 if(nb>0) di<<nb<<" SHELL\n";
494 nb = analyzer.NbSolids();
495 if(nb>0) di<<nb<<" SOLID\n";
496 nb = analyzer.NbVertices();
497 if(nb>0) di<<nb<<" VERTEX (Oriented)\n";
498 nb = analyzer.NbSharedVertices();
499 if(nb>0) di<<nb<<" VERTEX (Shared)\n";
500 nb = analyzer.NbWires();
501 if(nb>0) di<<nb<<" WIRE\n";
502 nb = analyzer.NbFaceWithSevWires();
503 if(nb>0) di<<nb<<" Face with more than one wire\n";
504 nb = analyzer.NbNoPCurve();
505 if(nb>0) di<<nb<<" No pcurve\n";
506 nb = analyzer.NbSolidsWithVoids();
507 if(nb>0) di<<nb<<" SOLID with voids\n";
508 nb = analyzer.NbWireWitnSeam();
509 if(nb>0) di<<nb<<" Wire(s) with one seam edge\n";
510 nb = analyzer.NbWireWithSevSeams();
511 if(nb>0) di<<nb<<" Wire(s) with several seam edges\n";
512 nb = analyzer.NbBigSplines();
513 if(nb>0) di<<nb<<" bigspl : BSpline > 8192 poles\n";
514 nb = analyzer.NbBezierSurf();
515 if(nb>0) di<<nb<<" bezsur : BezierSurface\n";
516 nb = analyzer.NbBSplibeSurf();
517 if(nb>0) di<<nb<<" bspsur : BSplineSurface\n";
518 nb = analyzer.NbC0Curves();
519 if(nb>0) di<<nb<<" c0curv : Curve Only C0\n";
520 nb = analyzer.NbC0Surfaces();
521 if(nb>0) di<<nb<<" c0surf : Surface Only C0\n";
522 nb = analyzer.NbIndirectSurf();
523 if(nb>0) di<<nb<<" indsur : Indirect Surface\n";
524 nb = analyzer.NbOffsetCurves();
525 if(nb>0) di<<nb<<" ofcur : Offset Curve(s)\n";
526 nb = analyzer.NbOffsetSurf();
527 if(nb>0) di<<nb<<" ofsur : Offset Surface\n";
528 nb = analyzer.NbTrimmedCurve2d();
529 if(nb>0) di<<nb<<" trc2d : Trimmed Curve2d\n";
530 nb = analyzer.NbTrimmedCurve3d();
531 if(nb>0) di<<nb<<" trc3d : Trimmed Curve3d\n";
532 nb = analyzer.NbTrimSurf();
533 if(nb>0) di<<nb<<" trimsu : RectangularTrimmedSurface\n";
535 if(arg3 ==NULL) return 0;
537 Handle(TopTools_HSequenceOfShape) sec;
538 if(analyzer.ModifyBigSplineMode()) {
539 sec = analyzer.BigSplineSec();
540 for(Standard_Integer i = 1; i <= sec->Length(); i++) {
541 Sprintf(nompart,"%s_bigspl_%d",arg2,i);
542 DBRep::Set (nompart,sec->Value(i));
545 if(analyzer.ModifyIndirectMode()) {
546 sec = analyzer.IndirectSec();
547 for(Standard_Integer i = 1; i <= sec->Length(); i++) {
548 Sprintf(nompart,"%s_indsur_%d",arg2,i);
549 DBRep::Set (nompart,sec->Value(i));
552 if(analyzer.ModifyOffestSurfaceMode()) {
553 sec = analyzer.OffsetSurfaceSec();
554 for(Standard_Integer i = 1; i <= sec->Length(); i++) {
555 Sprintf(nompart,"%s_ofsur_%d",arg2,i);
556 DBRep::Set (nompart,sec->Value(i));
559 if(analyzer.ModifyTrimmed3dMode()) {
560 sec = analyzer.Trimmed3dSec();
561 for(Standard_Integer i = 1; i <= sec->Length(); i++) {
562 Sprintf(nompart,"%s_trc3d_%d",arg2,i);
563 DBRep::Set (nompart,sec->Value(i));
566 if(analyzer.ModifyOffsetCurveMode()) {
567 sec = analyzer.OffsetCurveSec();
568 for(Standard_Integer i = 1; i <= sec->Length(); i++) {
569 Sprintf(nompart,"%s_ofcur_%d",arg2,i);
570 DBRep::Set (nompart,sec->Value(i));
573 if(analyzer.ModifyTrimmed2dMode()) {
574 sec = analyzer.Trimmed2dSec();
575 for(Standard_Integer i = 1; i <= sec->Length(); i++) {
576 Sprintf(nompart,"%s_trc2d_%d",arg2,i);
577 DBRep::Set (nompart,sec->Value(i));
583 static Standard_Integer XSHAPE_comptoledge
584 (Draw_Interpretor& di, Standard_Integer argc, const char** argv)
588 "> comptol shape [nbpoints=371] [prefix]\n\n"
589 "Computes real tolerance of edges in the shape \n"
590 "as maximal deviation of 3d curve and pcurves.\n"
591 "Deviation is computed by nbpoints sample points (default is 371).\n"
592 "Gives the max, min and average value on all edges in the shape\n"
593 "If prefix is defined, edges with maximal real tolerance and\n"
594 "relation (and corresponding faces) will be saved with such names\n\n";
598 TopoDS_Shape shape = DBRep::Get(argv[1]);
599 if (shape.IsNull()) { di << "Shape name \"" << argv[1] << "\" is invalid\n"; return 1; }
600 Standard_Integer nbpnts = 371;
601 Standard_CString prefix = 0;
603 if ( IsDigit(argv[2][0]) ) {
604 nbpnts = Draw::Atoi(argv[2]);
605 if ( nbpnts <2 ) nbpnts = 2;
606 if ( argc >3 ) prefix = argv[3];
608 else prefix = argv[2];
611 Standard_Integer num = 0;
612 Standard_Real max=0, min=0, ave=0.;
613 Standard_Real relmax=0, relmin=0, relave=0.;
614 ShapeAnalysis_Edge sae;
615 TopoDS_Edge edmax, edmaxrel;
616 for ( TopExp_Explorer exp(shape,TopAbs_EDGE); exp.More(); exp.Next() ) {
618 TopoDS_Edge edge = TopoDS::Edge(exp.Current());
619 sae.CheckSameParameter ( edge, tol, nbpnts );
620 Standard_Real t = BRep_Tool::Tolerance(edge);
621 Standard_Real rel = tol / ( t > Precision::Confusion() ? t : Precision::Confusion() );
624 if ( ! num ) { max = min = tol; relmax = relmin = rel; edmax = edmaxrel = edge; }
626 if ( max < tol ) { max = tol; edmax = edge; }
627 if ( min > tol ) min = tol;
628 if ( relmax < rel ) { relmax = rel; edmaxrel = edge; }
629 if ( relmin > rel ) relmin = rel;
633 if ( ! num ) { di << "No edges found in the shape\n"; return 1; }
635 di << "Edges tolerance computed by " << nbpnts << " points: \n"
636 "MAX=" << max << " AVG=" << ave/num << " MIN=" << min << "\n";
637 di << "Relation real tolerance / tolerance set in edge\n"
638 "MAX=" << relmax << " AVG=" << relave/num << " MIN=" << relmin << "\n";
639 if ( prefix && prefix[0] ) {
641 Sprintf ( name, "%.10s_edge_tol", prefix );
642 DBRep::Set (name,edmax);
643 di << "Edge with max tolerance saved to " << name;
644 if ( edmax.IsSame ( edmaxrel ) ) di << "\n";
646 Sprintf ( name, "%.10s_edge_rel", prefix );
647 DBRep::Set (name,edmaxrel);
648 di << "; edge with max relation saved to " << name << "\n";
650 Standard_Integer num1=0;
651 for ( TopExp_Explorer fac(shape,TopAbs_FACE); fac.More(); fac.Next() ) {
652 TopoDS_Face face = TopoDS::Face ( fac.Current() );
653 for ( TopExp_Explorer ed(face,TopAbs_EDGE); ed.More(); ed.Next() ) {
654 TopoDS_Edge edge = TopoDS::Edge ( ed.Current() );
655 if ( edge.IsSame ( edmax ) || edge.IsSame ( edmaxrel ) ) {
656 if ( ! num1 ) di << "Concerned faces saved to shapes ";
657 Sprintf ( name, "%.10s_%d", prefix, num1+1 );
658 DBRep::Set (name,face);
659 //std::cout << ( num1 ? ", " : "" ) << name;
670 if ( num1 >0 ) di << "\n";
676 //=======================================================================
677 //function : freebounds
679 //=======================================================================
680 static Standard_Integer freebounds (Draw_Interpretor& di,
681 Standard_Integer n, const char** a)
683 if ((n < 3) || (n > 5)) return 1;
684 TopoDS_Shape shape = DBRep::Get(a[1]);
685 if (shape.IsNull()) return 1;
686 Standard_Real toler = Draw::Atof (a[2]);
687 Standard_Boolean splitclosed = Standard_False, splitopen = Standard_False;
688 if ( n > 3) splitclosed = Draw::Atoi (a[3]) != 0;
689 if ( n > 4) splitopen = Draw::Atoi (a[4]) != 0;
691 ShapeAnalysis_FreeBounds F;
693 F = ShapeAnalysis_FreeBounds (shape, splitclosed, splitopen);
695 F = ShapeAnalysis_FreeBounds (shape, toler, splitclosed, splitopen);
698 TopoDS_Shape wires = F.GetClosedWires();
699 Sprintf (name, "%s_c", a[1]);
700 DBRep::Set (name, wires);
701 di << name << " - closed wires\n";
702 wires = F.GetOpenWires();
703 Sprintf (name, "%s_o", a[1]);
704 DBRep::Set (name, wires);
705 di << name << " - open wires\n";
711 //=======================================================================
712 //function : PrintProps
713 //purpose : auxilary for FreeBoundsProps
714 //=======================================================================
715 static void PrintProps(Standard_Integer i,
716 const Handle(ShapeAnalysis_FreeBoundData)& fbd,
717 Draw_Interpretor& di)
721 Standard_Real area = fbd->Area();
722 Standard_Real perimeter = fbd->Perimeter();
723 Standard_Real ratio = fbd->Ratio();
724 Standard_Real width = fbd->Width();
725 Standard_Integer notch = fbd->NbNotches();
726 Sprintf(str," %d\t%12.5f\t%12.5f\t%12.5f\t%12.5f\t%d", i, area, perimeter, ratio, width, notch);
731 //=======================================================================
732 //function : FreeBoundsProps
734 //=======================================================================
735 static Standard_Integer FreeBoundsProps(Draw_Interpretor& di,
736 Standard_Integer n, const char** a)
738 if ( (n < 2)||(n > 5) ) {
739 di<<"Usage : freeprops shapename [tolerance [splitclosed [splitopen]]]\n";
743 TopoDS_Shape source = DBRep::Get(a[1]);
744 if (source.IsNull()) {
745 di<<"Error : unknown shape "<<a[1]<<"\n";
749 Standard_Real toler = 0.;
750 Standard_Boolean splitclosed = Standard_False, splitopen = Standard_False;
751 if (n > 2) toler = Draw::Atof(a[2]);
752 if (n > 3) splitclosed = Draw::Atoi(a[3]) != 0;
753 if (n > 4) splitopen = Draw::Atoi(a[4]) != 0;
754 ShapeAnalysis_FreeBoundsProperties analyzer;
756 analyzer.Init(source, toler, splitclosed, splitopen);
758 analyzer.Init(source, splitclosed, splitopen);
760 TopoDS_Compound closed, open;
763 Standard_Integer nb = analyzer.NbClosedFreeBounds();
765 di<<" \tArea mm2\tLength mm\tRatio L/W\tWidth mm\tNb noth\n";
766 B.MakeCompound(closed);
768 di<<"Closed bounds properties\n";
769 for (Standard_Integer i=1; i <= nb; i++) {
770 Handle(ShapeAnalysis_FreeBoundData) fbd = analyzer.ClosedFreeBound(i);
771 PrintProps(i, fbd, di);
772 B.Add(closed,fbd->FreeBound());
776 nb = analyzer.NbOpenFreeBounds();
777 B.MakeCompound(open);
779 di<<"Open bounds properties\n";
780 for (Standard_Integer i=1; i <= nb; i++) {
781 Handle(ShapeAnalysis_FreeBoundData) fbd = analyzer.OpenFreeBound(i);
782 PrintProps(i, fbd, di);
783 B.Add(open,fbd->FreeBound());
788 Sprintf (name, "%s_c",a[1]);
789 di << name << " - closed wires, ";
790 DBRep::Set(name, closed);
791 Sprintf (name, "%s_o",a[1]);
792 di << name << " - closed wires \n";
793 DBRep::Set(name, open);
798 //=======================================================================
799 //function : closefreebounds
801 //=======================================================================
802 static Standard_Integer closefreebounds (Draw_Interpretor& di,
803 Standard_Integer n, const char** a)
805 if ((n < 4) || (n > 6)) return 1;
806 TopoDS_Shape shape = DBRep::Get(a[1]);
807 if (shape.IsNull()) return 1;
808 Standard_Real sewtoler = Draw::Atof (a[2]), closetoler = Draw::Atof (a[3]);
809 Standard_Boolean splitclosed = Standard_False, splitopen = Standard_False;
810 if ( n > 4) splitclosed = Draw::Atoi (a[3]) != 0;
811 if ( n > 5) splitopen = Draw::Atoi (a[4]) != 0;
813 ShapeFix_FreeBounds F;
815 F = ShapeFix_FreeBounds (shape, closetoler, splitclosed, splitopen);
817 F = ShapeFix_FreeBounds (shape, sewtoler, closetoler, splitclosed, splitopen);
820 TopoDS_Shape wires = F.GetClosedWires();
821 Sprintf (name, "%s_c", a[1]);
822 DBRep::Set (name, wires);
823 di << name << " - closed wires\n";
824 wires = F.GetOpenWires();
825 Sprintf (name, "%s_o", a[1]);
826 DBRep::Set (name, wires);
827 di << name << " - open wires\n";
833 static Standard_Integer getareacontour (Draw_Interpretor& di,
834 Standard_Integer n, const char** a)
837 TopoDS_Shape shape = DBRep::Get(a[1]);
838 if (shape.IsNull()) {
839 di<<"Shape is not defined\n";
842 if(shape.ShapeType() != TopAbs_WIRE) {
843 di<<"invalid type of argument\n";
846 //Handle(ShapeExtend_WireData) asewd = new ShapeExtend_WireData(TopoDS::Wire(shape));
847 Standard_Real anArea = ShapeAnalysis::ContourArea(TopoDS::Wire(shape));
848 di<<"Area = "<<anArea<<"\n";
853 static Standard_Integer checkselfintersection
854 (Draw_Interpretor& di, Standard_Integer argc, const char** argv)
858 di<<"Call please \"checkselfintersection wire [face]\"\n";
863 const char* arg1 = argv[1];
864 TopoDS_Shape wire = DBRep::Get(arg1);
865 if (wire.IsNull() || wire.ShapeType() != TopAbs_WIRE)
867 di<<"A null shape or not a wire is used.\n";
871 // Get face if the user provided us with a face.
875 const char* arg2 = argv[2];
876 face = DBRep::Get(arg2);
877 if (face.IsNull() || face.ShapeType() != TopAbs_FACE)
879 di<<"A null shape or not a face is used.\n";
884 // If the face is null, make a plane inside the wire.
887 BRepBuilderAPI_MakeFace mkFace(TopoDS::Wire(wire), true);
889 face = mkFace.Face();
892 di<<"Can't make a face for the wire. Provide please a face for analysis.\n";
897 ShapeAnalysis_Wire analyser(TopoDS::Wire(wire), TopoDS::Face(face), Precision::Confusion());
898 Standard_Boolean result = analyser.CheckSelfIntersection();
900 if (result == Standard_True)
901 di<<"A self-intersecting wire.\n";
903 di<<"Not self-intersecting wire.\n";
907 static Standard_Integer checkedge(Draw_Interpretor& di, Standard_Integer argc, const char** argv)
911 di<<"Call please \"checkedge edge [face]\"\n";
916 const char* arg1 = argv[1];
917 TopoDS_Shape edge = DBRep::Get(arg1);
918 if (edge.IsNull() || edge.ShapeType() != TopAbs_EDGE)
920 di<<"A null shape or not an edge is used.\n";
928 const char* arg2 = argv[2];
929 face = DBRep::Get(arg2);
930 if (face.IsNull() || face.ShapeType() != TopAbs_FACE)
932 di<<"A null shape or not a face is used.\n";
937 // Analysis of the edge.
938 ShapeAnalysis_Edge analyser;
939 Standard_Boolean isOk(Standard_True);
942 if (analyser.HasCurve3d(TopoDS::Edge(edge)))
945 if (analyser.CheckVerticesWithCurve3d(TopoDS::Edge(edge)))
947 isOk = Standard_False;
948 di<<"Vertices of the edge don't coincide with start/end points of 3d-curve (using tolerance of the vertices).\n";
953 isOk = Standard_False;
954 di<<"Edge doesn't have a 3d-curve\n";
960 if (analyser.HasPCurve(TopoDS::Edge(edge), TopoDS::Face(face)))
963 if (analyser.CheckVerticesWithPCurve(TopoDS::Edge(edge), TopoDS::Face(face)))
965 isOk = Standard_False;
966 di<<"Vertices of the edge don't coincide with start/end points of 2d-curve (using tolerance of the vertices).\n";
971 isOk = Standard_False;
972 di<<"Edge doesn't have a 2d-curve on this face\n";
977 di<<"Edge seems OK.\n";
982 //=======================================================================
983 //function : InitCommands
985 //=======================================================================
987 void SWDRAW_ShapeAnalysis::InitCommands(Draw_Interpretor& theCommands)
989 static Standard_Integer initactor = 0;
996 Standard_CString g = SWDRAW::GroupName();
998 theCommands.Add ("tolerance","shape [tolmin tolmax:real]", __FILE__,tolerance,g);
999 theCommands.Add ("projface","nom_face X Y [Z]", __FILE__,projface,g);
1000 theCommands.Add ("projcurve","nom_edge | curve3d | curve3d first last + X Y Z",
1001 __FILE__,projcurve,g);
1002 theCommands.Add("projpcurve", "edge face tol x y z [start_param]",
1003 __FILE__, projpcurve, g);
1004 theCommands.Add("anaface", "nomface", __FILE__, anaface, g);
1005 theCommands.Add ("statshape","shape [particul] : stats/particularites",
1006 __FILE__,XSHAPE_statshape,g);
1007 theCommands.Add ("comptol","shape [nbpoints]",__FILE__,XSHAPE_comptoledge,g);
1008 theCommands.Add("freebounds",
1009 "shp toler [splitclosed [splitopen]] - free bounds; toler <= 0 for shells (no sewing call)",
1010 __FILE__, freebounds, g);
1012 const char* groupold="DE: old";
1013 theCommands.Add("fbprops",
1014 "shp [toler [splitclosed [splitopen]]] - free bounds properties; toler <= 0 or not specified - for shells (no sewing call)",
1015 __FILE__, FreeBoundsProps, groupold);
1016 theCommands.Add("fbclose",
1017 "shp sewtoler closetoler [splitclosed [splitopen]] - closes free bounds; use sewtoler <= 0 for shells (no sewing call)",
1018 __FILE__, closefreebounds, groupold);
1020 theCommands.Add("getareacontour","wire ",__FILE__, getareacontour, groupold);
1021 theCommands.Add ("checkselfintersection","wire [face]", __FILE__,checkselfintersection,g);
1022 theCommands.Add ("checkedge","edge [face]", __FILE__,checkedge,g);