Skip to content

Commit

Permalink
E57SimpleReader: Ensure scaled integer fields are set as best we can …
Browse files Browse the repository at this point in the history
…when reading

See #157
Related to #126
  • Loading branch information
asmaloney committed Nov 1, 2022
1 parent 0fd8073 commit 9683bda
Show file tree
Hide file tree
Showing 3 changed files with 177 additions and 11 deletions.
25 changes: 16 additions & 9 deletions src/ReaderImpl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -834,7 +834,6 @@ namespace e57
data3DHeader.pointFields.cartesianZField = proto.isDefined( "cartesianZ" );
data3DHeader.pointFields.cartesianInvalidStateField = proto.isDefined( "cartesianInvalidState" );

data3DHeader.pointFields.pointRangeScaledInteger = E57_NOT_SCALED_USE_FLOAT; // FloatNode
data3DHeader.pointFields.pointRangeMinimum = 0.0;
data3DHeader.pointFields.pointRangeMaximum = 0.0;

Expand All @@ -860,7 +859,11 @@ namespace e57

data3DHeader.pointFields.pointRangeMinimum = floatCartesianX.minimum();
data3DHeader.pointFields.pointRangeMaximum = floatCartesianX.maximum();
data3DHeader.pointFields.pointRangeScaledInteger = E57_NOT_SCALED_USE_FLOAT;

if ( floatCartesianX.precision() == E57_DOUBLE )
{
data3DHeader.pointFields.pointRangeScaledInteger = -1.0;
}
}
}
else if ( proto.isDefined( "sphericalRange" ) )
Expand All @@ -885,7 +888,11 @@ namespace e57

data3DHeader.pointFields.pointRangeMinimum = floatSphericalRange.minimum();
data3DHeader.pointFields.pointRangeMaximum = floatSphericalRange.maximum();
data3DHeader.pointFields.pointRangeScaledInteger = E57_NOT_SCALED_USE_FLOAT;

if ( floatSphericalRange.precision() == E57_DOUBLE )
{
data3DHeader.pointFields.pointRangeScaledInteger = -1.0;
}
}
}

Expand All @@ -894,7 +901,6 @@ namespace e57
data3DHeader.pointFields.sphericalElevationField = proto.isDefined( "sphericalElevation" );
data3DHeader.pointFields.sphericalInvalidStateField = proto.isDefined( "sphericalInvalidState" );

data3DHeader.pointFields.angleScaledInteger = E57_NOT_SCALED_USE_FLOAT; // FloatNode
data3DHeader.pointFields.angleMinimum = 0.0;
data3DHeader.pointFields.angleMaximum = 0.0;

Expand All @@ -920,7 +926,11 @@ namespace e57

data3DHeader.pointFields.angleMinimum = floatSphericalAzimuth.minimum();
data3DHeader.pointFields.angleMaximum = floatSphericalAzimuth.maximum();
data3DHeader.pointFields.angleScaledInteger = E57_NOT_SCALED_USE_FLOAT;

if ( floatSphericalAzimuth.precision() == E57_DOUBLE )
{
data3DHeader.pointFields.angleScaledInteger = -1.0;
}
}
}

Expand Down Expand Up @@ -955,7 +965,6 @@ namespace e57
data3DHeader.pointFields.isTimeStampInvalidField = proto.isDefined( "isTimeStampInvalid" );
data3DHeader.pointFields.timeMaximum = 0.0;
data3DHeader.pointFields.timeMinimum = 0.0;
data3DHeader.pointFields.timeScaledInteger = E57_NOT_SCALED_USE_FLOAT;

if ( proto.isDefined( "timeStamp" ) )
{
Expand All @@ -967,7 +976,7 @@ namespace e57

data3DHeader.pointFields.timeMaximum = static_cast<double>( integerTimeStamp.maximum() );
data3DHeader.pointFields.timeMinimum = static_cast<double>( integerTimeStamp.minimum() );
data3DHeader.pointFields.timeScaledInteger = E57_NOT_SCALED_USE_FLOAT;
data3DHeader.pointFields.timeScaledInteger = -1.0;
}
else if ( timeStampProto.type() == E57_SCALED_INTEGER )
{
Expand All @@ -988,15 +997,13 @@ namespace e57

data3DHeader.pointFields.timeMinimum = floatTimeStamp.minimum();
data3DHeader.pointFields.timeMaximum = floatTimeStamp.maximum();
data3DHeader.pointFields.timeScaledInteger = E57_NOT_SCALED_USE_FLOAT;
}
}

