mirror of
https://git.dev.opencascade.org/repos/occt.git
synced 2025-08-04 13:13:25 +03:00
0028840: Data Exchange - rewrite the STL Reader/Writer
STL Reader and Writer tools have been refactored to improve performance and usability: - Basic reading of STL file is separated to abstract class RWStl_Reader which is not bound to particular data structures; the target data model can be bound via inheritance. - RWStl package uses class Poly_Triangulation to represent triangular mesh. - Obsolete data structures and tools (packages StlMesh and StlTransfer) are removed.
This commit is contained in:
@@ -1,6 +1,5 @@
|
||||
StlAPI.cxx
|
||||
StlAPI.hxx
|
||||
StlAPI_ErrorStatus.hxx
|
||||
StlAPI_Reader.cxx
|
||||
StlAPI_Reader.hxx
|
||||
StlAPI_Writer.cxx
|
||||
|
@@ -11,24 +11,32 @@
|
||||
// Alternatively, this file may be used under the terms of Open CASCADE
|
||||
// commercial license or contractual agreement.
|
||||
|
||||
|
||||
#include <StlAPI.hxx>
|
||||
|
||||
#include <StlAPI_Reader.hxx>
|
||||
#include <StlAPI_Writer.hxx>
|
||||
#include <TopoDS_Shape.hxx>
|
||||
|
||||
StlAPI_ErrorStatus StlAPI::Write(const TopoDS_Shape& aShape,
|
||||
const Standard_CString aFile,
|
||||
const Standard_Boolean aAsciiMode)
|
||||
//=============================================================================
|
||||
//function : Write
|
||||
//purpose :
|
||||
//=============================================================================
|
||||
Standard_Boolean StlAPI::Write (const TopoDS_Shape& theShape,
|
||||
const Standard_CString theFile,
|
||||
const Standard_Boolean theAsciiMode)
|
||||
{
|
||||
StlAPI_Writer writer;
|
||||
writer.ASCIIMode() = aAsciiMode;
|
||||
return writer.Write (aShape, aFile);
|
||||
StlAPI_Writer aWriter;
|
||||
aWriter.ASCIIMode() = theAsciiMode;
|
||||
return aWriter.Write (theShape, theFile);
|
||||
}
|
||||
|
||||
|
||||
void StlAPI::Read(TopoDS_Shape& aShape,const Standard_CString aFile)
|
||||
//=============================================================================
|
||||
//function : Read
|
||||
//purpose :
|
||||
//=============================================================================
|
||||
Standard_Boolean StlAPI::Read (TopoDS_Shape& theShape,
|
||||
const Standard_CString theFile)
|
||||
{
|
||||
StlAPI_Reader reader;
|
||||
reader.Read (aShape, aFile);
|
||||
StlAPI_Reader aReader;
|
||||
return aReader.Read(theShape, theFile);
|
||||
}
|
||||
|
@@ -17,57 +17,37 @@
|
||||
#ifndef _StlAPI_HeaderFile
|
||||
#define _StlAPI_HeaderFile
|
||||
|
||||
#include <Poly_Triangulation.hxx>
|
||||
#include <Standard.hxx>
|
||||
#include <Standard_DefineAlloc.hxx>
|
||||
#include <Standard_Handle.hxx>
|
||||
|
||||
#include <StlAPI_ErrorStatus.hxx>
|
||||
#include <Standard_CString.hxx>
|
||||
#include <Standard_Boolean.hxx>
|
||||
class TopoDS_Shape;
|
||||
class StlAPI_Writer;
|
||||
class StlAPI_Reader;
|
||||
|
||||
|
||||
//! Offers the API for STL data manipulation.
|
||||
class StlAPI
|
||||
class StlAPI
|
||||
{
|
||||
public:
|
||||
|
||||
DEFINE_STANDARD_ALLOC
|
||||
|
||||
|
||||
//! Convert and write shape to STL format.
|
||||
//! file is written in binary if aAsciiMode is False
|
||||
//! otherwise it is written in Ascii (by default)
|
||||
Standard_EXPORT static StlAPI_ErrorStatus Write (const TopoDS_Shape& aShape, const Standard_CString aFile, const Standard_Boolean aAsciiMode = Standard_True);
|
||||
|
||||
//! Create a shape from a STL format.
|
||||
Standard_EXPORT static void Read (TopoDS_Shape& aShape, const Standard_CString aFile);
|
||||
//! File is written in binary if aAsciiMode is False otherwise it is written in Ascii (by default).
|
||||
Standard_EXPORT static Standard_Boolean Write (const TopoDS_Shape& theShape,
|
||||
const Standard_CString theFile,
|
||||
const Standard_Boolean theAsciiMode = Standard_True);
|
||||
|
||||
|
||||
|
||||
|
||||
protected:
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
private:
|
||||
|
||||
|
||||
|
||||
|
||||
friend class StlAPI_Writer;
|
||||
friend class StlAPI_Reader;
|
||||
//! Legacy interface.
|
||||
//! Read STL file and create a shape composed of triangular faces, one per facet.
|
||||
//! This approach is very inefficient, especially for large files.
|
||||
//! Consider reading STL file to Poly_Triangulation object instead (see class RWStl).
|
||||
Standard_DEPRECATED("This method is very inefficient; see RWStl class for better alternative")
|
||||
Standard_EXPORT static Standard_Boolean Read (TopoDS_Shape& theShape,
|
||||
const Standard_CString aFile);
|
||||
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
#endif // _StlAPI_HeaderFile
|
||||
|
@@ -1,30 +0,0 @@
|
||||
// Created on: 1997-05-13
|
||||
// Created by: Fabien REUTER
|
||||
// Copyright (c) 1997-1999 Matra Datavision
|
||||
// Copyright (c) 1999-2014 OPEN CASCADE SAS
|
||||
//
|
||||
// This file is part of Open CASCADE Technology software library.
|
||||
//
|
||||
// This library is free software; you can redistribute it and/or modify it under
|
||||
// the terms of the GNU Lesser General Public License version 2.1 as published
|
||||
// by the Free Software Foundation, with special exception defined in the file
|
||||
// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
|
||||
// distribution for complete text of the license and disclaimer of any warranty.
|
||||
//
|
||||
// Alternatively, this file may be used under the terms of Open CASCADE
|
||||
// commercial license or contractual agreement.
|
||||
|
||||
#ifndef _StlAPI_ErrorStatus_HeaderFile
|
||||
#define _StlAPI_ErrorStatus_HeaderFile
|
||||
|
||||
//! Set of statuses to indicate a type of the error
|
||||
//! occurred during data retrieving and writing operations.
|
||||
enum StlAPI_ErrorStatus
|
||||
{
|
||||
StlAPI_StatusOK,
|
||||
StlAPI_MeshIsEmpty,
|
||||
StlAPI_CannotOpenFile,
|
||||
StlAPI_WriteError
|
||||
};
|
||||
|
||||
#endif // _StlAPI_ErrorStatus_HeaderFile
|
@@ -11,6 +11,7 @@
|
||||
// Alternatively, this file may be used under the terms of Open CASCADE
|
||||
// commercial license or contractual agreement.
|
||||
|
||||
#include <StlAPI_Reader.hxx>
|
||||
|
||||
#include <BRep_Builder.hxx>
|
||||
#include <BRepBuilderAPI_MakeFace.hxx>
|
||||
@@ -20,9 +21,6 @@
|
||||
#include <gp_Pnt.hxx>
|
||||
#include <OSD_Path.hxx>
|
||||
#include <RWStl.hxx>
|
||||
#include <StlAPI_Reader.hxx>
|
||||
#include <StlMesh_Mesh.hxx>
|
||||
#include <StlMesh_MeshExplorer.hxx>
|
||||
#include <TopoDS_Compound.hxx>
|
||||
#include <TopoDS_Edge.hxx>
|
||||
#include <TopoDS_Face.hxx>
|
||||
@@ -31,64 +29,68 @@
|
||||
#include <TopoDS_Vertex.hxx>
|
||||
#include <TopoDS_Wire.hxx>
|
||||
|
||||
StlAPI_Reader::StlAPI_Reader() {}
|
||||
|
||||
void StlAPI_Reader::Read(TopoDS_Shape& aShape, const Standard_CString aFileName)
|
||||
//=============================================================================
|
||||
//function : Read
|
||||
//purpose :
|
||||
//=============================================================================
|
||||
Standard_Boolean StlAPI_Reader::Read (TopoDS_Shape& theShape,
|
||||
const Standard_CString theFileName)
|
||||
{
|
||||
OSD_Path aFile(aFileName);
|
||||
|
||||
Handle(StlMesh_Mesh) aSTLMesh = RWStl::ReadFile(aFile);
|
||||
Standard_Integer NumberDomains = aSTLMesh->NbDomains();
|
||||
Standard_Integer iND;
|
||||
gp_XYZ p1, p2, p3;
|
||||
TopoDS_Vertex Vertex1, Vertex2, Vertex3;
|
||||
TopoDS_Face AktFace;
|
||||
TopoDS_Wire AktWire;
|
||||
Handle(Poly_Triangulation) aMesh = RWStl::ReadFile (theFileName);
|
||||
if (aMesh.IsNull())
|
||||
{
|
||||
return Standard_False;
|
||||
}
|
||||
|
||||
TopoDS_Vertex aTriVertexes[3];
|
||||
TopoDS_Face aFace;
|
||||
TopoDS_Wire aWire;
|
||||
BRepBuilderAPI_Sewing aSewingTool;
|
||||
Standard_Real x1, y1, z1;
|
||||
Standard_Real x2, y2, z2;
|
||||
Standard_Real x3, y3, z3;
|
||||
|
||||
aSewingTool.Init(1.0e-06,Standard_True);
|
||||
|
||||
aSewingTool.Init (1.0e-06, Standard_True);
|
||||
|
||||
TopoDS_Compound aComp;
|
||||
BRep_Builder BuildTool;
|
||||
BuildTool.MakeCompound( aComp );
|
||||
BuildTool.MakeCompound (aComp);
|
||||
|
||||
StlMesh_MeshExplorer aMExp (aSTLMesh);
|
||||
|
||||
for (iND=1;iND<=NumberDomains;iND++)
|
||||
const TColgp_Array1OfPnt& aNodes = aMesh->Nodes();
|
||||
const Poly_Array1OfTriangle& aTriangles = aMesh->Triangles();
|
||||
for (Standard_Integer aTriIdx = aTriangles.Lower();
|
||||
aTriIdx <= aTriangles.Upper();
|
||||
++aTriIdx)
|
||||
{
|
||||
for (aMExp.InitTriangle (iND); aMExp.MoreTriangle (); aMExp.NextTriangle ())
|
||||
const Poly_Triangle& aTriangle = aTriangles(aTriIdx);
|
||||
|
||||
Standard_Integer anId[3];
|
||||
aTriangle.Get(anId[0], anId[1], anId[2]);
|
||||
|
||||
const gp_Pnt& aPnt1 = aNodes (anId[0]);
|
||||
const gp_Pnt& aPnt2 = aNodes (anId[1]);
|
||||
const gp_Pnt& aPnt3 = aNodes (anId[2]);
|
||||
if ((!(aPnt1.IsEqual (aPnt2, 0.0)))
|
||||
&& (!(aPnt1.IsEqual (aPnt3, 0.0))))
|
||||
{
|
||||
aMExp.TriangleVertices (x1,y1,z1,x2,y2,z2,x3,y3,z3);
|
||||
p1.SetCoord(x1,y1,z1);
|
||||
p2.SetCoord(x2,y2,z2);
|
||||
p3.SetCoord(x3,y3,z3);
|
||||
|
||||
if ((!(p1.IsEqual(p2,0.0))) && (!(p1.IsEqual(p3,0.0))))
|
||||
aTriVertexes[0] = BRepBuilderAPI_MakeVertex (aPnt1);
|
||||
aTriVertexes[1] = BRepBuilderAPI_MakeVertex (aPnt2);
|
||||
aTriVertexes[2] = BRepBuilderAPI_MakeVertex (aPnt3);
|
||||
|
||||
aWire = BRepBuilderAPI_MakePolygon (aTriVertexes[0], aTriVertexes[1], aTriVertexes[2], Standard_True);
|
||||
if (!aWire.IsNull())
|
||||
{
|
||||
Vertex1 = BRepBuilderAPI_MakeVertex(p1);
|
||||
Vertex2 = BRepBuilderAPI_MakeVertex(p2);
|
||||
Vertex3 = BRepBuilderAPI_MakeVertex(p3);
|
||||
|
||||
AktWire = BRepBuilderAPI_MakePolygon( Vertex1, Vertex2, Vertex3, Standard_True);
|
||||
|
||||
if( !AktWire.IsNull())
|
||||
aFace = BRepBuilderAPI_MakeFace (aWire);
|
||||
if (!aFace.IsNull())
|
||||
{
|
||||
AktFace = BRepBuilderAPI_MakeFace( AktWire);
|
||||
if(!AktFace.IsNull())
|
||||
BuildTool.Add( aComp, AktFace );
|
||||
BuildTool.Add (aComp, aFace);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
aSTLMesh->Clear();
|
||||
|
||||
aSewingTool.Load( aComp );
|
||||
aSewingTool.Load (aComp);
|
||||
aSewingTool.Perform();
|
||||
aShape = aSewingTool.SewedShape();
|
||||
if ( aShape.IsNull() )
|
||||
aShape = aComp;
|
||||
theShape = aSewingTool.SewedShape();
|
||||
if (theShape.IsNull())
|
||||
{
|
||||
theShape = aComp;
|
||||
}
|
||||
return Standard_True;
|
||||
}
|
||||
|
||||
|
@@ -19,44 +19,20 @@
|
||||
#include <Standard.hxx>
|
||||
#include <Standard_DefineAlloc.hxx>
|
||||
#include <Standard_Handle.hxx>
|
||||
|
||||
#include <Standard_CString.hxx>
|
||||
|
||||
class TopoDS_Shape;
|
||||
|
||||
|
||||
//! Reading from stereolithography format.
|
||||
class StlAPI_Reader
|
||||
class StlAPI_Reader
|
||||
{
|
||||
public:
|
||||
|
||||
DEFINE_STANDARD_ALLOC
|
||||
|
||||
|
||||
Standard_EXPORT StlAPI_Reader();
|
||||
|
||||
Standard_EXPORT void Read (TopoDS_Shape& aShape, const Standard_CString aFileName);
|
||||
|
||||
|
||||
|
||||
|
||||
protected:
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
private:
|
||||
|
||||
|
||||
|
||||
|
||||
//! Reads STL file to the TopoDS_Shape (each triangle is converted to the face).
|
||||
//! @return True if reading is successful
|
||||
Standard_EXPORT Standard_Boolean Read (TopoDS_Shape& theShape,
|
||||
const Standard_CString theFileName);
|
||||
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
#endif // _StlAPI_Reader_HeaderFile
|
||||
|
@@ -11,198 +11,102 @@
|
||||
// Alternatively, this file may be used under the terms of Open CASCADE
|
||||
// commercial license or contractual agreement.
|
||||
|
||||
#include <StlAPI_Writer.hxx>
|
||||
|
||||
#include <Bnd_Box.hxx>
|
||||
#include <BRepBndLib.hxx>
|
||||
#include <OSD_Path.hxx>
|
||||
#include <OSD_OpenFile.hxx>
|
||||
#include <RWStl.hxx>
|
||||
#include <StlAPI_Writer.hxx>
|
||||
#include <StlMesh_Mesh.hxx>
|
||||
#include <StlTransfer.hxx>
|
||||
#include <BRep_Tool.hxx>
|
||||
#include <TopoDS.hxx>
|
||||
#include <TopoDS_Face.hxx>
|
||||
#include <TopExp_Explorer.hxx>
|
||||
#include <Poly_Triangulation.hxx>
|
||||
|
||||
//=============================================================================
|
||||
//function : StlAPI_Writer
|
||||
//purpose :
|
||||
//=============================================================================
|
||||
StlAPI_Writer::StlAPI_Writer()
|
||||
: myASCIIMode (Standard_True)
|
||||
{
|
||||
theStlMesh = new StlMesh_Mesh;
|
||||
theASCIIMode = Standard_True;
|
||||
//
|
||||
}
|
||||
|
||||
Standard_Boolean& StlAPI_Writer::ASCIIMode()
|
||||
//=============================================================================
|
||||
//function : Write
|
||||
//purpose :
|
||||
//=============================================================================
|
||||
Standard_Boolean StlAPI_Writer::Write (const TopoDS_Shape& theShape,
|
||||
const Standard_CString theFileName)
|
||||
{
|
||||
return theASCIIMode;
|
||||
}
|
||||
Standard_Integer aNbNodes = 0;
|
||||
Standard_Integer aNbTriangles = 0;
|
||||
|
||||
// Auxiliary tools
|
||||
namespace
|
||||
{
|
||||
// Tool to get triangles from triangulation taking into account face
|
||||
// orientation and location
|
||||
class TriangleAccessor
|
||||
// calculate total number of the nodes and triangles
|
||||
for (TopExp_Explorer anExpSF (theShape, TopAbs_FACE); anExpSF.More(); anExpSF.Next())
|
||||
{
|
||||
public:
|
||||
TriangleAccessor (const TopoDS_Face& aFace)
|
||||
{
|
||||
TopLoc_Location aLoc;
|
||||
myPoly = BRep_Tool::Triangulation (aFace, aLoc);
|
||||
myTrsf = aLoc.Transformation();
|
||||
myNbTriangles = (myPoly.IsNull() ? 0 : myPoly->Triangles().Length());
|
||||
myInvert = (aFace.Orientation() == TopAbs_REVERSED);
|
||||
if (myTrsf.IsNegative())
|
||||
myInvert = ! myInvert;
|
||||
}
|
||||
|
||||
int NbTriangles () const { return myNbTriangles; }
|
||||
|
||||
// get i-th triangle and outward normal
|
||||
void GetTriangle (int iTri, gp_Vec &theNormal, gp_Pnt &thePnt1, gp_Pnt &thePnt2, gp_Pnt &thePnt3)
|
||||
{
|
||||
// get positions of nodes
|
||||
int iNode1, iNode2, iNode3;
|
||||
myPoly->Triangles()(iTri).Get (iNode1, iNode2, iNode3);
|
||||
thePnt1 = myPoly->Nodes()(iNode1);
|
||||
thePnt2 = myPoly->Nodes()(myInvert ? iNode3 : iNode2);
|
||||
thePnt3 = myPoly->Nodes()(myInvert ? iNode2 : iNode3);
|
||||
|
||||
// apply transormation if not identity
|
||||
if (myTrsf.Form() != gp_Identity)
|
||||
{
|
||||
thePnt1.Transform (myTrsf);
|
||||
thePnt2.Transform (myTrsf);
|
||||
thePnt3.Transform (myTrsf);
|
||||
}
|
||||
|
||||
// calculate normal
|
||||
theNormal = (thePnt2.XYZ() - thePnt1.XYZ()) ^ (thePnt3.XYZ() - thePnt1.XYZ());
|
||||
Standard_Real aNorm = theNormal.Magnitude();
|
||||
if (aNorm > gp::Resolution())
|
||||
theNormal /= aNorm;
|
||||
}
|
||||
|
||||
private:
|
||||
Handle(Poly_Triangulation) myPoly;
|
||||
gp_Trsf myTrsf;
|
||||
int myNbTriangles;
|
||||
bool myInvert;
|
||||
};
|
||||
|
||||
// convert to float and, on big-endian platform, to little-endian representation
|
||||
inline float convertFloat (Standard_Real aValue)
|
||||
{
|
||||
#ifdef OCCT_BINARY_FILE_DO_INVERSE
|
||||
return OSD_BinaryFile::InverseShortReal ((float)aValue);
|
||||
#else
|
||||
return (float)aValue;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
StlAPI_ErrorStatus StlAPI_Writer::Write(const TopoDS_Shape& theShape, const Standard_CString theFileName)
|
||||
{
|
||||
// open file
|
||||
FILE* aFile = OSD_OpenFile (theFileName, "wb");
|
||||
if (!aFile)
|
||||
return StlAPI_CannotOpenFile;
|
||||
|
||||
// write
|
||||
if (theASCIIMode)
|
||||
{
|
||||
// header
|
||||
Fprintf (aFile, "solid shape, STL ascii file, created with Open CASCADE Technology\n");
|
||||
|
||||
// facets
|
||||
for (TopExp_Explorer exp (theShape, TopAbs_FACE); exp.More(); exp.Next())
|
||||
{
|
||||
TriangleAccessor aTool (TopoDS::Face (exp.Current()));
|
||||
for (int iTri = 1; iTri <= aTool.NbTriangles(); iTri++)
|
||||
{
|
||||
gp_Vec aNorm;
|
||||
gp_Pnt aPnt1, aPnt2, aPnt3;
|
||||
aTool.GetTriangle (iTri, aNorm, aPnt1, aPnt2, aPnt3);
|
||||
|
||||
Fprintf (aFile,
|
||||
" facet normal %12e %12e %12e\n"
|
||||
" outer loop\n"
|
||||
" vertex %12e %12e %12e\n"
|
||||
" vertex %12e %12e %12e\n"
|
||||
" vertex %12e %12e %12e\n"
|
||||
" endloop\n"
|
||||
" endfacet\n",
|
||||
aNorm.X(), aNorm.Y(), aNorm.Z(),
|
||||
aPnt1.X(), aPnt1.Y(), aPnt1.Z(),
|
||||
aPnt2.X(), aPnt2.Y(), aPnt2.Z(),
|
||||
aPnt3.X(), aPnt3.Y(), aPnt3.Z());
|
||||
}
|
||||
}
|
||||
|
||||
// footer
|
||||
Fprintf (aFile, "endsolid shape\n");
|
||||
}
|
||||
else
|
||||
{
|
||||
// header block (meaningless 80 bytes)
|
||||
Fprintf (aFile, "%-80.80s", "STL binary file, created with Open CASCADE Technology");
|
||||
|
||||
// number of facets
|
||||
int32_t aNbTri = 0;
|
||||
for (TopExp_Explorer exp (theShape, TopAbs_FACE); exp.More(); exp.Next())
|
||||
{
|
||||
TopLoc_Location aLoc;
|
||||
Handle(Poly_Triangulation) aPoly =
|
||||
BRep_Tool::Triangulation (TopoDS::Face (exp.Current()), aLoc);
|
||||
if (! aPoly.IsNull())
|
||||
aNbTri += aPoly->NbTriangles();
|
||||
}
|
||||
// suppose that number of triangles must be little endian...
|
||||
#ifdef OCCT_BINARY_FILE_DO_INVERSE
|
||||
aNbTri = OSD_BinaryFile::InverseInteger (aNbTri);
|
||||
#endif
|
||||
fwrite (&aNbTri, sizeof(int32_t), 1, aFile);
|
||||
|
||||
// facets
|
||||
struct Facet {
|
||||
float nx, ny, nz;
|
||||
float x1, y1, z1;
|
||||
float x2, y2, z2;
|
||||
float x3, y3, z3;
|
||||
uint16_t dummy;
|
||||
} f;
|
||||
f.dummy = 0;
|
||||
for (TopExp_Explorer exp (theShape, TopAbs_FACE); exp.More(); exp.Next())
|
||||
{
|
||||
TriangleAccessor aTool (TopoDS::Face (exp.Current()));
|
||||
for (int iTri = 1; iTri <= aTool.NbTriangles(); iTri++)
|
||||
{
|
||||
gp_Vec aNorm;
|
||||
gp_Pnt aPnt1, aPnt2, aPnt3;
|
||||
aTool.GetTriangle (iTri, aNorm, aPnt1, aPnt2, aPnt3);
|
||||
|
||||
f.nx = convertFloat (aNorm.X());
|
||||
f.ny = convertFloat (aNorm.Y());
|
||||
f.nz = convertFloat (aNorm.Z());
|
||||
|
||||
f.x1 = convertFloat (aPnt1.X());
|
||||
f.y1 = convertFloat (aPnt1.Y());
|
||||
f.z1 = convertFloat (aPnt1.Z());
|
||||
|
||||
f.x2 = convertFloat (aPnt2.X());
|
||||
f.y2 = convertFloat (aPnt2.Y());
|
||||
f.z2 = convertFloat (aPnt2.Z());
|
||||
|
||||
f.x3 = convertFloat (aPnt3.X());
|
||||
f.y3 = convertFloat (aPnt3.Y());
|
||||
f.z3 = convertFloat (aPnt3.Z());
|
||||
|
||||
fwrite (&f, 50 /* 50 bytes per facet */, 1, aFile);
|
||||
}
|
||||
}
|
||||
TopLoc_Location aLoc;
|
||||
Handle(Poly_Triangulation) aTriangulation = BRep_Tool::Triangulation (TopoDS::Face (anExpSF.Current()), aLoc);
|
||||
aNbNodes += aTriangulation->NbNodes();
|
||||
aNbTriangles += aTriangulation->NbTriangles();
|
||||
}
|
||||
|
||||
fclose (aFile);
|
||||
return ferror(aFile) ? StlAPI_WriteError : StlAPI_StatusOK;
|
||||
}
|
||||
// create temporary triangulation
|
||||
Handle(Poly_Triangulation) aMesh = new Poly_Triangulation (aNbNodes, aNbTriangles, Standard_False);
|
||||
|
||||
// fill temporary triangulation
|
||||
Standard_Integer aNodeOffset = 0;
|
||||
Standard_Integer aTriangleOffet = 0;
|
||||
for (TopExp_Explorer anExpSF (theShape, TopAbs_FACE); anExpSF.More(); anExpSF.Next())
|
||||
{
|
||||
TopLoc_Location aLoc;
|
||||
Handle(Poly_Triangulation) aTriangulation = BRep_Tool::Triangulation (TopoDS::Face (anExpSF.Current()), aLoc);
|
||||
|
||||
const TColgp_Array1OfPnt& aNodes = aTriangulation->Nodes();
|
||||
const Poly_Array1OfTriangle& aTriangles = aTriangulation->Triangles();
|
||||
|
||||
// copy nodes
|
||||
gp_Trsf aTrsf = aLoc.Transformation();
|
||||
for (Standard_Integer aNodeIter = aNodes.Lower(); aNodeIter <= aNodes.Upper(); ++aNodeIter)
|
||||
{
|
||||
gp_Pnt aPnt = aNodes (aNodeIter);
|
||||
aPnt.Transform (aTrsf);
|
||||
aMesh->ChangeNode (aNodeIter + aNodeOffset) = aPnt;
|
||||
}
|
||||
|
||||
// copy triangles
|
||||
const TopAbs_Orientation anOrientation = anExpSF.Current().Orientation();
|
||||
for (Standard_Integer aTriIter = aTriangles.Lower(); aTriIter <= aTriangles.Upper(); ++aTriIter)
|
||||
{
|
||||
Poly_Triangle aTri = aTriangles (aTriIter);
|
||||
|
||||
Standard_Integer anId[3];
|
||||
aTri.Get (anId[0], anId[1], anId[2]);
|
||||
if (anOrientation == TopAbs_REVERSED)
|
||||
{
|
||||
// Swap 1, 2.
|
||||
Standard_Integer aTmpIdx = anId[1];
|
||||
anId[1] = anId[2];
|
||||
anId[2] = aTmpIdx;
|
||||
}
|
||||
|
||||
// Update nodes according to the offset.
|
||||
anId[0] += aNodeOffset;
|
||||
anId[1] += aNodeOffset;
|
||||
anId[2] += aNodeOffset;
|
||||
|
||||
aTri.Set (anId[0], anId[1], anId[2]);
|
||||
aMesh->ChangeTriangle (aTriIter + aTriangleOffet) = aTri;
|
||||
}
|
||||
|
||||
aNodeOffset += aNodes.Size();
|
||||
aTriangleOffet += aTriangles.Size();
|
||||
}
|
||||
|
||||
OSD_Path aPath (theFileName);
|
||||
return myASCIIMode
|
||||
? RWStl::WriteAscii (aMesh, aPath)
|
||||
: RWStl::WriteBinary (aMesh, aPath);
|
||||
}
|
||||
|
@@ -16,66 +16,39 @@
|
||||
#ifndef _StlAPI_Writer_HeaderFile
|
||||
#define _StlAPI_Writer_HeaderFile
|
||||
|
||||
#include <Poly_Triangulation.hxx>
|
||||
#include <Standard.hxx>
|
||||
#include <Standard_DefineAlloc.hxx>
|
||||
#include <Standard_Handle.hxx>
|
||||
|
||||
#include <Standard_Boolean.hxx>
|
||||
#include <StlAPI_ErrorStatus.hxx>
|
||||
#include <Standard_CString.hxx>
|
||||
class StlMesh_Mesh;
|
||||
|
||||
class TopoDS_Shape;
|
||||
|
||||
|
||||
//! This class creates and writes
|
||||
//! STL files from Open CASCADE shapes. An STL file can be
|
||||
//! written to an existing STL file or to a new one..
|
||||
class StlAPI_Writer
|
||||
//! STL files from Open CASCADE shapes. An STL file can be written to an existing STL file or to a new one.
|
||||
class StlAPI_Writer
|
||||
{
|
||||
public:
|
||||
|
||||
DEFINE_STANDARD_ALLOC
|
||||
|
||||
|
||||
//! Creates a writer object with
|
||||
//! default parameters: ASCIIMode.
|
||||
//! Creates a writer object with default parameters: ASCIIMode.
|
||||
Standard_EXPORT StlAPI_Writer();
|
||||
|
||||
//! Returns the address to the
|
||||
//! flag defining the mode for writing the file. This address
|
||||
//! may be used to either read or change the flag.
|
||||
//! If the mode returns True (default value) the generated
|
||||
//! file is an ASCII file. If the mode returns False, the
|
||||
//! generated file is a binary file.
|
||||
Standard_EXPORT Standard_Boolean& ASCIIMode();
|
||||
|
||||
|
||||
//! Returns the address to the flag defining the mode for writing the file.
|
||||
//! This address may be used to either read or change the flag.
|
||||
//! If the mode returns True (default value) the generated file is an ASCII file.
|
||||
//! If the mode returns False, the generated file is a binary file.
|
||||
Standard_Boolean& ASCIIMode() { return myASCIIMode; }
|
||||
|
||||
//! Converts a given shape to STL format and writes it to file with a given filename.
|
||||
//! \return the error state.
|
||||
Standard_EXPORT StlAPI_ErrorStatus Write (const TopoDS_Shape& aShape, const Standard_CString aFileName);
|
||||
|
||||
|
||||
|
||||
|
||||
protected:
|
||||
|
||||
|
||||
|
||||
|
||||
Standard_EXPORT Standard_Boolean Write (const TopoDS_Shape& theShape,
|
||||
const Standard_CString theFileName);
|
||||
|
||||
private:
|
||||
|
||||
|
||||
|
||||
Standard_Boolean theASCIIMode;
|
||||
Handle(StlMesh_Mesh) theStlMesh;
|
||||
|
||||
|
||||
Standard_Boolean myASCIIMode;
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
#endif // _StlAPI_Writer_HeaderFile
|
||||
|
Reference in New Issue
Block a user