From 6f24496877a8f525aa82888f71eef3ec225e52e9 Mon Sep 17 00:00:00 2001 From: Andy Maloney Date: Fri, 11 Nov 2022 18:42:38 -0500 Subject: [PATCH] E57Simple: Simplify & clarify node types when setting up Data3D Note that Data3D's "intensity" has been changed to a double so we can allow writing them as doubles. Addresses some of #157 and #160 --- include/E57Exception.h | 2 + include/E57SimpleData.h | 134 ++++++++------ src/E57Exception.cpp | 3 + src/E57SimpleData.cpp | 46 ++++- src/E57SimpleWriter.cpp | 13 +- src/ReaderImpl.cpp | 316 +++++++++++++++++++++++---------- src/WriterImpl.cpp | 215 +++++++++++++++------- test/src/test_SimpleData.cpp | 46 ++++- test/src/test_SimpleWriter.cpp | 25 +-- 9 files changed, 548 insertions(+), 252 deletions(-) diff --git a/include/E57Exception.h b/include/E57Exception.h index 6846c35..f78b47f 100644 --- a/include/E57Exception.h +++ b/include/E57Exception.h @@ -95,6 +95,8 @@ namespace e57 ErrorBadConfiguration = 49, //!< bad configuration string ErrorInvarianceViolation = 50, //!< class invariance constraint violation in debug mode + ErrorInvalidNodeType = 51, ///< an invalid note type was passed in Data3D pointFields + /// @deprecated Will be removed in 4.0. Use e57::Success. E57_SUCCESS [[deprecated( "Will be removed in 4.0. Use Success." )]] = Success, /// @deprecated Will be removed in 4.0. Use e57::ErrorBadCVHeader. diff --git a/include/E57SimpleData.h b/include/E57SimpleData.h index 26b427f..0992635 100644 --- a/include/E57SimpleData.h +++ b/include/E57SimpleData.h @@ -37,12 +37,6 @@ namespace e57 { - //! Indicates to use FloatNode instead of ScaledIntegerNode in fields that can use both. - constexpr double E57_NOT_SCALED_USE_FLOAT = 0.0; - - //! Indicates to use ScaledIntegerNode instead of FloatNode in fields that can use both. - constexpr double E57_NOT_SCALED_USE_INTEGER = -1.0; - //! @cond documentNonPublic The following isn't part of the API, and isn't documented. class ReaderImpl; class WriterImpl; @@ -305,6 +299,15 @@ namespace e57 GroupingByLine groupingByLine; //!< Grouping information by row or column index }; + //! @brief Used to set the type of node in some PointStandardizedFieldsAvailable fields. + enum class NumericalNodeType + { + Integer = 0, ///< Use IntegerNode + ScaledInteger, ///< Use ScaledIntegerNode + Float, ///< Use FloatNode with floats + Double, ///< Use FloatNode with doubles + }; + //! @brief Used to interrogate if standardized fields are available struct E57_DLL PointStandardizedFieldsAvailable { @@ -326,14 +329,15 @@ namespace e57 //! E57_FLOAT_MAX or E57_DOUBLE_MAX. If using a ScaledIntegerNode then this needs to be a maximum range value. double pointRangeMaximum = DOUBLE_MAX; - //! @brief Controls the type of Node used for the PointRecord cartesian and range fields - //! @details The value determines which type of Node to use and whether to use floats or doubles. - //! Value | Node Type - //! -- | -- - //! < 0.0 | FloatNode using doubles - //! == 0.0 (e57::E57_NOT_SCALED_USE_FLOAT) | FloatNode using floats (@em default) - //! > 0.0 | ScaledIntegerNode with the value as the scale setting - double pointRangeScaledInteger = E57_NOT_SCALED_USE_FLOAT; + /// @brief Controls the type of Node used for the PointRecord cartesian and range fields + /// @details Accepts NumericalNodeType::ScaledInteger, NumericalNodeType::Float, and + /// NumericalNodeType::Double. + NumericalNodeType pointRangeNodeType = NumericalNodeType::Float; + + /// @brief Sets the scale if using scaled integers for point fields + /// @details If pointRangeNodeType == NumericalNodeType::ScaledInteger, it will use this value + /// to scale the numbers and it must be > 0.0. + double pointRangeScale = 0.0; //! Indicates that the PointRecord angle fields should be configured with this minimum value E57_FLOAT_MIN or //! E57_DOUBLE_MIN. If using a ScaledIntegerNode then this needs to be a minimum angle value. @@ -343,14 +347,15 @@ namespace e57 //! E57_DOUBLE_MAX. If using a ScaledIntegerNode then this needs to be a maximum angle value. double angleMaximum = DOUBLE_MAX; - //! @brief Controls the type of Node used for the PointRecord angle fields - //! @details The value determines which type of Node to use and whether to use floats or doubles. - //! Value | Node Type - //! -- | -- - //! < 0.0 | FloatNode using doubles - //! == 0.0 (e57::E57_NOT_SCALED_USE_FLOAT) | FloatNode using floats (@em default) - //! > 0.0 | ScaledIntegerNode with the value as the scale setting - double angleScaledInteger = E57_NOT_SCALED_USE_FLOAT; + /// @brief Controls the type of Node used for the PointRecord angle fields + /// @details Accepts NumericalNodeType::ScaledInteger, NumericalNodeType::Float, and + /// NumericalNodeType::Double. + NumericalNodeType angleNodeType = NumericalNodeType::Float; + + /// @brief Sets the scale if using scaled integers for angle fields + /// @details If angleNodeType == NumericalNodeType::ScaledInteger, it will use this value + /// to scale the numbers and it must be > 0.0. + double angleScale = 0.0; bool rowIndexField = false; //!< Indicates that the PointRecord @a rowIndex field is active @@ -381,36 +386,46 @@ namespace e57 //! E57_UINT32_MAX, E57_DOUBLE_MAX or E57_DOUBLE_MAX. double timeMaximum = DOUBLE_MAX; - //! @brief Controls the type of Node used for the PointRecord @a timeStamp fields - //! @details The value determines which type of Node to use and whether to use floats or doubles. - //! Value | Node Type - //! -- | -- - //! < 0.0 | IntegerNode - //! == 0.0 (e57::E57_NOT_SCALED_USE_FLOAT) | FloatNode using floats if (::timeMaximum == E57_FLOAT_MAX) - //! == 0.0 | FloatNode using doubles if (::timeMaximum == E57_DOUBLE_MAX) (@em default) - //! > 0.0 | ScaledIntegerNode with the value as the scale setting - double timeScaledInteger = E57_NOT_SCALED_USE_FLOAT; - - bool intensityField = false; //!< Indicates that the PointRecord @a intensity field is active - bool isIntensityInvalidField = false; //!< Indicates that the PointRecord @a isIntensityInvalid field is active - - //! @brief Controls the type of Node used for the PointRecord @a intensity fields - //! @details The value determines which type of Node to use. - //! Value | Node Type - //! -- | -- - //! < 0.0 | IntegerNode - //! == 0.0 (e57::E57_NOT_SCALED_USE_FLOAT) | FloatNode using floats (@em default) - //! > 0.0 | ScaledIntegerNode with the value as the scale setting - double intensityScaledInteger = E57_NOT_SCALED_USE_INTEGER; - - bool colorRedField = false; //!< Indicates that the PointRecord @a colorRed field is active - bool colorGreenField = false; //!< Indicates that the PointRecord @a colorGreen field is active - bool colorBlueField = false; //!< Indicates that the PointRecord @a colorBlue field is active - bool isColorInvalidField = false; //!< Indicates that the PointRecord @a isColorInvalid field is active - - bool normalXField = false; //!< Indicates that the PointRecord @a nor:normalX field is active - bool normalYField = false; //!< Indicates that the PointRecord @a nor:normalY field is active - bool normalZField = false; //!< Indicates that the PointRecord @a nor:normalZ field is active + /// @brief Controls the type of Node used for the PointRecord time fields + /// @details Accepts NumericalNodeType::Integer, NumericalNodeType::ScaledInteger, NumericalNodeType::Float, and + /// NumericalNodeType::Double. + NumericalNodeType timeNodeType = NumericalNodeType::Float; + + /// @brief Sets the scale if using scaled integers for time fields + /// @details If timeNodeType == NumericalNodeType::ScaledInteger, it will use this value + /// to scale the numbers and it must be > 0.0. + double timeScale = 0.0; + + /// Indicates that the PointRecord @a intensity field is active + bool intensityField = false; + /// Indicates that the PointRecord @a isIntensityInvalid field is active + bool isIntensityInvalidField = false; + + /// @brief Controls the type of Node used for the PointRecord intensity fields + /// @details Accepts NumericalNodeType::Integer, NumericalNodeType::ScaledInteger, NumericalNodeType::Float, and + /// NumericalNodeType::Double. + NumericalNodeType intensityNodeType = NumericalNodeType::Float; + + /// @brief Sets the scale if using scaled integers for intensity fields + /// @details If intensityNodeType == NumericalNodeType::ScaledInteger, it will use this value + /// to scale the numbers and it must be > 0.0. + double intensityScale = 0.0; + + /// Indicates that the PointRecord @a colorRed field is active + bool colorRedField = false; + /// Indicates that the PointRecord @a colorGreen field is active + bool colorGreenField = false; + /// Indicates that the PointRecord @a colorBlue field is active + bool colorBlueField = false; + /// Indicates that the PointRecord @a isColorInvalid field is active + bool isColorInvalidField = false; + + /// Indicates that the PointRecord @a nor:normalX field is active + bool normalXField = false; + /// Indicates that the PointRecord @a nor:normalY field is active + bool normalYField = false; + /// Indicates that the PointRecord @a nor:normalZ field is active + bool normalZField = false; }; //! @brief Stores the top-level information for a single lidar scan @@ -478,12 +493,15 @@ namespace e57 { static_assert( std::is_floating_point::value, "Floating point type required." ); - //! @brief Default constructor does not manage any memory or adjust min/max for floats. + //! @brief Default constructor does not manage any memory, adjust min/max for floats, or validate data. Data3DPointsData_t() = default; - //! @brief Constructor which allocates buffers for all valid fields in the given Data3D header - //! This constructor will also adjust the min/max fields in the data3D pointFields if we are using floats. - //! @param [in] data3D Completed header which indicates the fields we are using + /// @brief Constructor which allocates buffers for all valid fields in the given Data3D header. + /// @details This constructor will also adjust the min/max fields in the data3D pointFields if we are using + /// floats, and run some validation on the Data3D. + /// @param [in] data3D Completed header which indicates the fields we are using + /// @throw ::ErrorValueOutOfBounds + /// @throw ::ErrorInvalidNodeType explicit Data3DPointsData_t( e57::Data3D &data3D ); //! @brief Destructor will delete any memory allocated using the Data3DPointsData_t( const e57::Data3D & ) @@ -502,8 +520,8 @@ namespace e57 //! Value = 0 if the point is considered valid, 1 otherwise int8_t *cartesianInvalidState = nullptr; - //! Pointer to a buffer with the Point response intensity. Unit is unspecified. - float *intensity = nullptr; + /// @brief Pointer to a buffer with the Point response intensity. Unit is unspecified. + double *intensity = nullptr; //! Value = 0 if the intensity is considered valid, 1 otherwise int8_t *isIntensityInvalid = nullptr; diff --git a/src/E57Exception.cpp b/src/E57Exception.cpp index e2f00d3..3e172ef 100644 --- a/src/E57Exception.cpp +++ b/src/E57Exception.cpp @@ -447,6 +447,9 @@ namespace e57 case ErrorInvarianceViolation: return "class invariance constraint violation in debug mode " "(ErrorInvarianceViolation)"; + case ErrorInvalidNodeType: + return "an invalid node type was passed in Data3D pointFields"; + default: return "unknown error (" + std::to_string( ecode ) + ")"; } diff --git a/src/E57SimpleData.cpp b/src/E57SimpleData.cpp index f7ab2be..25fd62c 100644 --- a/src/E57SimpleData.cpp +++ b/src/E57SimpleData.cpp @@ -14,6 +14,25 @@ namespace e57 { + /// Validates a Data3D and throws on error. + void _validateData3D( const Data3D &inData3D ) + { + if ( inData3D.pointCount < 1 ) + { + throw E57_EXCEPTION2( ErrorValueOutOfBounds, "pointCount=" + toString( inData3D.pointCount ) + " minimum=1" ); + } + + if ( inData3D.pointFields.pointRangeNodeType == NumericalNodeType::Integer ) + { + throw E57_EXCEPTION2( ErrorInvalidNodeType, "pointRangeNodeType cannot be Integer" ); + } + + if ( inData3D.pointFields.angleNodeType == NumericalNodeType::Integer ) + { + throw E57_EXCEPTION2( ErrorInvalidNodeType, "angleNodeType cannot be Integer" ); + } + } + // To avoid exposing M_PI, we define the constructor here. SphericalBounds::SphericalBounds() { @@ -31,15 +50,12 @@ namespace e57 template Data3DPointsData_t::Data3DPointsData_t( Data3D &data3D ) : _selfAllocated( true ) { - const auto cPointCount = data3D.pointCount; + _validateData3D( data3D ); - if ( cPointCount < 1 ) - { - throw E57_EXCEPTION2( ErrorValueOutOfBounds, "pointCount=" + toString( cPointCount ) + " minimum=1" ); - } + constexpr bool cIsFloat = std::is_same::value; // We need to adjust min/max for floats. - if ( std::is_same::value ) + if ( cIsFloat ) { data3D.pointFields.pointRangeMinimum = FLOAT_MIN; data3D.pointFields.pointRangeMaximum = FLOAT_MAX; @@ -49,6 +65,22 @@ namespace e57 data3D.pointFields.timeMaximum = FLOAT_MAX; } + // IF point range node type is not ScaledInteger + // THEN make sure the proper floating point type is set + if ( data3D.pointFields.pointRangeNodeType != NumericalNodeType::ScaledInteger ) + { + data3D.pointFields.pointRangeNodeType = ( cIsFloat ? NumericalNodeType::Float : NumericalNodeType::Double ); + } + + // IF angle node type is not ScaledInteger + // THEN make sure the proper floating point type is set + if ( data3D.pointFields.angleNodeType != NumericalNodeType::ScaledInteger ) + { + data3D.pointFields.angleNodeType = ( cIsFloat ? NumericalNodeType::Float : NumericalNodeType::Double ); + } + + const auto cPointCount = data3D.pointCount; + if ( data3D.pointFields.cartesianXField ) { cartesianX = new COORDTYPE[cPointCount]; @@ -71,7 +103,7 @@ namespace e57 if ( data3D.pointFields.intensityField ) { - intensity = new float[cPointCount]; + intensity = new double[cPointCount]; } if ( data3D.pointFields.isIntensityInvalidField ) diff --git a/src/E57SimpleWriter.cpp b/src/E57SimpleWriter.cpp index e525195..3bf31b3 100644 --- a/src/E57SimpleWriter.cpp +++ b/src/E57SimpleWriter.cpp @@ -54,7 +54,7 @@ namespace auto pointRangeMinimum = cMax; auto pointRangeMaximum = cMin; - const bool writePointRange = ( pointFields.pointRangeScaledInteger != 0.0 ) && + const bool writePointRange = ( pointFields.pointRangeNodeType == e57::NumericalNodeType::ScaledInteger ) && ( pointFields.pointRangeMinimum == cMin ) && ( pointFields.pointRangeMaximum == cMax ); @@ -64,14 +64,14 @@ namespace auto angleMinimum = cMax; auto angleMaximum = cMin; - const bool writeAngle = ( pointFields.angleScaledInteger != 0.0 ) && ( pointFields.angleMinimum == cMin ) && - ( pointFields.angleMaximum == cMax ); + const bool writeAngle = ( pointFields.angleNodeType == e57::NumericalNodeType::ScaledInteger ) && + ( pointFields.angleMinimum == cMin ) && ( pointFields.angleMaximum == cMax ); // IF we are using intesity // AND we haven't set either min or max // THEN calculate them from the points - float intensityMinimum = std::numeric_limits::max(); - float intensityMaximum = std::numeric_limits::lowest(); + double intensityMinimum = std::numeric_limits::max(); + double intensityMaximum = std::numeric_limits::lowest(); const bool writeIntensity = pointFields.intensityField && ( ioData3DHeader.intensityLimits == e57::IntensityLimits{} ); @@ -82,7 +82,8 @@ namespace double timeMinimum = std::numeric_limits::max(); double timeMaximum = std::numeric_limits::lowest(); - const bool writeTimeStamp = pointFields.timeStampField && ( pointFields.timeScaledInteger != 0.0 ) && + const bool writeTimeStamp = pointFields.timeStampField && + ( pointFields.timeNodeType == e57::NumericalNodeType::ScaledInteger ) && ( pointFields.timeMinimum == cMin ) && ( pointFields.timeMaximum == cMax ); // Now run through the points and set the things we need to diff --git a/src/ReaderImpl.cpp b/src/ReaderImpl.cpp index 3e29da6..0273384 100644 --- a/src/ReaderImpl.cpp +++ b/src/ReaderImpl.cpp @@ -27,6 +27,8 @@ */ #include "ReaderImpl.h" +#include "Common.h" +#include "StringFunctions.h" namespace e57 { @@ -841,58 +843,108 @@ namespace e57 { const auto cartesianXProto = proto.get( "cartesianX" ); - if ( cartesianXProto.type() == TypeScaledInteger ) + switch ( cartesianXProto.type() ) { - const ScaledIntegerNode scaledCartesianX( cartesianXProto ); - const double scale = scaledCartesianX.scale(); - const double offset = scaledCartesianX.offset(); - const int64_t minimum = scaledCartesianX.minimum(); - const int64_t maximum = scaledCartesianX.maximum(); + case TypeInteger: + { + // Should be a warning that we don't handle this type, but we don't have a mechanism for warnings. + break; + } - data3DHeader.pointFields.pointRangeMinimum = static_cast( minimum ) * scale + offset; - data3DHeader.pointFields.pointRangeMaximum = static_cast( maximum ) * scale + offset; - data3DHeader.pointFields.pointRangeScaledInteger = scale; - } - else if ( cartesianXProto.type() == TypeFloat ) - { - const FloatNode floatCartesianX( cartesianXProto ); + case TypeScaledInteger: + { + const ScaledIntegerNode scaledCartesianX( cartesianXProto ); + const double scale = scaledCartesianX.scale(); + const double offset = scaledCartesianX.offset(); + const int64_t minimum = scaledCartesianX.minimum(); + const int64_t maximum = scaledCartesianX.maximum(); - data3DHeader.pointFields.pointRangeMinimum = floatCartesianX.minimum(); - data3DHeader.pointFields.pointRangeMaximum = floatCartesianX.maximum(); + data3DHeader.pointFields.pointRangeMinimum = static_cast( minimum ) * scale + offset; + data3DHeader.pointFields.pointRangeMaximum = static_cast( maximum ) * scale + offset; - if ( floatCartesianX.precision() == PrecisionDouble ) + data3DHeader.pointFields.pointRangeNodeType = NumericalNodeType::ScaledInteger; + data3DHeader.pointFields.pointRangeScale = scale; + + break; + } + + case TypeFloat: { - data3DHeader.pointFields.pointRangeScaledInteger = -1.0; + const FloatNode floatCartesianX( cartesianXProto ); + + data3DHeader.pointFields.pointRangeMinimum = floatCartesianX.minimum(); + data3DHeader.pointFields.pointRangeMaximum = floatCartesianX.maximum(); + + if ( floatCartesianX.precision() == PrecisionSingle ) + { + data3DHeader.pointFields.pointRangeNodeType = NumericalNodeType::Float; + } + else + { + data3DHeader.pointFields.pointRangeNodeType = NumericalNodeType::Double; + } + + break; } + + default: + throw E57_EXCEPTION2( ErrorInvalidNodeType, "invalid node type reading cartesianX field: " + + toString( cartesianXProto.type() ) ); + break; } } else if ( proto.isDefined( "sphericalRange" ) ) { const auto sphericalRangeProto = proto.get( "sphericalRange" ); - if ( sphericalRangeProto.type() == TypeScaledInteger ) + switch ( sphericalRangeProto.type() ) { - const ScaledIntegerNode scaledSphericalRange( sphericalRangeProto ); - const double scale = scaledSphericalRange.scale(); - const double offset = scaledSphericalRange.offset(); - const int64_t minimum = scaledSphericalRange.minimum(); - const int64_t maximum = scaledSphericalRange.maximum(); + case TypeInteger: + { + // Should be a warning that we don't handle this type, but we don't have a mechanism for warnings. + break; + } - data3DHeader.pointFields.pointRangeMinimum = static_cast( minimum ) * scale + offset; - data3DHeader.pointFields.pointRangeMaximum = static_cast( maximum ) * scale + offset; - data3DHeader.pointFields.pointRangeScaledInteger = scale; - } - else if ( sphericalRangeProto.type() == TypeFloat ) - { - const FloatNode floatSphericalRange( sphericalRangeProto ); + case TypeScaledInteger: + { + const ScaledIntegerNode scaledSphericalRange( sphericalRangeProto ); + const double scale = scaledSphericalRange.scale(); + const double offset = scaledSphericalRange.offset(); + const int64_t minimum = scaledSphericalRange.minimum(); + const int64_t maximum = scaledSphericalRange.maximum(); - data3DHeader.pointFields.pointRangeMinimum = floatSphericalRange.minimum(); - data3DHeader.pointFields.pointRangeMaximum = floatSphericalRange.maximum(); + data3DHeader.pointFields.pointRangeMinimum = static_cast( minimum ) * scale + offset; + data3DHeader.pointFields.pointRangeMaximum = static_cast( maximum ) * scale + offset; - if ( floatSphericalRange.precision() == PrecisionDouble ) + data3DHeader.pointFields.pointRangeNodeType = NumericalNodeType::ScaledInteger; + data3DHeader.pointFields.pointRangeScale = scale; + + break; + } + + case TypeFloat: { - data3DHeader.pointFields.pointRangeScaledInteger = -1.0; + const FloatNode floatSphericalRange( sphericalRangeProto ); + + data3DHeader.pointFields.pointRangeMinimum = floatSphericalRange.minimum(); + data3DHeader.pointFields.pointRangeMaximum = floatSphericalRange.maximum(); + + if ( floatSphericalRange.precision() == PrecisionSingle ) + { + data3DHeader.pointFields.pointRangeNodeType = NumericalNodeType::Float; + } + else + { + data3DHeader.pointFields.pointRangeNodeType = NumericalNodeType::Double; + } + + break; } + + default: + throw E57_EXCEPTION2( ErrorInvalidNodeType, "invalid node type reading sphericalRange field: " + + toString( sphericalRangeProto.type() ) ); + break; } } @@ -908,29 +960,48 @@ namespace e57 { const auto sphericalAzimuthProto = proto.get( "sphericalAzimuth" ); - if ( sphericalAzimuthProto.type() == TypeScaledInteger ) + switch ( sphericalAzimuthProto.type() ) { - const ScaledIntegerNode scaledSphericalAzimuth( sphericalAzimuthProto ); - const double scale = scaledSphericalAzimuth.scale(); - const double offset = scaledSphericalAzimuth.offset(); - const int64_t minimum = scaledSphericalAzimuth.minimum(); - const int64_t maximum = scaledSphericalAzimuth.maximum(); + case TypeScaledInteger: + { + const ScaledIntegerNode scaledSphericalAzimuth( sphericalAzimuthProto ); + const double scale = scaledSphericalAzimuth.scale(); + const double offset = scaledSphericalAzimuth.offset(); + const int64_t minimum = scaledSphericalAzimuth.minimum(); + const int64_t maximum = scaledSphericalAzimuth.maximum(); - data3DHeader.pointFields.angleMinimum = static_cast( minimum ) * scale + offset; - data3DHeader.pointFields.angleMaximum = static_cast( maximum ) * scale + offset; - data3DHeader.pointFields.angleScaledInteger = scale; - } - else if ( sphericalAzimuthProto.type() == TypeFloat ) - { - const FloatNode floatSphericalAzimuth( sphericalAzimuthProto ); + data3DHeader.pointFields.angleMinimum = static_cast( minimum ) * scale + offset; + data3DHeader.pointFields.angleMaximum = static_cast( maximum ) * scale + offset; - data3DHeader.pointFields.angleMinimum = floatSphericalAzimuth.minimum(); - data3DHeader.pointFields.angleMaximum = floatSphericalAzimuth.maximum(); + data3DHeader.pointFields.angleNodeType = NumericalNodeType::ScaledInteger; + data3DHeader.pointFields.angleScale = scale; + + break; + } - if ( floatSphericalAzimuth.precision() == PrecisionDouble ) + case TypeFloat: { - data3DHeader.pointFields.angleScaledInteger = -1.0; + const FloatNode floatSphericalAzimuth( sphericalAzimuthProto ); + + data3DHeader.pointFields.angleMinimum = floatSphericalAzimuth.minimum(); + data3DHeader.pointFields.angleMaximum = floatSphericalAzimuth.maximum(); + + if ( floatSphericalAzimuth.precision() == PrecisionSingle ) + { + data3DHeader.pointFields.angleNodeType = NumericalNodeType::Float; + } + else + { + data3DHeader.pointFields.angleNodeType = NumericalNodeType::Double; + } + + break; } + + default: + throw E57_EXCEPTION2( ErrorInvalidNodeType, "invalid node type reading sphericalAzimuth field: " + + toString( sphericalAzimuthProto.type() ) ); + break; } } @@ -970,33 +1041,61 @@ namespace e57 { const auto timeStampProto = proto.get( "timeStamp" ); - if ( timeStampProto.type() == TypeInteger ) + switch ( timeStampProto.type() ) { - const IntegerNode integerTimeStamp( timeStampProto ); + case TypeInteger: + { + const IntegerNode integerTimeStamp( timeStampProto ); - data3DHeader.pointFields.timeMaximum = static_cast( integerTimeStamp.maximum() ); - data3DHeader.pointFields.timeMinimum = static_cast( integerTimeStamp.minimum() ); - data3DHeader.pointFields.timeScaledInteger = -1.0; - } - else if ( timeStampProto.type() == TypeScaledInteger ) - { - const ScaledIntegerNode scaledTimeStamp( timeStampProto ); + data3DHeader.pointFields.timeMaximum = static_cast( integerTimeStamp.maximum() ); + data3DHeader.pointFields.timeMinimum = static_cast( integerTimeStamp.minimum() ); - const double scale = scaledTimeStamp.scale(); - const double offset = scaledTimeStamp.offset(); - const int64_t minimum = scaledTimeStamp.minimum(); - const int64_t maximum = scaledTimeStamp.maximum(); + data3DHeader.pointFields.timeNodeType = NumericalNodeType::Integer; - data3DHeader.pointFields.timeMinimum = static_cast( minimum ) * scale + offset; - data3DHeader.pointFields.timeMaximum = static_cast( maximum ) * scale + offset; - data3DHeader.pointFields.timeScaledInteger = scale; - } - else if ( timeStampProto.type() == TypeFloat ) - { - const FloatNode floatTimeStamp( timeStampProto ); + break; + } + + case TypeScaledInteger: + { + const ScaledIntegerNode scaledTimeStamp( timeStampProto ); + + const double scale = scaledTimeStamp.scale(); + const double offset = scaledTimeStamp.offset(); + const int64_t minimum = scaledTimeStamp.minimum(); + const int64_t maximum = scaledTimeStamp.maximum(); + + data3DHeader.pointFields.timeMinimum = static_cast( minimum ) * scale + offset; + data3DHeader.pointFields.timeMaximum = static_cast( maximum ) * scale + offset; + + data3DHeader.pointFields.timeNodeType = NumericalNodeType::ScaledInteger; + data3DHeader.pointFields.timeScale = scale; + + break; + } + + case TypeFloat: + { + const FloatNode floatTimeStamp( timeStampProto ); + + data3DHeader.pointFields.timeMinimum = floatTimeStamp.minimum(); + data3DHeader.pointFields.timeMaximum = floatTimeStamp.maximum(); + + if ( floatTimeStamp.precision() == PrecisionSingle ) + { + data3DHeader.pointFields.timeNodeType = NumericalNodeType::Float; + } + else + { + data3DHeader.pointFields.timeNodeType = NumericalNodeType::Double; + } - data3DHeader.pointFields.timeMinimum = floatTimeStamp.minimum(); - data3DHeader.pointFields.timeMaximum = floatTimeStamp.maximum(); + break; + } + + default: + throw E57_EXCEPTION2( ErrorInvalidNodeType, "invalid node type reading timeStamp field: " + + toString( timeStampProto.type() ) ); + break; } } @@ -1034,46 +1133,67 @@ namespace e57 { const auto intensityProto = proto.get( "intensity" ); - if ( intensityProto.type() == TypeInteger ) + switch ( intensityProto.type() ) { - const IntegerNode integerIntensity( intensityProto ); - - if ( data3DHeader.intensityLimits.intensityMaximum == 0.0 ) + case TypeInteger: { - data3DHeader.intensityLimits.intensityMinimum = static_cast( integerIntensity.minimum() ); - data3DHeader.intensityLimits.intensityMaximum = static_cast( integerIntensity.maximum() ); - } + const IntegerNode integerIntensity( intensityProto ); - data3DHeader.pointFields.intensityScaledInteger = E57_NOT_SCALED_USE_INTEGER; - } - else if ( intensityProto.type() == TypeScaledInteger ) - { - const ScaledIntegerNode scaledIntensity( intensityProto ); - double scale = scaledIntensity.scale(); - double offset = scaledIntensity.offset(); + if ( data3DHeader.intensityLimits.intensityMaximum == 0.0 ) + { + data3DHeader.intensityLimits.intensityMinimum = static_cast( integerIntensity.minimum() ); + data3DHeader.intensityLimits.intensityMaximum = static_cast( integerIntensity.maximum() ); + } + + data3DHeader.pointFields.intensityNodeType = NumericalNodeType::Integer; + + break; + } - if ( data3DHeader.intensityLimits.intensityMaximum == 0.0 ) + case TypeScaledInteger: { - const int64_t minimum = scaledIntensity.minimum(); - const int64_t maximum = scaledIntensity.maximum(); + const ScaledIntegerNode scaledIntensity( intensityProto ); + double scale = scaledIntensity.scale(); + double offset = scaledIntensity.offset(); + + if ( data3DHeader.intensityLimits.intensityMaximum == 0.0 ) + { + const int64_t minimum = scaledIntensity.minimum(); + const int64_t maximum = scaledIntensity.maximum(); + + data3DHeader.intensityLimits.intensityMinimum = static_cast( minimum ) * scale + offset; + data3DHeader.intensityLimits.intensityMaximum = static_cast( maximum ) * scale + offset; + } + + data3DHeader.pointFields.intensityNodeType = NumericalNodeType::ScaledInteger; + data3DHeader.pointFields.intensityScale = scale; - data3DHeader.intensityLimits.intensityMinimum = static_cast( minimum ) * scale + offset; - data3DHeader.intensityLimits.intensityMaximum = static_cast( maximum ) * scale + offset; + break; } - data3DHeader.pointFields.intensityScaledInteger = scale; - } - else if ( proto.get( "intensity" ).type() == TypeFloat ) - { - if ( data3DHeader.intensityLimits.intensityMaximum == 0.0 ) + case TypeFloat: { const FloatNode floatIntensity( intensityProto ); data3DHeader.intensityLimits.intensityMinimum = floatIntensity.minimum(); data3DHeader.intensityLimits.intensityMaximum = floatIntensity.maximum(); + + if ( floatIntensity.precision() == PrecisionSingle ) + { + data3DHeader.pointFields.intensityNodeType = NumericalNodeType::Float; + } + else + { + data3DHeader.pointFields.intensityNodeType = NumericalNodeType::Double; + } + + break; } - data3DHeader.pointFields.intensityScaledInteger = E57_NOT_SCALED_USE_FLOAT; + default: + throw E57_EXCEPTION2( ErrorInvalidNodeType, "invalid node type reading intensity field: " + + toString( intensityProto.type() ) ); + break; } } diff --git a/src/WriterImpl.cpp b/src/WriterImpl.cpp index 87f183b..be32eeb 100644 --- a/src/WriterImpl.cpp +++ b/src/WriterImpl.cpp @@ -526,28 +526,49 @@ namespace e57 const double intensityMin = data3DHeader.intensityLimits.intensityMinimum; const double intensityMax = data3DHeader.intensityLimits.intensityMaximum; - if ( data3DHeader.pointFields.intensityScaledInteger > E57_NOT_SCALED_USE_FLOAT ) + switch ( data3DHeader.pointFields.intensityNodeType ) { - const double scale = data3DHeader.pointFields.intensityScaledInteger; - const double offset = 0.0; + case NumericalNodeType::Integer: + { + intbox.set( "intensityMinimum", IntegerNode( imf_, static_cast( intensityMin ) ) ); + intbox.set( "intensityMaximum", IntegerNode( imf_, static_cast( intensityMax ) ) ); - const auto rawIntegerMinimum = static_cast( std::floor( ( intensityMin - offset ) / scale + .5 ) ); - const auto rawIntegerMaximum = static_cast( std::floor( ( intensityMax - offset ) / scale + .5 ) ); + break; + } - intbox.set( "intensityMinimum", ScaledIntegerNode( imf_, rawIntegerMinimum, rawIntegerMinimum, - rawIntegerMaximum, scale, offset ) ); - intbox.set( "intensityMaximum", ScaledIntegerNode( imf_, rawIntegerMaximum, rawIntegerMinimum, - rawIntegerMaximum, scale, offset ) ); - } - else if ( data3DHeader.pointFields.intensityScaledInteger == E57_NOT_SCALED_USE_FLOAT ) - { - intbox.set( "intensityMinimum", FloatNode( imf_, intensityMin ) ); - intbox.set( "intensityMaximum", FloatNode( imf_, intensityMax ) ); - } - else - { - intbox.set( "intensityMinimum", IntegerNode( imf_, static_cast( intensityMin ) ) ); - intbox.set( "intensityMaximum", IntegerNode( imf_, static_cast( intensityMax ) ) ); + case NumericalNodeType::ScaledInteger: + { + const double scale = data3DHeader.pointFields.intensityScale; + const double offset = 0.0; + + const auto rawIntegerMinimum = + static_cast( std::floor( ( intensityMin - offset ) / scale + .5 ) ); + const auto rawIntegerMaximum = + static_cast( std::floor( ( intensityMax - offset ) / scale + .5 ) ); + + intbox.set( "intensityMinimum", ScaledIntegerNode( imf_, rawIntegerMinimum, rawIntegerMinimum, + rawIntegerMaximum, scale, offset ) ); + intbox.set( "intensityMaximum", ScaledIntegerNode( imf_, rawIntegerMaximum, rawIntegerMinimum, + rawIntegerMaximum, scale, offset ) ); + + break; + } + + case NumericalNodeType::Float: + { + intbox.set( "intensityMinimum", FloatNode( imf_, 0.0, PrecisionSingle, intensityMin ) ); + intbox.set( "intensityMaximum", FloatNode( imf_, 0.0, PrecisionSingle, intensityMax ) ); + + break; + } + + case NumericalNodeType::Double: + { + intbox.set( "intensityMinimum", FloatNode( imf_, 0.0, PrecisionDouble, intensityMin ) ); + intbox.set( "intensityMaximum", FloatNode( imf_, 0.0, PrecisionDouble, intensityMax ) ); + + break; + } } scan.set( "intensityLimits", intbox ); @@ -716,7 +737,7 @@ namespace e57 StructureNode proto( imf_ ); // Because ScaledInteger min/max are the raw integer min/max, we must calculate them from the data min/max - const double pointRangeScale = data3DHeader.pointFields.pointRangeScaledInteger; + const double pointRangeScale = data3DHeader.pointFields.pointRangeScale; const double pointRangeOffset = 0.0; const double pointRangeMin = data3DHeader.pointFields.pointRangeMinimum; @@ -728,15 +749,29 @@ namespace e57 static_cast( std::floor( ( pointRangeMax - pointRangeOffset ) / pointRangeScale + .5 ) ); const auto getPointProto = [=]() -> Node { - if ( pointRangeScale > E57_NOT_SCALED_USE_FLOAT ) + switch ( data3DHeader.pointFields.pointRangeNodeType ) { - return ScaledIntegerNode( imf_, 0, pointRangeMinimum, pointRangeMaximum, pointRangeScale, - pointRangeOffset ); - } + case NumericalNodeType::Integer: + { + throw E57_EXCEPTION2( ErrorInvalidNodeType, "pointRangeNodeType cannot be Integer" ); + } + + case NumericalNodeType::ScaledInteger: + { + return ScaledIntegerNode( imf_, 0, pointRangeMinimum, pointRangeMaximum, pointRangeScale, + pointRangeOffset ); + } + + case NumericalNodeType::Float: + { + return FloatNode( imf_, 0.0, PrecisionSingle, pointRangeMin, pointRangeMax ); + } - return FloatNode( imf_, 0.0, - ( pointRangeScale < E57_NOT_SCALED_USE_FLOAT ) ? PrecisionDouble : PrecisionSingle, - pointRangeMin, pointRangeMax ); + case NumericalNodeType::Double: + { + return FloatNode( imf_, 0.0, PrecisionDouble, pointRangeMin, pointRangeMax ); + } + } }; if ( data3DHeader.pointFields.cartesianXField ) @@ -761,20 +796,35 @@ namespace e57 const double angleMin = data3DHeader.pointFields.angleMinimum; const double angleMax = data3DHeader.pointFields.angleMaximum; - const double angleScale = data3DHeader.pointFields.angleScaledInteger; + const double angleScale = data3DHeader.pointFields.angleScale; const double angleOffset = 0.0; const auto angleMinimum = static_cast( std::floor( ( angleMin - angleOffset ) / angleScale + .5 ) ); const auto angleMaximum = static_cast( std::floor( ( angleMax - angleOffset ) / angleScale + .5 ) ); const auto getAngleProto = [=]() -> Node { - if ( angleScale > E57_NOT_SCALED_USE_FLOAT ) + switch ( data3DHeader.pointFields.angleNodeType ) { - return ScaledIntegerNode( imf_, 0, angleMinimum, angleMaximum, angleScale, angleOffset ); - } + case NumericalNodeType::Integer: + { + throw E57_EXCEPTION2( ErrorInvalidNodeType, "angleNodeType cannot be Integer" ); + } + + case NumericalNodeType::ScaledInteger: + { + return ScaledIntegerNode( imf_, 0, angleMinimum, angleMaximum, angleScale, angleOffset ); + } - return FloatNode( imf_, 0.0, ( angleScale < E57_NOT_SCALED_USE_FLOAT ) ? PrecisionDouble : PrecisionSingle, - angleMin, angleMax ); + case NumericalNodeType::Float: + { + return FloatNode( imf_, 0.0, PrecisionSingle, angleMin, angleMax ); + } + + case NumericalNodeType::Double: + { + return FloatNode( imf_, 0.0, PrecisionDouble, angleMin, angleMax ); + } + } }; if ( data3DHeader.pointFields.sphericalAzimuthField ) @@ -792,26 +842,49 @@ namespace e57 const double intensityMin = data3DHeader.intensityLimits.intensityMinimum; const double intensityMax = data3DHeader.intensityLimits.intensityMaximum; - if ( data3DHeader.pointFields.intensityScaledInteger > 0.0 ) + switch ( data3DHeader.pointFields.intensityNodeType ) { - const double scale = data3DHeader.pointFields.intensityScaledInteger; - const double offset = 0.0; // could be data3DHeader.intensityLimits.intensityMinimum; + case NumericalNodeType::Integer: + { + proto.set( "intensity", IntegerNode( imf_, 0, static_cast( intensityMin ), + static_cast( intensityMax ) ) ); - const auto rawIntegerMaximum = static_cast( std::floor( ( intensityMax - offset ) / scale + .5 ) ); - const auto rawIntegerMinimum = static_cast( std::floor( ( intensityMin - offset ) / scale + .5 ) ); + break; + } - proto.set( "intensity", ScaledIntegerNode( imf_, 0, rawIntegerMinimum, rawIntegerMaximum, scale, offset ) ); - } - else if ( data3DHeader.pointFields.intensityScaledInteger == E57_NOT_SCALED_USE_FLOAT ) - { - proto.set( "intensity", - FloatNode( imf_, 0.0, PrecisionSingle, data3DHeader.intensityLimits.intensityMinimum, - data3DHeader.intensityLimits.intensityMaximum ) ); - } - else - { - proto.set( "intensity", IntegerNode( imf_, 0, static_cast( intensityMin ), - static_cast( intensityMax ) ) ); + case NumericalNodeType::ScaledInteger: + { + const double scale = data3DHeader.pointFields.intensityScale; + const double offset = 0.0; // could be data3DHeader.intensityLimits.intensityMinimum; + + const auto rawIntegerMaximum = + static_cast( std::floor( ( intensityMax - offset ) / scale + .5 ) ); + const auto rawIntegerMinimum = + static_cast( std::floor( ( intensityMin - offset ) / scale + .5 ) ); + + proto.set( "intensity", + ScaledIntegerNode( imf_, 0, rawIntegerMinimum, rawIntegerMaximum, scale, offset ) ); + + break; + } + + case NumericalNodeType::Float: + { + proto.set( "intensity", + FloatNode( imf_, 0.0, PrecisionSingle, data3DHeader.intensityLimits.intensityMinimum, + data3DHeader.intensityLimits.intensityMaximum ) ); + + break; + } + + case NumericalNodeType::Double: + { + proto.set( "intensity", + FloatNode( imf_, 0.0, PrecisionDouble, data3DHeader.intensityLimits.intensityMinimum, + data3DHeader.intensityLimits.intensityMaximum ) ); + + break; + } } } @@ -856,32 +929,42 @@ namespace e57 const double timeMinimum = data3DHeader.pointFields.timeMinimum; const double timeMaximum = data3DHeader.pointFields.timeMaximum; - if ( data3DHeader.pointFields.timeScaledInteger > 0.0 ) + switch ( data3DHeader.pointFields.timeNodeType ) { - const double scale = data3DHeader.pointFields.timeScaledInteger; - const double offset = 0.0; + case NumericalNodeType::Integer: + { + proto.set( "timeStamp", IntegerNode( imf_, 0, static_cast( timeMinimum ), + static_cast( timeMaximum ) ) ); + break; + } - const auto rawIntegerMinimum = static_cast( std::floor( ( timeMinimum - offset ) / scale + .5 ) ); - const auto rawIntegerMaximum = static_cast( std::floor( ( timeMaximum - offset ) / scale + .5 ) ); + case NumericalNodeType::ScaledInteger: + { + const double scale = data3DHeader.pointFields.timeScale; + const double offset = 0.0; - proto.set( "timeStamp", ScaledIntegerNode( imf_, 0, rawIntegerMinimum, rawIntegerMaximum, scale, offset ) ); - } - else if ( data3DHeader.pointFields.timeScaledInteger == E57_NOT_SCALED_USE_FLOAT ) - { - if ( data3DHeader.pointFields.timeMaximum == FLOAT_MAX ) + const auto rawIntegerMinimum = + static_cast( std::floor( ( timeMinimum - offset ) / scale + .5 ) ); + const auto rawIntegerMaximum = + static_cast( std::floor( ( timeMaximum - offset ) / scale + .5 ) ); + + proto.set( "timeStamp", + ScaledIntegerNode( imf_, 0, rawIntegerMinimum, rawIntegerMaximum, scale, offset ) ); + break; + } + + case NumericalNodeType::Float: { proto.set( "timeStamp", FloatNode( imf_, 0.0, PrecisionSingle, FLOAT_MIN, FLOAT_MAX ) ); + break; } - else if ( data3DHeader.pointFields.timeMaximum == DOUBLE_MAX ) + + case NumericalNodeType::Double: { proto.set( "timeStamp", FloatNode( imf_, 0.0, PrecisionDouble, DOUBLE_MIN, DOUBLE_MAX ) ); + break; } } - else - { - proto.set( "timeStamp", IntegerNode( imf_, 0, static_cast( timeMinimum ), - static_cast( timeMaximum ) ) ); - } } if ( data3DHeader.pointFields.cartesianInvalidStateField ) diff --git a/test/src/test_SimpleData.cpp b/test/src/test_SimpleData.cpp index b95f010..50976b3 100644 --- a/test/src/test_SimpleData.cpp +++ b/test/src/test_SimpleData.cpp @@ -10,13 +10,47 @@ #include "Helpers.h" #include "TestData.h" -TEST( SimpleDataHeader, InvalidPointSize ) +TEST( SimpleDataHeader, InvalidPointCount ) { e57::Data3D dataHeader; E57_ASSERT_THROW( e57::Data3DPointsData pointsData( dataHeader ) ); } +TEST( SimpleDataHeader, InvalidPointRangeNodeType ) +{ + e57::Data3D dataHeader; + + dataHeader.pointCount = 1; + dataHeader.pointFields.pointRangeNodeType = e57::NumericalNodeType::Integer; + + E57_ASSERT_THROW( e57::Data3DPointsData pointsData( dataHeader ) ); +} + +TEST( SimpleDataHeader, InvalidAngleNodeType ) +{ + e57::Data3D dataHeader; + + dataHeader.pointCount = 1; + dataHeader.pointFields.angleNodeType = e57::NumericalNodeType::Integer; + + E57_ASSERT_THROW( e57::Data3DPointsData pointsData( dataHeader ) ); +} + +TEST( SimpleDataHeader, AutoSetNodeTypes ) +{ + e57::Data3D dataHeader; + + dataHeader.pointCount = 1; + + // dataHeader.pointFields.pointRangeNodeType and dataHeader.pointFields.angleNodeType default to Float but we are + // using a double structure. The constructor should correct these and set them to Double. + e57::Data3DPointsData_d pointsData( dataHeader ); + + EXPECT_EQ( dataHeader.pointFields.pointRangeNodeType, e57::NumericalNodeType::Double ); + EXPECT_EQ( dataHeader.pointFields.angleNodeType, e57::NumericalNodeType::Double ); +} + TEST( SimpleDataHeader, HeaderMinMaxFloat ) { e57::Data3D dataHeader; @@ -155,12 +189,13 @@ TEST( SimpleData, ReadWrite ) 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.pointRangeNodeType, copyData3DHeader.pointFields.pointRangeNodeType ); + EXPECT_EQ( originalData3DHeader.pointFields.pointRangeScale, copyData3DHeader.pointFields.pointRangeScale ); 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.angleScale, copyData3DHeader.pointFields.angleScale ); EXPECT_EQ( originalData3DHeader.pointFields.rowIndexField, copyData3DHeader.pointFields.rowIndexField ); EXPECT_EQ( originalData3DHeader.pointFields.rowIndexMaximum, copyData3DHeader.pointFields.rowIndexMaximum ); @@ -181,8 +216,7 @@ TEST( SimpleData, ReadWrite ) 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.intensityScale, copyData3DHeader.pointFields.intensityScale ); EXPECT_EQ( originalData3DHeader.pointFields.colorRedField, copyData3DHeader.pointFields.colorRedField ); EXPECT_EQ( originalData3DHeader.pointFields.colorGreenField, copyData3DHeader.pointFields.colorGreenField ); diff --git a/test/src/test_SimpleWriter.cpp b/test/src/test_SimpleWriter.cpp index de0e0cc..03cae27 100644 --- a/test/src/test_SimpleWriter.cpp +++ b/test/src/test_SimpleWriter.cpp @@ -162,9 +162,6 @@ TEST( SimpleWriter, ColouredCubeDouble ) header.description = "libE57Format test: cube of coloured points using doubles"; header.pointCount = cNumPoints; - // setting this to < 0.0 indicates we want to write doubles - header.pointFields.pointRangeScaledInteger = -1.0; - setUsingColouredCartesianPoints( header ); e57::Data3DPointsData_d pointsData( header ); @@ -275,8 +272,8 @@ TEST( SimpleWriter, ColouredCubeScaledInt ) header.description = "libE57Format test: cube of coloured points using scaled integers"; header.pointCount = cNumPoints; - // setting this to > 0.0 indicates we want to write scaled ints and to use this as the scale - header.pointFields.pointRangeScaledInteger = 0.001; + header.pointFields.pointRangeNodeType = e57::NumericalNodeType::ScaledInteger; + header.pointFields.pointRangeScale = 0.001; setUsingColouredCartesianPoints( header ); @@ -462,11 +459,14 @@ TEST( SimpleWriter, MinMaxIssuesCartesianFloat ) header.pointFields.cartesianZField = true; // Using any of these without setting their min/max explicitly should not fail - header.pointFields.pointRangeScaledInteger = 0.1; + header.pointFields.pointRangeNodeType = e57::NumericalNodeType::ScaledInteger; + header.pointFields.pointRangeScale = 0.1; header.pointFields.timeStampField = true; - header.pointFields.timeScaledInteger = 0.1; + header.pointFields.timeNodeType = e57::NumericalNodeType::ScaledInteger; + header.pointFields.timeScale = 0.1; header.pointFields.intensityField = true; - header.pointFields.intensityScaledInteger = 0.1; + header.pointFields.intensityNodeType = e57::NumericalNodeType::ScaledInteger; + header.pointFields.intensityScale = 0.1; e57::Data3DPointsData pointsData( header ); @@ -521,11 +521,14 @@ TEST( SimpleWriter, MinMaxIssuesSpericalDouble ) header.pointFields.sphericalElevationField = true; // Using any of these without setting their min/max explicitly should not fail - header.pointFields.pointRangeScaledInteger = 0.1; + header.pointFields.pointRangeNodeType = e57::NumericalNodeType::ScaledInteger; + header.pointFields.pointRangeScale = 0.1; header.pointFields.timeStampField = true; - header.pointFields.timeScaledInteger = 0.1; + header.pointFields.timeNodeType = e57::NumericalNodeType::ScaledInteger; + header.pointFields.timeScale = 0.1; header.pointFields.intensityField = true; - header.pointFields.intensityScaledInteger = 0.1; + header.pointFields.intensityNodeType = e57::NumericalNodeType::ScaledInteger; + header.pointFields.intensityScale = 0.1; e57::Data3DPointsData_d pointsData( header );