0028026: Modeling Data - BRepTools::Clean() does not clean all triangulation from...
[occt.git] / src / MeshTest / MeshTest.cxx
CommitLineData
b311480e 1// Created on: 1993-09-22
2// Created by: Didier PIFFAULT
3// Copyright (c) 1993-1999 Matra Datavision
973c2be1 4// Copyright (c) 1999-2014 OPEN CASCADE SAS
b311480e 5//
973c2be1 6// This file is part of Open CASCADE Technology software library.
b311480e 7//
d5f74e42 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
973c2be1 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.
b311480e 13//
973c2be1 14// Alternatively, this file may be used under the terms of Open CASCADE
15// commercial license or contractual agreement.
7fd59977 16
4006ca98 17#include <MeshTest.hxx>
18
19#include <stdio.h>
7fd59977 20
42cf5bc1 21#include <Bnd_Box.hxx>
7fd59977 22#include <BRep_Builder.hxx>
42cf5bc1 23#include <BRepAdaptor_Surface.hxx>
24#include <BRepBndLib.hxx>
25#include <BRepBuilderAPI_MakeFace.hxx>
26#include <BRepBuilderAPI_MakePolygon.hxx>
27#include <BRepBuilderAPI_MakeVertex.hxx>
28#include <BRepLib.hxx>
7fd59977 29#include <BRepMesh_IncrementalMesh.hxx>
42cf5bc1 30#include <BRepTest.hxx>
31#include <BRepTools.hxx>
32#include <CSLib.hxx>
42cf5bc1 33#include <DBRep.hxx>
42cf5bc1 34#include <Draw_Appli.hxx>
ce97cd97 35#include <Draw_ProgressIndicator.hxx>
7fd59977 36#include <Draw_Segment2D.hxx>
42cf5bc1 37#include <DrawTrSurf.hxx>
42cf5bc1 38#include <GeometryTest.hxx>
4006ca98 39#include <IMeshData_Status.hxx>
d99f0355 40#include <Message.hxx>
ce97cd97 41#include <Message_ProgressRange.hxx>
84d0342c 42#include <OSD_OpenFile.hxx>
7fd59977 43#include <Poly_Connect.hxx>
7fd59977 44#include <TopExp_Explorer.hxx>
d51c7072 45#include <TopTools_MapIteratorOfMapOfShape.hxx>
5bae0beb 46#include <BRep_CurveRepresentation.hxx>
47#include <BRep_TEdge.hxx>
48#include <TopExp.hxx>
d51c7072 49
f2006a6f 50#include <BRepMesh_Context.hxx>
51#include <BRepMesh_FaceDiscret.hxx>
52#include <BRepMesh_MeshAlgoFactory.hxx>
53#include <BRepMesh_DelabellaMeshAlgoFactory.hxx>
54
42cf5bc1 55//epa Memory leaks test
56//OAN: for triepoints
57c28b61 57#ifdef _WIN32
7fd59977 58Standard_IMPORT Draw_Viewer dout;
59#endif
60
61#define MAX2(X, Y) ( Abs(X) > Abs(Y)? Abs(X) : Abs(Y) )
62#define MAX3(X, Y, Z) ( MAX2 ( MAX2(X,Y) , Z) )
63
7fd59977 64#define ONETHIRD 0.333333333333333333333333333333333333333333333333333333333333
65#define TWOTHIRD 0.666666666666666666666666666666666666666666666666666666666666
66
0797d9d3 67#ifdef OCCT_DEBUG_MESH_CHRONO
7fd59977 68#include <OSD_Chronometer.hxx>
69Standard_Integer D0Control, D0Internal, D0Unif, D0Edges, NbControls;
70OSD_Chronometer chTotal, chInternal, chControl, chUnif, chAddPoint;
71OSD_Chronometer chEdges, chMaillEdges, chEtuInter, chLastControl, chStock;
72OSD_Chronometer chAdd11, chAdd12, chAdd2, chUpdate, chPointValid;
73OSD_Chronometer chIsos, chPointsOnIsos;
74#endif
75
7fd59977 76//=======================================================================
77//function : incrementalmesh
78//purpose :
79//=======================================================================
d51c7072 80static Standard_Integer incrementalmesh(Draw_Interpretor& di, Standard_Integer nbarg, const char** argv)
7fd59977 81{
49cfd13d 82 if (nbarg < 3)
83 {
84 di << "\
85Builds triangular mesh for the shape\n\
86usage: incmesh Shape LinearDeflection [options]\n\
87options:\n\
46478ffe 88 -a val angular deflection for edges in deg\n\
74da0216 89 (default ~28.64 deg = 0.5 rad)\n\n\
46478ffe 90 -ai val angular deflection inside of faces in deg\n\
91 (default ~57.29 deg = 1 rad)\n\n\
92 -di val Linear deflection used to tessellate the face interior.\n\
74da0216 93 -min minimum size parameter limiting size of triangle's\n\
94 edges to prevent sinking into amplification in case\n\
95 of distorted curves and surfaces\n\n\
49cfd13d 96 -relative notifies that relative deflection is used\n\
74da0216 97 (switched off by default)\n\n\
a319f03f 98 -int_vert_off disables insertion of internal vertices into mesh\n\
99 (enabled by default)\n\
f43eff9f 100 -surf_def_off disables control of deflection of mesh from real\n\
101 surface (enabled by default)\n\
e71669c6 102 -parallel enables parallel execution (switched off by default)\n\
0da2ecac 103 -adjust_min enables local adjustment of min size depending on edge size (switched off by default)\n\
128654b6 104 -force_face_def disables usage of shape tolerances for computing face deflection (switched off by default)\n\
105 -decrease enforces the meshing of the shape even if current mesh satisfies the new criteria\
f2006a6f 106 (switched off by default).\n\
107 -algo {watson|delabella} changes core triangulation algorithm to one with specified id (watson is used by default)\n";
416d4426 108 return 0;
109 }
7fd59977 110
416d4426 111 TopoDS_Shape aShape = DBRep::Get(argv[1]);
49cfd13d 112 if (aShape.IsNull())
113 {
114 di << " Null shapes are not allowed here\n";
416d4426 115 return 0;
116 }
416d4426 117
7bd071ed 118 IMeshTools_Parameters aMeshParams;
46478ffe 119 aMeshParams.Deflection = aMeshParams.DeflectionInterior =
120 Max(Draw::Atof(argv[2]), Precision::Confusion());
49cfd13d 121
f2006a6f 122 Handle (IMeshTools_Context) aContext = new BRepMesh_Context;
49cfd13d 123 if (nbarg > 3)
124 {
125 Standard_Integer i = 3;
126 while (i < nbarg)
127 {
128 TCollection_AsciiString aOpt(argv[i++]);
129 aOpt.LowerCase();
130
131 if (aOpt == "")
132 continue;
133 else if (aOpt == "-relative")
7bd071ed 134 aMeshParams.Relative = Standard_True;
49cfd13d 135 else if (aOpt == "-parallel")
7bd071ed 136 aMeshParams.InParallel = Standard_True;
a319f03f 137 else if (aOpt == "-int_vert_off")
7bd071ed 138 aMeshParams.InternalVerticesMode = Standard_False;
f43eff9f 139 else if (aOpt == "-surf_def_off")
7bd071ed 140 aMeshParams.ControlSurfaceDeflection = Standard_False;
3c1b7084 141 else if (aOpt == "-adjust_min")
142 aMeshParams.AdjustMinSize = Standard_True;
0da2ecac 143 else if (aOpt == "-force_face_def")
144 aMeshParams.ForceFaceDeflection = Standard_True;
128654b6 145 else if (aOpt == "-decrease")
146 aMeshParams.AllowQualityDecrease = Standard_True;
49cfd13d 147 else if (i < nbarg)
148 {
f2006a6f 149 if (aOpt == "-algo")
46478ffe 150 {
f2006a6f 151 TCollection_AsciiString anAlgoStr (argv[i++]);
152 anAlgoStr.LowerCase();
153 if (anAlgoStr == "watson"
154 || anAlgoStr == "0")
155 {
156 aMeshParams.MeshAlgo = IMeshTools_MeshAlgoType_Watson;
157 aContext->SetFaceDiscret (new BRepMesh_FaceDiscret (new BRepMesh_MeshAlgoFactory));
158 }
159 else if (anAlgoStr == "delabella"
160 || anAlgoStr == "1")
161 {
162 aMeshParams.MeshAlgo = IMeshTools_MeshAlgoType_Delabella;
163 aContext->SetFaceDiscret (new BRepMesh_FaceDiscret (new BRepMesh_DelabellaMeshAlgoFactory));
164 }
165 else if (anAlgoStr == "-1"
166 || anAlgoStr == "default")
167 {
168 // already handled by BRepMesh_Context constructor
169 //aMeshParams.MeshAlgo = IMeshTools_MeshAlgoType_DEFAULT;
170 }
171 else
172 {
173 di << "Syntax error at " << anAlgoStr;
174 return 1;
175 }
46478ffe 176 }
f2006a6f 177 else
46478ffe 178 {
f2006a6f 179 Standard_Real aVal = Draw::Atof(argv[i++]);
180 if (aOpt == "-a")
181 {
182 aMeshParams.Angle = aVal * M_PI / 180.;
183 }
184 else if (aOpt == "-ai")
185 {
186 aMeshParams.AngleInterior = aVal * M_PI / 180.;
187 }
188 else if (aOpt == "-min")
189 aMeshParams.MinSize = aVal;
190 else if (aOpt == "-di")
191 {
192 aMeshParams.DeflectionInterior = aVal;
193 }
194 else
195 --i;
46478ffe 196 }
49cfd13d 197 }
198 }
416d4426 199 }
49cfd13d 200
416d4426 201 di << "Incremental Mesh, multi-threading "
7bd071ed 202 << (aMeshParams.InParallel ? "ON" : "OFF") << "\n";
203
ce97cd97 204 Handle(Draw_ProgressIndicator) aProgress = new Draw_ProgressIndicator(di, 1);
f2006a6f 205 BRepMesh_IncrementalMesh aMesher;
206 aMesher.SetShape (aShape);
207 aMesher.ChangeParameters() = aMeshParams;
208
209 aMesher.Perform (aContext, aProgress->Start());
d51c7072 210
49cfd13d 211 di << "Meshing statuses: ";
7bd071ed 212 const Standard_Integer aStatus = aMesher.GetStatusFlags();
213 if (!aStatus)
d51c7072
O
214 {
215 di << "NoError";
216 }
217 else
218 {
219 Standard_Integer i;
ce97cd97 220 for (i = 0; i < 9; i++)
d51c7072 221 {
7bd071ed 222 Standard_Integer aFlag = aStatus & (1 << i);
223 if (aFlag)
d51c7072 224 {
7bd071ed 225 switch ((IMeshData_Status) aFlag)
d51c7072 226 {
7bd071ed 227 case IMeshData_OpenWire:
228 di << "OpenWire ";
229 break;
230 case IMeshData_SelfIntersectingWire:
231 di << "SelfIntersectingWire ";
232 break;
233 case IMeshData_Failure:
234 di << "Failure ";
235 break;
236 case IMeshData_ReMesh:
237 di << "ReMesh ";
238 break;
239 case IMeshData_UnorientedWire:
240 di << "UnorientedWire ";
241 break;
242 case IMeshData_TooFewPoints:
243 di << "TooFewPoints ";
244 break;
245 case IMeshData_Outdated:
246 di << "Outdated ";
247 break;
248 case IMeshData_Reused:
249 di << "Reused ";
250 break;
ce97cd97 251 case IMeshData_UserBreak:
252 di << "User break";
253 break;
7bd071ed 254 case IMeshData_NoError:
255 default:
256 break;
d51c7072
O
257 }
258 }
259 }
260 }
261
7fd59977 262 return 0;
263}
264
b508cbc5 265//=======================================================================
266//function : tessellate
267//purpose :
268//=======================================================================
269static Standard_Integer tessellate (Draw_Interpretor& /*di*/, Standard_Integer nbarg, const char** argv)
270{
271 if (nbarg != 5)
272 {
d99f0355 273 Message::SendFail() << "Builds regular triangulation with specified number of triangles\n"
b508cbc5 274 " Usage: tessellate result {surface|face} nbu nbv\n"
275 " Triangulation is put into the face with natural bounds (result);\n"
276 " it will have 2*nbu*nbv triangles and (nbu+1)*(nbv+1) nodes";
277 return 1;
278 }
279
280 const char *aResName = argv[1];
281 const char *aSrcName = argv[2];
282 int aNbU = Draw::Atoi (argv[3]);
283 int aNbV = Draw::Atoi (argv[4]);
284
285 if (aNbU <= 0 || aNbV <= 0)
286 {
d99f0355 287 Message::SendFail() << "Error: Arguments nbu and nbv must be both greater than 0";
b508cbc5 288 return 1;
289 }
290
291 Handle(Geom_Surface) aSurf = DrawTrSurf::GetSurface(aSrcName);
292 double aUMin, aUMax, aVMin, aVMax;
293 if (! aSurf.IsNull())
294 {
295 aSurf->Bounds (aUMin, aUMax, aVMin, aVMax);
296 }
297 else
298 {
299 TopoDS_Shape aShape = DBRep::Get(aSrcName);
300 if (aShape.IsNull() || aShape.ShapeType() != TopAbs_FACE)
301 {
d99f0355 302 Message::SendFail() << "Error: " << aSrcName << " is not a face";
b508cbc5 303 return 1;
304 }
305 TopoDS_Face aFace = TopoDS::Face (aShape);
306 aSurf = BRep_Tool::Surface (aFace);
307 if (aSurf.IsNull())
308 {
d99f0355 309 Message::SendFail() << "Error: Face " << aSrcName << " has no surface";
b508cbc5 310 return 1;
311 }
312
313 BRepTools::UVBounds (aFace, aUMin, aUMax, aVMin, aVMax);
314 }
315 if (Precision::IsInfinite (aUMin) || Precision::IsInfinite (aUMax) ||
316 Precision::IsInfinite (aVMin) || Precision::IsInfinite (aVMax))
317 {
d99f0355 318 Message::SendFail() << "Error: surface has infinite parametric range, aborting";
b508cbc5 319 return 1;
320 }
321
322 BRepBuilderAPI_MakeFace aFaceMaker (aSurf, aUMin, aUMax, aVMin, aVMax, Precision::Confusion());
323 if (! aFaceMaker.IsDone())
324 {
d99f0355 325 Message::SendFail() << "Error: cannot build face with natural bounds, aborting";
b508cbc5 326 return 1;
327 }
328 TopoDS_Face aFace = aFaceMaker;
329
330 // create triangulation
331 int aNbNodes = (aNbU + 1) * (aNbV + 1);
332 int aNbTriangles = 2 * aNbU * aNbV;
333 Handle(Poly_Triangulation) aTriangulation =
334 new Poly_Triangulation (aNbNodes, aNbTriangles, Standard_False);
335
336 // fill nodes
337 TColgp_Array1OfPnt &aNodes = aTriangulation->ChangeNodes();
338 GeomAdaptor_Surface anAdSurf (aSurf);
339 double aDU = (aUMax - aUMin) / aNbU;
340 double aDV = (aVMax - aVMin) / aNbV;
341 for (int iU = 0, iShift = 1; iU <= aNbU; iU++, iShift += aNbV + 1)
342 {
343 double aU = aUMin + iU * aDU;
344 for (int iV = 0; iV <= aNbV; iV++)
345 {
346 double aV = aVMin + iV * aDV;
347 gp_Pnt aP = anAdSurf.Value (aU, aV);
348 aNodes.SetValue (iShift + iV, aP);
349 }
350 }
351
352 // fill triangles
353 Poly_Array1OfTriangle &aTriangles = aTriangulation->ChangeTriangles();
354 for (int iU = 0, iShift = 1, iTri = 0; iU < aNbU; iU++, iShift += aNbV + 1)
355 {
356 for (int iV = 0; iV < aNbV; iV++)
357 {
358 int iBase = iShift + iV;
359 Poly_Triangle aTri1 (iBase, iBase + aNbV + 2, iBase + 1);
360 Poly_Triangle aTri2 (iBase, iBase + aNbV + 1, iBase + aNbV + 2);
361 aTriangles.SetValue (++iTri, aTri1);
362 aTriangles.SetValue (++iTri, aTri2);
363 }
364 }
365
366 // put triangulation to face
367 BRep_Builder B;
368 B.UpdateFace (aFace, aTriangulation);
369
370 // fill edge polygons
371 TColStd_Array1OfInteger aUMinIso (1, aNbV + 1), aUMaxIso (1, aNbV + 1);
372 for (int iV = 0; iV <= aNbV; iV++)
373 {
374 aUMinIso.SetValue (1 + iV, 1 + iV);
375 aUMaxIso.SetValue (1 + iV, 1 + iV + aNbU * (1 + aNbV));
376 }
377 TColStd_Array1OfInteger aVMinIso (1, aNbU + 1), aVMaxIso (1, aNbU + 1);
378 for (int iU = 0; iU <= aNbU; iU++)
379 {
380 aVMinIso.SetValue (1 + iU, 1 + iU * (1 + aNbV));
381 aVMaxIso.SetValue (1 + iU, (1 + iU) * (1 + aNbV));
382 }
383 Handle(Poly_PolygonOnTriangulation) aUMinPoly = new Poly_PolygonOnTriangulation (aUMinIso);
384 Handle(Poly_PolygonOnTriangulation) aUMaxPoly = new Poly_PolygonOnTriangulation (aUMaxIso);
385 Handle(Poly_PolygonOnTriangulation) aVMinPoly = new Poly_PolygonOnTriangulation (aVMinIso);
386 Handle(Poly_PolygonOnTriangulation) aVMaxPoly = new Poly_PolygonOnTriangulation (aVMaxIso);
387 for (TopExp_Explorer exp (aFace, TopAbs_EDGE); exp.More(); exp.Next())
388 {
389 TopoDS_Edge anEdge = TopoDS::Edge (exp.Current());
390 Standard_Real aFirst, aLast;
391 Handle(Geom2d_Curve) aC = BRep_Tool::CurveOnSurface (anEdge, aFace, aFirst, aLast);
392 gp_Pnt2d aPFirst = aC->Value (aFirst);
393 gp_Pnt2d aPLast = aC->Value (aLast);
394 if (Abs (aPFirst.X() - aPLast.X()) < 0.1 * (aUMax - aUMin)) // U=const
395 {
396 if (BRep_Tool::IsClosed (anEdge, aFace))
397 B.UpdateEdge (anEdge, aUMinPoly, aUMaxPoly, aTriangulation);
398 else
399 B.UpdateEdge (anEdge, (aPFirst.X() < 0.5 * (aUMin + aUMax) ? aUMinPoly : aUMaxPoly), aTriangulation);
400 }
401 else // V=const
402 {
403 if (BRep_Tool::IsClosed (anEdge, aFace))
404 B.UpdateEdge (anEdge, aVMinPoly, aVMaxPoly, aTriangulation);
405 else
406 B.UpdateEdge (anEdge, (aPFirst.Y() < 0.5 * (aVMin + aVMax) ? aVMinPoly : aVMaxPoly), aTriangulation);
407 }
408 }
409
410 DBRep::Set (aResName, aFace);
411 return 0;
412}
413
7fd59977 414//=======================================================================
415//function : MemLeakTest
416//purpose :
417//=======================================================================
35e08fe8 418static Standard_Integer MemLeakTest(Draw_Interpretor&, Standard_Integer /*nbarg*/, const char** /*argv*/)
7fd59977 419{
420 for(int i=0;i<10000;i++)
421 {
422 BRepBuilderAPI_MakePolygon w(gp_Pnt(0,0,0),gp_Pnt(0,100,0),gp_Pnt(20,100,0),gp_Pnt(20,0,0));
423 w.Close();
424 TopoDS_Wire wireShape( w.Wire());
425 BRepBuilderAPI_MakeFace faceBuilder(wireShape);
426 TopoDS_Face f( faceBuilder.Face());
427 BRepMesh_IncrementalMesh im(f,1);
428 BRepTools::Clean(f);
429 }
430 return 0;
431}
432
7fd59977 433//=======================================================================
434//function : trianglesinfo
435//purpose :
436//=======================================================================
437static Standard_Integer trianglesinfo(Draw_Interpretor& di, Standard_Integer n, const char** a)
438{
439 if (n != 2) return 1;
440 TopoDS_Shape S = DBRep::Get(a[1]);
441 if (S.IsNull()) return 1;
442 TopExp_Explorer ex;
443 Handle(Poly_Triangulation) T;
444 TopLoc_Location L;
445
446 Standard_Real MaxDeflection = 0.0;
5bae0beb 447 Standard_Integer nbtriangles = 0, nbnodes = 0, nbrepresentations = 0;
7fd59977 448 for (ex.Init(S, TopAbs_FACE); ex.More(); ex.Next()) {
449 TopoDS_Face F = TopoDS::Face(ex.Current());
450 T = BRep_Tool::Triangulation(F, L);
451 if (!T.IsNull()) {
452 nbtriangles += T->NbTriangles();
453 nbnodes += T->NbNodes();
454 if (T->Deflection() > MaxDeflection)
455 MaxDeflection = T->Deflection();
456 }
457 }
5bae0beb 458 TopTools_IndexedMapOfShape anEdges;
459 TopExp::MapShapes(S, TopAbs_EDGE, anEdges);
460 for (int i = 1; i<=anEdges.Extent(); ++i)
461 {
462 const TopoDS_Edge& anEdge = TopoDS::Edge(anEdges(i));
463 Handle(BRep_CurveRepresentation) aCR;
464 BRep_TEdge* aTE = static_cast<BRep_TEdge*>(anEdge.TShape().get());
465 const BRep_ListOfCurveRepresentation& aLCR = aTE->Curves();
466 BRep_ListIteratorOfListOfCurveRepresentation anIterCR(aLCR);
467
468 while (anIterCR.More()) {
469 aCR = anIterCR.Value();
470 if (aCR->IsPolygonOnTriangulation())
471 {
472 nbrepresentations++;
473 }
474 anIterCR.Next();
475 }
476 }
7fd59977 477
478 di<<"\n";
5bae0beb 479 di << "This shape contains " << nbtriangles << " triangles.\n";
480 di << " " << nbnodes << " nodes.\n";
481 di << " " << nbrepresentations << " polygons on triangulation .\n";;
482 di << "Maximal deflection " << MaxDeflection << "\n";
483
7fd59977 484 di<<"\n";
0797d9d3 485#ifdef OCCT_DEBUG_MESH_CHRONO
7fd59977 486 Standard_Real tot, addp, unif, contr, inter;
487 Standard_Real edges, mailledges, etuinter, lastcontrol, stock;
488 Standard_Real add11, add12, add2, upda, pointvalid;
489 Standard_Real isos, pointsisos;
490 chTotal.Show(tot); chAddPoint.Show(addp); chUnif.Show(unif);
491 chControl.Show(contr); chInternal.Show(inter);
492 chEdges.Show(edges); chMaillEdges.Show(mailledges);
493 chEtuInter.Show(etuinter); chLastControl.Show(lastcontrol);
494 chStock.Show(stock);
495 chAdd11.Show(add11); chAdd12.Show(add12); chAdd2.Show(add2); chUpdate.Show(upda);
496 chPointValid.Show(pointvalid); chIsos.Show(isos); chPointsOnIsos.Show(pointsisos);
497
498 if (tot > 0.00001) {
586db386 499 di <<"temps total de maillage: "<<tot <<" seconds\n";
500 di <<"dont: \n";
501 di <<"discretisation des edges: "<<edges <<" seconds---> "<< 100*edges/tot <<" %\n";
502 di <<"maillage des edges: "<<mailledges <<" seconds---> "<< 100*mailledges/tot <<" %\n";
503 di <<"controle et points internes: "<<etuinter <<" seconds---> "<< 100*etuinter/tot <<" %\n";
504 di <<"derniers controles: "<<lastcontrol<<" seconds---> "<< 100*lastcontrol/tot<<" %\n";
505 di <<"stockage dans la S.D. "<<stock <<" seconds---> "<< 100*stock/tot <<" %\n";
0d88155b 506 di << "\n";
586db386 507 di <<"et plus precisement: \n";
508 di <<"Add 11ere partie : "<<add11 <<" seconds---> "<<100*add11/tot <<" %\n";
509 di <<"Add 12ere partie : "<<add12 <<" seconds---> "<<100*add12/tot <<" %\n";
510 di <<"Add 2eme partie : "<<add2 <<" seconds---> "<<100*add2/tot <<" %\n";
511 di <<"Update : "<<upda <<" seconds---> "<<100*upda/tot <<" %\n";
512 di <<"AddPoint : "<<addp <<" seconds---> "<<100*addp/tot <<" %\n";
513 di <<"UniformDeflection "<<unif <<" seconds---> "<<100*unif/tot <<" %\n";
514 di <<"Controle : "<<contr <<" seconds---> "<<100*contr/tot <<" %\n";
515 di <<"Points Internes: "<<inter <<" seconds---> "<<100*inter/tot <<" %\n";
516 di <<"calcul des isos et du, dv: "<<isos <<" seconds---> "<<100*isos/tot <<" %\n";
517 di <<"calcul des points sur isos: "<<pointsisos<<" seconds---> "<<100*pointsisos/tot <<" %\n";
518 di <<"IsPointValid: "<<pointvalid<<" seconds---> "<<100*pointvalid/tot <<" %\n";
0d88155b
O
519 di << "\n";
520
521
522 di <<"nombre d'appels de controle apres points internes : "<< NbControls << "\n";
523 di <<"nombre de points sur restrictions : "<< D0Edges << "\n";
524 di <<"nombre de points calcules par UniformDeflection : "<< D0Unif << "\n";
525 di <<"nombre de points calcules dans InternalVertices : "<< D0Internal << "\n";
526 di <<"nombre de points calcules dans Control : "<< D0Control << "\n";
527 if (nbnodes-D0Edges != 0) {
528 Standard_Real ratio = (Standard_Real)(D0Internal+D0Control)/ (Standard_Real)(nbnodes-D0Edges);
529 di <<"---> Ratio: (D0Internal+D0Control) / (nbNodes-nbOnEdges) : "<< ratio << "\n";
530 }
7fd59977 531
0d88155b 532 di << "\n";
7fd59977 533
0d88155b
O
534 chTotal.Reset(); chAddPoint.Reset(); chUnif.Reset();
535 chControl.Reset(); chInternal.Reset();
536 chEdges.Reset(); chMaillEdges.Reset();
537 chEtuInter.Reset(); chLastControl.Reset();
538 chStock.Reset();
539 chAdd11.Reset(); chAdd12.Reset(); chAdd2.Reset(); chUpdate.Reset();
540 chPointValid.Reset(); chIsos.Reset(); chPointsOnIsos.Reset();
7fd59977 541
542 }
543#endif
544 return 0;
545}
546
547//=======================================================================
548//function : veriftriangles
549//purpose :
550//=======================================================================
7fd59977 551static Standard_Integer veriftriangles(Draw_Interpretor& di, Standard_Integer n, const char** a)
552{
553 if (n < 2) return 1;
554 Standard_Boolean quiet = 1;
555 if (n == 3) quiet = 0;
556 TopoDS_Shape Sh = DBRep::Get(a[1]);
557 if (Sh.IsNull()) return 1;
558 TopExp_Explorer ex;
559 Handle(Poly_Triangulation) T;
560 TopLoc_Location L;
561 Standard_Integer i, n1, n2, n3;
562 gp_Pnt2d mitri, v1, v2, v3, mi2d1, mi2d2, mi2d3;
563 gp_XYZ vecEd1, vecEd2, vecEd3;
0d88155b 564 // Standard_Real dipo, dm, dv, d1, d2, d3, defle;
7fd59977 565 Standard_Real dipo, dv, d1, d2, d3, defle;
566 Handle(Geom_Surface) S;
567 Standard_Integer nbface = 0;
568 gp_Pnt PP;
569
570 for (ex.Init(Sh, TopAbs_FACE); ex.More(); ex.Next()) {
571 TopoDS_Face F = TopoDS::Face(ex.Current());
572 nbface++;
573 T = BRep_Tool::Triangulation(F, L);
574 Standard_Real deflemax = 0, deflemin = 1.e100;
575 if (!T.IsNull()) {
576 Standard_Real defstock = T->Deflection();
577 const Poly_Array1OfTriangle& triangles = T->Triangles();
578 const TColgp_Array1OfPnt2d& Nodes2d = T->UVNodes();
579 const TColgp_Array1OfPnt& Nodes = T->Nodes();
580
581 S = BRep_Tool::Surface(F, L);
582
583 for(i = 1; i <= triangles.Length(); i++) {
0d88155b
O
584 if (F.Orientation() == TopAbs_REVERSED)
585 triangles(i).Get(n1,n3,n2);
586 else
587 triangles(i).Get(n1,n2,n3);
588
589 const gp_XY& xy1 = Nodes2d(n1).XY();
590 const gp_XY& xy2 = Nodes2d(n2).XY();
591 const gp_XY& xy3 = Nodes2d(n3).XY();
592
593 mi2d1.SetCoord((xy2.X()+xy3.X())*0.5,
594 (xy2.Y()+xy3.Y())*0.5);
595 mi2d2.SetCoord((xy1.X()+xy3.X())*0.5,
596 (xy1.Y()+xy3.Y())*0.5);
597 mi2d3.SetCoord((xy1.X()+xy2.X())*0.5,
598 (xy1.Y()+xy2.Y())*0.5);
599
600 gp_XYZ p1 = Nodes(n1).Transformed(L.Transformation()).XYZ();
601 gp_XYZ p2 = Nodes(n2).Transformed(L.Transformation()).XYZ();
602 gp_XYZ p3 = Nodes(n3).Transformed(L.Transformation()).XYZ();
603
604 vecEd1=p2-p1;
605 vecEd2=p3-p2;
606 vecEd3=p1-p3;
607 d1=vecEd1.SquareModulus();
608 d2=vecEd2.SquareModulus();
609 d3=vecEd3.SquareModulus();
610
611 if (d1!=0. && d2!=0. && d3!=0.) {
612 gp_XYZ equa(vecEd1^vecEd2);
613 dv=equa.Modulus();
614 if (dv>0.) {
615 equa.SetCoord(equa.X()/dv, equa.Y()/dv, equa.Z()/dv);
616 dipo=equa*p1;
617
618
619 mitri.SetCoord(ONETHIRD*(xy1.X()+xy2.X()+xy3.X()),
620 ONETHIRD*(xy1.Y()+xy2.Y()+xy3.Y()));
621 v1.SetCoord(ONETHIRD*mi2d1.X()+TWOTHIRD*xy1.X(),
622 ONETHIRD*mi2d1.Y()+TWOTHIRD*xy1.Y());
623 v2.SetCoord(ONETHIRD*mi2d2.X()+TWOTHIRD*xy2.X(),
624 ONETHIRD*mi2d2.Y()+TWOTHIRD*xy2.Y());
625 v3.SetCoord(ONETHIRD*mi2d3.X()+TWOTHIRD*xy3.X(),
626 ONETHIRD*mi2d3.Y()+TWOTHIRD*xy3.Y());
627
628 S->D0(mi2d1.X(), mi2d1.Y(), PP);
629 PP = PP.Transformed(L.Transformation());
630 defle = Abs((equa*PP.XYZ())-dipo);
631 deflemax = Max(deflemax, defle);
632 deflemin = Min(deflemin, defle);
633
634 S->D0(mi2d2.X(), mi2d2.Y(), PP);
635 PP = PP.Transformed(L.Transformation());
636 defle = Abs((equa*PP.XYZ())-dipo);
637 deflemax = Max(deflemax, defle);
638 deflemin = Min(deflemin, defle);
639
640 S->D0(mi2d3.X(), mi2d3.Y(), PP);
641 PP = PP.Transformed(L.Transformation());
642 defle = Abs((equa*PP.XYZ())-dipo);
643 deflemax = Max(deflemax, defle);
644 deflemin = Min(deflemin, defle);
645
646 S->D0(v1.X(), v1.Y(), PP);
647 PP = PP.Transformed(L.Transformation());
648 defle = Abs((equa*PP.XYZ())-dipo);
649 deflemax = Max(deflemax, defle);
650 deflemin = Min(deflemin, defle);
651
652 S->D0(v2.X(), v2.Y(), PP);
653 PP = PP.Transformed(L.Transformation());
654 defle = Abs((equa*PP.XYZ())-dipo);
655 deflemax = Max(deflemax, defle);
656 deflemin = Min(deflemin, defle);
657
658 S->D0(v3.X(), v3.Y(), PP);
659 PP = PP.Transformed(L.Transformation());
660 defle = Abs((equa*PP.XYZ())-dipo);
661 deflemax = Max(deflemax, defle);
662 deflemin = Min(deflemin, defle);
663
664 S->D0(mitri.X(), mitri.Y(), PP);
665 PP = PP.Transformed(L.Transformation());
666 defle = Abs((equa*PP.XYZ())-dipo);
667 deflemax = Max(deflemax, defle);
668 deflemin = Min(deflemin, defle);
669
670 if (defle > defstock) {
586db386 671 di <<"face "<< nbface <<" deflection = " << defle <<" pour "<<defstock <<" stockee.\n";
0d88155b
O
672 }
673 }
674 }
7fd59977 675 }
676 if (!quiet) {
0d88155b 677 di <<"face "<< nbface<<", deflemin = "<< deflemin<<", deflemax = "<<deflemax<<"\n";
7fd59977 678 }
679
680 }
681 }
682
683
684 return 0;
685}
686
7fd59977 687//=======================================================================
688//function : tri2d
689//purpose :
690//=======================================================================
4006ca98 691static Standard_Integer tri2d(Draw_Interpretor&, Standard_Integer n, const char** a)
7fd59977 692{
693
694 if (n != 2) return 1;
695 TopoDS_Shape aLocalShape = DBRep::Get(a[1]);
696 TopoDS_Face F = TopoDS::Face(aLocalShape);
0d88155b 697 // TopoDS_Face F = TopoDS::Face(DBRep::Get(a[1]));
7fd59977 698 if (F.IsNull()) return 1;
699 Handle(Poly_Triangulation) T;
700 TopLoc_Location L;
701
702 T = BRep_Tool::Triangulation(F, L);
703 if (!T.IsNull()) {
7fd59977 704 // Build the connect tool
705 Poly_Connect pc(T);
0d88155b 706
7fd59977 707 Standard_Integer i,j, nFree, nInternal, nbTriangles = T->NbTriangles();
708 Standard_Integer t[3];
0d88155b 709
7fd59977 710 // count the free edges
711 nFree = 0;
712 for (i = 1; i <= nbTriangles; i++) {
713 pc.Triangles(i,t[0],t[1],t[2]);
714 for (j = 0; j < 3; j++)
0d88155b 715 if (t[j] == 0) nFree++;
7fd59977 716 }
0d88155b 717
7fd59977 718 // allocate the arrays
719 TColStd_Array1OfInteger Free(1,2*nFree);
720 nInternal = (3*nbTriangles - nFree) / 2;
721 TColStd_Array1OfInteger Internal(0,2*nInternal);
0d88155b 722
7fd59977 723 Standard_Integer fr = 1, in = 1;
724 const Poly_Array1OfTriangle& triangles = T->Triangles();
725 Standard_Integer nodes[3];
726 for (i = 1; i <= nbTriangles; i++) {
727 pc.Triangles(i,t[0],t[1],t[2]);
728 triangles(i).Get(nodes[0],nodes[1],nodes[2]);
729 for (j = 0; j < 3; j++) {
0d88155b
O
730 Standard_Integer k = (j+1) % 3;
731 if (t[j] == 0) {
732 Free(fr) = nodes[j];
733 Free(fr+1) = nodes[k];
734 fr += 2;
735 }
736 // internal edge if this triangle has a lower index than the adjacent
737 else if (i < t[j]) {
738 Internal(in) = nodes[j];
739 Internal(in+1) = nodes[k];
740 in += 2;
741 }
7fd59977 742 }
743 }
0d88155b 744
7fd59977 745 // Display the edges
746 if (T->HasUVNodes()) {
747 const TColgp_Array1OfPnt2d& Nodes2d = T->UVNodes();
748
749 Handle(Draw_Segment2D) Seg;
750
751 // free edges
752 Standard_Integer nn;
753 nn = Free.Length() / 2;
754 for (i = 1; i <= nn; i++) {
0d88155b
O
755 Seg = new Draw_Segment2D(Nodes2d(Free(2*i-1)),
756 Nodes2d(Free(2*i)),
757 Draw_rouge);
758 dout << Seg;
7fd59977 759 }
0d88155b 760
7fd59977 761 // internal edges
0d88155b 762
7fd59977 763 nn = nInternal;
764 for (i = 1; i <= nn; i++) {
0d88155b
O
765 Seg = new Draw_Segment2D(Nodes2d(Internal(2*i-1)),
766 Nodes2d(Internal(2*i)),
767 Draw_bleu);
768 dout << Seg;
7fd59977 769 }
770 }
771 dout.Flush();
772 }
773
774 return 0;
775}
776
7fd59977 777//=======================================================================
778//function : wavefront
779//purpose :
780//=======================================================================
7fd59977 781static Standard_Integer wavefront(Draw_Interpretor&, Standard_Integer nbarg, const char** argv)
782{
783 if (nbarg < 2) return 1;
784
785 TopoDS_Shape S = DBRep::Get(argv[1]);
786 if (S.IsNull()) return 1;
787
788 // creation du maillage s'il n'existe pas.
789
790 Bnd_Box B;
791 Standard_Real aXmin, aYmin, aZmin, aXmax, aYmax, aZmax;
792 BRepBndLib::Add(S, B);
793 B.Get(aXmin, aYmin, aZmin, aXmax, aYmax, aZmax);
794 Standard_Real aDeflection =
795 MAX3( aXmax-aXmin , aYmax-aYmin , aZmax-aZmin) * 0.004;
796
b3a7aa39 797 BRepMesh_IncrementalMesh aMesh (S, aDeflection);
7fd59977 798
799
800 TopLoc_Location L;
801 TopExp_Explorer ex;
802
803 Standard_Integer i, nbface = 0;
804 Standard_Boolean OK = Standard_True;
805 gp_Vec D1U,D1V;
806 gp_Vec D2U,D2V,D2UV;
807 gp_Dir Nor;
808 gp_Pnt P;
809 Standard_Real U, V;
9fd2d2c3 810 CSLib_DerivativeStatus aStatus;
7fd59977 811 CSLib_NormalStatus NStat;
812 Standard_Real x, y, z;
813 Standard_Integer n1, n2, n3;
814 Standard_Integer k1, k2, k3;
0d88155b 815
84d0342c 816 TCollection_AsciiString aFile;
0d88155b 817
7fd59977 818 if (nbarg == 3) {
84d0342c 819 aFile = argv[2];
820 aFile += ".obj";
7fd59977 821 }
84d0342c 822 else aFile = "wave.obj";
823 FILE* outfile = OSD_OpenFile(aFile.ToCString(), "w");
7fd59977 824
825
84d0342c 826 fprintf(outfile, "%s %s\n%s %s\n\n", "# CASCADE ","MATRA DATAVISION", "#", aFile.ToCString());
7fd59977 827
828 Standard_Integer nbNodes, totalnodes = 0, nbpolygons = 0;
829 for (ex.Init(S, TopAbs_FACE); ex.More(); ex.Next()) {
830 nbface++;
831 TopoDS_Face F = TopoDS::Face(ex.Current());
832 Handle(Poly_Triangulation) Tr = BRep_Tool::Triangulation(F, L);
0d88155b 833
7fd59977 834 if (!Tr.IsNull()) {
835 nbNodes = Tr->NbNodes();
836 const TColgp_Array1OfPnt& Nodes = Tr->Nodes();
0d88155b 837
7fd59977 838 // les noeuds.
839 for (i = 1; i <= nbNodes; i++) {
0d88155b
O
840 gp_Pnt Pnt = Nodes(i).Transformed(L.Transformation());
841 x = Pnt.X();
842 y = Pnt.Y();
843 z = Pnt.Z();
844 fprintf(outfile, "%s %f %f %f\n", "v", x, y, z);
7fd59977 845 }
0d88155b 846
7fd59977 847 fprintf(outfile, "\n%s %d\n\n", "# number of vertex", nbNodes);
0d88155b
O
848
849
7fd59977 850 // les normales.
0d88155b 851
7fd59977 852 if (Tr->HasUVNodes()) {
0d88155b
O
853 const TColgp_Array1OfPnt2d& UVNodes = Tr->UVNodes();
854 BRepAdaptor_Surface BS(F, Standard_False);
855
856 for (i = 1; i <= nbNodes; i++) {
857 U = UVNodes(i).X();
858 V = UVNodes(i).Y();
859
860 BS.D1(U,V,P,D1U,D1V);
9fd2d2c3 861 CSLib::Normal (D1U, D1V, Precision::Angular(), aStatus, Nor);
862 if (aStatus != CSLib_Done) {
0d88155b
O
863 BS.D2(U,V,P,D1U,D1V,D2U,D2V,D2UV);
864 CSLib::Normal(D1U,D1V,D2U,D2V,D2UV,Precision::Angular(),OK,NStat,Nor);
865 }
866 if (F.Orientation() == TopAbs_REVERSED) Nor.Reverse();
867
868 fprintf(outfile, "%s %f %f %f\n", "vn", Nor.X(), Nor.Y(), Nor.Z());
869 }
870
871 fprintf(outfile, "\n%s %d\n\n", "# number of vertex normals", nbNodes);
7fd59977 872 }
0d88155b 873
7fd59977 874 fprintf(outfile, "%s %d\n", "s", nbface);
0d88155b 875
7fd59977 876 // les triangles.
877 Standard_Integer nbTriangles = Tr->NbTriangles();
878 const Poly_Array1OfTriangle& triangles = Tr->Triangles();
0d88155b
O
879
880
7fd59977 881 for (i = 1; i <= nbTriangles; i++) {
0d88155b
O
882 if (F.Orientation() == TopAbs_REVERSED)
883 triangles(i).Get(n1, n3, n2);
884 else
885 triangles(i).Get(n1, n2, n3);
886 k1 = n1+totalnodes;
887 k2 = n2+totalnodes;
888 k3 = n3+totalnodes;
6b467e52 889 fprintf(outfile, "f %d%s%d %d%s%d %d%s%d\n", k1,"//", k1, k2,"//", k2, k3,"//", k3);
7fd59977 890 }
891 nbpolygons += nbTriangles;
892 totalnodes += nbNodes;
0d88155b 893
7fd59977 894 fprintf(outfile, "\n%s %d\n", "# number of smooth groups", nbface);
895 fprintf(outfile, "\n%s %d\n", "# number of polygons", nbpolygons);
0d88155b 896
7fd59977 897 }
898 }
899
900 fclose(outfile);
901
902 return 0;
903}
904
d51c7072
O
905//=======================================================================
906//function : triedgepoints
907//purpose :
908//=======================================================================
4006ca98 909static Standard_Integer triedgepoints(Draw_Interpretor& di, Standard_Integer nbarg, const char** argv)
d51c7072
O
910{
911 if( nbarg < 2 )
912 return 1;
7fd59977 913
d51c7072
O
914 for( Standard_Integer i = 1; i < nbarg; i++ )
915 {
916 TopoDS_Shape aShape = DBRep::Get(argv[i]);
917 if ( aShape.IsNull() )
918 continue;
919
920 Handle(Poly_PolygonOnTriangulation) aPoly;
921 Handle(Poly_Triangulation) aT;
922 TopLoc_Location aLoc;
923 TopTools_MapOfShape anEdgeMap;
924 TopTools_MapIteratorOfMapOfShape it;
925
926 if( aShape.ShapeType() == TopAbs_EDGE )
927 {
928 anEdgeMap.Add( aShape );
929 }
930 else
931 {
932 TopExp_Explorer ex(aShape, TopAbs_EDGE);
933 for(; ex.More(); ex.Next() )
934 anEdgeMap.Add( ex.Current() );
935 }
936
937 if ( anEdgeMap.Extent() == 0 )
938 continue;
939
940 char newname[1024];
941 strcpy(newname,argv[i]);
942 char* p = newname;
943 while (*p != '\0') p++;
944 *p = '_';
945 p++;
946
947 Standard_Integer nbEdge = 1;
948 for(it.Initialize(anEdgeMap); it.More(); it.Next())
949 {
950 BRep_Tool::PolygonOnTriangulation(TopoDS::Edge(it.Key()), aPoly, aT, aLoc);
951 if ( aT.IsNull() || aPoly.IsNull() )
952 continue;
953
954 const TColgp_Array1OfPnt& Nodes = aT->Nodes();
955 const TColStd_Array1OfInteger& Indices = aPoly->Nodes();
956 const Standard_Integer nbnodes = Indices.Length();
957
958 for( Standard_Integer j = 1; j <= nbnodes; j++ )
959 {
960 gp_Pnt P3d = Nodes(Indices(j));
961 if( !aLoc.IsIdentity() )
962 P3d.Transform(aLoc.Transformation());
963
964 if( anEdgeMap.Extent() > 1 )
91322f44 965 Sprintf(p,"%d_%d",nbEdge,j);
d51c7072 966 else
91322f44 967 Sprintf(p,"%d",j);
d51c7072
O
968 DBRep::Set( newname, BRepBuilderAPI_MakeVertex(P3d) );
969 di.AppendElement(newname);
970 }
971 nbEdge++;
972 }
973 }
974 return 0;
975}
7fd59977 976
7693827d 977//=======================================================================
978//function : correctnormals
979//purpose : Corrects normals in shape triangulation nodes (...)
980//=======================================================================
4006ca98 981static Standard_Integer correctnormals(Draw_Interpretor& theDI,
982 Standard_Integer /*theNArg*/,
983 const char** theArgVal)
7693827d 984{
985 TopoDS_Shape S = DBRep::Get(theArgVal[1]);
986
987 //Use "correctnormals shape"
988
989
990 if(!BRepLib::EnsureNormalConsistency(S))
991 {
992 theDI << "Normals have not been changed!\n";
993 }
994 else
995 {
996 theDI << "Some corrections in source shape have been made!\n";
997 }
998
999 return 0;
1000}
1001
7fd59977 1002//=======================================================================
0d88155b 1003void MeshTest::Commands(Draw_Interpretor& theCommands)
7fd59977 1004//=======================================================================
1005{
1006 Draw::Commands(theCommands);
1007 BRepTest::AllCommands(theCommands);
1008 GeometryTest::AllCommands(theCommands);
1009 MeshTest::PluginCommands(theCommands);
1010 const char* g;
1011
1012 g = "Mesh Commands";
0d88155b 1013
49cfd13d 1014 theCommands.Add("incmesh","Builds triangular mesh for the shape, run w/o args for help",__FILE__, incrementalmesh, g);
b508cbc5 1015 theCommands.Add("tessellate","Builds triangular mesh for the surface, run w/o args for help",__FILE__, tessellate, g);
7fd59977 1016 theCommands.Add("MemLeakTest","MemLeakTest",__FILE__, MemLeakTest, g);
7fd59977 1017
1018 theCommands.Add("tri2d", "tri2d facename",__FILE__, tri2d, g);
1019 theCommands.Add("trinfo","trinfo name, print triangles information on objects",__FILE__,trianglesinfo,g);
1020 theCommands.Add("veriftriangles","veriftriangles name, verif triangles",__FILE__,veriftriangles,g);
1021 theCommands.Add("wavefront","wavefront name",__FILE__, wavefront, g);
d51c7072 1022 theCommands.Add("triepoints", "triepoints shape1 [shape2 ...]",__FILE__, triedgepoints, g);
7fd59977 1023
7693827d 1024 theCommands.Add("correctnormals", "correctnormals shape",__FILE__, correctnormals, g);
7fd59977 1025}