1
0
mirror of https://git.dev.opencascade.org/repos/occt.git synced 2025-08-04 13:13:25 +03:00

0026338: STL export (especially binary) needs a lot of time if selected export path is not local

Method StlAPI_Writer::Write() is reimplemented to write triangulation directly, without conversion to StlMesh_Mesh.

New DRAW command "tessellate" is added to generate rapidly triangulation of prescribed size (on surface).

Command "tricheck" is protected to deal correctly with triangulation without UV data.

New tests added: perf de bug26338_1 and _2; bugs stlvrml bug26338

Correction of testing environment
This commit is contained in:
abv
2016-02-25 07:30:18 +03:00
committed by bugmaster
parent 6396eacb4f
commit b508cbc59f
8 changed files with 406 additions and 35 deletions

View File

@@ -232,6 +232,155 @@ options:\n\
return 0;
}
//=======================================================================
//function : tessellate
//purpose :
//=======================================================================
static Standard_Integer tessellate (Draw_Interpretor& /*di*/, Standard_Integer nbarg, const char** argv)
{
if (nbarg != 5)
{
std::cerr << "Builds regular triangulation with specified number of triangles\n"
" Usage: tessellate result {surface|face} nbu nbv\n"
" Triangulation is put into the face with natural bounds (result);\n"
" it will have 2*nbu*nbv triangles and (nbu+1)*(nbv+1) nodes";
return 1;
}
const char *aResName = argv[1];
const char *aSrcName = argv[2];
int aNbU = Draw::Atoi (argv[3]);
int aNbV = Draw::Atoi (argv[4]);
if (aNbU <= 0 || aNbV <= 0)
{
std::cerr << "Error: Arguments nbu and nbv must be both greater than 0\n";
return 1;
}
Handle(Geom_Surface) aSurf = DrawTrSurf::GetSurface(aSrcName);
double aUMin, aUMax, aVMin, aVMax;
if (! aSurf.IsNull())
{
aSurf->Bounds (aUMin, aUMax, aVMin, aVMax);
}
else
{
TopoDS_Shape aShape = DBRep::Get(aSrcName);
if (aShape.IsNull() || aShape.ShapeType() != TopAbs_FACE)
{
std::cerr << "Error: " << aSrcName << " is not a face\n";
return 1;
}
TopoDS_Face aFace = TopoDS::Face (aShape);
aSurf = BRep_Tool::Surface (aFace);
if (aSurf.IsNull())
{
std::cerr << "Error: Face " << aSrcName << " has no surface\n";
return 1;
}
BRepTools::UVBounds (aFace, aUMin, aUMax, aVMin, aVMax);
}
if (Precision::IsInfinite (aUMin) || Precision::IsInfinite (aUMax) ||
Precision::IsInfinite (aVMin) || Precision::IsInfinite (aVMax))
{
std::cerr << "Error: surface has infinite parametric range, aborting\n";
return 1;
}
BRepBuilderAPI_MakeFace aFaceMaker (aSurf, aUMin, aUMax, aVMin, aVMax, Precision::Confusion());
if (! aFaceMaker.IsDone())
{
std::cerr << "Error: cannot build face with natural bounds, aborting\n";
return 1;
}
TopoDS_Face aFace = aFaceMaker;
// create triangulation
int aNbNodes = (aNbU + 1) * (aNbV + 1);
int aNbTriangles = 2 * aNbU * aNbV;
Handle(Poly_Triangulation) aTriangulation =
new Poly_Triangulation (aNbNodes, aNbTriangles, Standard_False);
// fill nodes
TColgp_Array1OfPnt &aNodes = aTriangulation->ChangeNodes();
GeomAdaptor_Surface anAdSurf (aSurf);
double aDU = (aUMax - aUMin) / aNbU;
double aDV = (aVMax - aVMin) / aNbV;
for (int iU = 0, iShift = 1; iU <= aNbU; iU++, iShift += aNbV + 1)
{
double aU = aUMin + iU * aDU;
for (int iV = 0; iV <= aNbV; iV++)
{
double aV = aVMin + iV * aDV;
gp_Pnt aP = anAdSurf.Value (aU, aV);
aNodes.SetValue (iShift + iV, aP);
}
}
// fill triangles
Poly_Array1OfTriangle &aTriangles = aTriangulation->ChangeTriangles();
for (int iU = 0, iShift = 1, iTri = 0; iU < aNbU; iU++, iShift += aNbV + 1)
{
for (int iV = 0; iV < aNbV; iV++)
{
int iBase = iShift + iV;
Poly_Triangle aTri1 (iBase, iBase + aNbV + 2, iBase + 1);
Poly_Triangle aTri2 (iBase, iBase + aNbV + 1, iBase + aNbV + 2);
aTriangles.SetValue (++iTri, aTri1);
aTriangles.SetValue (++iTri, aTri2);
}
}
// put triangulation to face
BRep_Builder B;
B.UpdateFace (aFace, aTriangulation);
// fill edge polygons
TColStd_Array1OfInteger aUMinIso (1, aNbV + 1), aUMaxIso (1, aNbV + 1);
for (int iV = 0; iV <= aNbV; iV++)
{
aUMinIso.SetValue (1 + iV, 1 + iV);
aUMaxIso.SetValue (1 + iV, 1 + iV + aNbU * (1 + aNbV));
}
TColStd_Array1OfInteger aVMinIso (1, aNbU + 1), aVMaxIso (1, aNbU + 1);
for (int iU = 0; iU <= aNbU; iU++)
{
aVMinIso.SetValue (1 + iU, 1 + iU * (1 + aNbV));
aVMaxIso.SetValue (1 + iU, (1 + iU) * (1 + aNbV));
}
Handle(Poly_PolygonOnTriangulation) aUMinPoly = new Poly_PolygonOnTriangulation (aUMinIso);
Handle(Poly_PolygonOnTriangulation) aUMaxPoly = new Poly_PolygonOnTriangulation (aUMaxIso);
Handle(Poly_PolygonOnTriangulation) aVMinPoly = new Poly_PolygonOnTriangulation (aVMinIso);
Handle(Poly_PolygonOnTriangulation) aVMaxPoly = new Poly_PolygonOnTriangulation (aVMaxIso);
for (TopExp_Explorer exp (aFace, TopAbs_EDGE); exp.More(); exp.Next())
{
TopoDS_Edge anEdge = TopoDS::Edge (exp.Current());
Standard_Real aFirst, aLast;
Handle(Geom2d_Curve) aC = BRep_Tool::CurveOnSurface (anEdge, aFace, aFirst, aLast);
gp_Pnt2d aPFirst = aC->Value (aFirst);
gp_Pnt2d aPLast = aC->Value (aLast);
if (Abs (aPFirst.X() - aPLast.X()) < 0.1 * (aUMax - aUMin)) // U=const
{
if (BRep_Tool::IsClosed (anEdge, aFace))
B.UpdateEdge (anEdge, aUMinPoly, aUMaxPoly, aTriangulation);
else
B.UpdateEdge (anEdge, (aPFirst.X() < 0.5 * (aUMin + aUMax) ? aUMinPoly : aUMaxPoly), aTriangulation);
}
else // V=const
{
if (BRep_Tool::IsClosed (anEdge, aFace))
B.UpdateEdge (anEdge, aVMinPoly, aVMaxPoly, aTriangulation);
else
B.UpdateEdge (anEdge, (aPFirst.Y() < 0.5 * (aVMin + aVMax) ? aVMinPoly : aVMaxPoly), aTriangulation);
}
}
DBRep::Set (aResName, aFace);
return 0;
}
//=======================================================================
//function : MemLeakTest
//purpose :
@@ -1620,6 +1769,7 @@ void MeshTest::Commands(Draw_Interpretor& theCommands)
g = "Mesh Commands";
theCommands.Add("incmesh","Builds triangular mesh for the shape, run w/o args for help",__FILE__, incrementalmesh, g);
theCommands.Add("tessellate","Builds triangular mesh for the surface, run w/o args for help",__FILE__, tessellate, g);
theCommands.Add("MemLeakTest","MemLeakTest",__FILE__, MemLeakTest, g);
theCommands.Add("fastdiscret","fastdiscret shape deflection",__FILE__, fastdiscret, g);
theCommands.Add("mesh","mesh result Shape deflection",__FILE__, triangule, g);

