[Liblas-devel] Offset to Point Data Bug
Black, Tim
tblack at ball.com
Thu Dec 2 14:57:09 EST 2010
liblas-devs,
I believe I've isolated a bug that I was having a hard time tracking down. It seems to require a fairly narrow set of circumstances for it to appear. The particular circumstances that will cause the bug are when you have an existing LAS file with a data offset larger than the header size(Such as when you have VLRs), but there are zero points in the file. In my particular case, I was writing out the header in one method, then populating the points in another existing method designed to append points to existing files.(I have sample code demonstrating the problem below) In the writer/header.cpp file, at the end of the write() method, this block of code appears to be the problem.
if (!bAppendMode)
{
WriteVLRs();
// Write the 1.0 pad signature if we need to.
WriteLAS10PadSignature();
}
// If we already have points, we're going to put it at the end of the file.
// If we don't have any points, we're going to leave it where it is.
if (m_pointCount != 0)
m_ofs.seekp(0, std::ios::end);
Before entering this section, the m_ofs stream is positioned at the end of the file header. Since the file existed before being opened to write the points, the "bAppendMode" variable is true, skipping that block. However, there are no points in the file, so the stream position remains unchanged. Any VLRs after the header will be overridden when points are added to the file. Later, when the header write() method is called when the writer's destructor is called, the method uses the file size and data offset to calculate the number of points. Because the point data started before the data offset mark, the resulting file size is off by the difference between the header size and the offset. This results in the number of points reported by the header being changed to a lower figure than the number of points you've actually written. For a quick fix here, I've add an "else" block locally:
if (m_pointCount != 0)
{
m_ofs.seekp(0, std::ios::end);
}
else
{
m_ofs.seekp(0, m_header.getDataOffset();
}
I used the following code to duplicate the problem. If you comment out the line setting the data offset, the resulting file will have 500k points. With that line in place, the point count will be 499981.
std::string path( "MyTestFile.las" );
std::fstream out;
out.open( path.c_str(), std::ios::out | std::ios::binary );
liblas::LASHeader newHeader;
newHeader.SetPointRecordsCount( 500000 );
newHeader.SetDataOffset(759);//Toggle to see the differences
newHeader.SetDataFormatId( liblas::ePointFormat1 );
{
liblas::LASWriter testWriter( out, newHeader );
}
liblas::LASWriter test2Writer( out, newHeader);
for ( size_t i = 0; i < 500000 ; i++ )
{
liblas::LASPoint point;
point.SetCoordinates( 10 + i, 20 + i, 30 + i );
test2Writer.WritePoint( point );
}
Tim Black
Ball Aerospace
571-357-2158
This message and any enclosures are intended only for the addressee. Please
notify the sender by email if you are not the intended recipient. If you are
not the intended recipient, you may not use, copy, disclose, or distribute this
message or its contents or enclosures to any other person and any such actions
may be unlawful. Ball reserves the right to monitor and review all messages
and enclosures sent to or from this email address.
-------------- next part --------------
An HTML attachment was scrubbed...
URL: http://lists.osgeo.org/pipermail/liblas-devel/attachments/20101202/d9c31b9d/attachment-0001.html
More information about the Liblas-devel
mailing list