data3DHeader.pointFields.intensityField = proto.isDefined( "intensity" );
data3DHeader.pointFields.isIntensityInvalidField = proto.isDefined( "isIntensityInvalid" );
data3DHeader.intensityLimits.intensityMinimum = 0.0;
data3DHeader.intensityLimits.intensityMaximum = 0.0;
data3DHeader.pointFields.intensityScaledInteger = E57_NOT_SCALED_USE_FLOAT;

if ( scan.isDefined( "intensityLimits" ) )
{
Expand Down
4 changes: 2 additions & 2 deletions src/WriterImpl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -525,7 +525,7 @@ namespace e57
const double intensityMin = data3DHeader.intensityLimits.intensityMinimum;
const double intensityMax = data3DHeader.intensityLimits.intensityMaximum;

if ( data3DHeader.pointFields.intensityScaledInteger > 0.0 )
if ( data3DHeader.pointFields.intensityScaledInteger > E57_NOT_SCALED_USE_FLOAT )
{
const double scale = data3DHeader.pointFields.intensityScaledInteger;
const double offset = 0.0;
Expand All @@ -538,7 +538,7 @@ namespace e57
intbox.set( "intensityMaximum", ScaledIntegerNode( imf_, rawIntegerMaximum, rawIntegerMinimum,
rawIntegerMaximum, scale, offset ) );
}
else if ( data3DHeader.pointFields.intensityScaledInteger == 0.0 )
else if ( data3DHeader.pointFields.intensityScaledInteger == E57_NOT_SCALED_USE_FLOAT )
{
intbox.set( "intensityMinimum", FloatNode( imf_, intensityMin ) );
intbox.set( "intensityMaximum", FloatNode( imf_, intensityMax ) );
Expand Down
159 changes: 159 additions & 0 deletions test/src/test_SimpleData.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,11 @@
#include "gtest/gtest.h"

#include "E57SimpleData.h"
#include "E57SimpleReader.h"
#include "E57SimpleWriter.h"

#include "Helpers.h"
#include "TestData.h"

TEST( SimpleDataHeader, InvalidPointSize )
{
Expand Down Expand Up @@ -61,3 +64,159 @@ TEST( SimpleDataHeader, HeaderMinMaxDouble )
EXPECT_EQ( dataHeader.pointFields.timeMinimum, e57::E57_DOUBLE_MIN );
EXPECT_EQ( dataHeader.pointFields.timeMaximum, e57::E57_DOUBLE_MAX );
}

// Checks that the Data3D header and the the cartesianX FloatNode data are the same when read, written, and read again.
// https://github.com/asmaloney/libE57Format/issues/126
TEST( SimpleData, ReadWrite )
{
e57::Reader *originalReader = nullptr;
e57::E57Root originalFileHeader;
e57::Data3D originalData3DHeader;
e57::Data3DPointsData_d *originalPointsData = nullptr;

// 1. Read in original file
{
E57_ASSERT_NO_THROW( originalReader = new e57::Reader( TestData::Path() + "/self/ColouredCubeDouble.e57", {} ) );

ASSERT_TRUE( originalReader->GetE57Root( originalFileHeader ) );
ASSERT_TRUE( originalReader->ReadData3D( 0, originalData3DHeader ) );

const uint64_t cNumPoints = originalData3DHeader.pointsSize;

originalPointsData = new e57::Data3DPointsData_d( originalData3DHeader );

auto vectorReader = originalReader->SetUpData3DPointsData( 0, cNumPoints, *originalPointsData );

const uint64_t cNumRead = vectorReader.read();

vectorReader.close();

EXPECT_EQ( cNumRead, cNumPoints );
}

// 2. Write it out again using the Data3D header from the reader
{
e57::WriterOptions options;
options.guid = originalFileHeader.guid;

e57::Writer *writer = nullptr;
E57_ASSERT_NO_THROW( writer = new e57::Writer( "./ColouredCubeDoubleCopy.e57", options ) );

const int64_t cScanIndex1 = writer->NewData3D( originalData3DHeader );
const uint16_t cNumPoints = originalData3DHeader.pointsSize;

auto dataWriter = writer->SetUpData3DPointsData( cScanIndex1, cNumPoints, *originalPointsData );

dataWriter.write( cNumPoints );
dataWriter.close();

delete writer;
}

e57::Reader *copyReader = nullptr;
e57::E57Root copyFileHeader;
e57::Data3D copyData3DHeader;

// 3. Read in what we just wrote
{
E57_ASSERT_NO_THROW( copyReader = new e57::Reader( "./ColouredCubeDoubleCopy.e57", {} ) );

ASSERT_TRUE( copyReader->GetE57Root( copyFileHeader ) );
ASSERT_TRUE( copyReader->ReadData3D( 0, copyData3DHeader ) );

const uint64_t cNumPoints = copyData3DHeader.pointsSize;

e57::Data3DPointsData_d copyPointsData( copyData3DHeader );

auto vectorReader = copyReader->SetUpData3DPointsData( 0, cNumPoints, copyPointsData );

const uint64_t cNumRead = vectorReader.read();

vectorReader.close();

EXPECT_EQ( cNumRead, cNumPoints );
}

// 4. Compare the header data
EXPECT_EQ( originalData3DHeader.name, copyData3DHeader.name );
EXPECT_EQ( originalData3DHeader.guid, copyData3DHeader.guid );

EXPECT_EQ( originalData3DHeader.description, copyData3DHeader.description );

EXPECT_EQ( originalData3DHeader.colorLimits, copyData3DHeader.colorLimits );

EXPECT_EQ( originalData3DHeader.pointFields.cartesianXField, copyData3DHeader.pointFields.cartesianXField );
EXPECT_EQ( originalData3DHeader.pointFields.cartesianYField, copyData3DHeader.pointFields.cartesianYField );
EXPECT_EQ( originalData3DHeader.pointFields.cartesianZField, copyData3DHeader.pointFields.cartesianZField );
EXPECT_EQ( originalData3DHeader.pointFields.cartesianInvalidStateField,
copyData3DHeader.pointFields.cartesianInvalidStateField );

EXPECT_EQ( originalData3DHeader.pointFields.sphericalRangeField, copyData3DHeader.pointFields.sphericalRangeField );
EXPECT_EQ( originalData3DHeader.pointFields.sphericalAzimuthField,
copyData3DHeader.pointFields.sphericalAzimuthField );
EXPECT_EQ( originalData3DHeader.pointFields.sphericalElevationField,
copyData3DHeader.pointFields.sphericalElevationField );
EXPECT_EQ( originalData3DHeader.pointFields.sphericalInvalidStateField,
copyData3DHeader.pointFields.sphericalInvalidStateField );

EXPECT_EQ( originalData3DHeader.pointFields.pointRangeMinimum, copyData3DHeader.pointFields.pointRangeMinimum );
EXPECT_EQ( originalData3DHeader.pointFields.pointRangeMaximum, copyData3DHeader.pointFields.pointRangeMaximum );
EXPECT_EQ( originalData3DHeader.pointFields.pointRangeScaledInteger,
copyData3DHeader.pointFields.pointRangeScaledInteger );

EXPECT_EQ( originalData3DHeader.pointFields.angleMinimum, copyData3DHeader.pointFields.angleMinimum );
EXPECT_EQ( originalData3DHeader.pointFields.angleMaximum, copyData3DHeader.pointFields.angleMaximum );
EXPECT_EQ( originalData3DHeader.pointFields.angleScaledInteger, copyData3DHeader.pointFields.angleScaledInteger );

EXPECT_EQ( originalData3DHeader.pointFields.rowIndexField, copyData3DHeader.pointFields.rowIndexField );
EXPECT_EQ( originalData3DHeader.pointFields.rowIndexMaximum, copyData3DHeader.pointFields.rowIndexMaximum );

EXPECT_EQ( originalData3DHeader.pointFields.columnIndexField, copyData3DHeader.pointFields.columnIndexField );
EXPECT_EQ( originalData3DHeader.pointFields.columnIndexMaximum, copyData3DHeader.pointFields.columnIndexMaximum );

EXPECT_EQ( originalData3DHeader.pointFields.returnIndexField, copyData3DHeader.pointFields.returnIndexField );
EXPECT_EQ( originalData3DHeader.pointFields.returnCountField, copyData3DHeader.pointFields.returnCountField );
EXPECT_EQ( originalData3DHeader.pointFields.returnMaximum, copyData3DHeader.pointFields.returnMaximum );

EXPECT_EQ( originalData3DHeader.pointFields.timeStampField, copyData3DHeader.pointFields.timeStampField );
EXPECT_EQ( originalData3DHeader.pointFields.isTimeStampInvalidField,
copyData3DHeader.pointFields.isTimeStampInvalidField );
EXPECT_EQ( originalData3DHeader.pointFields.timeMinimum, copyData3DHeader.pointFields.timeMinimum );
EXPECT_EQ( originalData3DHeader.pointFields.timeMaximum, copyData3DHeader.pointFields.timeMaximum );

EXPECT_EQ( originalData3DHeader.pointFields.intensityField, copyData3DHeader.pointFields.intensityField );
EXPECT_EQ( originalData3DHeader.pointFields.isIntensityInvalidField,
copyData3DHeader.pointFields.isIntensityInvalidField );
EXPECT_EQ( originalData3DHeader.pointFields.intensityScaledInteger,
copyData3DHeader.pointFields.intensityScaledInteger );

EXPECT_EQ( originalData3DHeader.pointFields.colorRedField, copyData3DHeader.pointFields.colorRedField );
EXPECT_EQ( originalData3DHeader.pointFields.colorGreenField, copyData3DHeader.pointFields.colorGreenField );
EXPECT_EQ( originalData3DHeader.pointFields.colorBlueField, copyData3DHeader.pointFields.colorBlueField );
EXPECT_EQ( originalData3DHeader.pointFields.isColorInvalidField, copyData3DHeader.pointFields.isColorInvalidField );

EXPECT_EQ( originalData3DHeader.pointFields.normalXField, copyData3DHeader.pointFields.normalXField );
EXPECT_EQ( originalData3DHeader.pointFields.normalYField, copyData3DHeader.pointFields.normalYField );
EXPECT_EQ( originalData3DHeader.pointFields.normalZField, copyData3DHeader.pointFields.normalZField );

EXPECT_EQ( originalData3DHeader.pointsSize, copyData3DHeader.pointsSize );

// 5. Compare the cartesianX FloatNode data
e57::CompressedVectorNode originalPointsStructureNode( originalReader->GetRawData3D().get( "/data3D/0/points" ) );
e57::CompressedVectorNode copyPointsStructureNode( copyReader->GetRawData3D().get( "/data3D/0/points" ) );

const e57::StructureNode originalProto( originalPointsStructureNode.prototype() );
const e57::StructureNode copyProto( copyPointsStructureNode.prototype() );

e57::FloatNode originalCartesianXNode( originalProto.get( "cartesianX" ) );
e57::FloatNode copyCartesianXNode( copyProto.get( "cartesianX" ) );

EXPECT_EQ( originalCartesianXNode.precision(), copyCartesianXNode.precision() );
EXPECT_EQ( originalCartesianXNode.minimum(), copyCartesianXNode.minimum() );
EXPECT_EQ( originalCartesianXNode.maximum(), copyCartesianXNode.maximum() );

// 6. Cleanup
delete originalPointsData;
delete originalReader;
delete copyReader;
}

0 comments on commit 9683bda

Please sign in to comment.