diff --git a/common/include/pcl/common/point_tests.h b/common/include/pcl/common/point_tests.h index 54d038934dc..bcf2631d368 100644 --- a/common/include/pcl/common/point_tests.h +++ b/common/include/pcl/common/point_tests.h @@ -63,29 +63,30 @@ namespace pcl } #endif - template<> inline bool isFinite (const pcl::RGB&) { return (true); } - template<> inline bool isFinite (const pcl::Label&) { return (true); } - template<> inline bool isFinite (const pcl::Axis&) { return (true); } - template<> inline bool isFinite (const pcl::Intensity&) { return (true); } - template<> inline bool isFinite (const pcl::MomentInvariants&) { return (true); } - template<> inline bool isFinite (const pcl::PrincipalRadiiRSD&) { return (true); } - template<> inline bool isFinite (const pcl::Boundary&) { return (true); } - template<> inline bool isFinite (const pcl::PrincipalCurvatures&) { return (true); } - template<> inline bool isFinite (const pcl::SHOT352&) { return (true); } - template<> inline bool isFinite (const pcl::SHOT1344&) { return (true); } - template<> inline bool isFinite (const pcl::ReferenceFrame&) { return (true); } - template<> inline bool isFinite (const pcl::ShapeContext1980&) { return (true); } - template<> inline bool isFinite (const pcl::UniqueShapeContext1960&) { return (true); } - template<> inline bool isFinite (const pcl::PFHSignature125&) { return (true); } - template<> inline bool isFinite (const pcl::PFHRGBSignature250&) { return (true); } - template<> inline bool isFinite (const pcl::PPFSignature&) { return (true); } - template<> inline bool isFinite (const pcl::PPFRGBSignature&) { return (true); } - template<> inline bool isFinite (const pcl::NormalBasedSignature12&) { return (true); } - template<> inline bool isFinite (const pcl::FPFHSignature33&) { return (true); } - template<> inline bool isFinite (const pcl::VFHSignature308&) { return (true); } - template<> inline bool isFinite (const pcl::ESFSignature640&) { return (true); } - template<> inline bool isFinite (const pcl::IntensityGradient&) { return (true); } - template<> inline bool isFinite (const pcl::BRISKSignature512&) { return (true); } + template<> inline bool isFinite(const pcl::Axis&) { return (true); } + template<> inline bool isFinite(const pcl::BRISKSignature512&) { return (true); } + template<> inline bool isFinite(const pcl::BorderDescription &p) { return true; } + template<> inline bool isFinite(const pcl::Boundary&) { return (true); } + template<> inline bool isFinite(const pcl::ESFSignature640&) { return (true); } + template<> inline bool isFinite(const pcl::FPFHSignature33&) { return (true); } + template<> inline bool isFinite(const pcl::Intensity&) { return (true); } + template<> inline bool isFinite(const pcl::IntensityGradient&) { return (true); } + template<> inline bool isFinite(const pcl::Label&) { return (true); } + template<> inline bool isFinite(const pcl::MomentInvariants&) { return (true); } + template<> inline bool isFinite(const pcl::NormalBasedSignature12&) { return (true); } + template<> inline bool isFinite(const pcl::PFHRGBSignature250&) { return (true); } + template<> inline bool isFinite(const pcl::PFHSignature125&) { return (true); } + template<> inline bool isFinite(const pcl::PPFRGBSignature&) { return (true); } + template<> inline bool isFinite(const pcl::PPFSignature&) { return (true); } + template<> inline bool isFinite(const pcl::PrincipalCurvatures&) { return (true); } + template<> inline bool isFinite(const pcl::PrincipalRadiiRSD&) { return (true); } + template<> inline bool isFinite(const pcl::RGB&) { return (true); } + template<> inline bool isFinite(const pcl::ReferenceFrame&) { return (true); } + template<> inline bool isFinite(const pcl::SHOT1344&) { return (true); } + template<> inline bool isFinite(const pcl::SHOT352&) { return (true); } + template<> inline bool isFinite(const pcl::ShapeContext1980&) { return (true); } + template<> inline bool isFinite(const pcl::UniqueShapeContext1960&) { return (true); } + template<> inline bool isFinite(const pcl::VFHSignature308&) { return (true); } // specification for pcl::PointXY template <> inline bool @@ -94,13 +95,6 @@ namespace pcl return (std::isfinite (p.x) && std::isfinite (p.y)); } - // specification for pcl::BorderDescription - template <> inline bool - isFinite (const pcl::BorderDescription &p) - { - return (std::isfinite (p.x) && std::isfinite (p.y)); - } - // specification for pcl::Normal template <> inline bool isFinite (const pcl::Normal &n) diff --git a/io/include/pcl/io/file_io.h b/io/include/pcl/io/file_io.h index 0f3c15fe1c1..451801317d2 100644 --- a/io/include/pcl/io/file_io.h +++ b/io/include/pcl/io/file_io.h @@ -231,7 +231,8 @@ namespace pcl * \param[in] fields_count the current fields count * \param[out] stream the ostringstream to copy into */ - template inline void + template inline + std::enable_if_t::value> copyValueString (const pcl::PCLPointCloud2 &cloud, const unsigned int point_index, const int point_size, @@ -244,8 +245,23 @@ namespace pcl if (std::isnan (value)) stream << "nan"; else - stream << boost::numeric_cast(value); + stream << value; } + + template inline + std::enable_if_t::value> + copyValueString (const pcl::PCLPointCloud2 &cloud, + const unsigned int point_index, + const int point_size, + const unsigned int field_idx, + const unsigned int fields_count, + std::ostream &stream) + { + Type value; + memcpy (&value, &cloud.data[point_index * point_size + cloud.fields[field_idx].offset + fields_count * sizeof (Type)], sizeof (Type)); + stream << value; + } + template <> inline void copyValueString (const pcl::PCLPointCloud2 &cloud, const unsigned int point_index, @@ -256,27 +272,22 @@ namespace pcl { int8_t value; memcpy (&value, &cloud.data[point_index * point_size + cloud.fields[field_idx].offset + fields_count * sizeof (int8_t)], sizeof (int8_t)); - if (std::isnan (value)) - stream << "nan"; - else - // Numeric cast doesn't give us what we want for int8_t - stream << boost::numeric_cast(value); + //Cast to int to prevent value is handled as char + stream << boost::numeric_cast(value); } + template <> inline void copyValueString (const pcl::PCLPointCloud2 &cloud, - const unsigned int point_index, - const int point_size, - const unsigned int field_idx, - const unsigned int fields_count, - std::ostream &stream) + const unsigned int point_index, + const int point_size, + const unsigned int field_idx, + const unsigned int fields_count, + std::ostream &stream) { uint8_t value; memcpy (&value, &cloud.data[point_index * point_size + cloud.fields[field_idx].offset + fields_count * sizeof (uint8_t)], sizeof (uint8_t)); - if (std::isnan (value)) - stream << "nan"; - else - // Numeric cast doesn't give us what we want for uint8_t - stream << boost::numeric_cast(value); + //Cast to unsigned int to prevent value is handled as char + stream << boost::numeric_cast(value); } /** \brief Check whether a given value of type Type (uchar, char, uint, int, float, double, ...) is finite or not @@ -289,7 +300,8 @@ namespace pcl * * \return true if the value is finite, false otherwise */ - template inline bool + template inline + std::enable_if_t::value, bool> isValueFinite (const pcl::PCLPointCloud2 &cloud, const unsigned int point_index, const int point_size, @@ -298,9 +310,18 @@ namespace pcl { Type value; memcpy (&value, &cloud.data[point_index * point_size + cloud.fields[field_idx].offset + fields_count * sizeof (Type)], sizeof (Type)); - if (!std::isfinite (value)) - return (false); - return (true); + return std::isfinite (value); + } + + template inline + std::enable_if_t::value, bool> + isValueFinite (const pcl::PCLPointCloud2 &cloud, + const unsigned int point_index, + const int point_size, + const unsigned int field_idx, + const unsigned int fields_count) + { + return true; } /** \brief Copy one single value of type T (uchar, char, uint, int, float, double, ...) from a string diff --git a/io/include/pcl/io/impl/pcd_io.hpp b/io/include/pcl/io/impl/pcd_io.hpp index 2af72b00772..c9c95072300 100644 --- a/io/include/pcl/io/impl/pcd_io.hpp +++ b/io/include/pcl/io/impl/pcd_io.hpp @@ -494,60 +494,42 @@ pcl::PCDWriter::writeASCII (const std::string &file_name, const pcl::PointCloud< { int8_t value; memcpy (&value, reinterpret_cast (&cloud.points[i]) + fields[d].offset + c * sizeof (int8_t), sizeof (int8_t)); - if (std::isnan (value)) - stream << "nan"; - else - stream << boost::numeric_cast(value); + stream << boost::numeric_cast(value); break; } case pcl::PCLPointField::UINT8: { uint8_t value; memcpy (&value, reinterpret_cast (&cloud.points[i]) + fields[d].offset + c * sizeof (uint8_t), sizeof (uint8_t)); - if (std::isnan (value)) - stream << "nan"; - else - stream << boost::numeric_cast(value); + stream << boost::numeric_cast(value); break; } case pcl::PCLPointField::INT16: { int16_t value; memcpy (&value, reinterpret_cast (&cloud.points[i]) + fields[d].offset + c * sizeof (int16_t), sizeof (int16_t)); - if (std::isnan (value)) - stream << "nan"; - else - stream << boost::numeric_cast(value); + stream << boost::numeric_cast(value); break; } case pcl::PCLPointField::UINT16: { uint16_t value; memcpy (&value, reinterpret_cast (&cloud.points[i]) + fields[d].offset + c * sizeof (uint16_t), sizeof (uint16_t)); - if (std::isnan (value)) - stream << "nan"; - else - stream << boost::numeric_cast(value); + stream << boost::numeric_cast(value); break; } case pcl::PCLPointField::INT32: { int32_t value; memcpy (&value, reinterpret_cast (&cloud.points[i]) + fields[d].offset + c * sizeof (int32_t), sizeof (int32_t)); - if (std::isnan (value)) - stream << "nan"; - else - stream << boost::numeric_cast(value); + stream << boost::numeric_cast(value); break; } case pcl::PCLPointField::UINT32: { uint32_t value; memcpy (&value, reinterpret_cast (&cloud.points[i]) + fields[d].offset + c * sizeof (uint32_t), sizeof (uint32_t)); - if (std::isnan (value)) - stream << "nan"; - else - stream << boost::numeric_cast(value); + stream << boost::numeric_cast(value); break; } case pcl::PCLPointField::FLOAT32: @@ -561,10 +543,7 @@ pcl::PCDWriter::writeASCII (const std::string &file_name, const pcl::PointCloud< { uint32_t value; memcpy (&value, reinterpret_cast (&cloud.points[i]) + fields[d].offset + c * sizeof (float), sizeof (float)); - if (std::isnan (value)) - stream << "nan"; - else - stream << boost::numeric_cast(value); + stream << boost::numeric_cast(value); break; } else @@ -803,60 +782,42 @@ pcl::PCDWriter::writeASCII (const std::string &file_name, { int8_t value; memcpy (&value, reinterpret_cast (&cloud.points[indices[i]]) + fields[d].offset + c * sizeof (int8_t), sizeof (int8_t)); - if (std::isnan (value)) - stream << "nan"; - else - stream << boost::numeric_cast(value); + stream << boost::numeric_cast(value); break; } case pcl::PCLPointField::UINT8: { uint8_t value; memcpy (&value, reinterpret_cast (&cloud.points[indices[i]]) + fields[d].offset + c * sizeof (uint8_t), sizeof (uint8_t)); - if (std::isnan (value)) - stream << "nan"; - else - stream << boost::numeric_cast(value); + stream << boost::numeric_cast(value); break; } case pcl::PCLPointField::INT16: { int16_t value; memcpy (&value, reinterpret_cast (&cloud.points[indices[i]]) + fields[d].offset + c * sizeof (int16_t), sizeof (int16_t)); - if (std::isnan (value)) - stream << "nan"; - else - stream << boost::numeric_cast(value); + stream << boost::numeric_cast(value); break; } case pcl::PCLPointField::UINT16: { uint16_t value; memcpy (&value, reinterpret_cast (&cloud.points[indices[i]]) + fields[d].offset + c * sizeof (uint16_t), sizeof (uint16_t)); - if (std::isnan (value)) - stream << "nan"; - else - stream << boost::numeric_cast(value); + stream << boost::numeric_cast(value); break; } case pcl::PCLPointField::INT32: { int32_t value; memcpy (&value, reinterpret_cast (&cloud.points[indices[i]]) + fields[d].offset + c * sizeof (int32_t), sizeof (int32_t)); - if (std::isnan (value)) - stream << "nan"; - else - stream << boost::numeric_cast(value); + stream << boost::numeric_cast(value); break; } case pcl::PCLPointField::UINT32: { uint32_t value; memcpy (&value, reinterpret_cast (&cloud.points[indices[i]]) + fields[d].offset + c * sizeof (uint32_t), sizeof (uint32_t)); - if (std::isnan (value)) - stream << "nan"; - else - stream << boost::numeric_cast(value); + stream << boost::numeric_cast(value); break; } case pcl::PCLPointField::FLOAT32: @@ -870,10 +831,7 @@ pcl::PCDWriter::writeASCII (const std::string &file_name, { uint32_t value; memcpy (&value, reinterpret_cast (&cloud.points[indices[i]]) + fields[d].offset + c * sizeof (float), sizeof (float)); - if (std::isnan (value)) - stream << "nan"; - else - stream << boost::numeric_cast(value); + stream << boost::numeric_cast(value); } else { diff --git a/io/src/ply_io.cpp b/io/src/ply_io.cpp index 0461bb7fdef..a540b7e2f19 100644 --- a/io/src/ply_io.cpp +++ b/io/src/ply_io.cpp @@ -264,11 +264,25 @@ namespace pcl return (0); } + template inline + std::enable_if_t::value> + unsetDenseFlagIfNotFinite(T value, PCLPointCloud2& cloud) + { + if (!std::isfinite(value)) + cloud.is_dense = false; + } + + template inline + std::enable_if_t::value> + unsetDenseFlagIfNotFinite(T value, PCLPointCloud2& cloud) + { + } + template void PLYReader::vertexScalarPropertyCallback (Scalar value) { - if (!std::isfinite (value)) - cloud_->is_dense = false; + //MSVC is missing bool std::isfinite(IntegralType arg); variant, so we implement an own template specialization for this + unsetDenseFlagIfNotFinite(value, cloud_); memcpy (&cloud_->data[vertex_count_ * cloud_->point_step + vertex_offset_before_], &value, @@ -294,7 +308,8 @@ namespace pcl template void PLYReader::vertexListPropertyContentCallback (ContentType value) { - if (!std::isfinite (value)) + //MSVC is missing bool std::isfinite(IntegralType arg); variant, so we need to cast ourself to double + if (!std::isfinite (static_cast(value))) cloud_->is_dense = false; memcpy (&cloud_->data[vertex_count_ * cloud_->point_step + vertex_offset_before_], diff --git a/test/io/test_buffers.cpp b/test/io/test_buffers.cpp index fce0c98e01d..0637efa68d7 100644 --- a/test/io/test_buffers.cpp +++ b/test/io/test_buffers.cpp @@ -68,8 +68,9 @@ class BuffersTest : public ::testing::Test memcpy (d.data (), dptr, buffer.size () * sizeof (T)); buffer.push (d); for (size_t j = 0; j < buffer.size (); ++j) - if (std::isnan (eptr[j])) - EXPECT_TRUE (std::isnan (buffer[j])); + //MSVC is missing bool std::isnan(IntegralType arg); variant, so we need to cast ourself to double + if (std::isnan (static_cast(eptr[j]))) + EXPECT_TRUE (std::isnan (static_cast(buffer[j]))); else EXPECT_EQ (eptr[j], buffer[j]); dptr += buffer.size ();