Loading files
f2929057eThis file is pinned to the selected release. Download the original to open it in your design tool.
// 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.
#include <StlAPI_Writer.hxx>
#include <Bnd_Box.hxx>
#include <Message.hxx>
#include <OSD_OpenFile.hxx>
#include <RWStl.hxx>
#include <BRep_Tool.hxx>
#include <TopoDS.hxx>
#include <TopoDS_Face.hxx>
#include <TopExp_Explorer.hxx>
#include <Poly_Triangulation.hxx>
#include <fstream>
//=================================================================================================
StlAPI_Writer::StlAPI_Writer()
: myASCIIMode(true)
{
}
//=================================================================================================
bool StlAPI_Writer::Write(const TopoDS_Shape& theShape,
const char* const theFileName,
const Message_ProgressRange& theProgress)
{
std::ofstream aStream(theFileName, myASCIIMode ? std::ios::out : std::ios::binary);
if (!aStream.is_open())
{
return false;
}
return Write(theShape, aStream, theProgress);
}
//=================================================================================================
bool StlAPI_Writer::Write(const TopoDS_Shape& theShape,
Standard_OStream& theStream,
const Message_ProgressRange& theProgress)
{
int aNbNodes = 0;
int aNbTriangles = 0;
// calculate total number of the nodes and triangles
for (TopExp_Explorer anExpSF(theShape, TopAbs_FACE); anExpSF.More(); anExpSF.Next())
{
TopLoc_Location aLoc;
occ::handle<Poly_Triangulation> aTriangulation =
BRep_Tool::Triangulation(TopoDS::Face(anExpSF.Current()), aLoc);
if (!aTriangulation.IsNull())
{
aNbNodes += aTriangulation->NbNodes();
aNbTriangles += aTriangulation->NbTriangles();
}
}
if (aNbTriangles == 0)
{
// No triangulation on the shape
return false;
}
// create temporary triangulation
occ::handle<Poly_Triangulation> aMesh = new Poly_Triangulation(aNbNodes, aNbTriangles, false);
// count faces missing triangulation
int aNbFacesNoTri = 0;
// fill temporary triangulation
int aNodeOffset = 0;
int aTriangleOffet = 0;
for (TopExp_Explorer anExpSF(theShape, TopAbs_FACE); anExpSF.More(); anExpSF.Next())
{
const TopoDS_Shape& aFace = anExpSF.Current();
TopLoc_Location aLoc;
occ::handle<Poly_Triangulation> aTriangulation =
BRep_Tool::Triangulation(TopoDS::Face(aFace), aLoc);
if (aTriangulation.IsNull())
{
++aNbFacesNoTri;
continue;
}
// copy nodes
gp_Trsf aTrsf = aLoc.Transformation();
for (int aNodeIter = 1; aNodeIter <= aTriangulation->NbNodes(); ++aNodeIter)
{
gp_Pnt aPnt = aTriangulation->Node(aNodeIter);
aPnt.Transform(aTrsf);
aMesh->SetNode(aNodeIter + aNodeOffset, aPnt);
}
// copy triangles
const TopAbs_Orientation anOrientation = anExpSF.Current().Orientation();
for (int aTriIter = 1; aTriIter <= aTriangulation->NbTriangles(); ++aTriIter)
{
Poly_Triangle aTri = aTriangulation->Triangle(aTriIter);
int anId[3];
aTri.Get(anId[0], anId[1], anId[2]);
if (anOrientation == TopAbs_REVERSED)
{
// Swap 1, 2.
int 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->SetTriangle(aTriIter + aTriangleOffet, aTri);
}
aNodeOffset += aTriangulation->NbNodes();
aTriangleOffet += aTriangulation->NbTriangles();
}
bool isDone = (myASCIIMode ? RWStl::WriteAscii(aMesh, theStream, theProgress)
: RWStl::WriteBinary(aMesh, theStream, theProgress));
if (isDone && (aNbFacesNoTri > 0))
{
// Print warning with number of faces missing triangulation
TCollection_AsciiString aWarningMsg =
TCollection_AsciiString("Warning: ") + TCollection_AsciiString(aNbFacesNoTri)
+ TCollection_AsciiString((aNbFacesNoTri == 1) ? " face has" : " faces have")
+ TCollection_AsciiString(" been skipped due to null triangulation");
Message::SendWarning(aWarningMsg);
}
return isDone;
}