1 // Created on: 1993-09-22
2 // Created by: Didier PIFFAULT
3 // Copyright (c) 1993-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 #include <MeshTest.hxx>
21 #include <Bnd_Box.hxx>
22 #include <BRep_Builder.hxx>
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>
29 #include <BRepMesh_IncrementalMesh.hxx>
30 #include <BRepTest.hxx>
31 #include <BRepTools.hxx>
34 #include <Draw_Appli.hxx>
35 #include <Draw_Segment2D.hxx>
36 #include <DrawTrSurf.hxx>
37 #include <GeometryTest.hxx>
38 #include <IMeshData_Status.hxx>
39 #include <Poly_Connect.hxx>
40 #include <TopExp_Explorer.hxx>
41 #include <TopTools_MapIteratorOfMapOfShape.hxx>
43 //epa Memory leaks test
46 Standard_IMPORT Draw_Viewer dout;
49 #define MAX2(X, Y) ( Abs(X) > Abs(Y)? Abs(X) : Abs(Y) )
50 #define MAX3(X, Y, Z) ( MAX2 ( MAX2(X,Y) , Z) )
52 #define ONETHIRD 0.333333333333333333333333333333333333333333333333333333333333
53 #define TWOTHIRD 0.666666666666666666666666666666666666666666666666666666666666
55 #ifdef OCCT_DEBUG_MESH_CHRONO
56 #include <OSD_Chronometer.hxx>
57 Standard_Integer D0Control, D0Internal, D0Unif, D0Edges, NbControls;
58 OSD_Chronometer chTotal, chInternal, chControl, chUnif, chAddPoint;
59 OSD_Chronometer chEdges, chMaillEdges, chEtuInter, chLastControl, chStock;
60 OSD_Chronometer chAdd11, chAdd12, chAdd2, chUpdate, chPointValid;
61 OSD_Chronometer chIsos, chPointsOnIsos;
64 //=======================================================================
65 //function : incrementalmesh
67 //=======================================================================
68 static Standard_Integer incrementalmesh(Draw_Interpretor& di, Standard_Integer nbarg, const char** argv)
73 Builds triangular mesh for the shape\n\
74 usage: incmesh Shape LinearDeflection [options]\n\
76 -a val angular deflection for edges in deg\n\
77 (default ~28.64 deg = 0.5 rad)\n\n\
78 -ai val angular deflection inside of faces in deg\n\
79 (default ~57.29 deg = 1 rad)\n\n\
80 -di val Linear deflection used to tessellate the face interior.\n\
81 -min minimum size parameter limiting size of triangle's\n\
82 edges to prevent sinking into amplification in case\n\
83 of distorted curves and surfaces\n\n\
84 -relative notifies that relative deflection is used\n\
85 (switched off by default)\n\n\
86 -int_vert_off disables insertion of internal vertices into mesh\n\
87 (enabled by default)\n\
88 -surf_def_off disables control of deflection of mesh from real\n\
89 surface (enabled by default)\n\
90 -parallel enables parallel execution (switched off by default)\n\
91 -adaptive enables adaptive computation of minimal value in parametric space\n";
95 TopoDS_Shape aShape = DBRep::Get(argv[1]);
98 di << " Null shapes are not allowed here\n";
102 IMeshTools_Parameters aMeshParams;
103 aMeshParams.Deflection = aMeshParams.DeflectionInterior =
104 Max(Draw::Atof(argv[2]), Precision::Confusion());
108 Standard_Integer i = 3;
111 TCollection_AsciiString aOpt(argv[i++]);
116 else if (aOpt == "-relative")
117 aMeshParams.Relative = Standard_True;
118 else if (aOpt == "-parallel")
119 aMeshParams.InParallel = Standard_True;
120 else if (aOpt == "-int_vert_off")
121 aMeshParams.InternalVerticesMode = Standard_False;
122 else if (aOpt == "-surf_def_off")
123 aMeshParams.ControlSurfaceDeflection = Standard_False;
126 Standard_Real aVal = Draw::Atof(argv[i++]);
129 aMeshParams.Angle = aVal * M_PI / 180.;
131 else if (aOpt == "-ai")
133 aMeshParams.AngleInterior = aVal * M_PI / 180.;
135 else if (aOpt == "-min")
136 aMeshParams.MinSize = aVal;
137 else if (aOpt == "-di")
139 aMeshParams.DeflectionInterior = aVal;
147 di << "Incremental Mesh, multi-threading "
148 << (aMeshParams.InParallel ? "ON" : "OFF") << "\n";
150 BRepMesh_IncrementalMesh aMesher (aShape, aMeshParams);
152 di << "Meshing statuses: ";
153 const Standard_Integer aStatus = aMesher.GetStatusFlags();
161 for (i = 0; i < 8; i++)
163 Standard_Integer aFlag = aStatus & (1 << i);
166 switch ((IMeshData_Status) aFlag)
168 case IMeshData_OpenWire:
171 case IMeshData_SelfIntersectingWire:
172 di << "SelfIntersectingWire ";
174 case IMeshData_Failure:
177 case IMeshData_ReMesh:
180 case IMeshData_UnorientedWire:
181 di << "UnorientedWire ";
183 case IMeshData_TooFewPoints:
184 di << "TooFewPoints ";
186 case IMeshData_Outdated:
189 case IMeshData_Reused:
192 case IMeshData_NoError:
203 //=======================================================================
204 //function : tessellate
206 //=======================================================================
207 static Standard_Integer tessellate (Draw_Interpretor& /*di*/, Standard_Integer nbarg, const char** argv)
211 std::cerr << "Builds regular triangulation with specified number of triangles\n"
212 " Usage: tessellate result {surface|face} nbu nbv\n"
213 " Triangulation is put into the face with natural bounds (result);\n"
214 " it will have 2*nbu*nbv triangles and (nbu+1)*(nbv+1) nodes";
218 const char *aResName = argv[1];
219 const char *aSrcName = argv[2];
220 int aNbU = Draw::Atoi (argv[3]);
221 int aNbV = Draw::Atoi (argv[4]);
223 if (aNbU <= 0 || aNbV <= 0)
225 std::cerr << "Error: Arguments nbu and nbv must be both greater than 0\n";
229 Handle(Geom_Surface) aSurf = DrawTrSurf::GetSurface(aSrcName);
230 double aUMin, aUMax, aVMin, aVMax;
231 if (! aSurf.IsNull())
233 aSurf->Bounds (aUMin, aUMax, aVMin, aVMax);
237 TopoDS_Shape aShape = DBRep::Get(aSrcName);
238 if (aShape.IsNull() || aShape.ShapeType() != TopAbs_FACE)
240 std::cerr << "Error: " << aSrcName << " is not a face\n";
243 TopoDS_Face aFace = TopoDS::Face (aShape);
244 aSurf = BRep_Tool::Surface (aFace);
247 std::cerr << "Error: Face " << aSrcName << " has no surface\n";
251 BRepTools::UVBounds (aFace, aUMin, aUMax, aVMin, aVMax);
253 if (Precision::IsInfinite (aUMin) || Precision::IsInfinite (aUMax) ||
254 Precision::IsInfinite (aVMin) || Precision::IsInfinite (aVMax))
256 std::cerr << "Error: surface has infinite parametric range, aborting\n";
260 BRepBuilderAPI_MakeFace aFaceMaker (aSurf, aUMin, aUMax, aVMin, aVMax, Precision::Confusion());
261 if (! aFaceMaker.IsDone())
263 std::cerr << "Error: cannot build face with natural bounds, aborting\n";
266 TopoDS_Face aFace = aFaceMaker;
268 // create triangulation
269 int aNbNodes = (aNbU + 1) * (aNbV + 1);
270 int aNbTriangles = 2 * aNbU * aNbV;
271 Handle(Poly_Triangulation) aTriangulation =
272 new Poly_Triangulation (aNbNodes, aNbTriangles, Standard_False);
275 TColgp_Array1OfPnt &aNodes = aTriangulation->ChangeNodes();
276 GeomAdaptor_Surface anAdSurf (aSurf);
277 double aDU = (aUMax - aUMin) / aNbU;
278 double aDV = (aVMax - aVMin) / aNbV;
279 for (int iU = 0, iShift = 1; iU <= aNbU; iU++, iShift += aNbV + 1)
281 double aU = aUMin + iU * aDU;
282 for (int iV = 0; iV <= aNbV; iV++)
284 double aV = aVMin + iV * aDV;
285 gp_Pnt aP = anAdSurf.Value (aU, aV);
286 aNodes.SetValue (iShift + iV, aP);
291 Poly_Array1OfTriangle &aTriangles = aTriangulation->ChangeTriangles();
292 for (int iU = 0, iShift = 1, iTri = 0; iU < aNbU; iU++, iShift += aNbV + 1)
294 for (int iV = 0; iV < aNbV; iV++)
296 int iBase = iShift + iV;
297 Poly_Triangle aTri1 (iBase, iBase + aNbV + 2, iBase + 1);
298 Poly_Triangle aTri2 (iBase, iBase + aNbV + 1, iBase + aNbV + 2);
299 aTriangles.SetValue (++iTri, aTri1);
300 aTriangles.SetValue (++iTri, aTri2);
304 // put triangulation to face
306 B.UpdateFace (aFace, aTriangulation);
308 // fill edge polygons
309 TColStd_Array1OfInteger aUMinIso (1, aNbV + 1), aUMaxIso (1, aNbV + 1);
310 for (int iV = 0; iV <= aNbV; iV++)
312 aUMinIso.SetValue (1 + iV, 1 + iV);
313 aUMaxIso.SetValue (1 + iV, 1 + iV + aNbU * (1 + aNbV));
315 TColStd_Array1OfInteger aVMinIso (1, aNbU + 1), aVMaxIso (1, aNbU + 1);
316 for (int iU = 0; iU <= aNbU; iU++)
318 aVMinIso.SetValue (1 + iU, 1 + iU * (1 + aNbV));
319 aVMaxIso.SetValue (1 + iU, (1 + iU) * (1 + aNbV));
321 Handle(Poly_PolygonOnTriangulation) aUMinPoly = new Poly_PolygonOnTriangulation (aUMinIso);
322 Handle(Poly_PolygonOnTriangulation) aUMaxPoly = new Poly_PolygonOnTriangulation (aUMaxIso);
323 Handle(Poly_PolygonOnTriangulation) aVMinPoly = new Poly_PolygonOnTriangulation (aVMinIso);
324 Handle(Poly_PolygonOnTriangulation) aVMaxPoly = new Poly_PolygonOnTriangulation (aVMaxIso);
325 for (TopExp_Explorer exp (aFace, TopAbs_EDGE); exp.More(); exp.Next())
327 TopoDS_Edge anEdge = TopoDS::Edge (exp.Current());
328 Standard_Real aFirst, aLast;
329 Handle(Geom2d_Curve) aC = BRep_Tool::CurveOnSurface (anEdge, aFace, aFirst, aLast);
330 gp_Pnt2d aPFirst = aC->Value (aFirst);
331 gp_Pnt2d aPLast = aC->Value (aLast);
332 if (Abs (aPFirst.X() - aPLast.X()) < 0.1 * (aUMax - aUMin)) // U=const
334 if (BRep_Tool::IsClosed (anEdge, aFace))
335 B.UpdateEdge (anEdge, aUMinPoly, aUMaxPoly, aTriangulation);
337 B.UpdateEdge (anEdge, (aPFirst.X() < 0.5 * (aUMin + aUMax) ? aUMinPoly : aUMaxPoly), aTriangulation);
341 if (BRep_Tool::IsClosed (anEdge, aFace))
342 B.UpdateEdge (anEdge, aVMinPoly, aVMaxPoly, aTriangulation);
344 B.UpdateEdge (anEdge, (aPFirst.Y() < 0.5 * (aVMin + aVMax) ? aVMinPoly : aVMaxPoly), aTriangulation);
348 DBRep::Set (aResName, aFace);
352 //=======================================================================
353 //function : MemLeakTest
355 //=======================================================================
356 static Standard_Integer MemLeakTest(Draw_Interpretor&, Standard_Integer /*nbarg*/, const char** /*argv*/)
358 for(int i=0;i<10000;i++)
360 BRepBuilderAPI_MakePolygon w(gp_Pnt(0,0,0),gp_Pnt(0,100,0),gp_Pnt(20,100,0),gp_Pnt(20,0,0));
362 TopoDS_Wire wireShape( w.Wire());
363 BRepBuilderAPI_MakeFace faceBuilder(wireShape);
364 TopoDS_Face f( faceBuilder.Face());
365 BRepMesh_IncrementalMesh im(f,1);
371 //=======================================================================
372 //function : trianglesinfo
374 //=======================================================================
375 static Standard_Integer trianglesinfo(Draw_Interpretor& di, Standard_Integer n, const char** a)
377 if (n != 2) return 1;
378 TopoDS_Shape S = DBRep::Get(a[1]);
379 if (S.IsNull()) return 1;
381 Handle(Poly_Triangulation) T;
384 Standard_Real MaxDeflection = 0.0;
385 Standard_Integer nbtriangles = 0, nbnodes = 0;
386 for (ex.Init(S, TopAbs_FACE); ex.More(); ex.Next()) {
387 TopoDS_Face F = TopoDS::Face(ex.Current());
388 T = BRep_Tool::Triangulation(F, L);
390 nbtriangles += T->NbTriangles();
391 nbnodes += T->NbNodes();
392 if (T->Deflection() > MaxDeflection)
393 MaxDeflection = T->Deflection();
398 di<<"This shape contains " <<nbtriangles<<" triangles.\n";
399 di<<" " <<nbnodes <<" nodes.\n";
400 di<<"Maximal deflection " <<MaxDeflection<<"\n";
402 #ifdef OCCT_DEBUG_MESH_CHRONO
403 Standard_Real tot, addp, unif, contr, inter;
404 Standard_Real edges, mailledges, etuinter, lastcontrol, stock;
405 Standard_Real add11, add12, add2, upda, pointvalid;
406 Standard_Real isos, pointsisos;
407 chTotal.Show(tot); chAddPoint.Show(addp); chUnif.Show(unif);
408 chControl.Show(contr); chInternal.Show(inter);
409 chEdges.Show(edges); chMaillEdges.Show(mailledges);
410 chEtuInter.Show(etuinter); chLastControl.Show(lastcontrol);
412 chAdd11.Show(add11); chAdd12.Show(add12); chAdd2.Show(add2); chUpdate.Show(upda);
413 chPointValid.Show(pointvalid); chIsos.Show(isos); chPointsOnIsos.Show(pointsisos);
416 di <<"temps total de maillage: "<<tot <<" seconds\n";
418 di <<"discretisation des edges: "<<edges <<" seconds---> "<< 100*edges/tot <<" %\n";
419 di <<"maillage des edges: "<<mailledges <<" seconds---> "<< 100*mailledges/tot <<" %\n";
420 di <<"controle et points internes: "<<etuinter <<" seconds---> "<< 100*etuinter/tot <<" %\n";
421 di <<"derniers controles: "<<lastcontrol<<" seconds---> "<< 100*lastcontrol/tot<<" %\n";
422 di <<"stockage dans la S.D. "<<stock <<" seconds---> "<< 100*stock/tot <<" %\n";
424 di <<"et plus precisement: \n";
425 di <<"Add 11ere partie : "<<add11 <<" seconds---> "<<100*add11/tot <<" %\n";
426 di <<"Add 12ere partie : "<<add12 <<" seconds---> "<<100*add12/tot <<" %\n";
427 di <<"Add 2eme partie : "<<add2 <<" seconds---> "<<100*add2/tot <<" %\n";
428 di <<"Update : "<<upda <<" seconds---> "<<100*upda/tot <<" %\n";
429 di <<"AddPoint : "<<addp <<" seconds---> "<<100*addp/tot <<" %\n";
430 di <<"UniformDeflection "<<unif <<" seconds---> "<<100*unif/tot <<" %\n";
431 di <<"Controle : "<<contr <<" seconds---> "<<100*contr/tot <<" %\n";
432 di <<"Points Internes: "<<inter <<" seconds---> "<<100*inter/tot <<" %\n";
433 di <<"calcul des isos et du, dv: "<<isos <<" seconds---> "<<100*isos/tot <<" %\n";
434 di <<"calcul des points sur isos: "<<pointsisos<<" seconds---> "<<100*pointsisos/tot <<" %\n";
435 di <<"IsPointValid: "<<pointvalid<<" seconds---> "<<100*pointvalid/tot <<" %\n";
439 di <<"nombre d'appels de controle apres points internes : "<< NbControls << "\n";
440 di <<"nombre de points sur restrictions : "<< D0Edges << "\n";
441 di <<"nombre de points calcules par UniformDeflection : "<< D0Unif << "\n";
442 di <<"nombre de points calcules dans InternalVertices : "<< D0Internal << "\n";
443 di <<"nombre de points calcules dans Control : "<< D0Control << "\n";
444 if (nbnodes-D0Edges != 0) {
445 Standard_Real ratio = (Standard_Real)(D0Internal+D0Control)/ (Standard_Real)(nbnodes-D0Edges);
446 di <<"---> Ratio: (D0Internal+D0Control) / (nbNodes-nbOnEdges) : "<< ratio << "\n";
451 chTotal.Reset(); chAddPoint.Reset(); chUnif.Reset();
452 chControl.Reset(); chInternal.Reset();
453 chEdges.Reset(); chMaillEdges.Reset();
454 chEtuInter.Reset(); chLastControl.Reset();
456 chAdd11.Reset(); chAdd12.Reset(); chAdd2.Reset(); chUpdate.Reset();
457 chPointValid.Reset(); chIsos.Reset(); chPointsOnIsos.Reset();
464 //=======================================================================
465 //function : veriftriangles
467 //=======================================================================
468 static Standard_Integer veriftriangles(Draw_Interpretor& di, Standard_Integer n, const char** a)
471 Standard_Boolean quiet = 1;
472 if (n == 3) quiet = 0;
473 TopoDS_Shape Sh = DBRep::Get(a[1]);
474 if (Sh.IsNull()) return 1;
476 Handle(Poly_Triangulation) T;
478 Standard_Integer i, n1, n2, n3;
479 gp_Pnt2d mitri, v1, v2, v3, mi2d1, mi2d2, mi2d3;
480 gp_XYZ vecEd1, vecEd2, vecEd3;
481 // Standard_Real dipo, dm, dv, d1, d2, d3, defle;
482 Standard_Real dipo, dv, d1, d2, d3, defle;
483 Handle(Geom_Surface) S;
484 Standard_Integer nbface = 0;
487 for (ex.Init(Sh, TopAbs_FACE); ex.More(); ex.Next()) {
488 TopoDS_Face F = TopoDS::Face(ex.Current());
490 T = BRep_Tool::Triangulation(F, L);
491 Standard_Real deflemax = 0, deflemin = 1.e100;
493 Standard_Real defstock = T->Deflection();
494 const Poly_Array1OfTriangle& triangles = T->Triangles();
495 const TColgp_Array1OfPnt2d& Nodes2d = T->UVNodes();
496 const TColgp_Array1OfPnt& Nodes = T->Nodes();
498 S = BRep_Tool::Surface(F, L);
500 for(i = 1; i <= triangles.Length(); i++) {
501 if (F.Orientation() == TopAbs_REVERSED)
502 triangles(i).Get(n1,n3,n2);
504 triangles(i).Get(n1,n2,n3);
506 const gp_XY& xy1 = Nodes2d(n1).XY();
507 const gp_XY& xy2 = Nodes2d(n2).XY();
508 const gp_XY& xy3 = Nodes2d(n3).XY();
510 mi2d1.SetCoord((xy2.X()+xy3.X())*0.5,
511 (xy2.Y()+xy3.Y())*0.5);
512 mi2d2.SetCoord((xy1.X()+xy3.X())*0.5,
513 (xy1.Y()+xy3.Y())*0.5);
514 mi2d3.SetCoord((xy1.X()+xy2.X())*0.5,
515 (xy1.Y()+xy2.Y())*0.5);
517 gp_XYZ p1 = Nodes(n1).Transformed(L.Transformation()).XYZ();
518 gp_XYZ p2 = Nodes(n2).Transformed(L.Transformation()).XYZ();
519 gp_XYZ p3 = Nodes(n3).Transformed(L.Transformation()).XYZ();
524 d1=vecEd1.SquareModulus();
525 d2=vecEd2.SquareModulus();
526 d3=vecEd3.SquareModulus();
528 if (d1!=0. && d2!=0. && d3!=0.) {
529 gp_XYZ equa(vecEd1^vecEd2);
532 equa.SetCoord(equa.X()/dv, equa.Y()/dv, equa.Z()/dv);
536 mitri.SetCoord(ONETHIRD*(xy1.X()+xy2.X()+xy3.X()),
537 ONETHIRD*(xy1.Y()+xy2.Y()+xy3.Y()));
538 v1.SetCoord(ONETHIRD*mi2d1.X()+TWOTHIRD*xy1.X(),
539 ONETHIRD*mi2d1.Y()+TWOTHIRD*xy1.Y());
540 v2.SetCoord(ONETHIRD*mi2d2.X()+TWOTHIRD*xy2.X(),
541 ONETHIRD*mi2d2.Y()+TWOTHIRD*xy2.Y());
542 v3.SetCoord(ONETHIRD*mi2d3.X()+TWOTHIRD*xy3.X(),
543 ONETHIRD*mi2d3.Y()+TWOTHIRD*xy3.Y());
545 S->D0(mi2d1.X(), mi2d1.Y(), PP);
546 PP = PP.Transformed(L.Transformation());
547 defle = Abs((equa*PP.XYZ())-dipo);
548 deflemax = Max(deflemax, defle);
549 deflemin = Min(deflemin, defle);
551 S->D0(mi2d2.X(), mi2d2.Y(), PP);
552 PP = PP.Transformed(L.Transformation());
553 defle = Abs((equa*PP.XYZ())-dipo);
554 deflemax = Max(deflemax, defle);
555 deflemin = Min(deflemin, defle);
557 S->D0(mi2d3.X(), mi2d3.Y(), PP);
558 PP = PP.Transformed(L.Transformation());
559 defle = Abs((equa*PP.XYZ())-dipo);
560 deflemax = Max(deflemax, defle);
561 deflemin = Min(deflemin, defle);
563 S->D0(v1.X(), v1.Y(), PP);
564 PP = PP.Transformed(L.Transformation());
565 defle = Abs((equa*PP.XYZ())-dipo);
566 deflemax = Max(deflemax, defle);
567 deflemin = Min(deflemin, defle);
569 S->D0(v2.X(), v2.Y(), PP);
570 PP = PP.Transformed(L.Transformation());
571 defle = Abs((equa*PP.XYZ())-dipo);
572 deflemax = Max(deflemax, defle);
573 deflemin = Min(deflemin, defle);
575 S->D0(v3.X(), v3.Y(), PP);
576 PP = PP.Transformed(L.Transformation());
577 defle = Abs((equa*PP.XYZ())-dipo);
578 deflemax = Max(deflemax, defle);
579 deflemin = Min(deflemin, defle);
581 S->D0(mitri.X(), mitri.Y(), PP);
582 PP = PP.Transformed(L.Transformation());
583 defle = Abs((equa*PP.XYZ())-dipo);
584 deflemax = Max(deflemax, defle);
585 deflemin = Min(deflemin, defle);
587 if (defle > defstock) {
588 di <<"face "<< nbface <<" deflection = " << defle <<" pour "<<defstock <<" stockee.\n";
594 di <<"face "<< nbface<<", deflemin = "<< deflemin<<", deflemax = "<<deflemax<<"\n";
604 //=======================================================================
607 //=======================================================================
608 static Standard_Integer tri2d(Draw_Interpretor&, Standard_Integer n, const char** a)
611 if (n != 2) return 1;
612 TopoDS_Shape aLocalShape = DBRep::Get(a[1]);
613 TopoDS_Face F = TopoDS::Face(aLocalShape);
614 // TopoDS_Face F = TopoDS::Face(DBRep::Get(a[1]));
615 if (F.IsNull()) return 1;
616 Handle(Poly_Triangulation) T;
619 T = BRep_Tool::Triangulation(F, L);
621 // Build the connect tool
624 Standard_Integer i,j, nFree, nInternal, nbTriangles = T->NbTriangles();
625 Standard_Integer t[3];
627 // count the free edges
629 for (i = 1; i <= nbTriangles; i++) {
630 pc.Triangles(i,t[0],t[1],t[2]);
631 for (j = 0; j < 3; j++)
632 if (t[j] == 0) nFree++;
635 // allocate the arrays
636 TColStd_Array1OfInteger Free(1,2*nFree);
637 nInternal = (3*nbTriangles - nFree) / 2;
638 TColStd_Array1OfInteger Internal(0,2*nInternal);
640 Standard_Integer fr = 1, in = 1;
641 const Poly_Array1OfTriangle& triangles = T->Triangles();
642 Standard_Integer nodes[3];
643 for (i = 1; i <= nbTriangles; i++) {
644 pc.Triangles(i,t[0],t[1],t[2]);
645 triangles(i).Get(nodes[0],nodes[1],nodes[2]);
646 for (j = 0; j < 3; j++) {
647 Standard_Integer k = (j+1) % 3;
650 Free(fr+1) = nodes[k];
653 // internal edge if this triangle has a lower index than the adjacent
655 Internal(in) = nodes[j];
656 Internal(in+1) = nodes[k];
663 if (T->HasUVNodes()) {
664 const TColgp_Array1OfPnt2d& Nodes2d = T->UVNodes();
666 Handle(Draw_Segment2D) Seg;
670 nn = Free.Length() / 2;
671 for (i = 1; i <= nn; i++) {
672 Seg = new Draw_Segment2D(Nodes2d(Free(2*i-1)),
681 for (i = 1; i <= nn; i++) {
682 Seg = new Draw_Segment2D(Nodes2d(Internal(2*i-1)),
683 Nodes2d(Internal(2*i)),
694 //=======================================================================
695 //function : wavefront
697 //=======================================================================
698 static Standard_Integer wavefront(Draw_Interpretor&, Standard_Integer nbarg, const char** argv)
700 if (nbarg < 2) return 1;
702 TopoDS_Shape S = DBRep::Get(argv[1]);
703 if (S.IsNull()) return 1;
705 // creation du maillage s'il n'existe pas.
708 Standard_Real aXmin, aYmin, aZmin, aXmax, aYmax, aZmax;
709 BRepBndLib::Add(S, B);
710 B.Get(aXmin, aYmin, aZmin, aXmax, aYmax, aZmax);
711 Standard_Real aDeflection =
712 MAX3( aXmax-aXmin , aYmax-aYmin , aZmax-aZmin) * 0.004;
714 BRepMesh_IncrementalMesh aMesh (S, aDeflection);
720 Standard_Integer i, nbface = 0;
721 Standard_Boolean OK = Standard_True;
727 CSLib_DerivativeStatus aStatus;
728 CSLib_NormalStatus NStat;
729 Standard_Real x, y, z;
730 Standard_Integer n1, n2, n3;
731 Standard_Integer k1, k2, k3;
736 strcpy(ffile, argv[2]);
737 strcat(ffile, ".obj");
739 else strcpy(ffile, "wave.obj");
740 FILE* outfile = fopen(ffile, "w");
743 fprintf(outfile, "%s %s\n%s %s\n\n", "# CASCADE ","MATRA DATAVISION", "#", ffile);
745 Standard_Integer nbNodes, totalnodes = 0, nbpolygons = 0;
746 for (ex.Init(S, TopAbs_FACE); ex.More(); ex.Next()) {
748 TopoDS_Face F = TopoDS::Face(ex.Current());
749 Handle(Poly_Triangulation) Tr = BRep_Tool::Triangulation(F, L);
752 nbNodes = Tr->NbNodes();
753 const TColgp_Array1OfPnt& Nodes = Tr->Nodes();
756 for (i = 1; i <= nbNodes; i++) {
757 gp_Pnt Pnt = Nodes(i).Transformed(L.Transformation());
761 fprintf(outfile, "%s %f %f %f\n", "v", x, y, z);
764 fprintf(outfile, "\n%s %d\n\n", "# number of vertex", nbNodes);
769 if (Tr->HasUVNodes()) {
770 const TColgp_Array1OfPnt2d& UVNodes = Tr->UVNodes();
771 BRepAdaptor_Surface BS(F, Standard_False);
773 for (i = 1; i <= nbNodes; i++) {
777 BS.D1(U,V,P,D1U,D1V);
778 CSLib::Normal (D1U, D1V, Precision::Angular(), aStatus, Nor);
779 if (aStatus != CSLib_Done) {
780 BS.D2(U,V,P,D1U,D1V,D2U,D2V,D2UV);
781 CSLib::Normal(D1U,D1V,D2U,D2V,D2UV,Precision::Angular(),OK,NStat,Nor);
783 if (F.Orientation() == TopAbs_REVERSED) Nor.Reverse();
785 fprintf(outfile, "%s %f %f %f\n", "vn", Nor.X(), Nor.Y(), Nor.Z());
788 fprintf(outfile, "\n%s %d\n\n", "# number of vertex normals", nbNodes);
791 fprintf(outfile, "%s %d\n", "s", nbface);
794 Standard_Integer nbTriangles = Tr->NbTriangles();
795 const Poly_Array1OfTriangle& triangles = Tr->Triangles();
798 for (i = 1; i <= nbTriangles; i++) {
799 if (F.Orientation() == TopAbs_REVERSED)
800 triangles(i).Get(n1, n3, n2);
802 triangles(i).Get(n1, n2, n3);
806 fprintf(outfile, "%s %d%s%d %d%s%d %d%s%d\n", "fo", k1,"//", k1, k2,"//", k2, k3,"//", k3);
808 nbpolygons += nbTriangles;
809 totalnodes += nbNodes;
811 fprintf(outfile, "\n%s %d\n", "# number of smooth groups", nbface);
812 fprintf(outfile, "\n%s %d\n", "# number of polygons", nbpolygons);
822 //=======================================================================
823 //function : triedgepoints
825 //=======================================================================
826 static Standard_Integer triedgepoints(Draw_Interpretor& di, Standard_Integer nbarg, const char** argv)
831 for( Standard_Integer i = 1; i < nbarg; i++ )
833 TopoDS_Shape aShape = DBRep::Get(argv[i]);
834 if ( aShape.IsNull() )
837 Handle(Poly_PolygonOnTriangulation) aPoly;
838 Handle(Poly_Triangulation) aT;
839 TopLoc_Location aLoc;
840 TopTools_MapOfShape anEdgeMap;
841 TopTools_MapIteratorOfMapOfShape it;
843 if( aShape.ShapeType() == TopAbs_EDGE )
845 anEdgeMap.Add( aShape );
849 TopExp_Explorer ex(aShape, TopAbs_EDGE);
850 for(; ex.More(); ex.Next() )
851 anEdgeMap.Add( ex.Current() );
854 if ( anEdgeMap.Extent() == 0 )
858 strcpy(newname,argv[i]);
860 while (*p != '\0') p++;
864 Standard_Integer nbEdge = 1;
865 for(it.Initialize(anEdgeMap); it.More(); it.Next())
867 BRep_Tool::PolygonOnTriangulation(TopoDS::Edge(it.Key()), aPoly, aT, aLoc);
868 if ( aT.IsNull() || aPoly.IsNull() )
871 const TColgp_Array1OfPnt& Nodes = aT->Nodes();
872 const TColStd_Array1OfInteger& Indices = aPoly->Nodes();
873 const Standard_Integer nbnodes = Indices.Length();
875 for( Standard_Integer j = 1; j <= nbnodes; j++ )
877 gp_Pnt P3d = Nodes(Indices(j));
878 if( !aLoc.IsIdentity() )
879 P3d.Transform(aLoc.Transformation());
881 if( anEdgeMap.Extent() > 1 )
882 Sprintf(p,"%d_%d",nbEdge,j);
885 DBRep::Set( newname, BRepBuilderAPI_MakeVertex(P3d) );
886 di.AppendElement(newname);
894 //=======================================================================
895 //function : correctnormals
896 //purpose : Corrects normals in shape triangulation nodes (...)
897 //=======================================================================
898 static Standard_Integer correctnormals(Draw_Interpretor& theDI,
899 Standard_Integer /*theNArg*/,
900 const char** theArgVal)
902 TopoDS_Shape S = DBRep::Get(theArgVal[1]);
904 //Use "correctnormals shape"
907 if(!BRepLib::EnsureNormalConsistency(S))
909 theDI << "Normals have not been changed!\n";
913 theDI << "Some corrections in source shape have been made!\n";
919 //=======================================================================
920 void MeshTest::Commands(Draw_Interpretor& theCommands)
921 //=======================================================================
923 Draw::Commands(theCommands);
924 BRepTest::AllCommands(theCommands);
925 GeometryTest::AllCommands(theCommands);
926 MeshTest::PluginCommands(theCommands);
931 theCommands.Add("incmesh","Builds triangular mesh for the shape, run w/o args for help",__FILE__, incrementalmesh, g);
932 theCommands.Add("tessellate","Builds triangular mesh for the surface, run w/o args for help",__FILE__, tessellate, g);
933 theCommands.Add("MemLeakTest","MemLeakTest",__FILE__, MemLeakTest, g);
935 theCommands.Add("tri2d", "tri2d facename",__FILE__, tri2d, g);
936 theCommands.Add("trinfo","trinfo name, print triangles information on objects",__FILE__,trianglesinfo,g);
937 theCommands.Add("veriftriangles","veriftriangles name, verif triangles",__FILE__,veriftriangles,g);
938 theCommands.Add("wavefront","wavefront name",__FILE__, wavefront, g);
939 theCommands.Add("triepoints", "triepoints shape1 [shape2 ...]",__FILE__, triedgepoints, g);
941 theCommands.Add("correctnormals", "correctnormals shape",__FILE__, correctnormals, g);