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_ProgressIndicator.hxx>
36 #include <Draw_Segment2D.hxx>
37 #include <DrawTrSurf.hxx>
38 #include <GeometryTest.hxx>
39 #include <IMeshData_Status.hxx>
40 #include <Message.hxx>
41 #include <Message_ProgressRange.hxx>
42 #include <OSD_OpenFile.hxx>
43 #include <Poly_Connect.hxx>
44 #include <Poly_MergeNodesTool.hxx>
45 #include <Poly_TriangulationParameters.hxx>
46 #include <Prs3d_Drawer.hxx>
47 #include <StdPrs_ToolTriangulatedShape.hxx>
48 #include <TopExp_Explorer.hxx>
49 #include <TopTools_MapIteratorOfMapOfShape.hxx>
50 #include <BRep_CurveRepresentation.hxx>
51 #include <BRep_TEdge.hxx>
54 #include <BRepMesh_Context.hxx>
55 #include <BRepMesh_FaceDiscret.hxx>
56 #include <BRepMesh_MeshAlgoFactory.hxx>
57 #include <BRepMesh_DelabellaMeshAlgoFactory.hxx>
61 //epa Memory leaks test
64 Standard_IMPORT Draw_Viewer dout;
67 #define MAX2(X, Y) ( Abs(X) > Abs(Y)? Abs(X) : Abs(Y) )
68 #define MAX3(X, Y, Z) ( MAX2 ( MAX2(X,Y) , Z) )
70 #define ONETHIRD 0.333333333333333333333333333333333333333333333333333333333333
71 #define TWOTHIRD 0.666666666666666666666666666666666666666666666666666666666666
73 #ifdef OCCT_DEBUG_MESH_CHRONO
74 #include <OSD_Chronometer.hxx>
75 Standard_Integer D0Control, D0Internal, D0Unif, D0Edges, NbControls;
76 OSD_Chronometer chTotal, chInternal, chControl, chUnif, chAddPoint;
77 OSD_Chronometer chEdges, chMaillEdges, chEtuInter, chLastControl, chStock;
78 OSD_Chronometer chAdd11, chAdd12, chAdd2, chUpdate, chPointValid;
79 OSD_Chronometer chIsos, chPointsOnIsos;
82 //=======================================================================
83 //function : incrementalmesh
85 //=======================================================================
86 static Standard_Integer incrementalmesh (Draw_Interpretor& theDI,
87 Standard_Integer theNbArgs,
88 const char** theArgVec)
92 theDI << "Syntax error: wrong number of arguments";
96 TopoDS_ListOfShape aListOfShapes;
97 IMeshTools_Parameters aMeshParams;
98 bool hasDefl = false, hasAngDefl = false, isPrsDefl = false;
100 Handle(IMeshTools_Context) aContext = new BRepMesh_Context();
101 for (Standard_Integer anArgIter = 1; anArgIter < theNbArgs; ++anArgIter)
103 TCollection_AsciiString aNameCase (theArgVec[anArgIter]);
104 aNameCase.LowerCase();
105 if (aNameCase == "-relative"
106 || aNameCase == "-norelative")
108 aMeshParams.Relative = Draw::ParseOnOffNoIterator (theNbArgs, theArgVec, anArgIter);
110 else if (aNameCase == "-parallel"
111 || aNameCase == "-noparallel")
113 aMeshParams.InParallel = Draw::ParseOnOffNoIterator (theNbArgs, theArgVec, anArgIter);
115 else if (aNameCase == "-int_vert_off")
117 aMeshParams.InternalVerticesMode = !Draw::ParseOnOffIterator (theNbArgs, theArgVec, anArgIter);
119 else if (aNameCase == "-surf_def_off")
121 aMeshParams.ControlSurfaceDeflection = !Draw::ParseOnOffIterator (theNbArgs, theArgVec, anArgIter);
123 else if (aNameCase == "-adjust_min")
125 aMeshParams.AdjustMinSize = Draw::ParseOnOffNoIterator (theNbArgs, theArgVec, anArgIter);
127 else if (aNameCase == "-force_face_def")
129 aMeshParams.ForceFaceDeflection = Draw::ParseOnOffNoIterator (theNbArgs, theArgVec, anArgIter);
131 else if (aNameCase == "-decrease")
133 aMeshParams.AllowQualityDecrease = Draw::ParseOnOffNoIterator (theNbArgs, theArgVec, anArgIter);
135 else if (aNameCase == "-algo"
136 && anArgIter + 1 < theNbArgs)
138 TCollection_AsciiString anAlgoStr (theArgVec[++anArgIter]);
139 anAlgoStr.LowerCase();
140 if (anAlgoStr == "watson"
143 aMeshParams.MeshAlgo = IMeshTools_MeshAlgoType_Watson;
144 aContext->SetFaceDiscret (new BRepMesh_FaceDiscret (new BRepMesh_MeshAlgoFactory()));
146 else if (anAlgoStr == "delabella"
149 aMeshParams.MeshAlgo = IMeshTools_MeshAlgoType_Delabella;
150 aContext->SetFaceDiscret (new BRepMesh_FaceDiscret (new BRepMesh_DelabellaMeshAlgoFactory()));
152 else if (anAlgoStr == "-1"
153 || anAlgoStr == "default")
155 // already handled by BRepMesh_Context constructor
156 //aMeshParams.MeshAlgo = IMeshTools_MeshAlgoType_DEFAULT;
160 theDI << "Syntax error at '" << anAlgoStr << "'";
164 else if ((aNameCase == "-prs"
165 || aNameCase == "-presentation"
166 || aNameCase == "-vis"
167 || aNameCase == "-visualization")
172 else if ((aNameCase == "-angular"
173 || aNameCase == "-angdefl"
174 || aNameCase == "-angulardeflection"
175 || aNameCase == "-a")
176 && anArgIter + 1 < theNbArgs)
178 Standard_Real aVal = Draw::Atof (theArgVec[++anArgIter]) * M_PI / 180.;
179 if (aVal <= Precision::Angular())
181 theDI << "Syntax error: invalid input parameter '" << theArgVec[anArgIter] << "'";
184 aMeshParams.Angle = aVal;
187 else if (aNameCase == "-ai"
188 && anArgIter + 1 < theNbArgs)
190 Standard_Real aVal = Draw::Atof (theArgVec[++anArgIter]) * M_PI / 180.;
191 if (aVal <= Precision::Angular())
193 theDI << "Syntax error: invalid input parameter '" << theArgVec[anArgIter] << "'";
196 aMeshParams.AngleInterior = aVal;
198 else if (aNameCase == "-min"
199 && anArgIter + 1 < theNbArgs)
201 Standard_Real aVal = Draw::Atof (theArgVec[++anArgIter]);
202 if (aVal <= Precision::Confusion())
204 theDI << "Syntax error: invalid input parameter '" << theArgVec[anArgIter] << "'";
207 aMeshParams.MinSize = aVal;
209 else if (aNameCase == "-di"
210 && anArgIter + 1 < theNbArgs)
212 Standard_Real aVal = Draw::Atof (theArgVec[++anArgIter]);
213 if (aVal <= Precision::Confusion())
215 theDI << "Syntax error: invalid input parameter '" << theArgVec[anArgIter] << "'";
218 aMeshParams.DeflectionInterior = aVal;
220 else if (aNameCase.IsRealValue (true)
223 aMeshParams.Deflection = Max (Draw::Atof (theArgVec[anArgIter]), Precision::Confusion());
224 if (aMeshParams.DeflectionInterior < Precision::Confusion())
226 aMeshParams.DeflectionInterior = aMeshParams.Deflection;
232 TopoDS_Shape aShape = DBRep::Get (theArgVec[anArgIter]);
235 theDI << "Syntax error: null shapes are not allowed here '" << theArgVec[anArgIter] << "'\n";
238 aListOfShapes.Append (aShape);
242 if (aListOfShapes.IsEmpty())
244 Message::SendFail ("Syntax error: wrong number of arguments.");
248 theDI << "Incremental Mesh, multi-threading "
249 << (aMeshParams.InParallel ? "ON" : "OFF") << "\n";
252 if (aListOfShapes.Size() == 1)
254 aShape = aListOfShapes.First();
258 TopoDS_Compound aCompound;
259 BRep_Builder().MakeCompound (aCompound);
260 for (TopoDS_ListOfShape::Iterator anIterShape (aListOfShapes); anIterShape.More(); anIterShape.Next())
262 BRep_Builder().Add (aCompound, anIterShape.Value());
269 Handle(Prs3d_Drawer) aDrawer = new Prs3d_Drawer();
272 aDrawer->SetDeviationCoefficient (aMeshParams.Deflection);
274 aMeshParams.Deflection = StdPrs_ToolTriangulatedShape::GetDeflection (aShape, aDrawer);
277 aMeshParams.Angle = aDrawer->DeviationAngle();
281 Handle(Draw_ProgressIndicator) aProgress = new Draw_ProgressIndicator (theDI, 1);
282 BRepMesh_IncrementalMesh aMesher;
283 aMesher.SetShape (aShape);
284 aMesher.ChangeParameters() = aMeshParams;
285 aMesher.Perform (aContext, aProgress->Start());
287 theDI << "Meshing statuses: ";
288 const Standard_Integer aStatus = aMesher.GetStatusFlags();
295 for (Standard_Integer i = 0; i < 9; i++)
297 Standard_Integer aFlag = aStatus & (1 << i);
300 switch ((IMeshData_Status) aFlag)
302 case IMeshData_OpenWire: theDI << "OpenWire "; break;
303 case IMeshData_SelfIntersectingWire: theDI << "SelfIntersectingWire "; break;
304 case IMeshData_Failure: theDI << "Failure "; break;
305 case IMeshData_ReMesh: theDI << "ReMesh "; break;
306 case IMeshData_UnorientedWire: theDI << "UnorientedWire "; break;
307 case IMeshData_TooFewPoints: theDI << "TooFewPoints "; break;
308 case IMeshData_Outdated: theDI << "Outdated "; break;
309 case IMeshData_Reused: theDI << "Reused "; break;
310 case IMeshData_UserBreak: theDI << "UserBreak "; break;
311 case IMeshData_NoError: break;
318 //=======================================================================
319 //function : tessellate
321 //=======================================================================
322 static Standard_Integer tessellate (Draw_Interpretor& /*di*/, Standard_Integer nbarg, const char** argv)
326 Message::SendFail() << "Builds regular triangulation with specified number of triangles\n"
327 " Usage: tessellate result {surface|face} nbu nbv\n"
328 " Triangulation is put into the face with natural bounds (result);\n"
329 " it will have 2*nbu*nbv triangles and (nbu+1)*(nbv+1) nodes";
333 const char *aResName = argv[1];
334 const char *aSrcName = argv[2];
335 int aNbU = Draw::Atoi (argv[3]);
336 int aNbV = Draw::Atoi (argv[4]);
338 if (aNbU <= 0 || aNbV <= 0)
340 Message::SendFail() << "Error: Arguments nbu and nbv must be both greater than 0";
344 Handle(Geom_Surface) aSurf = DrawTrSurf::GetSurface(aSrcName);
345 double aUMin, aUMax, aVMin, aVMax;
346 if (! aSurf.IsNull())
348 aSurf->Bounds (aUMin, aUMax, aVMin, aVMax);
352 TopoDS_Shape aShape = DBRep::Get(aSrcName);
353 if (aShape.IsNull() || aShape.ShapeType() != TopAbs_FACE)
355 Message::SendFail() << "Error: " << aSrcName << " is not a face";
358 TopoDS_Face aFace = TopoDS::Face (aShape);
359 aSurf = BRep_Tool::Surface (aFace);
362 Message::SendFail() << "Error: Face " << aSrcName << " has no surface";
366 BRepTools::UVBounds (aFace, aUMin, aUMax, aVMin, aVMax);
368 if (Precision::IsInfinite (aUMin) || Precision::IsInfinite (aUMax) ||
369 Precision::IsInfinite (aVMin) || Precision::IsInfinite (aVMax))
371 Message::SendFail() << "Error: surface has infinite parametric range, aborting";
375 BRepBuilderAPI_MakeFace aFaceMaker (aSurf, aUMin, aUMax, aVMin, aVMax, Precision::Confusion());
376 if (! aFaceMaker.IsDone())
378 Message::SendFail() << "Error: cannot build face with natural bounds, aborting";
381 TopoDS_Face aFace = aFaceMaker;
383 // create triangulation
384 int aNbNodes = (aNbU + 1) * (aNbV + 1);
385 int aNbTriangles = 2 * aNbU * aNbV;
386 Handle(Poly_Triangulation) aTriangulation =
387 new Poly_Triangulation (aNbNodes, aNbTriangles, Standard_False);
390 GeomAdaptor_Surface anAdSurf (aSurf);
391 double aDU = (aUMax - aUMin) / aNbU;
392 double aDV = (aVMax - aVMin) / aNbV;
393 for (int iU = 0, iShift = 1; iU <= aNbU; iU++, iShift += aNbV + 1)
395 double aU = aUMin + iU * aDU;
396 for (int iV = 0; iV <= aNbV; iV++)
398 double aV = aVMin + iV * aDV;
399 gp_Pnt aP = anAdSurf.Value (aU, aV);
400 aTriangulation->SetNode (iShift + iV, aP);
405 for (int iU = 0, iShift = 1, iTri = 0; iU < aNbU; iU++, iShift += aNbV + 1)
407 for (int iV = 0; iV < aNbV; iV++)
409 int iBase = iShift + iV;
410 Poly_Triangle aTri1 (iBase, iBase + aNbV + 2, iBase + 1);
411 Poly_Triangle aTri2 (iBase, iBase + aNbV + 1, iBase + aNbV + 2);
412 aTriangulation->SetTriangle (++iTri, aTri1);
413 aTriangulation->SetTriangle (++iTri, aTri2);
417 // put triangulation to face
419 B.UpdateFace (aFace, aTriangulation);
421 // fill edge polygons
422 TColStd_Array1OfInteger aUMinIso (1, aNbV + 1), aUMaxIso (1, aNbV + 1);
423 for (int iV = 0; iV <= aNbV; iV++)
425 aUMinIso.SetValue (1 + iV, 1 + iV);
426 aUMaxIso.SetValue (1 + iV, 1 + iV + aNbU * (1 + aNbV));
428 TColStd_Array1OfInteger aVMinIso (1, aNbU + 1), aVMaxIso (1, aNbU + 1);
429 for (int iU = 0; iU <= aNbU; iU++)
431 aVMinIso.SetValue (1 + iU, 1 + iU * (1 + aNbV));
432 aVMaxIso.SetValue (1 + iU, (1 + iU) * (1 + aNbV));
434 Handle(Poly_PolygonOnTriangulation) aUMinPoly = new Poly_PolygonOnTriangulation (aUMinIso);
435 Handle(Poly_PolygonOnTriangulation) aUMaxPoly = new Poly_PolygonOnTriangulation (aUMaxIso);
436 Handle(Poly_PolygonOnTriangulation) aVMinPoly = new Poly_PolygonOnTriangulation (aVMinIso);
437 Handle(Poly_PolygonOnTriangulation) aVMaxPoly = new Poly_PolygonOnTriangulation (aVMaxIso);
438 for (TopExp_Explorer exp (aFace, TopAbs_EDGE); exp.More(); exp.Next())
440 TopoDS_Edge anEdge = TopoDS::Edge (exp.Current());
441 Standard_Real aFirst, aLast;
442 Handle(Geom2d_Curve) aC = BRep_Tool::CurveOnSurface (anEdge, aFace, aFirst, aLast);
443 gp_Pnt2d aPFirst = aC->Value (aFirst);
444 gp_Pnt2d aPLast = aC->Value (aLast);
445 if (Abs (aPFirst.X() - aPLast.X()) < 0.1 * (aUMax - aUMin)) // U=const
447 if (BRep_Tool::IsClosed (anEdge, aFace))
448 B.UpdateEdge (anEdge, aUMinPoly, aUMaxPoly, aTriangulation);
450 B.UpdateEdge (anEdge, (aPFirst.X() < 0.5 * (aUMin + aUMax) ? aUMinPoly : aUMaxPoly), aTriangulation);
454 if (BRep_Tool::IsClosed (anEdge, aFace))
455 B.UpdateEdge (anEdge, aVMinPoly, aVMaxPoly, aTriangulation);
457 B.UpdateEdge (anEdge, (aPFirst.Y() < 0.5 * (aVMin + aVMax) ? aVMinPoly : aVMaxPoly), aTriangulation);
461 DBRep::Set (aResName, aFace);
465 //=======================================================================
466 //function : MemLeakTest
468 //=======================================================================
469 static Standard_Integer MemLeakTest(Draw_Interpretor&, Standard_Integer /*nbarg*/, const char** /*argv*/)
471 for(int i=0;i<10000;i++)
473 BRepBuilderAPI_MakePolygon w(gp_Pnt(0,0,0),gp_Pnt(0,100,0),gp_Pnt(20,100,0),gp_Pnt(20,0,0));
475 TopoDS_Wire wireShape( w.Wire());
476 BRepBuilderAPI_MakeFace faceBuilder(wireShape);
477 TopoDS_Face f( faceBuilder.Face());
478 BRepMesh_IncrementalMesh im(f,1);
484 //=======================================================================
485 //function : TrLateLoad
487 //=======================================================================
488 static Standard_Integer TrLateLoad (Draw_Interpretor& theDI, Standard_Integer theNbArgs, const char** theArgVec)
492 theDI << "Syntax error: not enough arguments\n";
495 TopoDS_Shape aShape = DBRep::Get (theArgVec[1]);
498 theDI << "Syntax error: '" << theArgVec[1] << "' is not a shape\n";
501 for (Standard_Integer anArgIter = 2; anArgIter < theNbArgs; ++anArgIter)
503 TCollection_AsciiString anArgCase(theArgVec[anArgIter]);
504 anArgCase.LowerCase();
505 if (anArgCase == "-load")
507 if (anArgIter + 1 < theNbArgs)
509 TCollection_AsciiString aLoadArg(theArgVec[anArgIter + 1]);
510 aLoadArg.LowerCase();
511 if (aLoadArg == "all"
514 // Load all triangulations
516 if (BRepTools::LoadAllTriangulations (aShape))
518 theDI << "All triangulations of shape " << theArgVec[1] << " were loaded\n";
522 if (aLoadArg.IsIntegerValue())
524 // Load defined triangulation
526 Standard_Integer anIndexToLoad = aLoadArg.IntegerValue();
527 if (anIndexToLoad < -1)
529 Message::SendWarning ("Invalid negative triangulation index to be loaded");
532 if (BRepTools::LoadTriangulation (aShape, anIndexToLoad))
534 theDI << "The " << anIndexToLoad << " triangulation of shape " << theArgVec[1] << " was loaded\n";
539 // Load active triangulation
540 if (BRepTools::LoadTriangulation (aShape))
542 theDI << "The active triangulation of shape " << theArgVec[1] << " was loaded\n";
546 else if (anArgCase == "-unload")
548 if (anArgIter + 1 < theNbArgs)
550 TCollection_AsciiString anUnloadArg(theArgVec[anArgIter + 1]);
551 anUnloadArg.LowerCase();
552 if (anUnloadArg == "all"
553 || anUnloadArg == "*")
555 // Unload all triangulations
557 if (BRepTools::UnloadAllTriangulations (aShape))
559 theDI << "All triangulations of shape " << theArgVec[1] << " were unloaded\n";
563 if (anUnloadArg.IsIntegerValue())
565 // Unload defined triangulation
567 Standard_Integer anIndexToUnload = anUnloadArg.IntegerValue();
568 if (anIndexToUnload < -1)
570 Message::SendWarning ("Invalid negative triangulation index to be unloaded");
573 if (BRepTools::UnloadTriangulation (aShape, anIndexToUnload))
575 theDI << "The " << anIndexToUnload << " triangulation of shape " << theArgVec[1] << " was unloaded\n";
580 // Unload active triangulation
581 if (BRepTools::UnloadTriangulation (aShape))
583 theDI << "The active triangulation of shape " << theArgVec[1] << " was unloaded\n";
587 else if (anArgIter + 1 < theNbArgs
588 && anArgCase == "-activate"
589 && TCollection_AsciiString(theArgVec[anArgIter + 1]).IsIntegerValue())
591 Standard_Integer anIndexToActivate = TCollection_AsciiString(theArgVec[++anArgIter]).IntegerValue();
592 if (anIndexToActivate < 0)
594 Message::SendWarning ("Invalid negative triangulation index to be activated");
597 if (BRepTools::ActivateTriangulation (aShape, anIndexToActivate, false))
599 theDI << "The " << anIndexToActivate << " triangulation of shape " << theArgVec[1] << " was activated\n";
602 else if (anArgIter + 1 < theNbArgs
603 && (anArgCase == "-activatestrict" || anArgCase == "-activateexact")
604 && TCollection_AsciiString(theArgVec[anArgIter + 1]).IsIntegerValue())
606 Standard_Integer anIndexToActivate = TCollection_AsciiString(theArgVec[++anArgIter]).IntegerValue();
607 if (anIndexToActivate < 0)
609 Message::SendWarning ("Invalid negative triangulation index to be activated");
612 if (BRepTools::ActivateTriangulation (aShape, anIndexToActivate, true))
614 theDI << "The " << anIndexToActivate << " triangulation of shape " << theArgVec[1] << " was activated\n";
617 else if (anArgCase == "-loadsingle")
619 Standard_Integer anIndexToSingleLoad = -1;
620 if (anArgIter + 1 < theNbArgs
621 && TCollection_AsciiString(theArgVec[anArgIter + 1]).IsIntegerValue())
623 anIndexToSingleLoad = TCollection_AsciiString(theArgVec[++anArgIter]).IntegerValue();
625 if (anIndexToSingleLoad < -1)
627 Message::SendWarning ("Invalid negative triangulation index to be single loaded");
630 // Unload all triangulations
631 if (BRepTools::UnloadAllTriangulations (aShape))
633 theDI << "All triangulations of shape " << theArgVec[1] << " were unloaded\n";
635 // Activate required triangulation
636 if (anIndexToSingleLoad > -1
637 && BRepTools::ActivateTriangulation (aShape, anIndexToSingleLoad))
639 theDI << "The " << anIndexToSingleLoad << " triangulation of shape " << theArgVec[1] << " was activated\n";
641 // Load active triangulation
642 if (BRepTools::LoadTriangulation (aShape))
644 theDI << "The " << anIndexToSingleLoad << " triangulation of shape " << theArgVec[1] << " was loaded\n";
649 else if (anArgCase == "-loadsingleexact" ||
650 anArgCase == "-loadsinglestrict")
652 Standard_Integer anIndexToSingleLoad = -1;
653 if (anArgIter + 1 < theNbArgs
654 && TCollection_AsciiString(theArgVec[anArgIter + 1]).IsIntegerValue())
656 anIndexToSingleLoad = TCollection_AsciiString(theArgVec[++anArgIter]).IntegerValue();
658 if (anIndexToSingleLoad <= -1)
660 Message::SendWarning ("Invalid negative triangulation index to be single loaded");
663 // Unload all triangulations
664 if (BRepTools::UnloadAllTriangulations (aShape))
666 theDI << "All triangulations of shape " << theArgVec[1] << " were unloaded\n";
668 // Load required triangulation
669 if (BRepTools::LoadTriangulation (aShape, anIndexToSingleLoad, true))
671 theDI << "The " << anIndexToSingleLoad << " triangulation of shape " << theArgVec[1] << " was loaded and activated\n";
677 theDI << "Syntax error: incorrect arguments";
684 //=======================================================================
685 //function : trianglesinfo
687 //=======================================================================
688 static Standard_Integer trianglesinfo (Draw_Interpretor& theDI, Standard_Integer theNbArgs, const char** theArgVec)
692 Message::SendFail ("Syntax error: not enough arguments");
695 TopoDS_Shape aShape = DBRep::Get (theArgVec[1]);
698 theDI << theArgVec[1] << " is not a shape\n";
702 struct TriangulationStat
710 NbUnloadedTriangles (0) {}
712 NCollection_IndexedDataMap<Handle(Standard_Type), Standard_Integer> TypeMap;
713 Standard_Integer NbFaces;
714 Standard_Integer NbEmptyFaces;
715 Standard_Integer NbTriangles;
716 Standard_Integer NbDeferredFaces;
717 Standard_Integer NbUnloadedFaces;
718 Standard_Integer NbUnloadedTriangles;
721 Standard_Boolean toPrintLODs = false;
724 TCollection_AsciiString anArgCase(theArgVec[2]);
725 anArgCase.LowerCase();
726 if (anArgCase == "-lods")
732 TopExp_Explorer anExp;
733 Handle(Poly_Triangulation) aTriangulation;
734 TopLoc_Location aLoc;
735 Standard_Real aMaxDeflection = 0.0, aMeshingDefl = -1.0, aMeshingAngDefl = -1.0, aMeshingMinSize = -1.0;
736 Standard_Integer aNbFaces = 0, aNbEmptyFaces = 0, aNbTriangles = 0, aNbNodes = 0, aNbRepresentations = 0;
737 NCollection_IndexedDataMap<Standard_Integer, TriangulationStat> aLODsStat;
738 NCollection_Vector<Standard_Integer> aNbLODs;
739 for (anExp.Init (aShape, TopAbs_FACE); anExp.More(); anExp.Next())
741 TopoDS_Face aFace = TopoDS::Face (anExp.Current());
743 aTriangulation = BRep_Tool::Triangulation (aFace, aLoc);
744 if (!aTriangulation.IsNull())
746 aNbTriangles += aTriangulation->NbTriangles();
747 aNbNodes += aTriangulation->NbNodes();
748 aMaxDeflection = Max (aMaxDeflection, aTriangulation->Deflection());
749 if (!aTriangulation->Parameters().IsNull())
751 aMeshingDefl = Max (aMeshingDefl, aTriangulation->Parameters()->Deflection());
752 aMeshingAngDefl = Max (aMeshingAngDefl, aTriangulation->Parameters()->Angle());
753 aMeshingMinSize = Max (aMeshingMinSize, aTriangulation->Parameters()->MinSize());
762 // Collect LODs information
763 const Poly_ListOfTriangulation& aLODs = BRep_Tool::Triangulations (aFace, aLoc);
764 if (aLODs.Size() != 0)
766 aNbLODs.Append (aLODs.Size());
768 Standard_Integer aTriangIndex = 0;
769 for (Poly_ListOfTriangulation::Iterator anIter(aLODs); anIter.More(); anIter.Next(), ++aTriangIndex)
771 TriangulationStat* aStats = aLODsStat.ChangeSeek (aTriangIndex);
774 Standard_Integer aNewIndex = aLODsStat.Add (aTriangIndex, TriangulationStat());
775 aStats = &aLODsStat.ChangeFromIndex (aNewIndex);
778 const Handle(Poly_Triangulation)& aLOD = anIter.Value();
781 aStats->NbEmptyFaces++;
784 Standard_Integer* aDynTypeCounter = aStats->TypeMap.ChangeSeek (aLOD->DynamicType());
785 if (aDynTypeCounter == NULL)
787 Standard_Integer aNewIndex = aStats->TypeMap.Add (aLOD->DynamicType(), 0);
788 aDynTypeCounter = &aStats->TypeMap.ChangeFromIndex (aNewIndex);
790 (*aDynTypeCounter)++;
791 if (aLOD->HasDeferredData())
793 aStats->NbDeferredFaces++;
794 if (aLOD->HasGeometry())
796 aStats->NbTriangles += aLOD->NbTriangles();
800 aStats->NbUnloadedFaces++;
801 aStats->NbTriangles += aLOD->NbDeferredTriangles();
802 aStats->NbUnloadedTriangles += aLOD->NbDeferredTriangles();
807 if (aLOD->HasGeometry())
809 aStats->NbTriangles += aLOD->NbTriangles();
813 aStats->NbEmptyFaces++;
819 TopTools_IndexedMapOfShape anEdges;
820 TopExp::MapShapes (aShape, TopAbs_EDGE, anEdges);
821 for (int i = 1; i<=anEdges.Extent(); ++i)
823 const TopoDS_Edge& anEdge = TopoDS::Edge(anEdges(i));
824 Handle(BRep_CurveRepresentation) aCR;
825 BRep_TEdge* aTE = static_cast<BRep_TEdge*>(anEdge.TShape().get());
826 const BRep_ListOfCurveRepresentation& aLCR = aTE->Curves();
827 BRep_ListIteratorOfListOfCurveRepresentation anIterCR(aLCR);
829 while (anIterCR.More()) {
830 aCR = anIterCR.Value();
831 if (aCR->IsPolygonOnTriangulation())
833 aNbRepresentations++;
840 theDI << "This shape contains " << aNbFaces << " faces.\n";
841 if (aNbEmptyFaces > 0)
843 theDI << " " << aNbEmptyFaces << " empty faces.\n";
845 theDI << " " << aNbTriangles << " triangles.\n";
846 theDI << " " << aNbNodes << " nodes.\n";
847 theDI << " " << aNbRepresentations << " polygons on triangulation.\n";
848 theDI << "Maximal deflection " << aMaxDeflection << "\n";
849 if (aMeshingDefl > 0.0)
851 theDI << "Meshing deflection " << aMeshingDefl << "\n";
853 if (aMeshingAngDefl > 0.0)
855 theDI << "Meshing angular deflection " << (aMeshingAngDefl * 180.0 / M_PI) << "\n";
857 if (aMeshingMinSize > 0.0)
859 theDI << "Meshing min size " << aMeshingMinSize << "\n";
862 if (aNbLODs.Size() > 0)
864 // Find all different numbers of triangulation LODs and their average value per face
865 if (aNbLODs.Size() > 1)
867 std::sort (aNbLODs.begin(), aNbLODs.end());
869 NCollection_IndexedMap<Standard_Integer> aLODsRange;
870 for (NCollection_Vector<Standard_Integer>::Iterator aNbIter(aNbLODs); aNbIter.More(); aNbIter.Next())
872 if (!aLODsRange.Contains (aNbIter.Value()))
874 aLODsRange.Add (aNbIter.Value());
877 TCollection_AsciiString aLODsRangeStr;
878 Standard_Integer anIndex = 0;
879 for (NCollection_IndexedMap<Standard_Integer>::Iterator aRangeIter(aLODsRange); aRangeIter.More(); aRangeIter.Next(), anIndex++)
881 aLODsRangeStr += TCollection_AsciiString(aRangeIter.Value());
882 if (anIndex < aLODsRange.Size() - 1)
884 aLODsRangeStr += " ";
887 theDI << TCollection_AsciiString("Number of triangulation LODs [") + aLODsRangeStr + "]\n";
888 if (aLODsRange.Size() > 1)
890 // Find average number of triangulation LODs per face
891 Standard_Integer aMedian = aNbLODs.Value (aNbLODs.Lower() + aNbLODs.Size() / 2);
892 if ((aNbLODs.Size() % 2) == 0)
894 aMedian += aNbLODs.Value (aNbLODs.Lower() + aNbLODs.Size() / 2 - 1);
897 theDI << TCollection_AsciiString(" [average per face: ") + aMedian + "]\n";
900 if (!aLODsStat.IsEmpty())
902 TCollection_AsciiString aLODsStatStr;
903 for (NCollection_IndexedDataMap<Standard_Integer, TriangulationStat>::Iterator anIter(aLODsStat);
904 anIter.More(); anIter.Next())
906 const TriangulationStat& aLodStat = anIter.Value();
907 aLODsStatStr += TCollection_AsciiString("LOD #") + anIter.Key() + ". ";
908 //aLODsStatStr += TCollection_AsciiString("NbFaces: ") + aLodStat.NbFaces;
909 if (aLodStat.NbEmptyFaces > 0 || aLodStat.NbFaces < aNbFaces)
911 const Standard_Integer aNbEmpty = aLodStat.NbEmptyFaces + (aNbFaces - aLodStat.NbFaces);
912 aLODsStatStr += TCollection_AsciiString("NbEmpty: ") + aNbEmpty + ", ";
914 aLODsStatStr += TCollection_AsciiString("NbTris: ") + aLodStat.NbTriangles;
915 if (aLodStat.NbDeferredFaces > 0)
917 aLODsStatStr += TCollection_AsciiString(", NbDeferred: ") + aLodStat.NbDeferredFaces;
918 if (aLodStat.NbUnloadedFaces > 0)
920 aLODsStatStr += TCollection_AsciiString(", NbUnloaded: ") + aLodStat.NbUnloadedFaces + ", NbUnloadedTris: " + aLodStat.NbUnloadedTriangles;
923 aLODsStatStr += ".\n";
926 aLODsStatStr += TCollection_AsciiString(" Types: ");
927 Standard_Integer aCounter = 0;
928 for (NCollection_IndexedDataMap<Handle(Standard_Type), Standard_Integer>::Iterator aTypeIter(aLodStat.TypeMap);
929 aTypeIter.More(); aTypeIter.Next(), aCounter++)
931 aLODsStatStr += TCollection_AsciiString(aTypeIter.Key()->Name()) + " (" + aTypeIter.Value() + ")";
932 if (aCounter < aLodStat.TypeMap.Size() - 1)
934 aLODsStatStr += TCollection_AsciiString(", ");
937 aLODsStatStr += ".\n";
940 theDI << aLODsStatStr;
944 #ifdef OCCT_DEBUG_MESH_CHRONO
945 Standard_Real tot, addp, unif, contr, inter;
946 Standard_Real edges, mailledges, etuinter, lastcontrol, stock;
947 Standard_Real add11, add12, add2, upda, pointvalid;
948 Standard_Real isos, pointsisos;
949 chTotal.Show(tot); chAddPoint.Show(addp); chUnif.Show(unif);
950 chControl.Show(contr); chInternal.Show(inter);
951 chEdges.Show(edges); chMaillEdges.Show(mailledges);
952 chEtuInter.Show(etuinter); chLastControl.Show(lastcontrol);
954 chAdd11.Show(add11); chAdd12.Show(add12); chAdd2.Show(add2); chUpdate.Show(upda);
955 chPointValid.Show(pointvalid); chIsos.Show(isos); chPointsOnIsos.Show(pointsisos);
958 theDI <<"temps total de maillage: "<<tot <<" seconds\n";
960 theDI <<"discretisation des edges: "<<edges <<" seconds---> "<< 100*edges/tot <<" %\n";
961 theDI <<"maillage des edges: "<<mailledges <<" seconds---> "<< 100*mailledges/tot <<" %\n";
962 theDI <<"controle et points internes: "<<etuinter <<" seconds---> "<< 100*etuinter/tot <<" %\n";
963 theDI <<"derniers controles: "<<lastcontrol<<" seconds---> "<< 100*lastcontrol/tot<<" %\n";
964 theDI <<"stockage dans la S.D. "<<stock <<" seconds---> "<< 100*stock/tot <<" %\n";
966 theDI <<"et plus precisement: \n";
967 theDI <<"Add 11ere partie : "<<add11 <<" seconds---> "<<100*add11/tot <<" %\n";
968 theDI <<"Add 12ere partie : "<<add12 <<" seconds---> "<<100*add12/tot <<" %\n";
969 theDI <<"Add 2eme partie : "<<add2 <<" seconds---> "<<100*add2/tot <<" %\n";
970 theDI <<"Update : "<<upda <<" seconds---> "<<100*upda/tot <<" %\n";
971 theDI <<"AddPoint : "<<addp <<" seconds---> "<<100*addp/tot <<" %\n";
972 theDI <<"UniformDeflection "<<unif <<" seconds---> "<<100*unif/tot <<" %\n";
973 theDI <<"Controle : "<<contr <<" seconds---> "<<100*contr/tot <<" %\n";
974 theDI <<"Points Internes: "<<inter <<" seconds---> "<<100*inter/tot <<" %\n";
975 theDI <<"calcul des isos et du, dv: "<<isos <<" seconds---> "<<100*isos/tot <<" %\n";
976 theDI <<"calcul des points sur isos: "<<pointsisos<<" seconds---> "<<100*pointsisos/tot <<" %\n";
977 theDI <<"IsPointValid: "<<pointvalid<<" seconds---> "<<100*pointvalid/tot <<" %\n";
981 theDI <<"nombre d'appels de controle apres points internes : "<< NbControls << "\n";
982 theDI <<"nombre de points sur restrictions : "<< D0Edges << "\n";
983 theDI <<"nombre de points calcules par UniformDeflection : "<< D0Unif << "\n";
984 theDI <<"nombre de points calcules dans InternalVertices : "<< D0Internal << "\n";
985 theDI <<"nombre de points calcules dans Control : "<< D0Control << "\n";
986 if (nbnodes-D0Edges != 0) {
987 Standard_Real ratio = (Standard_Real)(D0Internal+D0Control)/ (Standard_Real)(nbnodes-D0Edges);
988 theDI <<"---> Ratio: (D0Internal+D0Control) / (nbNodes-nbOnEdges) : "<< ratio << "\n";
993 chTotal.Reset(); chAddPoint.Reset(); chUnif.Reset();
994 chControl.Reset(); chInternal.Reset();
995 chEdges.Reset(); chMaillEdges.Reset();
996 chEtuInter.Reset(); chLastControl.Reset();
998 chAdd11.Reset(); chAdd12.Reset(); chAdd2.Reset(); chUpdate.Reset();
999 chPointValid.Reset(); chIsos.Reset(); chPointsOnIsos.Reset();
1006 //=======================================================================
1007 //function : veriftriangles
1009 //=======================================================================
1010 static Standard_Integer veriftriangles(Draw_Interpretor& di, Standard_Integer n, const char** a)
1012 if (n < 2) return 1;
1013 Standard_Boolean quiet = 1;
1014 if (n == 3) quiet = 0;
1015 TopoDS_Shape Sh = DBRep::Get(a[1]);
1016 if (Sh.IsNull()) return 1;
1018 Handle(Poly_Triangulation) T;
1020 Standard_Integer i, n1, n2, n3;
1021 gp_Pnt2d mitri, v1, v2, v3, mi2d1, mi2d2, mi2d3;
1022 gp_XYZ vecEd1, vecEd2, vecEd3;
1023 // Standard_Real dipo, dm, dv, d1, d2, d3, defle;
1024 Standard_Real dipo, dv, d1, d2, d3, defle;
1025 Handle(Geom_Surface) S;
1026 Standard_Integer nbface = 0;
1029 for (ex.Init(Sh, TopAbs_FACE); ex.More(); ex.Next()) {
1030 TopoDS_Face F = TopoDS::Face(ex.Current());
1032 T = BRep_Tool::Triangulation(F, L);
1033 Standard_Real deflemax = 0, deflemin = 1.e100;
1035 Standard_Real defstock = T->Deflection();
1037 S = BRep_Tool::Surface(F, L);
1039 for(i = 1; i <= T->NbTriangles(); i++) {
1040 if (F.Orientation() == TopAbs_REVERSED)
1041 T->Triangle (i).Get (n1,n3,n2);
1043 T->Triangle (i).Get (n1,n2,n3);
1045 const gp_XY& xy1 = T->UVNode (n1).XY();
1046 const gp_XY& xy2 = T->UVNode (n2).XY();
1047 const gp_XY& xy3 = T->UVNode (n3).XY();
1049 mi2d1.SetCoord((xy2.X()+xy3.X())*0.5,
1050 (xy2.Y()+xy3.Y())*0.5);
1051 mi2d2.SetCoord((xy1.X()+xy3.X())*0.5,
1052 (xy1.Y()+xy3.Y())*0.5);
1053 mi2d3.SetCoord((xy1.X()+xy2.X())*0.5,
1054 (xy1.Y()+xy2.Y())*0.5);
1056 gp_XYZ p1 = T->Node (n1).Transformed (L.Transformation()).XYZ();
1057 gp_XYZ p2 = T->Node (n2).Transformed (L.Transformation()).XYZ();
1058 gp_XYZ p3 = T->Node (n3).Transformed (L.Transformation()).XYZ();
1063 d1=vecEd1.SquareModulus();
1064 d2=vecEd2.SquareModulus();
1065 d3=vecEd3.SquareModulus();
1067 if (d1!=0. && d2!=0. && d3!=0.) {
1068 gp_XYZ equa(vecEd1^vecEd2);
1071 equa.SetCoord(equa.X()/dv, equa.Y()/dv, equa.Z()/dv);
1075 mitri.SetCoord(ONETHIRD*(xy1.X()+xy2.X()+xy3.X()),
1076 ONETHIRD*(xy1.Y()+xy2.Y()+xy3.Y()));
1077 v1.SetCoord(ONETHIRD*mi2d1.X()+TWOTHIRD*xy1.X(),
1078 ONETHIRD*mi2d1.Y()+TWOTHIRD*xy1.Y());
1079 v2.SetCoord(ONETHIRD*mi2d2.X()+TWOTHIRD*xy2.X(),
1080 ONETHIRD*mi2d2.Y()+TWOTHIRD*xy2.Y());
1081 v3.SetCoord(ONETHIRD*mi2d3.X()+TWOTHIRD*xy3.X(),
1082 ONETHIRD*mi2d3.Y()+TWOTHIRD*xy3.Y());
1084 S->D0(mi2d1.X(), mi2d1.Y(), PP);
1085 PP = PP.Transformed(L.Transformation());
1086 defle = Abs((equa*PP.XYZ())-dipo);
1087 deflemax = Max(deflemax, defle);
1088 deflemin = Min(deflemin, defle);
1090 S->D0(mi2d2.X(), mi2d2.Y(), PP);
1091 PP = PP.Transformed(L.Transformation());
1092 defle = Abs((equa*PP.XYZ())-dipo);
1093 deflemax = Max(deflemax, defle);
1094 deflemin = Min(deflemin, defle);
1096 S->D0(mi2d3.X(), mi2d3.Y(), PP);
1097 PP = PP.Transformed(L.Transformation());
1098 defle = Abs((equa*PP.XYZ())-dipo);
1099 deflemax = Max(deflemax, defle);
1100 deflemin = Min(deflemin, defle);
1102 S->D0(v1.X(), v1.Y(), PP);
1103 PP = PP.Transformed(L.Transformation());
1104 defle = Abs((equa*PP.XYZ())-dipo);
1105 deflemax = Max(deflemax, defle);
1106 deflemin = Min(deflemin, defle);
1108 S->D0(v2.X(), v2.Y(), PP);
1109 PP = PP.Transformed(L.Transformation());
1110 defle = Abs((equa*PP.XYZ())-dipo);
1111 deflemax = Max(deflemax, defle);
1112 deflemin = Min(deflemin, defle);
1114 S->D0(v3.X(), v3.Y(), PP);
1115 PP = PP.Transformed(L.Transformation());
1116 defle = Abs((equa*PP.XYZ())-dipo);
1117 deflemax = Max(deflemax, defle);
1118 deflemin = Min(deflemin, defle);
1120 S->D0(mitri.X(), mitri.Y(), PP);
1121 PP = PP.Transformed(L.Transformation());
1122 defle = Abs((equa*PP.XYZ())-dipo);
1123 deflemax = Max(deflemax, defle);
1124 deflemin = Min(deflemin, defle);
1126 if (defle > defstock) {
1127 di <<"face "<< nbface <<" deflection = " << defle <<" pour "<<defstock <<" stockee.\n";
1133 di <<"face "<< nbface<<", deflemin = "<< deflemin<<", deflemax = "<<deflemax<<"\n";
1143 //=======================================================================
1146 //=======================================================================
1147 static Standard_Integer tri2d(Draw_Interpretor&, Standard_Integer n, const char** a)
1150 if (n != 2) return 1;
1151 TopoDS_Shape aLocalShape = DBRep::Get(a[1]);
1152 TopoDS_Face F = TopoDS::Face(aLocalShape);
1153 // TopoDS_Face F = TopoDS::Face(DBRep::Get(a[1]));
1154 if (F.IsNull()) return 1;
1155 Handle(Poly_Triangulation) T;
1158 T = BRep_Tool::Triangulation(F, L);
1160 // Build the connect tool
1163 Standard_Integer i,j, nFree, nInternal, nbTriangles = T->NbTriangles();
1164 Standard_Integer t[3];
1166 // count the free edges
1168 for (i = 1; i <= nbTriangles; i++) {
1169 pc.Triangles(i,t[0],t[1],t[2]);
1170 for (j = 0; j < 3; j++)
1171 if (t[j] == 0) nFree++;
1174 // allocate the arrays
1175 TColStd_Array1OfInteger Free(1,2*nFree);
1176 nInternal = (3*nbTriangles - nFree) / 2;
1177 TColStd_Array1OfInteger Internal(0,2*nInternal);
1179 Standard_Integer fr = 1, in = 1;
1180 Standard_Integer nodes[3];
1181 for (i = 1; i <= nbTriangles; i++) {
1182 pc.Triangles(i,t[0],t[1],t[2]);
1183 T->Triangle (i).Get (nodes[0],nodes[1],nodes[2]);
1184 for (j = 0; j < 3; j++) {
1185 Standard_Integer k = (j+1) % 3;
1187 Free(fr) = nodes[j];
1188 Free(fr+1) = nodes[k];
1191 // internal edge if this triangle has a lower index than the adjacent
1192 else if (i < t[j]) {
1193 Internal(in) = nodes[j];
1194 Internal(in+1) = nodes[k];
1200 // Display the edges
1201 if (T->HasUVNodes()) {
1202 Handle(Draw_Segment2D) Seg;
1205 Standard_Integer nn;
1206 nn = Free.Length() / 2;
1207 for (i = 1; i <= nn; i++) {
1208 Seg = new Draw_Segment2D (T->UVNode (Free[2*i-1]),
1209 T->UVNode (Free[2*i]),
1217 for (i = 1; i <= nn; i++) {
1218 Seg = new Draw_Segment2D (T->UVNode (Internal[2*i-1]),
1219 T->UVNode (Internal[2*i]),
1230 //=======================================================================
1231 //function : wavefront
1233 //=======================================================================
1234 static Standard_Integer wavefront(Draw_Interpretor&, Standard_Integer nbarg, const char** argv)
1236 if (nbarg < 2) return 1;
1238 TopoDS_Shape S = DBRep::Get(argv[1]);
1239 if (S.IsNull()) return 1;
1241 // creation du maillage s'il n'existe pas.
1244 Standard_Real aXmin, aYmin, aZmin, aXmax, aYmax, aZmax;
1245 BRepBndLib::Add(S, B);
1246 B.Get(aXmin, aYmin, aZmin, aXmax, aYmax, aZmax);
1247 Standard_Real aDeflection =
1248 MAX3( aXmax-aXmin , aYmax-aYmin , aZmax-aZmin) * 0.004;
1250 BRepMesh_IncrementalMesh aMesh (S, aDeflection);
1256 Standard_Integer i, nbface = 0;
1257 Standard_Boolean OK = Standard_True;
1259 gp_Vec D2U,D2V,D2UV;
1263 CSLib_DerivativeStatus aStatus;
1264 CSLib_NormalStatus NStat;
1265 Standard_Real x, y, z;
1266 Standard_Integer n1, n2, n3;
1267 Standard_Integer k1, k2, k3;
1269 TCollection_AsciiString aFile;
1275 else aFile = "wave.obj";
1276 FILE* outfile = OSD_OpenFile(aFile.ToCString(), "w");
1279 fprintf(outfile, "%s %s\n%s %s\n\n", "# CASCADE ","MATRA DATAVISION", "#", aFile.ToCString());
1281 Standard_Integer nbNodes, totalnodes = 0, nbpolygons = 0;
1282 for (ex.Init(S, TopAbs_FACE); ex.More(); ex.Next()) {
1284 TopoDS_Face F = TopoDS::Face(ex.Current());
1285 Handle(Poly_Triangulation) Tr = BRep_Tool::Triangulation(F, L);
1288 nbNodes = Tr->NbNodes();
1291 for (i = 1; i <= nbNodes; i++) {
1292 gp_Pnt Pnt = Tr->Node (i).Transformed (L.Transformation());
1296 fprintf(outfile, "%s %f %f %f\n", "v", x, y, z);
1299 fprintf(outfile, "\n%s %d\n\n", "# number of vertex", nbNodes);
1304 if (Tr->HasUVNodes()) {
1305 BRepAdaptor_Surface BS(F, Standard_False);
1307 for (i = 1; i <= nbNodes; i++) {
1308 U = Tr->UVNode (i).X();
1309 V = Tr->UVNode (i).Y();
1311 BS.D1(U,V,P,D1U,D1V);
1312 CSLib::Normal (D1U, D1V, Precision::Angular(), aStatus, Nor);
1313 if (aStatus != CSLib_Done) {
1314 BS.D2(U,V,P,D1U,D1V,D2U,D2V,D2UV);
1315 CSLib::Normal(D1U,D1V,D2U,D2V,D2UV,Precision::Angular(),OK,NStat,Nor);
1317 if (F.Orientation() == TopAbs_REVERSED) Nor.Reverse();
1319 fprintf(outfile, "%s %f %f %f\n", "vn", Nor.X(), Nor.Y(), Nor.Z());
1322 fprintf(outfile, "\n%s %d\n\n", "# number of vertex normals", nbNodes);
1325 fprintf(outfile, "%s %d\n", "s", nbface);
1328 Standard_Integer nbTriangles = Tr->NbTriangles();
1330 for (i = 1; i <= nbTriangles; i++) {
1331 if (F.Orientation() == TopAbs_REVERSED)
1332 Tr->Triangle (i).Get (n1, n3, n2);
1334 Tr->Triangle (i).Get (n1, n2, n3);
1338 fprintf(outfile, "f %d%s%d %d%s%d %d%s%d\n", k1,"//", k1, k2,"//", k2, k3,"//", k3);
1340 nbpolygons += nbTriangles;
1341 totalnodes += nbNodes;
1343 fprintf(outfile, "\n%s %d\n", "# number of smooth groups", nbface);
1344 fprintf(outfile, "\n%s %d\n", "# number of polygons", nbpolygons);
1354 //=======================================================================
1355 //function : triedgepoints
1357 //=======================================================================
1358 static Standard_Integer triedgepoints(Draw_Interpretor& di, Standard_Integer nbarg, const char** argv)
1363 for( Standard_Integer i = 1; i < nbarg; i++ )
1365 TopoDS_Shape aShape = DBRep::Get(argv[i]);
1366 if ( aShape.IsNull() )
1369 Handle(Poly_PolygonOnTriangulation) aPoly;
1370 Handle(Poly_Triangulation) aT;
1371 TopLoc_Location aLoc;
1372 TopTools_MapOfShape anEdgeMap;
1373 TopTools_MapIteratorOfMapOfShape it;
1375 if( aShape.ShapeType() == TopAbs_EDGE )
1377 anEdgeMap.Add( aShape );
1381 TopExp_Explorer ex(aShape, TopAbs_EDGE);
1382 for(; ex.More(); ex.Next() )
1383 anEdgeMap.Add( ex.Current() );
1386 if ( anEdgeMap.Extent() == 0 )
1390 strcpy(newname,argv[i]);
1392 while (*p != '\0') p++;
1396 Standard_Integer nbEdge = 1;
1397 for(it.Initialize(anEdgeMap); it.More(); it.Next())
1399 BRep_Tool::PolygonOnTriangulation(TopoDS::Edge(it.Key()), aPoly, aT, aLoc);
1400 if ( aT.IsNull() || aPoly.IsNull() )
1403 const TColStd_Array1OfInteger& Indices = aPoly->Nodes();
1404 const Standard_Integer nbnodes = Indices.Length();
1406 for( Standard_Integer j = 1; j <= nbnodes; j++ )
1408 gp_Pnt P3d = aT->Node (Indices[j]);
1409 if( !aLoc.IsIdentity() )
1410 P3d.Transform(aLoc.Transformation());
1412 if( anEdgeMap.Extent() > 1 )
1413 Sprintf(p,"%d_%d",nbEdge,j);
1416 DBRep::Set( newname, BRepBuilderAPI_MakeVertex(P3d) );
1417 di.AppendElement(newname);
1425 //=======================================================================
1426 //function : TrMergeNodes
1428 //=======================================================================
1429 static Standard_Integer TrMergeNodes (Draw_Interpretor& theDI, Standard_Integer theNbArgs, const char** theArgVec)
1433 theDI << "Syntax error: not enough arguments";
1437 TopoDS_Shape aShape = DBRep::Get (theArgVec[1]);
1438 if (aShape.IsNull())
1440 theDI << "Syntax error: '" << theArgVec[1] << "' is not a shape";
1444 Standard_Real aMergeAngle = M_PI / 4.0, aMergeToler = 0.0;
1445 bool toForce = false;
1446 TCollection_AsciiString aResFace;
1447 for (Standard_Integer anArgIter = 2; anArgIter < theNbArgs; ++anArgIter)
1449 TCollection_AsciiString anArgCase (theArgVec[anArgIter]);
1450 anArgCase.LowerCase();
1451 if (anArgIter + 1 < theNbArgs
1452 && (anArgCase == "-angle"
1453 || anArgCase == "-smoothangle"
1454 || anArgCase == "-mergeangle")
1455 && Draw::ParseReal (theArgVec[anArgIter + 1], aMergeAngle))
1457 if (aMergeAngle < 0.0 || aMergeAngle > 90.0)
1459 theDI << "Syntax error: angle should be within [0,90] range";
1464 aMergeAngle = aMergeAngle * M_PI / 180.0;
1466 else if (anArgIter + 1 < theNbArgs
1467 && anArgCase == "-tolerance"
1468 && Draw::ParseReal (theArgVec[anArgIter + 1], aMergeToler))
1470 if (aMergeToler < 0.0)
1472 theDI << "Syntax error: tolerance should be within >=0";
1478 else if (anArgCase == "-force")
1480 toForce = Draw::ParseOnOffIterator (theNbArgs, theArgVec, anArgIter);
1482 else if (anArgIter + 1 < theNbArgs
1483 && anArgCase == "-oneface")
1485 aResFace = theArgVec[++anArgIter];
1489 theDI << "Syntax error at '" << theArgVec[anArgIter] << "'";
1494 Standard_Integer aNbNodesOld = 0, aNbTrisOld = 0;
1495 Standard_Integer aNbNodesNew = 0, aNbTrisNew = 0;
1496 if (!aResFace.IsEmpty())
1498 TopLoc_Location aFaceLoc;
1499 Poly_MergeNodesTool aMergeTool (aMergeAngle, aMergeToler);
1500 for (TopExp_Explorer aFaceIter (aShape, TopAbs_FACE); aFaceIter.More(); aFaceIter.Next())
1502 const TopoDS_Face& aFace = TopoDS::Face (aFaceIter.Value());
1503 Handle(Poly_Triangulation) aTris = BRep_Tool::Triangulation (aFace, aFaceLoc);
1505 || aTris->NbNodes() < 3
1506 || aTris->NbTriangles() < 1)
1511 aNbNodesOld += aTris->NbNodes();
1512 aNbTrisOld += aTris->NbTriangles();
1513 aMergeTool.AddTriangulation (aTris, aFaceLoc, aFace.Orientation() == TopAbs_REVERSED);
1515 Handle(Poly_Triangulation) aNewTris = aMergeTool.Result();
1516 if (aNewTris.IsNull())
1518 theDI << "Error: empty result";
1522 aNbNodesNew += aNewTris->NbNodes();
1523 aNbTrisNew += aNewTris->NbTriangles();
1525 BRep_Builder().MakeFace (aFace, aNewTris);
1526 DBRep::Set (aResFace.ToCString(), aFace);
1530 TopTools_MapOfShape aProcessedFaces;
1531 TopLoc_Location aDummy;
1532 for (TopExp_Explorer aFaceIter (aShape, TopAbs_FACE); aFaceIter.More(); aFaceIter.Next())
1534 const TopoDS_Face& aFace = TopoDS::Face (aFaceIter.Value());
1535 if (!aProcessedFaces.Add (aFace.Located (TopLoc_Location())))
1540 Handle(Poly_Triangulation) aTris = BRep_Tool::Triangulation (aFace, aDummy);
1542 || aTris->NbNodes() < 3
1543 || aTris->NbTriangles() < 1)
1548 aNbNodesOld += aTris->NbNodes();
1549 aNbTrisOld += aTris->NbTriangles();
1550 Poly_MergeNodesTool aMergeTool (aMergeAngle, aMergeToler, aTris->NbTriangles());
1551 aMergeTool.AddTriangulation (aTris);
1553 || aMergeTool.NbNodes() != aTris->NbNodes()
1554 || aMergeTool.NbElements() != aTris->NbTriangles())
1556 BRep_Builder().UpdateFace (aFace, aMergeTool.Result(), false);
1559 aTris = BRep_Tool::Triangulation (aFace, aDummy);
1560 aNbNodesNew += aTris->NbNodes();
1561 aNbTrisNew += aTris->NbTriangles();
1564 theDI << "Old, Triangles: " << aNbTrisOld << ", Nodes: " << aNbNodesOld << "\n";
1565 theDI << "New, Triangles: " << aNbTrisNew << ", Nodes: " << aNbNodesNew << "\n";
1569 //=======================================================================
1570 //function : correctnormals
1571 //purpose : Corrects normals in shape triangulation nodes (...)
1572 //=======================================================================
1573 static Standard_Integer correctnormals(Draw_Interpretor& theDI,
1574 Standard_Integer /*theNArg*/,
1575 const char** theArgVal)
1577 TopoDS_Shape S = DBRep::Get(theArgVal[1]);
1579 //Use "correctnormals shape"
1582 if(!BRepLib::EnsureNormalConsistency(S))
1584 theDI << "Normals have not been changed!\n";
1588 theDI << "Some corrections in source shape have been made!\n";
1594 //=======================================================================
1595 void MeshTest::Commands(Draw_Interpretor& theCommands)
1596 //=======================================================================
1598 Draw::Commands(theCommands);
1599 BRepTest::AllCommands(theCommands);
1600 GeometryTest::AllCommands(theCommands);
1601 MeshTest::PluginCommands(theCommands);
1604 g = "Mesh Commands";
1606 theCommands.Add("incmesh",
1607 "incmesh Shape LinDefl [-angular Angle]=28.64 [-prs]"
1608 "\n\t\t: [-relative {0|1}]=0 [-parallel {0|1}]=0 [-min Size]"
1609 "\n\t\t: [-algo {watson|delabella}]=watson"
1610 "\n\t\t: [-di Value] [-ai Angle]=57.29"
1611 "\n\t\t: [-int_vert_off {0|1}]=0 [-surf_def_off {0|1}]=0 [-adjust_min {0|1}]=0"
1612 "\n\t\t: [-force_face_def {0|1}]=0 [-decrease {0|1}]=0"
1613 "\n\t\t: Builds triangular mesh for the shape."
1614 "\n\t\t: LinDefl linear deflection to control mesh quality;"
1615 "\n\t\t: -angular angular deflection for edges in deg (~28.64 deg = 0.5 rad by default);"
1616 "\n\t\t: -prs apply default meshing parameters for visualization purposes"
1617 "\n\t\t: (20 deg angular deflection, 0.001 of bounding box linear deflection);"
1618 "\n\t\t: -relative notifies that relative deflection is used (FALSE by default);"
1619 "\n\t\t: -parallel enables parallel execution (FALSE by default);"
1620 "\n\t\t: -algo changes core triangulation algorithm to one with specified id (watson by default);"
1621 "\n\t\t: -min minimum size parameter limiting size of triangle's edges to prevent sinking"
1622 "\n\t\t: into amplification in case of distorted curves and surfaces;"
1623 "\n\t\t: -di linear deflection used to tessellate the face interior;"
1624 "\n\t\t: -ai angular deflection inside of faces in deg (~57.29 deg = 1 rad by default);"
1625 "\n\t\t: -int_vert_off disables insertion of internal vertices into mesh (enabled by default);"
1626 "\n\t\t: -surf_def_off disables control of deflection of mesh from real surface (enabled by default);"
1627 "\n\t\t: -adjust_min enables local adjustment of min size depending on edge size (FALSE by default);"
1628 "\n\t\t: -force_face_def disables usage of shape tolerances for computing face deflection (FALSE by default);"
1629 "\n\t\t: -decrease enforces the meshing of the shape even if current mesh satisfies the new criteria"
1630 "\n\t\t: (FALSE by default).",
1631 __FILE__, incrementalmesh, g);
1632 theCommands.Add("tessellate","Builds triangular mesh for the surface, run w/o args for help",__FILE__, tessellate, g);
1633 theCommands.Add("MemLeakTest","MemLeakTest",__FILE__, MemLeakTest, g);
1635 theCommands.Add("tri2d", "tri2d facename",__FILE__, tri2d, g);
1636 theCommands.Add("trinfo",
1637 "trinfo shapeName [-lods], print triangles information on objects"
1638 "\n\t\t: -lods Print detailed LOD information",
1639 __FILE__,trianglesinfo,g);
1640 theCommands.Add("veriftriangles","veriftriangles name, verif triangles",__FILE__,veriftriangles,g);
1641 theCommands.Add("wavefront","wavefront name",__FILE__, wavefront, g);
1642 theCommands.Add("triepoints", "triepoints shape1 [shape2 ...]",__FILE__, triedgepoints, g);
1643 theCommands.Add("trlateload",
1644 "trlateload shapeName"
1645 "\n\t\t: [-load {-1|Index|ALL}=-1] [-unload {-1|Index|ALL}=-1]"
1646 "\n\t\t: [-activate Index] [-activateExact Index]"
1647 "\n\t\t: [-loadSingle {-1|Index}=-1] [-loadSingleExact {Index}=-1]"
1648 "\n\t\t: Interaction with deferred triangulations."
1649 "\n\t\t: '-load' - load triangulation (-1 - currently active one, Index - with defined index,"
1650 "\n\t\t: ALL - all available ones)"
1651 "\n\t\t: '-unload' - unload triangulation (-1 - currently active one, Index - with defined index,"
1652 "\n\t\t: ALL - all available ones)"
1653 "\n\t\t: '-activate' - activate triangulation with defined index. If it doesn't exist -"
1654 "\n\t\t: activate the last available triangulation."
1655 "\n\t\t: '-activateExact' - activate exactly triangulation with defined index or do nothing."
1656 "\n\t\t: '-loadSingle' - make loaded and active ONLY specified triangulation (-1 - currently active one,"
1657 "\n\t\t: Index - with defined index or last available if it doesn't exist)."
1658 "\n\t\t: All other triangulations will be unloaded."
1659 "\n\t\t: '-loadSingleExact' - make loaded and active ONLY exactly specified triangulation. All other triangulations"
1660 "\n\t\t: will be unloaded. If triangulation with such Index doesn't exist do nothing",
1661 __FILE__, TrLateLoad, g);
1662 theCommands.Add("trmergenodes",
1663 "trmergenodes shapeName"
1664 "\n\t\t: [-angle Angle] [-tolerance Value] [-oneFace Result]"
1665 "\n\t\t: Merging nodes within triangulation data."
1666 "\n\t\t: -angle merge angle upper limit in degrees; 45 when unspecified"
1667 "\n\t\t: -tolerance linear tolerance to merge nodes; 0.0 when unspecified"
1668 "\n\t\t: -oneFace create a new single Face with specified name for the whole triangulation",
1669 __FILE__, TrMergeNodes, g);
1670 theCommands.Add("correctnormals", "correctnormals shape",__FILE__, correctnormals, g);