mirror of
https://git.dev.opencascade.org/repos/occt.git
synced 2025-04-07 18:30:55 +03:00
0027561: Since OCCT 7.0.0, exporting a curve to STL creates a file that results in an endless loop when read
Add check for empty triangulation when writing STL file to report error instead of creation of empty file. STL reader has been improved to properly handle case of empty or small files, and Ascii files without EOL at the end.
This commit is contained in:
parent
d21ddc4f17
commit
22e7073865
@ -80,6 +80,9 @@ namespace
|
|||||||
//! Creates Poly_Triangulation from collected data
|
//! Creates Poly_Triangulation from collected data
|
||||||
Handle(Poly_Triangulation) GetTriangulation()
|
Handle(Poly_Triangulation) GetTriangulation()
|
||||||
{
|
{
|
||||||
|
if (myTriangles.IsEmpty())
|
||||||
|
return Handle(Poly_Triangulation)();
|
||||||
|
|
||||||
Handle(Poly_Triangulation) aPoly = new Poly_Triangulation (myNodes.Length(), myTriangles.Length(), Standard_False);
|
Handle(Poly_Triangulation) aPoly = new Poly_Triangulation (myNodes.Length(), myTriangles.Length(), Standard_False);
|
||||||
for (Standard_Integer aNodeIter = 0; aNodeIter < myNodes.Size(); ++aNodeIter)
|
for (Standard_Integer aNodeIter = 0; aNodeIter < myNodes.Size(); ++aNodeIter)
|
||||||
{
|
{
|
||||||
@ -109,10 +112,9 @@ Handle(Poly_Triangulation) RWStl::ReadFile (const Standard_CString theFile,
|
|||||||
const Handle(Message_ProgressIndicator)& theProgress)
|
const Handle(Message_ProgressIndicator)& theProgress)
|
||||||
{
|
{
|
||||||
Reader aReader;
|
Reader aReader;
|
||||||
if (!aReader.Read (theFile, theProgress))
|
aReader.Read (theFile, theProgress);
|
||||||
{
|
// note that returned bool value is ignored intentionally -- even if something went wrong,
|
||||||
return Handle(Poly_Triangulation)();
|
// but some data have been read, we at least will return these data
|
||||||
}
|
|
||||||
return aReader.GetTriangulation();
|
return aReader.GetTriangulation();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -209,10 +211,15 @@ Handle(Poly_Triangulation) RWStl::ReadAscii (const OSD_Path& theFile,
|
|||||||
//function : Write
|
//function : Write
|
||||||
//purpose :
|
//purpose :
|
||||||
//=============================================================================
|
//=============================================================================
|
||||||
Standard_Boolean RWStl::WriteBinary (const Handle(Poly_Triangulation)& aMesh,
|
Standard_Boolean RWStl::WriteBinary (const Handle(Poly_Triangulation)& theMesh,
|
||||||
const OSD_Path& thePath,
|
const OSD_Path& thePath,
|
||||||
const Handle(Message_ProgressIndicator)& theProgInd)
|
const Handle(Message_ProgressIndicator)& theProgInd)
|
||||||
{
|
{
|
||||||
|
if (theMesh.IsNull() || theMesh->NbTriangles() <= 0)
|
||||||
|
{
|
||||||
|
return Standard_False;
|
||||||
|
}
|
||||||
|
|
||||||
TCollection_AsciiString aPath;
|
TCollection_AsciiString aPath;
|
||||||
thePath.SystemName (aPath);
|
thePath.SystemName (aPath);
|
||||||
|
|
||||||
@ -222,7 +229,7 @@ Standard_Boolean RWStl::WriteBinary (const Handle(Poly_Triangulation)& aMesh,
|
|||||||
return Standard_False;
|
return Standard_False;
|
||||||
}
|
}
|
||||||
|
|
||||||
Standard_Boolean isOK = writeBinary (aMesh, aFile, theProgInd);
|
Standard_Boolean isOK = writeBinary (theMesh, aFile, theProgInd);
|
||||||
|
|
||||||
fclose (aFile);
|
fclose (aFile);
|
||||||
return isOK;
|
return isOK;
|
||||||
@ -236,6 +243,11 @@ Standard_Boolean RWStl::WriteAscii (const Handle(Poly_Triangulation)& theMesh,
|
|||||||
const OSD_Path& thePath,
|
const OSD_Path& thePath,
|
||||||
const Handle(Message_ProgressIndicator)& theProgInd)
|
const Handle(Message_ProgressIndicator)& theProgInd)
|
||||||
{
|
{
|
||||||
|
if (theMesh.IsNull() || theMesh->NbTriangles() <= 0)
|
||||||
|
{
|
||||||
|
return Standard_False;
|
||||||
|
}
|
||||||
|
|
||||||
TCollection_AsciiString aPath;
|
TCollection_AsciiString aPath;
|
||||||
thePath.SystemName (aPath);
|
thePath.SystemName (aPath);
|
||||||
|
|
||||||
|
@ -138,9 +138,15 @@ Standard_Boolean RWStl_Reader::Read (const char* theFile,
|
|||||||
std::streampos theEnd = aStream.tellg();
|
std::streampos theEnd = aStream.tellg();
|
||||||
aStream.seekg (0, aStream.beg);
|
aStream.seekg (0, aStream.beg);
|
||||||
|
|
||||||
while (!aStream.eof() && !aStream.bad())
|
// binary STL files cannot be shorter than 134 bytes
|
||||||
|
// (80 bytes header + 4 bytes facet count + 50 bytes for one facet);
|
||||||
|
// thus assume files shorter than 134 as Ascii without probing
|
||||||
|
// (probing may bring stream to fail state if EOF is reached)
|
||||||
|
bool isAscii = ((size_t)theEnd < THE_STL_MIN_FILE_SIZE || IsAscii (aStream));
|
||||||
|
|
||||||
|
while (aStream.good())
|
||||||
{
|
{
|
||||||
if (IsAscii (aStream))
|
if (isAscii)
|
||||||
{
|
{
|
||||||
if (!ReadAscii (aStream, theEnd, theProgress))
|
if (!ReadAscii (aStream, theEnd, theProgress))
|
||||||
{
|
{
|
||||||
@ -156,7 +162,7 @@ Standard_Boolean RWStl_Reader::Read (const char* theFile,
|
|||||||
}
|
}
|
||||||
aStream >> std::ws; // skip any white spaces
|
aStream >> std::ws; // skip any white spaces
|
||||||
}
|
}
|
||||||
return !aStream.bad();
|
return ! aStream.fail();
|
||||||
}
|
}
|
||||||
|
|
||||||
//==============================================================================
|
//==============================================================================
|
||||||
@ -172,7 +178,7 @@ Standard_Boolean RWStl_Reader::IsAscii (Standard_IStream& theStream)
|
|||||||
if (! theStream)
|
if (! theStream)
|
||||||
{
|
{
|
||||||
Message::DefaultMessenger()->Send ("Error: Cannot read file", Message_Fail);
|
Message::DefaultMessenger()->Send ("Error: Cannot read file", Message_Fail);
|
||||||
return false;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
// put back the read symbols
|
// put back the read symbols
|
||||||
@ -240,7 +246,8 @@ Standard_Boolean RWStl_Reader::ReadAscii (Standard_IStream& theStream,
|
|||||||
// use method seekpos() to get true 64-bit offset to enable
|
// use method seekpos() to get true 64-bit offset to enable
|
||||||
// handling of large files (VS 2010 64-bit)
|
// handling of large files (VS 2010 64-bit)
|
||||||
const int64_t aStartPos = GETPOS(theStream.tellg());
|
const int64_t aStartPos = GETPOS(theStream.tellg());
|
||||||
const int64_t aEndPos = (theUntilPos > 0 ? GETPOS(theUntilPos) : std::numeric_limits<int64_t>::max());
|
// Note: 1 is added to theUntilPos to be sure to read the last symbol (relevant for files without EOL at the end)
|
||||||
|
const int64_t aEndPos = (theUntilPos > 0 ? 1 + GETPOS(theUntilPos) : std::numeric_limits<int64_t>::max());
|
||||||
|
|
||||||
// skip header "solid ..."
|
// skip header "solid ..."
|
||||||
theStream.ignore (aEndPos - aStartPos, '\n');
|
theStream.ignore (aEndPos - aStartPos, '\n');
|
||||||
|
@ -49,9 +49,12 @@ Standard_Boolean StlAPI_Writer::Write (const TopoDS_Shape& theShape,
|
|||||||
{
|
{
|
||||||
TopLoc_Location aLoc;
|
TopLoc_Location aLoc;
|
||||||
Handle(Poly_Triangulation) aTriangulation = BRep_Tool::Triangulation (TopoDS::Face (anExpSF.Current()), aLoc);
|
Handle(Poly_Triangulation) aTriangulation = BRep_Tool::Triangulation (TopoDS::Face (anExpSF.Current()), aLoc);
|
||||||
|
if (! aTriangulation.IsNull())
|
||||||
|
{
|
||||||
aNbNodes += aTriangulation->NbNodes ();
|
aNbNodes += aTriangulation->NbNodes ();
|
||||||
aNbTriangles += aTriangulation->NbTriangles ();
|
aNbTriangles += aTriangulation->NbTriangles ();
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// create temporary triangulation
|
// create temporary triangulation
|
||||||
Handle(Poly_Triangulation) aMesh = new Poly_Triangulation (aNbNodes, aNbTriangles, Standard_False);
|
Handle(Poly_Triangulation) aMesh = new Poly_Triangulation (aNbNodes, aNbTriangles, Standard_False);
|
||||||
|
91
tests/de_mesh/stl_read/D1
Normal file
91
tests/de_mesh/stl_read/D1
Normal file
@ -0,0 +1,91 @@
|
|||||||
|
puts "\n#======================================================================"
|
||||||
|
puts "# Check reading empty or small STL files"
|
||||||
|
puts "#======================================================================\n"
|
||||||
|
|
||||||
|
set minimal_ascii_stl {solid
|
||||||
|
facet normal 0 0 1
|
||||||
|
outer loop
|
||||||
|
vertex 0 0 0
|
||||||
|
vertex 1 0 0
|
||||||
|
vertex 0 1 0
|
||||||
|
endloop
|
||||||
|
endfacet
|
||||||
|
endsolid}
|
||||||
|
|
||||||
|
puts "\n#======================================================================"
|
||||||
|
puts "# Ascii file with single facet, CRLF"
|
||||||
|
puts "#======================================================================"
|
||||||
|
set fd [open ${imagedir}/${casename}_one_ascii_dos.stl w]
|
||||||
|
fconfigure $fd -translation crlf
|
||||||
|
puts $fd $minimal_ascii_stl
|
||||||
|
close $fd
|
||||||
|
readstl res_one_ascii_dos ${imagedir}/${casename}_one_ascii_dos.stl
|
||||||
|
checknbshapes res_one_ascii_dos -face 1
|
||||||
|
|
||||||
|
puts "\n#======================================================================"
|
||||||
|
puts "# Ascii file with single facet, LF"
|
||||||
|
puts "#======================================================================"
|
||||||
|
set fd [open ${imagedir}/${casename}_one_ascii_unix.stl w]
|
||||||
|
fconfigure $fd -translation lf
|
||||||
|
puts $fd $minimal_ascii_stl
|
||||||
|
close $fd
|
||||||
|
readstl res_one_ascii_unix ${imagedir}/${casename}_one_ascii_unix.stl
|
||||||
|
checknbshapes res_one_ascii_unix -face 1
|
||||||
|
|
||||||
|
puts "\n#======================================================================"
|
||||||
|
puts "# Ascii file with single facet, LF, no EOL at the last line"
|
||||||
|
puts "#======================================================================"
|
||||||
|
set fd [open ${imagedir}/${casename}_one_ascii_noeol.stl w]
|
||||||
|
fconfigure $fd -translation lf
|
||||||
|
puts -nonewline $fd $minimal_ascii_stl
|
||||||
|
close $fd
|
||||||
|
readstl res_one_ascii_noeol ${imagedir}/${casename}_one_ascii_noeol.stl
|
||||||
|
checknbshapes res_one_ascii_noeol -face 1
|
||||||
|
|
||||||
|
puts "\n#======================================================================"
|
||||||
|
puts "# Ascii file with no facets, CRLF"
|
||||||
|
puts "#======================================================================"
|
||||||
|
set fd [open ${imagedir}/${casename}_zero_ascii_dos.stl w]
|
||||||
|
fconfigure $fd -translation crlf
|
||||||
|
puts $fd "solid \nendsolid"
|
||||||
|
close $fd
|
||||||
|
readstl res_zero_ascii_dos ${imagedir}/${casename}_zero_ascii_dos.stl
|
||||||
|
|
||||||
|
puts "\n#======================================================================"
|
||||||
|
puts "# Ascii file with no facets, LF"
|
||||||
|
puts "#======================================================================"
|
||||||
|
set fd [open ${imagedir}/${casename}_zero_ascii_unix.stl w]
|
||||||
|
fconfigure $fd -translation lf
|
||||||
|
puts $fd "solid \nendsolid"
|
||||||
|
close $fd
|
||||||
|
readstl res_zero_ascii_unix ${imagedir}/${casename}_zero_ascii_unix.stl
|
||||||
|
|
||||||
|
puts "\n#======================================================================"
|
||||||
|
puts "# Binary file with single facet"
|
||||||
|
puts "#======================================================================"
|
||||||
|
set fd [open ${imagedir}/${casename}_one_binary.stl w]
|
||||||
|
fconfigure $fd -translation binary
|
||||||
|
puts -nonewline $fd "stl [string repeat { } 76]"
|
||||||
|
puts -nonewline $fd [binary format if3f3f3f3t 1 {0 0 1} {0 0 0} {1 0 0} {0 1 0} 0]
|
||||||
|
close $fd
|
||||||
|
readstl res_one_binary ${imagedir}/${casename}_one_binary.stl
|
||||||
|
checknbshapes res_one_binary -face 1
|
||||||
|
|
||||||
|
puts "\n#======================================================================"
|
||||||
|
puts "# Binary file with no facets -- will be treated as Ascii and generate e r r o r"
|
||||||
|
puts "#======================================================================"
|
||||||
|
puts "REQUIRED ALL: Error: unexpected format of facet at line 2"
|
||||||
|
set fd [open ${imagedir}/${casename}_zero_binary.stl w]
|
||||||
|
fconfigure $fd -translation binary
|
||||||
|
puts -nonewline $fd "stl [string repeat { } 76][binary format i 0]"
|
||||||
|
close $fd
|
||||||
|
readstl res_zero_binary ${imagedir}/${casename}_zero_binary.stl
|
||||||
|
|
||||||
|
puts "\n#======================================================================"
|
||||||
|
puts "# Empty file"
|
||||||
|
puts "#======================================================================"
|
||||||
|
puts "REQUIRED ALL: Error: unexpected format of facet at line 2"
|
||||||
|
set fd [open ${imagedir}/${casename}_empty.stl w]
|
||||||
|
close $fd
|
||||||
|
readstl res_empty ${imagedir}/${casename}_empty.stl
|
||||||
|
|
Loading…
x
Reference in New Issue
Block a user