Test for 0022778: Bug in BRepMesh
[occt.git] / src / SWDRAW / SWDRAW_ShapeAnalysis.cxx
CommitLineData
b311480e 1// Created on: 1999-03-09
2// Created by: data exchange team
3// Copyright (c) 1999-1999 Matra Datavision
4// Copyright (c) 1999-2012 OPEN CASCADE SAS
5//
6// The content of this file is subject to the Open CASCADE Technology Public
7// License Version 6.5 (the "License"). You may not use the content of this file
8// except in compliance with the License. Please obtain a copy of the License
9// at http://www.opencascade.org and read it completely before using this file.
10//
11// The Initial Developer of the Original Code is Open CASCADE S.A.S., having its
12// main offices at: 1, place des Freres Montgolfier, 78280 Guyancourt, France.
13//
14// The Original Code and all software distributed under the License is
15// distributed on an "AS IS" basis, without warranty of any kind, and the
16// Initial Developer hereby disclaims all such warranties, including without
17// limitation, any warranties of merchantability, fitness for a particular
18// purpose or non-infringement. Please see the License for the specific terms
19// and conditions governing the rights and limitations under the License.
20
7fd59977 21// sln 19.11.2001. Bug 2: Correction of output of 'statshape' draw function.
22
23#include <SWDRAW_ShapeAnalysis.ixx>
24#include <stdio.h>
25#include <DBRep.hxx>
26#include <DrawTrSurf.hxx>
27#include <SWDRAW.hxx>
28#include <Precision.hxx>
29#include <gp_Pnt2d.hxx>
30#include <gp_Pnt.hxx>
31#include <Geom_Curve.hxx>
32#include <Geom_Surface.hxx>
33#include <GeomAPI_ProjectPointOnSurf.hxx>
34#include <TopoDS.hxx>
35#include <TopoDS_Shape.hxx>
36#include <TopoDS_Edge.hxx>
37#include <TopoDS_Face.hxx>
38#include <TopTools_HSequenceOfShape.hxx>
39#include <BRep_Tool.hxx>
40#include <BRepBuilderAPI.hxx>
41#include <ShapeAnalysis.hxx>
42#include <ShapeAnalysis_ShapeTolerance.hxx>
43#include <ShapeAnalysis_Curve.hxx>
44#include <ShapeAnalysis_Surface.hxx>
45#include <ShapeAnalysis_Edge.hxx>
46#include <TopExp_Explorer.hxx>
47#include <TopoDS_Wire.hxx>
48#include <gp_Pnt.hxx>
49#include <gp_Pnt2d.hxx>
50#include <TopoDS_Vertex.hxx>
51#include <TopoDS_Iterator.hxx>
52#include <TopoDS_Edge.hxx>
53#include <Geom_Curve.hxx>
54#include <Geom2d_Curve.hxx>
55#include <BRep_Tool.hxx>
56#include <TopExp.hxx>
57#include <GProp_GProps.hxx>
58#include <BRepGProp.hxx>
59#include <BRepTopAdaptor_FClass2d.hxx>
60#include <ShapeAnalysis_ShapeContents.hxx>
ef57920a 61#include <BRepBuilderAPI_MakeFace.hxx>
7fd59977 62
63#include <TopoDS_Compound.hxx>
64#include <BRep_Builder.hxx>
65#include <TColStd_MapOfInteger.hxx>
66#include <TCollection_AsciiString.hxx>
67
68#include <ShapeAnalysis_FreeBounds.hxx>
69#include <ShapeAnalysis_FreeBoundsProperties.hxx>
70#include <ShapeAnalysis_FreeBoundData.hxx>
71#include <ShapeFix_FreeBounds.hxx>
72
73#include <ShapeExtend_WireData.hxx>
ef57920a 74#include <ShapeAnalysis_Wire.hxx>
7fd59977 75
76static Standard_Integer tolerance
77 (Draw_Interpretor& di, Standard_Integer argc, const char** argv)
78{
79 if (argc < 2) { di<<"myshape : analyses a shape\n"
80 << "myshape [mode] valmin : sub-shapes over valmin\n"
81 <<"myshape [mode] valmin valmax : between valmin and valmax\n"
82 <<"myshape [mode] 0 valmax : below valmax\n"
83 <<" more : all shapes(D) v vertices e edges f faces c combined(faces)"<<"\n";
84 return (argc < 2 ? 0 : 1 /* Error */); }
85 Standard_CString arg1 = argv[1];
86 TopoDS_Shape Shape = DBRep::Get(arg1);
87 if (Shape.IsNull()) { di<<"Shape unknown : "<<arg1<<"\n"; return 1 /* Error */; }
88
89 ShapeAnalysis_ShapeTolerance sat;
90 if (argc == 2) {
91 sat.InitTolerance();
92 sat.AddTolerance (Shape);
93 di<<"Tolerance MAX="<<sat.GlobalTolerance(1)<<" AVG="<<sat.GlobalTolerance(0)<<" MIN="<<sat.GlobalTolerance(-1)<<"\n";
94 sat.InitTolerance();
95 sat.AddTolerance (Shape,TopAbs_FACE);
96 di<<"FACE : MAX="<<sat.GlobalTolerance(1)<<" AVG="<<sat.GlobalTolerance(0)<<" MIN="<<sat.GlobalTolerance(-1)<<"\n";
97 sat.InitTolerance();
98 sat.AddTolerance (Shape,TopAbs_EDGE);
99 di<<"EDGE : MAX="<<sat.GlobalTolerance(1)<<" AVG="<<sat.GlobalTolerance(0)<<" MIN="<<sat.GlobalTolerance(-1)<<"\n";
100 sat.InitTolerance();
101 sat.AddTolerance (Shape,TopAbs_VERTEX);
102 di<<"VERTEX : MAX="<<sat.GlobalTolerance(1)<<" AVG="<<sat.GlobalTolerance(0)<<" MIN="<<sat.GlobalTolerance(-1)<<"\n";
103 } else {
104// Analyse plus fouillee
105 Standard_Integer nextarg = 2;
106 char opt = argv[2][0];
107 TopAbs_ShapeEnum type = TopAbs_SHAPE;
108 if (opt == 'a') nextarg = 3;
109 else if (opt == 'c') { nextarg = 3; type = TopAbs_SHELL; }
110 else if (opt == 'e') { nextarg = 3; type = TopAbs_EDGE; }
111 else if (opt == 'f') { nextarg = 3; type = TopAbs_FACE; }
112 else if (opt == 'v') { nextarg = 3; type = TopAbs_VERTEX; }
113 if (nextarg < 3) opt = 'a';
114
115 Standard_Real tol1= 0., tol2= 0.;
116 if (nextarg < argc) tol1 = atof (argv[nextarg]);
117 if (nextarg < argc-1) tol2 = atof (argv[nextarg+1]);
118// Standard_Real tol = atof (argv[2]);
119 Handle(TopTools_HSequenceOfShape) list = sat.InTolerance (Shape,tol1,tol2,type);
120 Standard_Integer i, nb = list->Length();
121 switch (type) {
122 case TopAbs_VERTEX : di<<"Analysing Vertices gives "; break;
123 case TopAbs_EDGE : di<<"Analysing Edges gives "; break;
124 case TopAbs_FACE : di<<"Analysing Faces gives "; break;
125 case TopAbs_SHELL : di<<"Analysing Shells,Faces+content gives "; break;
126 default : di<<"Analysing all sub-shapes gives ";
127 }
128 if (tol1 == 0) di<<nb<<" Shapes below tol="<<tol2;
129 else if (tol2 == 0) di<<nb<<" Shapes over tol="<<tol1;
130 else di<<nb<<" Shapes between tol1="<<tol1<<" and tol2="<<tol2;
131 if (nb == 1) di<<" , named tol_1";
132 if (nb > 1) di<<" , named tol_1 to tol_"<<nb;
133 di<<"\n";
134 char nomsh[30];
135 for (i = 1; i <= nb; i ++) {
136 sprintf (nomsh,"tol_%d",i);
137 DBRep::Set (nomsh,list->Value(i));
138 }
139 }
140 return 0;
141}
142
143static Standard_Integer projface
144 (Draw_Interpretor& di, Standard_Integer argc, const char** argv)
145{
146 if (argc < 4) { di<<"Give FACE name and X Y [Z]"<<"\n"; return 1 /* Error */; }
147 Standard_CString arg1 = argv[1];
148 TopoDS_Shape Shape = DBRep::Get(arg1);
149 if (Shape.IsNull()) { di<<"Shape unknown : "<<arg1<<"\n"; return 1 /* Error */; }
150 if (Shape.ShapeType() != TopAbs_FACE) { di<<"Not a face"<<"\n"; return 1 /* Error */; }
151 TopoDS_Face F = TopoDS::Face (Shape);
152 Handle(Geom_Surface) thesurf = BRep_Tool::Surface (F); // pas locface
153// On y va
154 Standard_Real X,Y,Z,U,V;
155 X = U = atof (argv[2]);
156 Y = V = atof (argv[3]);
157 if (argc > 4) {
158 Z = atof (argv[4]);
159 gp_Pnt P3D (X,Y,Z);
160 di<<" Point 3D X = "<<X<<" Y = "<<Y<<" Z = "<<Z<<"\n";
161 Standard_Real uf, ul, vf, vl;
162 thesurf->Bounds(uf, ul, vf, vl);
163
164 if (Precision::IsInfinite(uf)) uf = -1000;
165 if (Precision::IsInfinite(ul)) ul = 1000;
166 if (Precision::IsInfinite(vf)) vf = -1000;
167 if (Precision::IsInfinite(vl)) vl = 1000;
168 Standard_Real du = Abs(ul-uf)/10; Standard_Real dv = Abs(vl-vf)/10;
169
170 GeomAPI_ProjectPointOnSurf proj(P3D, thesurf, uf-du, ul+du, vf-dv, vl+dv);
171 Standard_Integer sol, nPSurf = proj.NbPoints();
172 di<<" Found "<<nPSurf<<" Points"<<"\n";
173 for (sol = 1; sol <= nPSurf; sol ++) {
174 di<<"n0 "<<sol<<" Distance "<<proj.Distance(sol);
175 proj.Parameters(sol, U,V);
176 di<<" U = "<<U<<" V = "<<V<<"\n";
177// reprojection
178 P3D = thesurf->Value (U,V);
179 di<<" => reproj X = "<<P3D.X()<<" Y = "<<P3D.Y()<<" Z = "<<P3D.Z()<<"\n";
180 }
181// Que donne ShapeTool ?
182 P3D.SetCoord (X,Y,Z);
183 Handle(ShapeAnalysis_Surface) su = new ShapeAnalysis_Surface(thesurf);
184 gp_Pnt2d suval = su->ValueOfUV (P3D,BRep_Tool::Tolerance(F));
185 suval.Coord(U,V);
186 di<<"** ShapeAnalysis_Surface gives U = "<<U<<" V = "<<V<<"\n";
187 P3D = thesurf->Value(U,V);
188 di<<" => reproj X = "<<P3D.X()<<" Y = "<<P3D.Y()<<" Z = "<<P3D.Z()<<"\n";
189
190 } else {
191 di<<" Point UV U = "<<U<<" V = "<<V<<"\n";
192 gp_Pnt P3D = thesurf->Value(U,V);
193 di<<" => proj X = "<<P3D.X()<<" Y = "<<P3D.Y()<<" Z = "<<P3D.Z()<<"\n";
194 }
195 return 0;
196}
197
198static Standard_Integer projcurve
199 (Draw_Interpretor& di, Standard_Integer argc, const char** argv)
200{
201// admet une EDGE ou une CURVE
202 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 */; }
203 const char * arg1 = argv[1];
204 Standard_Integer i0 = 0;
205 TopoDS_Shape Shape = DBRep::Get(arg1);
206
207 Handle(Geom_Curve) C; Standard_Real cf,cl;
208 if (!Shape.IsNull()) {
209 if (Shape.ShapeType() == TopAbs_EDGE) {
210 TopoDS_Edge E = TopoDS::Edge(Shape);
211 C = BRep_Tool::Curve (E,cf,cl);
212 di<<"Edge "<<arg1<<" Params from "<<cf<<" to "<<cl<<"\n";
213 } else {
214 di<<"SHAPE "<<arg1<<" Not an EDGE"<<"\n"; return 1 /* Error */;
215 }
216 } else {
217 const char* a1 = arg1;
218 C = DrawTrSurf::GetCurve (a1);
219 if (C.IsNull())
220 { di<<arg1<<" neither EDGE nor CURVE 3D"<<"\n"; return 1 /* Error */; }
221 cf = C->FirstParameter(); cl = C->LastParameter();
222 if (argc >= 7) { cf = atof (argv[2]); cl = atof (argv[3]); i0 = 2; }
223 di<<"Curve 3D "<<arg1<<" Params from "<<cf<<" to "<<cl<<"\n";
224 }
225
226 Standard_Real X,Y,Z;
227 X = atof (argv[2+i0]);
228 Y = atof (argv[3+i0]);
229 Z = atof (argv[4+i0]);
230 di<<"Precision (BRepBuilderAPI) : "<<BRepBuilderAPI::Precision()
231 <<" Projection : "<<X<<" "<<Y<<" "<<Z<<"\n";
232
233 gp_Pnt P3D (X,Y,Z);
234 gp_Pnt res; Standard_Real param,dist;
235
236 dist = ShapeAnalysis_Curve().Project (C,P3D,BRepBuilderAPI::Precision(),res,param, cf,cl);
237 res.Coord(X,Y,Z);
238 di<<"Result : "<<X<<" "<<Y<<" "<<Z<<"\n"<<"Param = "<<param<<" Gap = "<<dist<<"\n";
239 return 0;
240}
241
242static Standard_Integer anaface
243 (Draw_Interpretor& di, Standard_Integer argc, const char** argv)
244{
245 if (argc < 2) { di<<"donner un nom de face"<<"\n"; return 1 /* Error */; }
246 Standard_CString arg1 = argv[1];
247 TopoDS_Shape Shape = DBRep::Get(arg1);
248 if (Shape.IsNull()) { di<<arg1<<" inconnu"<<"\n"; return 1 /* Error */; }
249// if (Shape.ShapeType() != TopAbs_FACE) { di<<"Pas une FACE"<<"\n"; return 1 /* Error */; }
250
251// On regarde les wires, sont-ils bien fermes
252 Standard_Integer nbw = 0, nbe = 0;
253 Handle(Geom_Surface) surface;
254 TopoDS_Face Face;
255 if (Shape.ShapeType() == TopAbs_FACE) {
256 Face = TopoDS::Face(Shape);
257 surface = BRep_Tool::Surface (Face); // pas locface
258// TopLoc_Location locface;
259 di<<"Face, surface type = "<<surface->DynamicType()->Name()<<" Tol="<<BRep_Tool::Tolerance(Face);
260 if (Face.Orientation() == TopAbs_REVERSED) {
261 di<<" (REV)";
262// Face.Orientation(TopAbs_FORWARD);
263 }
264 di<<"\n";
265 }
266 else { di<<"Analyse Wires, Ignore Faces"<<"\n"; }
267 Standard_Boolean iasurf = !surface.IsNull();
268//:sw if (!Face.IsNull()) STW.SetFace (Face);
269//:sw else STW.SetPrecision (BRepBuilderAPI::Precision());
270
271 for (TopExp_Explorer exp(Shape,TopAbs_WIRE); exp.More(); exp.Next()) {
272 TopoDS_Wire Wire = TopoDS::Wire (exp.Current()); nbw ++; nbe = 0;
273 di<<"WIRE "<<nbw;
274 if (Wire.Orientation() == TopAbs_FORWARD) di<<" (FWD)"<<"\n";
275 else di<<" (REV)"<<"\n";
276 gp_Pnt fin,debut;
277 gp_Pnt2d finuv,debuv; gp_XY baseuv;
278 TopoDS_Vertex fv,lv;
279 Standard_Real maxp3d = 0., maxuv = 0., maxvtx = 0.;
280 Standard_Real df3d= 0.,dl3d= 0.,dvtx= 0.,duv= 0.;
281 Standard_Boolean iaw2d = iasurf;
282 Standard_Real u1= 0.,u2= 0.,v1= 0.,v2= 0.,umin= 0.,umax= 0.,vmin= 0.,vmax= 0., totcross= 0.;
283
284//:sw STW.ClearWire(); STW.Load (Wire);
285// if (STW.Reorder()) di<<"Wire reordered to explore"<<"\n";
286// for (TopExp_Explorer exe(Wire.Oriented(TopAbs_FORWARD),TopAbs_EDGE); exe.More(); exe.Next()) {
287// TopoDS_Edge Edge = TopoDS::Edge (exe.Current()); nbe ++;
288//:sw for (nbe = 1; nbe <= STW.NbEdges(); nbe ++) {
289//:sw TopoDS_Edge Edge = STW.Edge(nbe);
290 TopoDS_Iterator it (Wire); //:sw: ShapeTool_Wire -> TopoDS_Iterator (it is the same)
291 for (; it.More(); it.Next()) {
292 TopoDS_Edge Edge = TopoDS::Edge (it.Value());
293
294 di<<"Wire "<<nbw<<", Edge "<<nbe;
295 if (Edge.Orientation() == TopAbs_FORWARD) di<<" (FWD";
296 else di<<" (REV";
297 di<<" , Tol= "<<BRep_Tool::Tolerance (Edge)<<" )"<<"\n";
298 Standard_Real f3d,l3d,f2d,l2d;
299 Handle(Geom_Curve) curve3d = BRep_Tool::Curve (Edge,f3d,l3d);
300 Handle(Geom2d_Curve) curve2d;
301 if (iasurf) curve2d = BRep_Tool::CurveOnSurface(Edge,Face,f2d,l2d);
302 Standard_Boolean ia2d = !curve2d.IsNull(); iaw2d |= ia2d;
303 if (!ia2d) di<<"-- No PCurve"<<"\n";
304 if (curve3d.IsNull()) di<<"-- no Curve 3d"<<"\n";
305
306// On va tacher de calculer les positions et les comparer
307 gp_Pnt2d fuv,luv;
308 if (Edge.Orientation() == TopAbs_FORWARD)
309 { TopExp::Vertices (Edge,fv,lv);
310 if (ia2d) BRep_Tool::UVPoints (Edge,Face,fuv,luv); }
311 else
312 { TopExp::Vertices (Edge,lv,fv);
313 if (ia2d) BRep_Tool::UVPoints (Edge,Face,luv,fuv); }
314 gp_Pnt fp = BRep_Tool::Pnt (fv);
315 gp_Pnt lp = BRep_Tool::Pnt (lv);
316 gp_Pnt fxyz, lxyz;
317 if (ia2d) {
318 surface->D0 (fuv.X(),fuv.Y(),fxyz);
319 surface->D0 (luv.X(),luv.Y(),lxyz);
320 df3d = fp.Distance (fxyz); maxp3d = Max (maxp3d,df3d);
321 dl3d = lp.Distance (lxyz); maxp3d = Max (maxp3d,dl3d);
322 if (nbe > 1) duv = finuv.Distance (fuv); maxuv = Max (maxuv, duv);
323// et les min-max
324 u1 = Min (fuv.X(),luv.X()); u2 = Max (fuv.X(),luv.X());
325 v1 = Min (fuv.Y(),luv.Y()); v2 = Max (fuv.Y(),luv.Y());
326 if (nbe == 1) { umin = u1; umax = u2; vmin = v1; vmax = v2; }
327 else { umin = Min(umin,u1); umax = Max(umax,u2); vmin = Min(vmin,v1); vmax = Max(vmax,v2); }
328// et la classification directe
329 if (nbe == 1) { baseuv = fuv.XY(); totcross = 0; }
330 else {
331 gp_XY buv1 = fuv.XY() - baseuv;
332 gp_XY buv2 = luv.XY() - baseuv;
333 totcross += buv2.Crossed(buv1);
334 }
335 }
336
337// Resultats ...
338 if (nbe == 1) { debut = fxyz; debuv = fuv; }
339 else {
340 duv = finuv.Distance (fuv); maxuv = Max (maxuv, duv);
341 dvtx = fin.Distance (fxyz); maxvtx = Max (maxvtx,dvtx);
342 di<<" Fin("<<nbe-1<<")-Debut("<<nbe<<"): DISTANCE="<<dvtx;
343 if (ia2d) di<<" DeltaUV="<<duv;
344 di<<" Tol(Fin)="<<BRep_Tool::Tolerance(lv)<<"\n";
345 }
346 fin = lxyz; finuv = luv;
347
348 di<<"-- Deb : VTX="<<fp.X()<<" , "<<fp.Y()<<" , "<<fp.Z()
349 <<"\n XYZ="<<fxyz.X()<<" , "<<fxyz.Y()<<" , "<<fxyz.Z()
350 <<"\n UV="<<fuv.X()<<" , "<<fuv.Y()<<" -- D.UV/3D="<<df3d<<"\n";
351 di<<"-- Fin : VTX="<<lp.X()<<" , "<<lp.Y()<<" , "<<lp.Z()
352 <<"\n XYZ="<<lxyz.X()<<" , "<<lxyz.Y()<<" , "<<lxyz.Z()
353 <<"\n UV="<<luv.X()<<" , "<<luv.Y()<<" -- D.UV/3D="<<dl3d<<"\n";
354 }
355 dvtx = fin.Distance (debut); maxvtx = Max (maxvtx,dvtx);
356 if (iaw2d) { duv = finuv.Distance (debuv); maxuv = Max (maxuv, duv); }
357 di<<" Fin("<<nbe<<")-Debut(1): DISTANCE="<<dvtx;
358 if (iaw2d) di <<" DeltaUV="<<duv;
359 di<<" Tol(Fin)="<<BRep_Tool::Tolerance(lv)<<"\n";
360
361 di<<" Wire "<<nbw<<" Max : Dist.Vertex="<<maxvtx;
362 if (iaw2d) di<<" Ecart UV/3D="<<maxp3d<<" DeltaUV="<<maxuv;
363 di<<"\n";
364// Min Max
365 if (iaw2d) {
366 di<<"TotCross="<<totcross;
367 di<<" UMin-Max:"<<umin<<" , "<<umax<<" VMin-Max:"<<vmin<<" , "<<vmax<<"\n";
368 Standard_Real difu = umax - umin, difv = vmax - vmin;
369 GProp_GProps G;
370 BRepGProp::SurfaceProperties(Face,G);
371 if (G.Mass() > 0) di<<"GProps:Mass Out"<<"\n";
372 else di<<"GProps:Mass In"<<"\n";
373/// return (G.Mass() > 0);
374 BRepTopAdaptor_FClass2d fcl (Face,BRep_Tool::Tolerance(Face));
375 if (fcl.PerformInfinitePoint () == TopAbs_OUT) di<<"Classifier Infinite : Out"<<"\n";
376 else di<<"Classifier Infinite : In"<<"\n";
377 gp_Pnt2d pcl;
378 pcl.SetCoord(umin-difu,vmin-difv);
379 if (fcl.Perform (pcl) == TopAbs_OUT) di<<"Classifier UMin-VMin : Out"<<"\n";
380 pcl.SetCoord(umin-difu,vmax+difv);
381 if (fcl.Perform (pcl) == TopAbs_OUT) di<<"Classifier UMin-VMax : Out"<<"\n";
382 pcl.SetCoord(umax+difu,vmin-difv);
383 if (fcl.Perform (pcl) == TopAbs_OUT) di<<"Classifier UMax-VMin : Out"<<"\n";
384 pcl.SetCoord(umax+difu,vmax+difv);
385 if (fcl.Perform (pcl) == TopAbs_OUT) di<<"Classifier UMax-VMax : Out"<<"\n";
386 }
387 }
388 if (ShapeAnalysis::IsOuterBound (Face)) di<<"ShapeAnalysis: Outer Bound"<<"\n";
389 else di<<"ShapeAnalysis: Not Outer Bound"<<"\n";
390 di<<" Total "<<nbw<<" Wire(s)"<<"\n";
391 return 0;
392}
393
394static Standard_Integer XSHAPE_statshape(Draw_Interpretor& di, Standard_Integer argc, const char** argv)
395{
396 if (argc < 2) { di<<"ShapeName; + options : prefix for particular cases : what to get"<<"\n"; return 1 /* Error */; }
397 Standard_CString arg1 = argv[1];
398 Standard_CString arg2 = NULL;
399 Standard_CString arg3 = NULL;
400 if (argc > 2) arg2 = argv[2];
401 if (argc > 3) arg3 = argv[3];
402 TopoDS_Shape Shape = DBRep::Get(arg1);
403 if (Shape.IsNull()) { di<<"Shape unknown : "<<arg1<<"\n"; return 1 /* Error */; }
404 char nompart[100];
405 Standard_Integer nb;
406
407 ShapeAnalysis_ShapeContents analyzer;
408 if(argc > 3) {
409 analyzer.ModifyBigSplineMode()=(strstr("bigspl",arg3)!=NULL);
410 analyzer.ModifyIndirectMode()=(strstr("indsur",arg3)!=NULL);
411 analyzer.ModifyOffestSurfaceMode()=(strstr("ofsur",arg3)!=NULL);
412 analyzer.ModifyTrimmed3dMode()=(strstr("trc3d",arg3)!=NULL);
413 analyzer.ModifyOffsetCurveMode()=(strstr("ofcur",arg3)!=NULL);
414 analyzer.ModifyTrimmed2dMode()=(strstr("trc2d",arg3)!=NULL);
415 }
416 analyzer.Perform(Shape);
417
418 di<<"Count Item\n----- ----"<<"\n";
419 nb = analyzer.NbEdges();
420 if(nb>0) di<<nb<<" "<<" EDGE (Oriented)"<<"\n";
421 nb = analyzer.NbSharedEdges();
422 if(nb>0) di<<nb<<" "<<" EDGE (Shared)"<<"\n";
423 nb = analyzer.NbFreeEdges();
424 if(nb>0) di<<nb<<" "<<" EDGE (Free)"<<"\n";
425 nb = analyzer.NbFaces();
426 if(nb>0) di<<nb<<" "<<" FACE"<<"\n";
427 nb = analyzer.NbFreeFaces();
428 if(nb>0) di<<nb<<" "<<" FACE (Free)"<<"\n";
429 nb = analyzer.NbFreeWires();
430 if(nb>0) di<<nb<<" "<<" WIRE (Free)"<<"\n";
431 nb = analyzer.NbShells();
432 if(nb>0) di<<nb<<" "<<" SHELL"<<"\n";
433 nb = analyzer.NbSolids();
434 if(nb>0) di<<nb<<" "<<" SOLID"<<"\n";
435 nb = analyzer.NbVertices();
436 if(nb>0) di<<nb<<" "<<" VERTEX (Oriented)"<<"\n";
437 nb = analyzer.NbSharedVertices();
438 if(nb>0) di<<nb<<" "<<" VERTEX (Shared)"<<"\n";
439 nb = analyzer.NbWires();
440 if(nb>0) di<<nb<<" "<<" WIRE"<<"\n";
441 nb = analyzer.NbFaceWithSevWires();
442 if(nb>0) di<<nb<<" "<<"Face with more than one wire"<<"\n";
443 nb = analyzer.NbNoPCurve();
444 if(nb>0) di<<nb<<" "<<"No pcurve"<<"\n";
445 nb = analyzer.NbSolidsWithVoids();
446 if(nb>0) di<<nb<<" "<<"SOLID with voids"<<"\n";
447 nb = analyzer.NbWireWitnSeam();
448 if(nb>0) di<<nb<<" "<<"Wire(s) with one seam edge"<<"\n";
449 nb = analyzer.NbWireWithSevSeams();
450 if(nb>0) di<<nb<<" "<<"Wire(s) with several seam edges"<<"\n";
451 nb = analyzer.NbBigSplines();
452 if(nb>0) di<<nb<<" "<<"bigspl : BSpline > 8192 poles"<<"\n";
453 nb = analyzer.NbBezierSurf();
454 if(nb>0) di<<nb<<" "<<"bezsur : BezierSurface"<<"\n";
455 nb = analyzer.NbBSplibeSurf();
456 if(nb>0) di<<nb<<" "<<"bspsur : BSplineSurface"<<"\n";
457 nb = analyzer.NbC0Curves();
458 if(nb>0) di<<nb<<" "<<"c0curv : Curve Only C0"<<"\n";
459 nb = analyzer.NbC0Surfaces();
460 if(nb>0) di<<nb<<" "<<"c0surf : Surface Only C0"<<"\n";
461 nb = analyzer.NbIndirectSurf();
462 if(nb>0) di<<nb<<" "<<"indsur : Indirect Surface"<<"\n";
463 nb = analyzer.NbOffsetCurves();
464 if(nb>0) di<<nb<<" "<<"ofcur : Offset Curve(s)"<<"\n";
465 nb = analyzer.NbOffsetSurf();
466 if(nb>0) di<<nb<<" "<<"ofsur : Offset Surface"<<"\n";
467 nb = analyzer.NbTrimmedCurve2d();
468 if(nb>0) di<<nb<<" "<<"trc2d : Trimmed Curve2d"<<"\n";
469 nb = analyzer.NbTrimmedCurve3d();
470 if(nb>0) di<<nb<<" "<<"trc3d : Trimmed Curve3d"<<"\n";
471 nb = analyzer.NbTrimSurf();
472 if(nb>0) di<<nb<<" "<<"trimsu : RectangularTrimmedSurface"<<"\n";
473
474 if(arg3 ==NULL) return 0;
475
476 Handle(TopTools_HSequenceOfShape) sec;
477 if(analyzer.ModifyBigSplineMode()) {
478 sec = analyzer.BigSplineSec();
479 for(Standard_Integer i = 1; i <= sec->Length(); i++) {
480 sprintf(nompart,"%s_bigspl_%d",arg2,i);
481 DBRep::Set (nompart,sec->Value(i));
482 }
483 }
484 if(analyzer.ModifyIndirectMode()) {
485 sec = analyzer.IndirectSec();
486 for(Standard_Integer i = 1; i <= sec->Length(); i++) {
487 sprintf(nompart,"%s_indsur_%d",arg2,i);
488 DBRep::Set (nompart,sec->Value(i));
489 }
490 }
491 if(analyzer.ModifyOffestSurfaceMode()) {
492 sec = analyzer.OffsetSurfaceSec();
493 for(Standard_Integer i = 1; i <= sec->Length(); i++) {
494 sprintf(nompart,"%s_ofsur_%d",arg2,i);
495 DBRep::Set (nompart,sec->Value(i));
496 }
497 }
498 if(analyzer.ModifyTrimmed3dMode()) {
499 sec = analyzer.Trimmed3dSec();
500 for(Standard_Integer i = 1; i <= sec->Length(); i++) {
501 sprintf(nompart,"%s_trc3d_%d",arg2,i);
502 DBRep::Set (nompart,sec->Value(i));
503 }
504 }
505 if(analyzer.ModifyOffsetCurveMode()) {
506 sec = analyzer.OffsetCurveSec();
507 for(Standard_Integer i = 1; i <= sec->Length(); i++) {
508 sprintf(nompart,"%s_ofcur_%d",arg2,i);
509 DBRep::Set (nompart,sec->Value(i));
510 }
511 }
512 if(analyzer.ModifyTrimmed2dMode()) {
513 sec = analyzer.Trimmed2dSec();
514 for(Standard_Integer i = 1; i <= sec->Length(); i++) {
515 sprintf(nompart,"%s_trc2d_%d",arg2,i);
516 DBRep::Set (nompart,sec->Value(i));
517 }
518 }
519 return 0;
520}
521
522static Standard_Integer XSHAPE_comptoledge
523 (Draw_Interpretor& di, Standard_Integer argc, const char** argv)
524{
525 if ( argc <2 ) {
526 di << "Use:\n"
527 "> comptol shape [nbpoints=371] [prefix]\n\n"
528 "Computes real tolerance of edges in the shape \n"
529 "as maximal deviation of 3d curve and pcurves.\n"
530 "Deviation is computed by nbpoints sample points (default is 371).\n"
531 "Gives the max, min and average value on all edges in the shape\n"
532 "If prefix is defined, edges with maximal real tolerance and\n"
533 "relation (and corresponding faces) will be saved with such names\n" << "\n";
534 return 0;
535 }
536
537 TopoDS_Shape shape = DBRep::Get(argv[1]);
538 if (shape.IsNull()) { di << "Shape name \"" << argv[1] << "\" is invalid" << "\n"; return 1; }
539 Standard_Integer nbpnts = 371;
540 Standard_CString prefix = 0;
541 if ( argc >2 ) {
542 if ( IsDigit(argv[2][0]) ) {
543 nbpnts = atoi(argv[2]);
544 if ( nbpnts <2 ) nbpnts = 2;
545 if ( argc >3 ) prefix = argv[3];
546 }
547 else prefix = argv[2];
548 }
549
550 Standard_Integer num = 0;
551 Standard_Real max=0, min=0, ave=0.;
552 Standard_Real relmax=0, relmin=0, relave=0.;
553 ShapeAnalysis_Edge sae;
554 TopoDS_Edge edmax, edmaxrel;
555 for ( TopExp_Explorer exp(shape,TopAbs_EDGE); exp.More(); exp.Next() ) {
556 Standard_Real tol;
557 TopoDS_Edge edge = TopoDS::Edge(exp.Current());
558 sae.CheckSameParameter ( edge, tol, nbpnts );
559 Standard_Real t = BRep_Tool::Tolerance(edge);
560 Standard_Real rel = tol / ( t > Precision::Confusion() ? t : Precision::Confusion() );
561 ave += tol;
562 relave += rel;
563 if ( ! num ) { max = min = tol; relmax = relmin = rel; edmax = edmaxrel = edge; }
564 else {
565 if ( max < tol ) { max = tol; edmax = edge; }
566 if ( min > tol ) min = tol;
567 if ( relmax < rel ) { relmax = rel; edmaxrel = edge; }
568 if ( relmin > rel ) relmin = rel;
569 }
570 num++;
571 }
572 if ( ! num ) { di << "No edges found in the shape" << "\n"; return 1; }
573
574 di << "Edges tolerance computed by " << nbpnts << " points: \n"
575 "MAX=" << max << " AVG=" << ave/num << " MIN=" << min << "\n";
576 di << "Relation real tolerance / tolerance set in edge\n"
577 "MAX=" << relmax << " AVG=" << relave/num << " MIN=" << relmin << "\n";
578 if ( prefix && prefix[0] ) {
579 char name[21];
580 sprintf ( name, "%.10s_edge_tol", prefix );
581 DBRep::Set (name,edmax);
582 di << "Edge with max tolerance saved to " << name;
583 if ( edmax.IsSame ( edmaxrel ) ) di << "\n";
584 else {
585 sprintf ( name, "%.10s_edge_rel", prefix );
586 DBRep::Set (name,edmaxrel);
587 di << "; edge with max relation saved to " << name << "\n";
588 }
589 Standard_Integer num1=0;
590 for ( TopExp_Explorer fac(shape,TopAbs_FACE); fac.More(); fac.Next() ) {
591 TopoDS_Face face = TopoDS::Face ( fac.Current() );
592 for ( TopExp_Explorer ed(face,TopAbs_EDGE); ed.More(); ed.Next() ) {
593 TopoDS_Edge edge = TopoDS::Edge ( ed.Current() );
594 if ( edge.IsSame ( edmax ) || edge.IsSame ( edmaxrel ) ) {
595 if ( ! num1 ) di << "Concerned faces saved to shapes ";
596 sprintf ( name, "%.10s_%d", prefix, num1+1 );
597 DBRep::Set (name,face);
598 //cout << ( num1 ? ", " : "" ) << name;
599 if (num1 == 0) {
600 di << "" << name;
601 } else {
602 di << ", " << name;
603 }
604 num1++;
605 break;
606 }
607 }
608 }
609 if ( num1 >0 ) di << "\n";
610 }
611 return 0;
612}
613
614
615//=======================================================================
616//function : freebounds
617//purpose :
618//=======================================================================
619static Standard_Integer freebounds (Draw_Interpretor& di,
620 Standard_Integer n, const char** a)
621{
622 if ((n < 3) || (n > 5)) return 1;
623 TopoDS_Shape shape = DBRep::Get(a[1]);
624 if (shape.IsNull()) return 1;
625 Standard_Real toler = atof (a[2]);
626 Standard_Boolean splitclosed = Standard_False, splitopen = Standard_False;
627 if ( n > 3) splitclosed = atoi (a[3]);
628 if ( n > 4) splitopen = atoi (a[4]);
629
630 ShapeAnalysis_FreeBounds F;
631 if (toler <= 0)
632 F = ShapeAnalysis_FreeBounds (shape, splitclosed, splitopen);
633 else
634 F = ShapeAnalysis_FreeBounds (shape, toler, splitclosed, splitopen);
635
636 char name[100];
637 TopoDS_Shape wires = F.GetClosedWires();
638 sprintf (name, "%s_c", a[1]);
639 DBRep::Set (name, wires);
640 di << name << " - closed wires" << "\n";
641 wires = F.GetOpenWires();
642 sprintf (name, "%s_o", a[1]);
643 DBRep::Set (name, wires);
644 di << name << " - open wires" << "\n";
645
646 return 0;
647}
648
649
650//=======================================================================
651//function : PrintProps
652//purpose : auxilary for FreeBoundsProps
653//=======================================================================
654static void PrintProps(Standard_Integer i,
655 const Handle(ShapeAnalysis_FreeBoundData)& fbd,
656 Draw_Interpretor& di)
657{
658 char str[100];
659
660 Standard_Real area = fbd->Area();
661 Standard_Real perimeter = fbd->Perimeter();
662 Standard_Real ratio = fbd->Ratio();
663 Standard_Real width = fbd->Width();
664 Standard_Integer notch = fbd->NbNotches();
665 sprintf(str," %d\t%12.5f\t%12.5f\t%12.5f\t%12.5f\t%d", i, area, perimeter, ratio, width, notch);
666 di<<str<<"\n";
667}
668
669
670//=======================================================================
671//function : FreeBoundsProps
672//purpose :
673//=======================================================================
674static Standard_Integer FreeBoundsProps(Draw_Interpretor& di,
675 Standard_Integer n, const char** a)
676{
677 if ( (n < 2)||(n > 5) ) {
678 di<<"Usage : freeprops shapename [tolerance [splitclosed [splitopen]]]"<<"\n";
679 return 1;
680 }
681
682 TopoDS_Shape source = DBRep::Get(a[1]);
683 if (source.IsNull()) {
684 di<<"Error : unknown shape "<<a[1]<<"\n";
685 return 1;
686 }
687
688 Standard_Real toler = 0.;
689 Standard_Boolean splitclosed = Standard_False, splitopen = Standard_False;
690 if (n > 2) toler = atof(a[2]);
691 if (n > 3) splitclosed = atoi(a[3]);
692 if (n > 4) splitopen = atoi(a[4]);
693 ShapeAnalysis_FreeBoundsProperties analyzer;
694 if (toler > 0)
695 analyzer.Init(source, toler, splitclosed, splitopen);
696 else
697 analyzer.Init(source, splitclosed, splitopen);
698 analyzer.Perform();
699 TopoDS_Compound closed, open;
700 BRep_Builder B;
701
702 Standard_Integer nb = analyzer.NbClosedFreeBounds();
703 di<<"\n";
704 di<<" \t"<<"Area mm2"<<"\t"<<"Length mm"<<"\t"<<"Ratio L/W"<<"\t"<<"Width mm"<<"\t"<<"Nb noth"<<"\n";
705 B.MakeCompound(closed);
706 if (nb) {
707 di<<"Closed bounds properties"<<"\n";
708 for (Standard_Integer i=1; i <= nb; i++) {
709 Handle(ShapeAnalysis_FreeBoundData) fbd = analyzer.ClosedFreeBound(i);
710 PrintProps(i, fbd, di);
711 B.Add(closed,fbd->FreeBound());
712 }
713 }
714
715 nb = analyzer.NbOpenFreeBounds();
716 B.MakeCompound(open);
717 if (nb) {
718 di<<"Open bounds properties"<<"\n";
719 for (Standard_Integer i=1; i <= nb; i++) {
720 Handle(ShapeAnalysis_FreeBoundData) fbd = analyzer.OpenFreeBound(i);
721 PrintProps(i, fbd, di);
722 B.Add(open,fbd->FreeBound());
723 }
724 }
725
726 char name[100];
727 sprintf (name, "%s_c",a[1]);
728 di << name << " - closed wires, ";
729 DBRep::Set(name, closed);
730 sprintf (name, "%s_o",a[1]);
731 di << name << " - closed wires " << "\n";
732 DBRep::Set(name, open);
733 return 0;
734}
735
736
737//=======================================================================
738//function : closefreebounds
739//purpose :
740//=======================================================================
741static Standard_Integer closefreebounds (Draw_Interpretor& di,
742 Standard_Integer n, const char** a)
743{
744 if ((n < 4) || (n > 6)) return 1;
745 TopoDS_Shape shape = DBRep::Get(a[1]);
746 if (shape.IsNull()) return 1;
747 Standard_Real sewtoler = atof (a[2]), closetoler = atof (a[3]);
748 Standard_Boolean splitclosed = Standard_False, splitopen = Standard_False;
749 if ( n > 4) splitclosed = atoi (a[3]);
750 if ( n > 5) splitopen = atoi (a[4]);
751
752 ShapeFix_FreeBounds F;
753 if (sewtoler <= 0)
754 F = ShapeFix_FreeBounds (shape, closetoler, splitclosed, splitopen);
755 else
756 F = ShapeFix_FreeBounds (shape, sewtoler, closetoler, splitclosed, splitopen);
757
758 char name[100];
759 TopoDS_Shape wires = F.GetClosedWires();
760 sprintf (name, "%s_c", a[1]);
761 DBRep::Set (name, wires);
762 di << name << " - closed wires" << "\n";
763 wires = F.GetOpenWires();
764 sprintf (name, "%s_o", a[1]);
765 DBRep::Set (name, wires);
766 di << name << " - open wires" << "\n";
767
768 return 0;
769}
770
771
772//=======================================================================
773//function : MyVISEDG
774//purpose :
775//=======================================================================
776static Standard_Integer MyVISEDG (Draw_Interpretor& /*di*/,
777 Standard_Integer n, const char** a)
778{
779 if (n >4) return 1;
780 TopoDS_Shape MaListe = DBRep::Get(a[1]);
781 if (MaListe.IsNull()) return 1;
782 TopoDS_Compound TheList = TopoDS::Compound(MaListe);
783 if (TheList.IsNull()) return 1;
784 Standard_Real toler = 0.001;
785 int create = 0;
786 if ( n >= 3) toler = atof(a[2]);
787 if (n == 4 && !strcmp(a[3],"C")) create = 1;
788 ShapeAnalysis_FreeBounds F(TheList,toler);
789 //
790 //
791 //
792 char name[100];
793 char num[5];
794 if (!create)
795 {
796 TopoDS_Compound Wires = F.GetClosedWires();
797 TopoDS_Iterator S(Wires);
798 Standard_Integer iwire = 0;
799 while (S.More())
800 {
801 sprintf (num,"%d",iwire);
802 name[0] = 'w';
803 name[1] = '\0';
804 strncat(name,num,strlen(num));
805 name[strlen(name)] = '\0';
806 DBRep::Set(name,S.Value());
807 S.Next();
808 iwire++;
809 }
810 iwire = 0;
811 TopoDS_Compound Edges = F.GetOpenWires();
812 S.Initialize(Edges);
813 iwire = 0;
814 while (S.More())
815 {
816 sprintf (num,"%d",iwire);
817 name[0] = 'E';
818 name[1] = '\0';
819 strncat(name,num,strlen(num));
820 name[strlen(name)] = '\0';
821 DBRep::Set(name,S.Value());
822 S.Next();
823 iwire++;
824 }
825 }
826 else
827 {
828 }
829 return 0;
830}
831
832static Standard_Integer getareacontour (Draw_Interpretor& di,
833 Standard_Integer n, const char** a)
834{
835 if (n < 2) return 1;
836 TopoDS_Shape shape = DBRep::Get(a[1]);
837 if (shape.IsNull()) {
838 di<<"Shape is not defined"<<"\n";
839 return 1;
840 }
841 if(shape.ShapeType() != TopAbs_WIRE) {
842 di<<"invalid type of argument"<<"\n";
843 return 1;
844 }
845 //Handle(ShapeExtend_WireData) asewd = new ShapeExtend_WireData(TopoDS::Wire(shape));
846 Standard_Real anArea = ShapeAnalysis::ContourArea(TopoDS::Wire(shape));
847 di<<"Area = "<<anArea<<"\n";
848 return 0;
849}
850
ef57920a
V
851
852static Standard_Integer checkselfintersection
853 (Draw_Interpretor& di, Standard_Integer argc, const char** argv)
854{
855 if (argc < 2)
856 {
857 di<<"Call please \"checkselfintersection wire [face]\""<<"\n";
858 return 1;
859 }
860
861 // Get wire.
862 const char* arg1 = argv[1];
863 TopoDS_Shape wire = DBRep::Get(arg1);
864 if (wire.IsNull() || wire.ShapeType() != TopAbs_WIRE)
865 {
866 di<<"A null shape or not a wire is used."<<"\n";
867 return 2;
868 }
869
870 // Get face if the user provided us with a face.
871 TopoDS_Shape face;
872 if (argc > 2)
873 {
874 const char* arg2 = argv[2];
875 face = DBRep::Get(arg2);
876 if (face.IsNull() || face.ShapeType() != TopAbs_FACE)
877 {
878 di<<"A null shape or not a face is used."<<"\n";
879 return 3;
880 }
881 }
882
883 // If the face is null, make a plane inside the wire.
884 if (face.IsNull())
885 {
886 BRepBuilderAPI_MakeFace mkFace(TopoDS::Wire(wire), true);
887 if (mkFace.IsDone())
888 face = mkFace.Face();
889 else
890 {
891 di<<"Can't make a face for the wire. Provide please a face for analysis."<<"\n";
892 return 4;
893 }
894 }
895
896 ShapeAnalysis_Wire analyser(TopoDS::Wire(wire), TopoDS::Face(face), Precision::Confusion());
897 Standard_Boolean result = analyser.CheckSelfIntersection();
898
899 if (result == Standard_True)
900 di<<"A self-intersecting wire."<<"\n";
901 else
902 di<<"Not self-intersecting wire."<<"\n";
903 return 0;
904}
905
7fd59977 906//=======================================================================
907//function : InitCommands
908//purpose :
909//=======================================================================
910
911 void SWDRAW_ShapeAnalysis::InitCommands(Draw_Interpretor& theCommands)
912{
913 static Standard_Integer initactor = 0;
914 if (initactor) return; initactor = 1;
915
916 Standard_CString g = SWDRAW::GroupName();
917
918 theCommands.Add ("tolerance","shape [tolmin tolmax:real]", __FILE__,tolerance,g);
919 theCommands.Add ("projface","nom_face X Y [Z]", __FILE__,projface,g);
920 theCommands.Add ("projcurve","nom_edge | curve3d | curve3d first last + X Y Z",
921 __FILE__,projcurve,g);
922 theCommands.Add ("anaface","nomface",__FILE__,anaface,g);
923 theCommands.Add ("statshape","shape [particul] : stats/particularites",
924 __FILE__,XSHAPE_statshape,g);
925 theCommands.Add ("comptol","shape [nbpoints]",__FILE__,XSHAPE_comptoledge,g);
926 theCommands.Add("freebounds",
927 "shp toler [splitclosed [splitopen]] - free bounds; toler <= 0 for shells (no sewing call)",
928 __FILE__, freebounds, g);
929
930 const char* groupold="DE: old";
931 theCommands.Add("fbprops",
932 "shp [toler [splitclosed [splitopen]]] - free bounds properties; toler <= 0 or not specified - for shells (no sewing call)",
933 __FILE__, FreeBoundsProps, groupold);
934 theCommands.Add("fbclose",
935 "shp sewtoler closetoler [splitclosed [splitopen]] - closes free bounds; use sewtoler <= 0 for shells (no sewing call)",
936 __FILE__, closefreebounds, groupold);
937 theCommands.Add("K_VISEDG",
938 "K_VISEDG Visu of free edge of a compound of faces.",
939 __FILE__, MyVISEDG, groupold);
940
941 theCommands.Add("getareacontour","wire ",__FILE__, getareacontour, groupold);
ef57920a 942 theCommands.Add ("checkselfintersection","wire [face]", __FILE__,checkselfintersection,g);
7fd59977 943}