View File

@@ -366,7 +366,6 @@ static Standard_Integer tricheck (Draw_Interpretor& di, int n, const char ** a)
TopLoc_Location aLoc;
Handle(Poly_Triangulation) aT = BRep_Tool::Triangulation(aFace, aLoc);
const TColgp_Array1OfPnt& aPoints = aT->Nodes();
const TColgp_Array1OfPnt2d& aPoints2d = aT->UVNodes();
const gp_Trsf& trsf = aLoc.Transformation();
TColgp_Array1OfPnt pnts(1,2);
@@ -381,12 +380,16 @@ static Standard_Integer tricheck (Draw_Interpretor& di, int n, const char ** a)
DrawTrSurf::Set (name, poly);
DrawTrSurf::Set (name, pnts(1));
DrawTrSurf::Set (name, pnts(2));
pnts2d(1) = aPoints2d(n1);
pnts2d(2) = aPoints2d(n2);
Handle(Poly_Polygon2D) poly2d = new Poly_Polygon2D (pnts2d);
DrawTrSurf::Set (name, poly2d);
DrawTrSurf::Set (name, pnts2d(1));
DrawTrSurf::Set (name, pnts2d(2));
if (aT->HasUVNodes())
{
const TColgp_Array1OfPnt2d& aPoints2d = aT->UVNodes();
pnts2d(1) = aPoints2d(n1);
pnts2d(2) = aPoints2d(n2);
Handle(Poly_Polygon2D) poly2d = new Poly_Polygon2D (pnts2d);
DrawTrSurf::Set (name, poly2d);
DrawTrSurf::Set (name, pnts2d(1));
DrawTrSurf::Set (name, pnts2d(2));
}
}
di << "\n";
}
@@ -428,10 +431,12 @@ static Standard_Integer tricheck (Draw_Interpretor& di, int n, const char ** a)
TopLoc_Location aLoc;
Handle(Poly_Triangulation) aT = BRep_Tool::Triangulation(aFace, aLoc);
const TColgp_Array1OfPnt& aPoints = aT->Nodes();
const TColgp_Array1OfPnt2d& aPoints2d = aT->UVNodes();
const gp_Trsf& trsf = aLoc.Transformation();
DrawTrSurf::Set (name, aPoints(inode).Transformed(trsf));
DrawTrSurf::Set (name, aPoints2d(inode));
if (aT->HasUVNodes())
{
DrawTrSurf::Set (name, aT->UVNodes()(inode));
}
di << "{" << iface << " " << inode << "} ";
}
@@ -520,7 +525,6 @@ static Standard_Integer tricheck (Draw_Interpretor& di, int n, const char ** a)
di << "Not connected mesh inside face " << aFaceId << "\n";
const TColgp_Array1OfPnt& aPoints = aT->Nodes();
const TColgp_Array1OfPnt2d& aPoints2d = aT->UVNodes();
const gp_Trsf& trsf = aLoc.Transformation();
TColgp_Array1OfPnt pnts(1,2);
@@ -536,12 +540,16 @@ static Standard_Integer tricheck (Draw_Interpretor& di, int n, const char ** a)
DrawTrSurf::Set (name, poly);
DrawTrSurf::Set (name, pnts(1));
DrawTrSurf::Set (name, pnts(2));
pnts2d(1) = aPoints2d(aLink.FirstNode());
pnts2d(2) = aPoints2d(aLink.LastNode());
Handle(Poly_Polygon2D) poly2d = new Poly_Polygon2D (pnts2d);
DrawTrSurf::Set (name, poly2d);
DrawTrSurf::Set (name, pnts2d(1));
DrawTrSurf::Set (name, pnts2d(2));
if (aT->HasUVNodes())
{
const TColgp_Array1OfPnt2d& aPoints2d = aT->UVNodes();
pnts2d(1) = aPoints2d(aLink.FirstNode());
pnts2d(2) = aPoints2d(aLink.LastNode());
Handle(Poly_Polygon2D) poly2d = new Poly_Polygon2D (pnts2d);
DrawTrSurf::Set (name, poly2d);
DrawTrSurf::Set (name, pnts2d(1));
DrawTrSurf::Set (name, pnts2d(2));
}
}
di << "\n";
}