From 4795c1d21f23925ef8aa8b0c00f8168fb61a876e Mon Sep 17 00:00:00 2001 From: Christopher Lee Date: Wed, 7 Sep 2022 12:24:12 -0600 Subject: [PATCH 01/15] Store points as doubles internally --- cpp/include/copc-lib/las/point.hpp | 31 +++++++++++++++--------------- cpp/include/copc-lib/utils.hpp | 15 +++++++++++++++ cpp/src/las/point.cpp | 25 +++++++++++++----------- 3 files changed, 45 insertions(+), 26 deletions(-) create mode 100644 cpp/include/copc-lib/utils.hpp diff --git a/cpp/include/copc-lib/las/point.hpp b/cpp/include/copc-lib/las/point.hpp index 740e3e32..00d68ace 100644 --- a/cpp/include/copc-lib/las/point.hpp +++ b/cpp/include/copc-lib/las/point.hpp @@ -22,24 +22,25 @@ class Point #pragma region XYZ // XYZ Scaled - double X() const { return ApplyScale(x_, scale_.x, offset_.x); } - void X(const double &x) { x_ = RemoveScale(x, scale_.x, offset_.x); } + double X() const { return x_scaled_; } + void X(const double &x) { x_scaled_ = x; } - double Y() const { return ApplyScale(y_, scale_.y, offset_.y); } - void Y(const double &y) { y_ = RemoveScale(y, scale_.y, offset_.y); } + double Y() const { return y_scaled_; } + void Y(const double &y) { y_scaled_ = y; } - double Z() const { return ApplyScale(z_, scale_.z, offset_.z); } - void Z(const double &z) { z_ = RemoveScale(z, scale_.z, offset_.z); } + double Z() const { return z_scaled_; } + void Z(const double &z) { z_scaled_ = z; } // XYZ Unscaled - int32_t UnscaledX() const { return x_; } - void UnscaledX(const int32_t &x) { x_ = x; } + int32_t UnscaledX() const { return RemoveScale(x_scaled_, scale_.x, offset_.x); } + void UnscaledX(const int32_t &x) { x_scaled_ = ApplyScale(x, scale_.x, offset_.x); } - int32_t UnscaledY() const { return y_; } - void UnscaledY(const int32_t &y) { y_ = y; } + int32_t UnscaledY() const { return RemoveScale(y_scaled_, scale_.y, offset_.y); } + void UnscaledY(const int32_t &y) { y_scaled_ = ApplyScale(y, scale_.y, offset_.y); } - int32_t UnscaledZ() const { return z_; } - void UnscaledZ(const int32_t &z) { z_ = z; } + int32_t UnscaledZ() const { return RemoveScale(z_scaled_, scale_.z, offset_.z); } + void UnscaledZ(const int32_t &z) { z_scaled_ = ApplyScale(z, scale_.z, offset_.z); } + #pragma endregion XYZ uint16_t Intensity() const { return intensity_; } @@ -235,9 +236,9 @@ class Point void ToPointFormat(const int8_t &point_format_id); protected: - int32_t x_{}; - int32_t y_{}; - int32_t z_{}; + double x_scaled_{}; + double y_scaled_{}; + double z_scaled_{}; uint16_t intensity_{}; uint8_t returns_{}; uint8_t flags_{}; diff --git a/cpp/include/copc-lib/utils.hpp b/cpp/include/copc-lib/utils.hpp new file mode 100644 index 00000000..5c57d140 --- /dev/null +++ b/cpp/include/copc-lib/utils.hpp @@ -0,0 +1,15 @@ +#ifndef COPCLIB_UTILS_H_ +#define COPCLIB_UTILS_H_ + +#include + +namespace copc +{ + +bool AreClose(double a, double b, double epsilon) +{ + return fabs(a - b) < epsilon; +} + +} // namespace copc +#endif // COPCLIB_UTILS_H_ diff --git a/cpp/src/las/point.cpp b/cpp/src/las/point.cpp index 2ac7c29b..3e07cc7d 100644 --- a/cpp/src/las/point.cpp +++ b/cpp/src/las/point.cpp @@ -1,4 +1,5 @@ #include "copc-lib/las/point.hpp" +#include "copc-lib/utils.hpp" namespace copc::las { @@ -23,9 +24,9 @@ Point::Point(const LasHeader &header) Point::Point(const Point &other) : Point(other.point_format_id_, other.Scale(), other.Offset(), other.EbByteSize()) { - x_ = other.x_; - y_ = other.y_; - z_ = other.z_; + x_scaled_ = other.x_scaled_; + y_scaled_ = other.y_scaled_; + z_scaled_ = other.z_scaled_; intensity_ = other.intensity_; returns_ = other.returns_; flags_ = other.flags_; @@ -56,7 +57,9 @@ bool Point::operator==(const Point &other) const { if (point_format_id_ != other.point_format_id_ || point_record_length_ != other.point_record_length_) return false; - if (x_ != other.UnscaledX() || y_ != other.UnscaledY() || z_ != other.UnscaledZ() || + if (AreClose(X(), other.X(), std::max(scale_.x, other.scale_.x)) + || AreClose(Y(), other.Y(), std::max(scale_.y, other.scale_.y)) + || AreClose(Z(), other.Z(), std::max(scale_.z, other.scale_.z)) || intensity_ != other.Intensity()) return false; if (returns_ != other.ReturnsBitField()) @@ -85,9 +88,9 @@ std::shared_ptr Point::Unpack(std::istream &in_stream, const int8_t &poin { std::shared_ptr p = std::make_shared(point_format_id, scale, offset, eb_byte_size); - p->x_ = unpack(in_stream); - p->y_ = unpack(in_stream); - p->z_ = unpack(in_stream); + p->UnscaledX(unpack(in_stream)); + p->UnscaledY(unpack(in_stream)); + p->UnscaledZ(unpack(in_stream)); p->intensity_ = unpack(in_stream); p->returns_ = unpack(in_stream); p->flags_ = unpack(in_stream); @@ -117,9 +120,9 @@ std::shared_ptr Point::Unpack(std::istream &in_stream, const int8_t &poin void Point::Pack(std::ostream &out_stream) const { // Point - pack(x_, out_stream); - pack(y_, out_stream); - pack(z_, out_stream); + pack(UnscaledX(), out_stream); + pack(UnscaledY(), out_stream); + pack(UnscaledZ(), out_stream); pack(intensity_, out_stream); pack(returns_, out_stream); pack(flags_, out_stream); @@ -157,7 +160,7 @@ std::string Point::ToString() const { std::stringstream ss; ss << "Point: " << std::endl; - ss << "\tX: " << x_ << ", Y: " << y_ << ", Z: " << z_ << std::endl; + ss << "\tX: " << x_scaled_ << ", Y: " << y_scaled_ << ", Z: " << z_scaled_ << std::endl; ss << "\tIntensity: " << intensity_ << std::endl; ss << "\tReturn Number: " << static_cast(ReturnNumber()) << ", Number of Returns: " << static_cast(NumberOfReturns()) << std::endl; From 76926d7139fca06e8bb5f65b23ebacc3d237f1b0 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Wed, 7 Sep 2022 18:24:36 +0000 Subject: [PATCH 02/15] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- cpp/include/copc-lib/las/point.hpp | 2 +- cpp/include/copc-lib/utils.hpp | 5 +---- cpp/src/las/point.cpp | 7 +++---- 3 files changed, 5 insertions(+), 9 deletions(-) diff --git a/cpp/include/copc-lib/las/point.hpp b/cpp/include/copc-lib/las/point.hpp index 00d68ace..f334dd9a 100644 --- a/cpp/include/copc-lib/las/point.hpp +++ b/cpp/include/copc-lib/las/point.hpp @@ -40,7 +40,7 @@ class Point int32_t UnscaledZ() const { return RemoveScale(z_scaled_, scale_.z, offset_.z); } void UnscaledZ(const int32_t &z) { z_scaled_ = ApplyScale(z, scale_.z, offset_.z); } - + #pragma endregion XYZ uint16_t Intensity() const { return intensity_; } diff --git a/cpp/include/copc-lib/utils.hpp b/cpp/include/copc-lib/utils.hpp index 5c57d140..3d011456 100644 --- a/cpp/include/copc-lib/utils.hpp +++ b/cpp/include/copc-lib/utils.hpp @@ -6,10 +6,7 @@ namespace copc { -bool AreClose(double a, double b, double epsilon) -{ - return fabs(a - b) < epsilon; -} +bool AreClose(double a, double b, double epsilon) { return fabs(a - b) < epsilon; } } // namespace copc #endif // COPCLIB_UTILS_H_ diff --git a/cpp/src/las/point.cpp b/cpp/src/las/point.cpp index 3e07cc7d..dbf15252 100644 --- a/cpp/src/las/point.cpp +++ b/cpp/src/las/point.cpp @@ -57,10 +57,9 @@ bool Point::operator==(const Point &other) const { if (point_format_id_ != other.point_format_id_ || point_record_length_ != other.point_record_length_) return false; - if (AreClose(X(), other.X(), std::max(scale_.x, other.scale_.x)) - || AreClose(Y(), other.Y(), std::max(scale_.y, other.scale_.y)) - || AreClose(Z(), other.Z(), std::max(scale_.z, other.scale_.z)) || - intensity_ != other.Intensity()) + if (AreClose(X(), other.X(), std::max(scale_.x, other.scale_.x)) || + AreClose(Y(), other.Y(), std::max(scale_.y, other.scale_.y)) || + AreClose(Z(), other.Z(), std::max(scale_.z, other.scale_.z)) || intensity_ != other.Intensity()) return false; if (returns_ != other.ReturnsBitField()) return false; From 325a18ac387e1146d8d7f00767da0fe33df4c488 Mon Sep 17 00:00:00 2001 From: Christopher Lee Date: Wed, 7 Sep 2022 14:43:59 -0600 Subject: [PATCH 03/15] Fix equality typo --- cpp/src/las/point.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/cpp/src/las/point.cpp b/cpp/src/las/point.cpp index dbf15252..578ebd38 100644 --- a/cpp/src/las/point.cpp +++ b/cpp/src/las/point.cpp @@ -57,9 +57,9 @@ bool Point::operator==(const Point &other) const { if (point_format_id_ != other.point_format_id_ || point_record_length_ != other.point_record_length_) return false; - if (AreClose(X(), other.X(), std::max(scale_.x, other.scale_.x)) || - AreClose(Y(), other.Y(), std::max(scale_.y, other.scale_.y)) || - AreClose(Z(), other.Z(), std::max(scale_.z, other.scale_.z)) || intensity_ != other.Intensity()) + if (!AreClose(X(), other.X(), std::max(scale_.x, other.scale_.x)) || + !AreClose(Y(), other.Y(), std::max(scale_.y, other.scale_.y)) || + !AreClose(Z(), other.Z(), std::max(scale_.z, other.scale_.z)) || intensity_ != other.Intensity()) return false; if (returns_ != other.ReturnsBitField()) return false; From 97a531c13d42f586b4906443f1621d05dce5a429 Mon Sep 17 00:00:00 2001 From: Christopher Lee Date: Wed, 7 Sep 2022 14:53:58 -0600 Subject: [PATCH 04/15] update tests --- test/point_test.cpp | 59 +++++++++++++++++++++++++++------------------ test/point_test.py | 19 ++++++++++++--- 2 files changed, 52 insertions(+), 26 deletions(-) diff --git a/test/point_test.cpp b/test/point_test.cpp index 969557eb..96682924 100644 --- a/test/point_test.cpp +++ b/test/point_test.cpp @@ -5,6 +5,7 @@ #include #include #include +#include using namespace copc::las; using namespace std; @@ -496,29 +497,36 @@ TEST_CASE("Point tests", "[Point]") { copc::Vector3 scale = {1, 1, 1}; copc::Vector3 offset = {50001.456, 4443.123, -255.001}; - auto point = Point(pfid, scale, offset); + auto points = Points(pfid, scale, offset); + auto point = points.CreatePoint(); - point.UnscaledX(0); - point.UnscaledY(-800); - point.UnscaledZ(3); + point->UnscaledX(0); + point->UnscaledY(-800); + point->UnscaledZ(3); - REQUIRE(point.X() == 0 + offset.x); - REQUIRE(point.Y() == -800 + offset.y); - REQUIRE(point.Z() == 3 + offset.z); + REQUIRE(point->X() == 0 + offset.x); + REQUIRE(point->Y() == -800 + offset.y); + REQUIRE(point->Z() == 3 + offset.z); - point.X(50502.888); - point.Y(4002.111); - point.Z(-80.5); + point->X(50502.888); + point->Y(4002.111); + point->Z(-80.5); // static_cast(std::round((value - offset) / scale)); - REQUIRE(point.UnscaledX() == 501); // 50502.888 - 50001.456 = 501.432 - REQUIRE(point.UnscaledY() == -441); - REQUIRE(point.UnscaledZ() == 175); // -80.5 - -255.001 = 255.001 - 80.5 = 175 - - // (value * scale) + offset - REQUIRE_THAT(point.X(), WithinAbs(50502.456, 0.000001)); - REQUIRE_THAT(point.Y(), WithinAbs(4002.123, 0.000001)); - REQUIRE_THAT(point.Z(), WithinAbs(-80.001, 0.000001)); + REQUIRE(point->UnscaledX() == 501); // 50502.888 - 50001.456 = 501.432 + REQUIRE(point->UnscaledY() == -441); + REQUIRE(point->UnscaledZ() == 175); // -80.5 - -255.001 = 255.001 - 80.5 = 175 + + REQUIRE_THAT(point->X(), WithinAbs(50502.888, 0.000001)); + REQUIRE_THAT(point->Y(), WithinAbs(4002.111, 0.000001)); + REQUIRE_THAT(point->Z(), WithinAbs(-80.5, 0.000001)); + points.AddPoint(point); + + // scale and offset only get updated after packing + point = Points::Unpack(points.Pack(), pfid, 0, scale, offset)[0]; + REQUIRE_THAT(point->X(), WithinAbs(50502.456, 0.000001)); + REQUIRE_THAT(point->Y(), WithinAbs(4002.123, 0.000001)); + REQUIRE_THAT(point->Z(), WithinAbs(-80.001, 0.000001)); } SECTION("Scale and Offset test") { @@ -549,13 +557,18 @@ TEST_CASE("Point tests", "[Point]") SECTION("Precision checks") { { - auto point = Point(pfid, {0.000001, 0.000001, 0.000001}, {0, 0, 0}); - - REQUIRE_THROWS(point.X(50501132.888123)); + auto points = Points(pfid, {0.000001, 0.000001, 0.000001}, {0, 0, 0}); + auto point = points.CreatePoint(); + point->X(50501132.888123); + points.AddPoint(point); + REQUIRE_THROWS(points.Pack()); } { - auto point = Point(pfid, {1, 1, 1}, {-8001100065, 0, 0}); - REQUIRE_THROWS(point.X(0)); + auto points = Points(pfid, {1, 1, 1}, {-8001100065, 0, 0}); + auto point = points.CreatePoint(); + point->X(0); + points.AddPoint(point); + REQUIRE_THROWS(points.Pack()); } } } diff --git a/test/point_test.py b/test/point_test.py index 28ab0ac1..abbfbf1c 100644 --- a/test/point_test.py +++ b/test/point_test.py @@ -434,7 +434,8 @@ def test_scaled_xyz(): scale = [1, 1, 1] offset = copc.Vector3([50001.456, 4443.123, -255.001]) - point = copc.Points(pfid, scale, offset).CreatePoint() + points = copc.Points(pfid, scale, offset) + point = points.CreatePoint() point.X = 0 point.Y = -800 @@ -452,7 +453,13 @@ def test_scaled_xyz(): assert point.Y == -441 assert point.Z == 175 # -80.5 - -255.001 = 255.001 - 80.5 = 175 - # (value * scale) + offset + assert point.x == pytest.approx(50502.888, 0.000001) + assert point.y == pytest.approx(4002.111, 0.000001) + assert point.z == pytest.approx(-80.5, 0.000001) + points.AddPoint(point) + + # scale and offset only get updated after packing + point = copc.Points.Unpack(points.Pack(), pfid, 0, scale, offset)[0] assert point.x == pytest.approx(50502.456, 0.000001) assert point.y == pytest.approx(4002.123, 0.000001) assert point.z == pytest.approx(-80.001, 0.000001) @@ -484,14 +491,20 @@ def test_scaled_xyz(): assert point.z == pytest.approx(-80.5, 0.000001) # Precision checks - point = copc.Points(pfid, [0.000001, 0.000001, 0.000001], [0, 0, 0]).CreatePoint() + points = copc.Points(pfid, [0.000001, 0.000001, 0.000001], [0, 0, 0]) + point = points.CreatePoint() with pytest.raises(RuntimeError): point.x = 50501132.888123 + points.AddPoint(point) + points.Pack() + point = copc.Points(pfid, [1, 1, 1], [-8001100065, 0, 0]).CreatePoint() with pytest.raises(RuntimeError): point.x = 0 + points.AddPoint(point) + points.Pack() def test_within(): From e86cbf324113526bd56cc0752f1e0df2ee5691d1 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Wed, 7 Sep 2022 20:54:42 +0000 Subject: [PATCH 05/15] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- test/point_test.py | 1 - 1 file changed, 1 deletion(-) diff --git a/test/point_test.py b/test/point_test.py index abbfbf1c..4d0d64e2 100644 --- a/test/point_test.py +++ b/test/point_test.py @@ -499,7 +499,6 @@ def test_scaled_xyz(): points.AddPoint(point) points.Pack() - point = copc.Points(pfid, [1, 1, 1], [-8001100065, 0, 0]).CreatePoint() with pytest.raises(RuntimeError): point.x = 0 From 91af2717323f1d5ff76c790152c710144cae4e11 Mon Sep 17 00:00:00 2001 From: Christopher Lee Date: Wed, 7 Sep 2022 17:32:23 -0600 Subject: [PATCH 06/15] Have scale and offset apply only at pack/unpack time --- cpp/include/copc-lib/las/point.hpp | 21 ++------- cpp/include/copc-lib/las/points.hpp | 66 ++++------------------------- cpp/src/io/copc_writer_public.cpp | 2 +- cpp/src/io/laz_writer.cpp | 2 +- cpp/src/las/point.cpp | 31 +++++++------- cpp/src/las/points.cpp | 28 +++++++----- python/bindings.cpp | 20 +++------ 7 files changed, 52 insertions(+), 118 deletions(-) diff --git a/cpp/include/copc-lib/las/point.hpp b/cpp/include/copc-lib/las/point.hpp index f334dd9a..c8aa1db6 100644 --- a/cpp/include/copc-lib/las/point.hpp +++ b/cpp/include/copc-lib/las/point.hpp @@ -13,8 +13,7 @@ namespace copc::las class Point { public: - Point(const int8_t &point_format_id, const Vector3 &scale = Vector3::DefaultScale(), - const Vector3 &offset = Vector3::DefaultOffset(), const uint16_t &eb_byte_size = 0); + Point(const int8_t &point_format_id, const uint16_t &eb_byte_size = 0); Point(const LasHeader &header); Point(const Point &other); @@ -31,16 +30,6 @@ class Point double Z() const { return z_scaled_; } void Z(const double &z) { z_scaled_ = z; } - // XYZ Unscaled - int32_t UnscaledX() const { return RemoveScale(x_scaled_, scale_.x, offset_.x); } - void UnscaledX(const int32_t &x) { x_scaled_ = ApplyScale(x, scale_.x, offset_.x); } - - int32_t UnscaledY() const { return RemoveScale(y_scaled_, scale_.y, offset_.y); } - void UnscaledY(const int32_t &y) { y_scaled_ = ApplyScale(y, scale_.y, offset_.y); } - - int32_t UnscaledZ() const { return RemoveScale(z_scaled_, scale_.z, offset_.z); } - void UnscaledZ(const int32_t &z) { z_scaled_ = ApplyScale(z, scale_.z, offset_.z); } - #pragma endregion XYZ uint16_t Intensity() const { return intensity_; } @@ -220,9 +209,6 @@ class Point int8_t PointFormatId() const { return point_format_id_; } uint16_t EbByteSize() const; - Vector3 Scale() const { return scale_; } - Vector3 Offset() const { return offset_; } - bool operator==(const Point &other) const; bool operator!=(const Point &other) const { return !(*this == other); }; @@ -232,7 +218,8 @@ class Point static std::shared_ptr Unpack(std::istream &in_stream, const int8_t &point_format_id, const Vector3 &scale, const Vector3 &offset, const uint16_t &eb_byte_size); - void Pack(std::ostream &out_stream) const; + void Pack(std::ostream &out_stream,const Vector3 &scale, + const Vector3 &offset) const; void ToPointFormat(const int8_t &point_format_id); protected: @@ -259,8 +246,6 @@ class Point private: uint32_t point_record_length_; int8_t point_format_id_; - Vector3 scale_; - Vector3 offset_; }; } // namespace copc::las diff --git a/cpp/include/copc-lib/las/points.hpp b/cpp/include/copc-lib/las/points.hpp index 0a41761e..514ea884 100644 --- a/cpp/include/copc-lib/las/points.hpp +++ b/cpp/include/copc-lib/las/points.hpp @@ -18,8 +18,7 @@ namespace copc::las class Points { public: - Points(const int8_t &point_format_id, const Vector3 &scale, const Vector3 &offset, - const uint16_t &eb_byte_size = 0); + Points(const int8_t &point_format_id, const uint16_t &eb_byte_size = 0); Points(const LasHeader &header); // Will create Points object given a points vector Points(const std::vector> &points); @@ -49,13 +48,17 @@ class Points // Point functions std::shared_ptr CreatePoint() { - return std::make_shared(point_format_id_, scale_, offset_, EbByteSize()); + return std::make_shared(point_format_id_, EbByteSize()); } void ToPointFormat(const int8_t &point_format_id); // Pack/unpack - std::vector Pack() const; - void Pack(std::ostream &out_stream) const; + std::vector Pack(const LasHeader &header) const; + std::vector Pack(const Vector3 &scale, + const Vector3 &offset) const; + void Pack(std::ostream &out_stream, const Vector3 &scale, + const Vector3 &offset) const; + void Pack(std::ostream &out_stream, const LasHeader &header) const; static Points Unpack(const std::vector &point_data, const int8_t &point_format_id, const uint16_t &eb_byte_size, const Vector3 &scale, const Vector3 &offset); static Points Unpack(const std::vector &point_data, const LasHeader &header); @@ -114,57 +117,6 @@ class Points points_[i]->Z(in[i]); } - std::vector UnscaledX() const - { - std::vector out; - out.resize(Size()); - std::transform(points_.begin(), points_.end(), out.begin(), - [](const std::shared_ptr &p) { return p->UnscaledX(); }); - return out; - } - void UnscaledX(const std::vector &in) - { - if (in.size() != Size()) - throw std::runtime_error("UnscaledX setter array must be same size as Points array!"); - - for (unsigned i = 0; i < points_.size(); ++i) - points_[i]->UnscaledX(in[i]); - } - - std::vector UnscaledY() const - { - std::vector out; - out.resize(Size()); - std::transform(points_.begin(), points_.end(), out.begin(), - [](const std::shared_ptr &p) { return p->UnscaledY(); }); - return out; - } - void UnscaledY(const std::vector &in) - { - if (in.size() != Size()) - throw std::runtime_error("UnscaledY setter array must be same size as Points array!"); - - for (unsigned i = 0; i < points_.size(); ++i) - points_[i]->UnscaledY(in[i]); - } - - std::vector UnscaledZ() const - { - std::vector out; - out.resize(Size()); - std::transform(points_.begin(), points_.end(), out.begin(), - [](const std::shared_ptr &p) { return p->UnscaledZ(); }); - return out; - } - void UnscaledZ(const std::vector &in) - { - if (in.size() != Size()) - throw std::runtime_error("UnscaledZ setter array must be same size as Points array!"); - - for (unsigned i = 0; i < points_.size(); ++i) - points_[i]->UnscaledZ(in[i]); - } - std::vector Classification() const { std::vector out; @@ -279,8 +231,6 @@ class Points std::vector> points_; int8_t point_format_id_; uint32_t point_record_length_; - Vector3 scale_; - Vector3 offset_; }; } // namespace copc::las #endif // COPCLIB_LAS_POINTS_H_ diff --git a/cpp/src/io/copc_writer_public.cpp b/cpp/src/io/copc_writer_public.cpp index 9eb6d012..b482f43c 100644 --- a/cpp/src/io/copc_writer_public.cpp +++ b/cpp/src/io/copc_writer_public.cpp @@ -107,7 +107,7 @@ Node Writer::AddNode(const VoxelKey &key, const las::Points &points, const Voxel points.PointRecordLength() != config_->LasHeader()->PointRecordLength()) throw std::runtime_error("Writer::AddNode: New points must be of same format and size."); - std::vector uncompressed_data = points.Pack(); + std::vector uncompressed_data = points.Pack(config_->LasHeader()->Scale(), config_->LasHeader()->Offset()); return AddNode(key, uncompressed_data, page_key); } diff --git a/cpp/src/io/laz_writer.cpp b/cpp/src/io/laz_writer.cpp index b6bbabd6..e98eab7e 100644 --- a/cpp/src/io/laz_writer.cpp +++ b/cpp/src/io/laz_writer.cpp @@ -22,7 +22,7 @@ void LazWriter::WritePoints(const las::Points &points) points.PointRecordLength() != config_->LasHeader().PointRecordLength()) throw std::runtime_error("LazWriter::WritePoints: New points must be of same format and size."); - std::vector uncompressed_data = points.Pack(); + std::vector uncompressed_data = points.Pack(config_->LasHeader()); WriteChunk(uncompressed_data); } diff --git a/cpp/src/las/point.cpp b/cpp/src/las/point.cpp index 578ebd38..f383f3c8 100644 --- a/cpp/src/las/point.cpp +++ b/cpp/src/las/point.cpp @@ -3,8 +3,8 @@ namespace copc::las { -Point::Point(const int8_t &point_format_id, const Vector3 &scale, const Vector3 &offset, const uint16_t &eb_byte_size) - : scale_(scale), offset_(offset), point_format_id_(point_format_id) +Point::Point(const int8_t &point_format_id, const uint16_t &eb_byte_size) + : point_format_id_(point_format_id) { if (point_format_id < 6 || point_format_id > 8) throw std::runtime_error("Point: Point format must be 6-8"); @@ -18,11 +18,11 @@ Point::Point(const int8_t &point_format_id, const Vector3 &scale, const Vector3 } Point::Point(const LasHeader &header) - : Point(header.PointFormatId(), header.Scale(), header.Offset(), header.EbByteSize()) + : Point(header.PointFormatId(), header.EbByteSize()) { } -Point::Point(const Point &other) : Point(other.point_format_id_, other.Scale(), other.Offset(), other.EbByteSize()) +Point::Point(const Point &other) : Point(other.point_format_id_, other.EbByteSize()) { x_scaled_ = other.x_scaled_; y_scaled_ = other.y_scaled_; @@ -57,9 +57,9 @@ bool Point::operator==(const Point &other) const { if (point_format_id_ != other.point_format_id_ || point_record_length_ != other.point_record_length_) return false; - if (!AreClose(X(), other.X(), std::max(scale_.x, other.scale_.x)) || - !AreClose(Y(), other.Y(), std::max(scale_.y, other.scale_.y)) || - !AreClose(Z(), other.Z(), std::max(scale_.z, other.scale_.z)) || intensity_ != other.Intensity()) + if (!AreClose(X(), other.X(), 0.01) || + !AreClose(Y(), other.Y(), 0.01) || + !AreClose(Z(), other.Z(), 0.01) || intensity_ != other.Intensity()) return false; if (returns_ != other.ReturnsBitField()) return false; @@ -85,11 +85,11 @@ bool Point::Within(const Box &box) const { return box.Contains(Vector3(X(), Y(), std::shared_ptr Point::Unpack(std::istream &in_stream, const int8_t &point_format_id, const Vector3 &scale, const Vector3 &offset, const uint16_t &eb_byte_size) { - std::shared_ptr p = std::make_shared(point_format_id, scale, offset, eb_byte_size); + std::shared_ptr p = std::make_shared(point_format_id, eb_byte_size); - p->UnscaledX(unpack(in_stream)); - p->UnscaledY(unpack(in_stream)); - p->UnscaledZ(unpack(in_stream)); + p->x_scaled_ = ApplyScale(unpack(in_stream), scale.x, offset.x); + p->y_scaled_ = ApplyScale(unpack(in_stream), scale.y, offset.y); + p->z_scaled_ = ApplyScale(unpack(in_stream), scale.z, offset.z); p->intensity_ = unpack(in_stream); p->returns_ = unpack(in_stream); p->flags_ = unpack(in_stream); @@ -116,12 +116,13 @@ std::shared_ptr Point::Unpack(std::istream &in_stream, const int8_t &poin return p; } -void Point::Pack(std::ostream &out_stream) const +void Point::Pack(std::ostream &out_stream,const Vector3 &scale, + const Vector3 &offset) const { // Point - pack(UnscaledX(), out_stream); - pack(UnscaledY(), out_stream); - pack(UnscaledZ(), out_stream); + pack(RemoveScale(x_scaled_, scale.x, offset.x), out_stream); + pack(RemoveScale(y_scaled_, scale.y, offset.y), out_stream); + pack(RemoveScale(z_scaled_, scale.z, offset.z), out_stream); pack(intensity_, out_stream); pack(returns_, out_stream); pack(flags_, out_stream); diff --git a/cpp/src/las/points.cpp b/cpp/src/las/points.cpp index da5ff075..a85ecaf6 100644 --- a/cpp/src/las/points.cpp +++ b/cpp/src/las/points.cpp @@ -7,8 +7,8 @@ namespace copc::las { -Points::Points(const int8_t &point_format_id, const Vector3 &scale, const Vector3 &offset, const uint16_t &eb_byte_size) - : point_format_id_(point_format_id), scale_(scale), offset_(offset) +Points::Points(const int8_t &point_format_id, const uint16_t &eb_byte_size) + : point_format_id_(point_format_id) { if (point_format_id < 0 || point_format_id > 10) throw std::runtime_error("Point format must be 0-10."); @@ -17,7 +17,7 @@ Points::Points(const int8_t &point_format_id, const Vector3 &scale, const Vector } Points::Points(const LasHeader &header) - : Points(header.PointFormatId(), header.Scale(), header.Offset(), header.EbByteSize()) + : Points(header.PointFormatId(), header.EbByteSize()) { } @@ -28,8 +28,6 @@ Points::Points(const std::vector> &points) point_record_length_ = points[0]->PointRecordLength(); point_format_id_ = points[0]->PointFormatId(); - scale_ = points[0]->Scale(); - offset_ = points[0]->Offset(); AddPoints(points); } @@ -91,7 +89,7 @@ Points Points::Unpack(const std::vector &point_data, const int8_t &point_f auto ss = std::istringstream(std::string(point_data.begin(), point_data.end())); // Go through each Point to unpack the data from the stream - Points points(point_format_id, scale, offset, eb_byte_size); + Points points(point_format_id, eb_byte_size); points.Reserve(point_count); // Unpack points @@ -103,16 +101,26 @@ Points Points::Unpack(const std::vector &point_data, const int8_t &point_f return points; } -void Points::Pack(std::ostream &out_stream) const +void Points::Pack(std::ostream &out_stream, const LasHeader &header) const +{ Pack(out_stream, header.Scale(), header.Offset()); } + +void Points::Pack(std::ostream &out_stream, const Vector3 &scale, + const Vector3 &offset) const { for (const auto &point : points_) - point->Pack(out_stream); + point->Pack(out_stream, scale, offset); +} + +std::vector Points::Pack(const LasHeader &header) const +{ + return Pack(header.Scale(), header.Offset()); } -std::vector Points::Pack() const +std::vector Points::Pack(const Vector3 &scale, + const Vector3 &offset) const { std::stringstream out; - Pack(out); + Pack(out, scale, offset); auto ostr = out.str(); return std::vector(ostr.begin(), ostr.end()); } diff --git a/python/bindings.cpp b/python/bindings.cpp index d6a6d4ae..95579bc1 100644 --- a/python/bindings.cpp +++ b/python/bindings.cpp @@ -216,12 +216,6 @@ PYBIND11_MODULE(_core, m) py::overload_cast(&las::Point::Y)) .def_property("z", py::overload_cast<>(&las::Point::Z, py::const_), py::overload_cast(&las::Point::Z)) - .def_property("X", py::overload_cast<>(&las::Point::UnscaledX, py::const_), - py::overload_cast(&las::Point::UnscaledX)) - .def_property("Y", py::overload_cast<>(&las::Point::UnscaledY, py::const_), - py::overload_cast(&las::Point::UnscaledY)) - .def_property("Z", py::overload_cast<>(&las::Point::UnscaledZ, py::const_), - py::overload_cast(&las::Point::UnscaledZ)) .def_property("intensity", py::overload_cast<>(&las::Point::Intensity, py::const_), py::overload_cast(&las::Point::Intensity)) .def_property("returns_bit_field", py::overload_cast<>(&las::Point::ReturnsBitField, py::const_), @@ -294,8 +288,8 @@ PYBIND11_MODULE(_core, m) }; py::class_(m, "Points") - .def(py::init(), - py::arg("point_format_id"), py::arg("scale"), py::arg("offset"), py::arg("eb_byte_size") = 0) + .def(py::init(), + py::arg("point_format_id"), py::arg("eb_byte_size") = 0) .def(py::init> &>(), py::arg("points")) .def(py::init()) .def_property("x", py::overload_cast<>(&las::Points::X, py::const_), @@ -304,12 +298,6 @@ PYBIND11_MODULE(_core, m) py::overload_cast &>(&las::Points::Y)) .def_property("z", py::overload_cast<>(&las::Points::Z, py::const_), py::overload_cast &>(&las::Points::Z)) - .def_property("X", py::overload_cast<>(&las::Points::UnscaledX, py::const_), - py::overload_cast &>(&las::Points::UnscaledX)) - .def_property("Y", py::overload_cast<>(&las::Points::UnscaledY, py::const_), - py::overload_cast &>(&las::Points::UnscaledY)) - .def_property("Z", py::overload_cast<>(&las::Points::UnscaledZ, py::const_), - py::overload_cast &>(&las::Points::UnscaledZ)) .def_property("classification", py::overload_cast<>(&las::Points::Classification, py::const_), py::overload_cast &>(&las::Points::Classification)) .def_property("point_source_id", py::overload_cast<>(&las::Points::PointSourceId, py::const_), @@ -330,7 +318,9 @@ PYBIND11_MODULE(_core, m) .def("ToPointFormat", &las::Points::ToPointFormat, py::arg("point_format_id")) .def("Within", &las::Points::Within, py::arg("box")) .def("GetWithin", &las::Points::GetWithin, py::arg("box")) - .def("Pack", py::overload_cast<>(&las::Points::Pack, py::const_)) + .def("Pack", py::overload_cast(&las::Points::Pack, py::const_)) + .def("Pack", py::overload_cast(&las::Points::Pack, py::const_)) .def("Unpack", py::overload_cast &, const las::LasHeader &>(&las::Points::Unpack)) .def("Unpack", py::overload_cast &, const int8_t &, const uint16_t &, const Vector3 &, const Vector3 &>(&las::Points::Unpack)) From 524d177c3cd418ef90b1c74b2e748683f975bdb5 Mon Sep 17 00:00:00 2001 From: Christopher Lee Date: Wed, 7 Sep 2022 17:33:12 -0600 Subject: [PATCH 07/15] Fix cpp tests --- test/hierarchy_test.cpp | 2 +- test/point_test.cpp | 214 +++++++++++++++++++------------------- test/points_test.cpp | 85 ++++++--------- test/reader_node_test.cpp | 18 ++-- test/writer_test.cpp | 26 ++--- 5 files changed, 163 insertions(+), 182 deletions(-) diff --git a/test/hierarchy_test.cpp b/test/hierarchy_test.cpp index d409a7b7..e1ff1861 100644 --- a/test/hierarchy_test.cpp +++ b/test/hierarchy_test.cpp @@ -23,7 +23,7 @@ TEST_CASE("Packing Test", "[Hierarchy] ") // Pack loaded points into stream ostringstream oss; - points.Pack(oss); + points.Pack(oss, reader.CopcConfig().LasHeader()); // Write stream into vector to compare with point_data vector point_data_write; diff --git a/test/point_test.cpp b/test/point_test.cpp index 96682924..41e52b77 100644 --- a/test/point_test.cpp +++ b/test/point_test.cpp @@ -11,6 +11,13 @@ using namespace copc::las; using namespace std; using Catch::Matchers::WithinAbs; +Point PackAndUnpack(Point p, copc::Vector3 scale, copc::Vector3 offset) +{ + std::stringstream out; + p.Pack(out, scale, offset); + return *Point::Unpack(out, p.PointFormatId(), scale, offset, p.EbByteSize()); +} + TEST_CASE("Point tests", "[Point]") { SECTION("Point Format Initialization") @@ -31,12 +38,12 @@ TEST_CASE("Point tests", "[Point]") { auto point6 = Point(6); // Position - point6.UnscaledX(std::numeric_limits::max()); - point6.UnscaledY(std::numeric_limits::max()); - point6.UnscaledZ(std::numeric_limits::max()); - REQUIRE(point6.UnscaledX() == std::numeric_limits::max()); - REQUIRE(point6.UnscaledY() == std::numeric_limits::max()); - REQUIRE(point6.UnscaledZ() == std::numeric_limits::max()); + point6.X(0.05); + point6.Y(1.11); + point6.Z(-9.99); + REQUIRE_THAT(point6.X(), WithinAbs(0.05, 0.000001)); + REQUIRE_THAT(point6.Y(), WithinAbs(1.11, 0.000001)); + REQUIRE_THAT(point6.Z(), WithinAbs(-9.99, 0.000001)); // Intensity point6.Intensity(std::numeric_limits::max()); @@ -271,19 +278,19 @@ TEST_CASE("Point tests", "[Point]") // Atributes - point.UnscaledX(4); + point.X(4); REQUIRE(point != point_other); - point_other.UnscaledX(4); + point_other.X(4); REQUIRE(point == point_other); - point.UnscaledY(4); + point.Y(4); REQUIRE(point != point_other); - point_other.UnscaledY(4); + point_other.Y(4); REQUIRE(point == point_other); - point.UnscaledZ(4); + point.Z(4); REQUIRE(point != point_other); - point_other.UnscaledZ(4); + point_other.Z(4); REQUIRE(point == point_other); point.Intensity(4); @@ -386,7 +393,7 @@ TEST_CASE("Point tests", "[Point]") REQUIRE(point.ExtraBytes().empty()); REQUIRE(point.EbByteSize() == 0); - point = Point(6, {}, {}, 5); + point = Point(6, 5); REQUIRE(point.PointFormatId() == 6); REQUIRE(point.PointRecordLength() == 30 + 5); REQUIRE(point.EbByteSize() == 5); @@ -398,11 +405,11 @@ TEST_CASE("Point tests", "[Point]") SECTION("Operator =") { - auto point = Point(8, copc::Vector3::DefaultScale(), copc::Vector3::DefaultOffset(), 2); + auto point = Point(8, 2); - point.UnscaledX(4); - point.UnscaledY(4); - point.UnscaledZ(4); + point.X(4); + point.Y(4); + point.Z(4); point.GPSTime(4.0); point.Red(4.0); @@ -420,30 +427,31 @@ TEST_CASE("Point tests", "[Point]") { std::stringstream ss; - auto orig_point = - Point(6, copc::Vector3::DefaultScale(), copc::Vector3::DefaultOffset(), 2); // use two extra bytes - orig_point.UnscaledX(20); - orig_point.UnscaledY(-20); - orig_point.UnscaledZ(100000); + auto scale = copc::Vector3::DefaultScale(); + auto offset = copc::Vector3::DefaultOffset(); + auto orig_point = Point(6, 2); // use two extra bytes + orig_point.X(20); + orig_point.Y(-20); + orig_point.Z(100000); orig_point.ScanAngle(2000); // Format 6 auto point = orig_point; - point.Pack(ss); + point.Pack(ss, scale, offset); auto point_other = *Point::Unpack(ss, 6, copc::Vector3::DefaultScale(), copc::Vector3::DefaultOffset(), point.EbByteSize()); REQUIRE(point == point_other); // Format 7 point.ToPointFormat(7); - point.Pack(ss); + point.Pack(ss, scale, offset); point_other = *Point::Unpack(ss, 7, copc::Vector3::DefaultScale(), copc::Vector3::DefaultOffset(), point.EbByteSize()); REQUIRE(point == point_other); // Format 8 point.ToPointFormat(8); - point.Pack(ss); + point.Pack(ss, scale, offset); point_other = *Point::Unpack(ss, 8, copc::Vector3::DefaultScale(), copc::Vector3::DefaultOffset(), point.EbByteSize()); REQUIRE(point == point_other); @@ -455,126 +463,122 @@ TEST_CASE("Point tests", "[Point]") SECTION("No scale and offset") { - auto point = Point(pfid, {1, 1, 1}, {0, 0, 0}); + auto point = Point(pfid); - point.UnscaledX(4); - point.UnscaledY(4); - point.UnscaledZ(4); + point.X(4); + point.Y(4.5); + point.Z(-0.1); - REQUIRE(point.X() == 4); - REQUIRE(point.Y() == 4); - REQUIRE(point.Z() == 4); + auto test_point = PackAndUnpack(point, copc::Vector3(1, 1, 1), copc::Vector3(0, 0, 0)); - point.X(5); - point.Y(6); - point.Z(7); - - REQUIRE(point.UnscaledX() == 5); - REQUIRE(point.UnscaledY() == 6); - REQUIRE(point.UnscaledZ() == 7); + REQUIRE(test_point.X() == 4); + REQUIRE(test_point.Y() == 5); + REQUIRE(test_point.Z() == 0); } SECTION("Scale test") { - auto point = Point(pfid, copc::Vector3::DefaultScale(), copc::Vector3::DefaultOffset()); + auto point = Point(pfid); + + point.X(0.01); + point.Y(0.02); + point.Z(0.03); - point.UnscaledX(1); - point.UnscaledY(2); - point.UnscaledZ(3); + auto test_point = PackAndUnpack(point, copc::Vector3(1, 1, 1), copc::Vector3(0, 0, 0)); - REQUIRE(point.X() == 0.01); - REQUIRE(point.Y() == 0.02); - REQUIRE(point.Z() == 0.03); + REQUIRE(test_point.X() == 0); + REQUIRE(test_point.Y() == 0); + REQUIRE(test_point.Z() == 0); - point.X(200); - point.Y(300); - point.Z(400); + test_point = PackAndUnpack(point, copc::Vector3(0.01, 0.01, 0.01), copc::Vector3(0, 0, 0)); - REQUIRE(point.UnscaledX() == 200 * 100); - REQUIRE(point.UnscaledY() == 300 * 100); - REQUIRE(point.UnscaledZ() == 400 * 100); + REQUIRE(test_point.X() == 0.01); + REQUIRE(test_point.Y() == 0.02); + REQUIRE(test_point.Z() == 0.03); } SECTION("Offset test") { copc::Vector3 scale = {1, 1, 1}; copc::Vector3 offset = {50001.456, 4443.123, -255.001}; - auto points = Points(pfid, scale, offset); - auto point = points.CreatePoint(); - - point->UnscaledX(0); - point->UnscaledY(-800); - point->UnscaledZ(3); - - REQUIRE(point->X() == 0 + offset.x); - REQUIRE(point->Y() == -800 + offset.y); - REQUIRE(point->Z() == 3 + offset.z); - - point->X(50502.888); - point->Y(4002.111); - point->Z(-80.5); - - // static_cast(std::round((value - offset) / scale)); - REQUIRE(point->UnscaledX() == 501); // 50502.888 - 50001.456 = 501.432 - REQUIRE(point->UnscaledY() == -441); - REQUIRE(point->UnscaledZ() == 175); // -80.5 - -255.001 = 255.001 - 80.5 = 175 - - REQUIRE_THAT(point->X(), WithinAbs(50502.888, 0.000001)); - REQUIRE_THAT(point->Y(), WithinAbs(4002.111, 0.000001)); - REQUIRE_THAT(point->Z(), WithinAbs(-80.5, 0.000001)); - points.AddPoint(point); - - // scale and offset only get updated after packing - point = Points::Unpack(points.Pack(), pfid, 0, scale, offset)[0]; - REQUIRE_THAT(point->X(), WithinAbs(50502.456, 0.000001)); - REQUIRE_THAT(point->Y(), WithinAbs(4002.123, 0.000001)); - REQUIRE_THAT(point->Z(), WithinAbs(-80.001, 0.000001)); + auto point = Point(pfid); + + point.X(50502.888); + point.Y(4002.111); + point.Z(-80.5); + + auto test_point = PackAndUnpack(point, scale, offset); + REQUIRE_THAT(test_point.X(), WithinAbs(50502.456, 0.000001)); + REQUIRE_THAT(test_point.Y(), WithinAbs(4002.123, 0.000001)); + REQUIRE_THAT(test_point.Z(), WithinAbs(-80.001, 0.000001)); } SECTION("Scale and Offset test") { - auto point = Point(pfid, {0.001, 0.001, 0.001}, {50001.456, 4443.123, -255.001}); + copc::Vector3 scale = {0.001, 0.001, 0.001}; + copc::Vector3 offset = {50001.456, 4443.123, -255.001}; + auto point = Point(pfid); - point.UnscaledX(0); - point.UnscaledY(-800); - point.UnscaledZ(300532); + point.X(50502.888); + point.Y(4002.111); + point.Z(-80.5); - REQUIRE_THAT(point.X(), WithinAbs(50001.456, 0.000001)); - REQUIRE_THAT(point.Y(), WithinAbs(4442.323, 0.000001)); - REQUIRE_THAT(point.Z(), WithinAbs(45.531, 0.000001)); + auto test_point = PackAndUnpack(point, scale, offset); + REQUIRE_THAT(test_point.X(), WithinAbs(50502.888, 0.000001)); + REQUIRE_THAT(test_point.Y(), WithinAbs(4002.111, 0.000001)); + REQUIRE_THAT(test_point.Z(), WithinAbs(-80.5, 0.000001)); + } + SECTION("Change Scale test") + { + copc::Vector3 offset = {50001.456, 4443.123, -255.001}; + copc::Vector3 scale = {0.001, 0.001, 0.001}; + copc::Vector3 new_scale = {1, 1, 1}; + // This tests the case that we want to change the point's scale when we pack it + auto point = Point(pfid); point.X(50502.888); point.Y(4002.111); point.Z(-80.5); - // static_cast(std::round((value - offset) / scale)); - REQUIRE(point.UnscaledX() == 501432); - REQUIRE(point.UnscaledY() == -441012); - REQUIRE(point.UnscaledZ() == 174501); - // (value * scale) + offset REQUIRE_THAT(point.X(), WithinAbs(50502.888, 0.000001)); REQUIRE_THAT(point.Y(), WithinAbs(4002.111, 0.000001)); REQUIRE_THAT(point.Z(), WithinAbs(-80.5, 0.000001)); + + // When we pack the points, that's when we unscale the internally stored double. + // so we end up with: + // UnscaledX = static_cast(std::round((50502.888 - 50001.456) / 1)) = 501 + // UnscaledY = static_cast(std::round((4002.111 - 4443.123) / 1)) = -441 + // UnscaledZ = static_cast(std::round((-80.5 - -255.001) / 1)) = 175 + + // Then when we unpack the points, we do the inverse: + // (value * scale) + offset + // X = 501 * 1 + 50001.456 = 50502.456 + // Y = -441 * 1 + 4443.123 = 4002.123 + // Z = 175 * 1 + -255.001 = -80.001 + auto test_point = PackAndUnpack(point, new_scale, offset); + + REQUIRE_THAT(test_point.X(), WithinAbs(50502.456, 0.0001)); + REQUIRE_THAT(test_point.Y(), WithinAbs(4002.123, 0.0001)); + REQUIRE_THAT(test_point.Z(), WithinAbs(-80.001, 0.0001)); } + // todo: add change offset and change offset/scale tests SECTION("Precision checks") { { - auto points = Points(pfid, {0.000001, 0.000001, 0.000001}, {0, 0, 0}); - auto point = points.CreatePoint(); - point->X(50501132.888123); - points.AddPoint(point); - REQUIRE_THROWS(points.Pack()); + auto point = Point(pfid); + point.X(50501132.888123); + std::stringstream out; + REQUIRE_THROWS(point.Pack(out, {0.000001, 0.000001, 0.000001}, {0, 0, 0})); } { - auto points = Points(pfid, {1, 1, 1}, {-8001100065, 0, 0}); - auto point = points.CreatePoint(); - point->X(0); - points.AddPoint(point); - REQUIRE_THROWS(points.Pack()); + auto point = Point(pfid); + point.X(0); + std::stringstream out; + REQUIRE_THROWS(point.Pack(out, {1, 1, 1}, {-8001100065, 0, 0})); } } } SECTION("Within") { - auto point = Point(6, {1, 1, 1}, copc::Vector3::DefaultOffset()); + auto point = Point(6); point.X(5); point.Y(5); diff --git a/test/points_test.cpp b/test/points_test.cpp index 11956825..7006395c 100644 --- a/test/points_test.cpp +++ b/test/points_test.cpp @@ -14,16 +14,16 @@ TEST_CASE("Points tests", "[Point]") { SECTION("Points constructors") { - auto points = Points(6, {1, 1, 1}, {0, 0, 0}, 4); + auto points = Points(6, 4); REQUIRE(points.PointFormatId() == 6); REQUIRE(points.PointRecordLength() == 34); REQUIRE(points.Get().empty()); auto point_vec = std::vector>(); auto point1 = points.CreatePoint(); - point1->UnscaledX(11); - point1->UnscaledY(11); - point1->UnscaledZ(11); + point1->X(11.1); + point1->Y(11.2); + point1->Z(11.3); point_vec.push_back(point1); auto point2 = points.CreatePoint(); @@ -37,54 +37,54 @@ TEST_CASE("Points tests", "[Point]") REQUIRE(points.PointRecordLength() == 34); for (const auto &point : points.Get()) REQUIRE(point->PointFormatId() == 6); - REQUIRE(points.Get(0)->UnscaledX() == 11); - REQUIRE(points.Get(0)->UnscaledY() == 11); - REQUIRE(points.Get(0)->UnscaledZ() == 11); + REQUIRE(points.Get(0)->X() == 11.1); + REQUIRE(points.Get(0)->Y() == 11.2); + REQUIRE(points.Get(0)->Z() == 11.3); points.ToString(); } SECTION("Adding Point to Points") { - auto points = Points(6, {1, 1, 1}, {0, 0, 0}, 0); + auto points = Points(6, 0); auto point = points.CreatePoint(); - point->UnscaledX(11); - point->UnscaledY(11); - point->UnscaledZ(11); + point->X(11.1); + point->Y(11.2); + point->Z(11.3); points.AddPoint(point); REQUIRE(points.Get().size() == 1); - REQUIRE(points.Get(0)->UnscaledX() == 11); - REQUIRE(points.Get(0)->UnscaledY() == 11); - REQUIRE(points.Get(0)->UnscaledZ() == 11); + REQUIRE(points.Get(0)->X() == 11.1); + REQUIRE(points.Get(0)->Y() == 11.2); + REQUIRE(points.Get(0)->Z() == 11.3); point = points.CreatePoint(); - point->UnscaledX(22); - point->UnscaledY(22); - point->UnscaledZ(22); + point->X(22.5); + point->Y(22.6); + point->Z(22.7); points.AddPoint(point); REQUIRE(points.Get().size() == 2); - REQUIRE(points.Get(1)->UnscaledX() == 22); - REQUIRE(points.Get(1)->UnscaledY() == 22); - REQUIRE(points.Get(1)->UnscaledZ() == 22); + REQUIRE(points.Get(1)->X() == 22.5); + REQUIRE(points.Get(1)->Y() == 22.6); + REQUIRE(points.Get(1)->Z() == 22.7); // Test check on point format - point = std::make_shared(7, copc::Vector3::DefaultScale(), copc::Vector3::DefaultOffset(), 0); + point = std::make_shared(7, 0); REQUIRE_THROWS(points.AddPoint(point)); // Test check on extra bytes - point = std::make_shared(6, copc::Vector3::DefaultScale(), copc::Vector3::DefaultOffset(), 1); + point = std::make_shared(6, 1); REQUIRE_THROWS(points.AddPoint(point)); } SECTION("Adding Points to Points") { auto points = Points(std::vector>( - 10, std::make_shared(6, copc::Vector3::DefaultScale(), copc::Vector3::DefaultOffset(), 4))); + 10, std::make_shared(6, 4))); auto points_other = Points(std::vector>( - 10, std::make_shared(6, copc::Vector3::DefaultScale(), copc::Vector3::DefaultOffset(), 4))); + 10, std::make_shared(6, 4))); points.AddPoints(points_other); @@ -92,19 +92,19 @@ TEST_CASE("Points tests", "[Point]") // Test check on point format points_other = Points(std::vector>( - 10, std::make_shared(7, copc::Vector3::DefaultScale(), copc::Vector3::DefaultOffset(), 4))); + 10, std::make_shared(7, 4))); REQUIRE_THROWS(points.AddPoints(points_other)); // Test check on extra bytes points_other = Points(std::vector>( - 10, std::make_shared(6, copc::Vector3::DefaultScale(), copc::Vector3::DefaultOffset(), 1))); + 10, std::make_shared(6, 1))); REQUIRE_THROWS(points.AddPoints(points_other)); } SECTION("Points format conversion") { auto points = Points(std::vector>( - 10, std::make_shared(6, copc::Vector3::DefaultScale(), copc::Vector3::DefaultOffset(), 4))); + 10, std::make_shared(6, 4))); points.ToPointFormat(7); REQUIRE(points.PointFormatId() == 7); @@ -118,7 +118,7 @@ TEST_CASE("Points tests", "[Point]") SECTION("Points Group Accessors") { - auto points = Points(7, copc::Vector3::DefaultScale(), copc::Vector3::DefaultOffset(), 4); + auto points = Points(7, 4); // generate points int num_points = 2000; @@ -142,9 +142,6 @@ TEST_CASE("Points tests", "[Point]") auto X = points.X(); auto Y = points.Y(); auto Z = points.Z(); - auto UnscaledX = points.UnscaledX(); - auto UnscaledY = points.UnscaledY(); - auto UnscaledZ = points.UnscaledZ(); auto classification = points.Classification(); auto point_source_id = points.PointSourceId(); auto red = points.Red(); @@ -155,11 +152,6 @@ TEST_CASE("Points tests", "[Point]") REQUIRE(X[i] == i); REQUIRE(Y[i] == i * 3); REQUIRE(Z[i] == i - 80); - REQUIRE(UnscaledX[i] == int32_t((i - copc::Vector3::DefaultOffset().x) / copc::Vector3::DefaultScale().x)); - REQUIRE(UnscaledY[i] == - int32_t(((i * 3) - copc::Vector3::DefaultOffset().y) / copc::Vector3::DefaultScale().y)); - REQUIRE(UnscaledZ[i] == - int32_t(((i - 80) - copc::Vector3::DefaultOffset().z) / copc::Vector3::DefaultScale().z)); REQUIRE(classification[i] == i * 255 / num_points); REQUIRE(point_source_id[i] == i * 255 / num_points); REQUIRE(red[i] == i * 4); @@ -183,9 +175,6 @@ TEST_CASE("Points tests", "[Point]") REQUIRE_THROWS(points.X(Xn)); REQUIRE_THROWS(points.Y(Yn)); REQUIRE_THROWS(points.Z(Zn)); - REQUIRE_THROWS(points.UnscaledX(UnscaledXn)); - REQUIRE_THROWS(points.UnscaledY(UnscaledYn)); - REQUIRE_THROWS(points.UnscaledZ(UnscaledZn)); REQUIRE_THROWS(points.Classification(classification_n)); REQUIRE_THROWS(points.PointSourceId(point_source_id_n)); REQUIRE_THROWS(points.Red(red_n)); @@ -239,12 +228,6 @@ TEST_CASE("Points tests", "[Point]") REQUIRE(p->X() == i * 50 + 8); REQUIRE(p->Y() == i + 800); REQUIRE(p->Z() == i * 4); - REQUIRE(p->UnscaledX() == - int32_t(((i * 50 + 8) - copc::Vector3::DefaultOffset().x) / copc::Vector3::DefaultScale().x)); - REQUIRE(p->UnscaledY() == - int32_t(((i + 800) - copc::Vector3::DefaultOffset().y) / copc::Vector3::DefaultScale().y)); - REQUIRE(p->UnscaledZ() == - int32_t(((i * 4) - copc::Vector3::DefaultOffset().z) / copc::Vector3::DefaultScale().z)); REQUIRE(p->Classification() == i * 255 / 2000); REQUIRE(p->PointSourceId() == i * 255 / 2000); REQUIRE(p->Red() == i * 4); @@ -257,12 +240,6 @@ TEST_CASE("Points tests", "[Point]") REQUIRE(last_point->X() == 1); REQUIRE(last_point->Y() == 2); REQUIRE(last_point->Z() == 3); - REQUIRE(last_point->UnscaledX() == - int32_t((1 - copc::Vector3::DefaultOffset().x) / copc::Vector3::DefaultScale().x)); - REQUIRE(last_point->UnscaledY() == - int32_t((2 - copc::Vector3::DefaultOffset().y) / copc::Vector3::DefaultScale().y)); - REQUIRE(last_point->UnscaledZ() == - int32_t((3 - copc::Vector3::DefaultOffset().z) / copc::Vector3::DefaultScale().z)); REQUIRE(last_point->Classification() == 255); REQUIRE(last_point->PointSourceId() == 255); REQUIRE(last_point->Red() == num_points * 4); @@ -272,7 +249,7 @@ TEST_CASE("Points tests", "[Point]") SECTION("Points Indexers") { - auto points = Points(6, copc::Vector3::DefaultScale(), copc::Vector3::DefaultOffset(), 4); + auto points = Points(6, 4); // generate points int num_points = 2000; @@ -367,7 +344,7 @@ TEST_CASE("Points tests", "[Point]") SECTION("Within") { - auto points = Points(6, {1, 1, 1}, copc::Vector3::DefaultOffset()); + auto points = Points(6); std::random_device rd; std::mt19937 gen(rd()); @@ -397,7 +374,7 @@ TEST_CASE("Points tests", "[Point]") SECTION("GetWithin") { - auto points = Points(6, {1, 1, 1}, copc::Vector3::DefaultOffset()); + auto points = Points(6); std::random_device rd; std::mt19937 gen(rd()); diff --git a/test/reader_node_test.cpp b/test/reader_node_test.cpp index 216f0062..9861a965 100644 --- a/test/reader_node_test.cpp +++ b/test/reader_node_test.cpp @@ -76,9 +76,9 @@ TEST_CASE("GetPoints Test", "[Reader] ") REQUIRE(points.size() == hier_entry.point_count); // Getters - REQUIRE(points[0]->UnscaledX() == -113822); - REQUIRE(points[0]->UnscaledY() == -118589); - REQUIRE(points[0]->UnscaledZ() == -221965); + REQUIRE_THAT(points[0]->X(), Catch::Matchers::WithinAbs(636767.32, 0.01)); + REQUIRE_THAT(points[0]->Y(), Catch::Matchers::WithinAbs(850024.01, 0.01)); + REQUIRE_THAT(points[0]->Z(), Catch::Matchers::WithinAbs(514.24, 0.01)); REQUIRE(points[0]->Intensity() == 11); REQUIRE(points[0]->NumberOfReturns() == 3); REQUIRE(points[0]->ReturnNumber() == 1); @@ -99,9 +99,9 @@ TEST_CASE("GetPoints Test", "[Reader] ") REQUIRE_THROWS(points[0]->Nir()); // Setters - points[0]->UnscaledX(std::numeric_limits::max()); - points[0]->UnscaledY(std::numeric_limits::max()); - points[0]->UnscaledZ(std::numeric_limits::max()); + points[0]->X(11.1); + points[0]->Y(11.2); + points[0]->Z(11.3); points[0]->Intensity(std::numeric_limits::max()); points[0]->NumberOfReturns(7); points[0]->ReturnNumber(7); @@ -117,9 +117,9 @@ TEST_CASE("GetPoints Test", "[Reader] ") points[0]->Blue(std::numeric_limits::max()); REQUIRE_THROWS(points[0]->Nir(std::numeric_limits::max())); - REQUIRE(points[0]->UnscaledX() == std::numeric_limits::max()); - REQUIRE(points[0]->UnscaledY() == std::numeric_limits::max()); - REQUIRE(points[0]->UnscaledZ() == std::numeric_limits::max()); + REQUIRE(points[0]->X() == 11.1); + REQUIRE(points[0]->Y() == 11.2); + REQUIRE(points[0]->Z() == 11.3); REQUIRE(points[0]->Intensity() == std::numeric_limits::max()); REQUIRE(points[0]->NumberOfReturns() == 7); REQUIRE(points[0]->ReturnNumber() == 7); diff --git a/test/writer_test.cpp b/test/writer_test.cpp index 1ed4e30e..75d0cf22 100644 --- a/test/writer_test.cpp +++ b/test/writer_test.cpp @@ -204,9 +204,9 @@ TEST_CASE("Writer Config Tests", "[Writer]") // Check that we can add a point of new format auto new_points = las::Points(*copy_writer.CopcConfig()->LasHeader()); auto new_point = new_points.CreatePoint(); - new_point->UnscaledX(10); - new_point->UnscaledY(15); - new_point->UnscaledZ(20); + new_point->X(10); + new_point->Y(15); + new_point->Z(20); new_point->GPSTime(1.5); new_point->Red(25); new_point->Nir(30); @@ -235,9 +235,9 @@ TEST_CASE("Writer Config Tests", "[Writer]") // Check that the written point is read correctly auto points = reader.GetPoints(VoxelKey::RootKey()); REQUIRE(points.Size() == 1); - REQUIRE(points[0]->UnscaledX() == 10); - REQUIRE(points[0]->UnscaledY() == 15); - REQUIRE(points[0]->UnscaledZ() == 20); + REQUIRE(points[0]->X() == 10); + REQUIRE(points[0]->Y() == 15); + REQUIRE(points[0]->Z() == 20); REQUIRE(points[0]->GPSTime() == 1.5); REQUIRE(points[0]->Red() == 25); REQUIRE(points[0]->Nir() == 30); @@ -596,7 +596,7 @@ TEST_CASE("Writer Pages", "[Writer]") REQUIRE(!writer.FindNode(VoxelKey::InvalidKey()).IsValid()); REQUIRE(!writer.FindNode(VoxelKey(5, 4, 3, 2)).IsValid()); auto header = *writer.CopcConfig()->LasHeader(); - las::Points points(header.PointFormatId(), header.Scale(), header.Offset()); + las::Points points(header.PointFormatId()); points.AddPoint(points.CreatePoint()); // Add a node with root key as page writer.AddNode(VoxelKey(1, 1, 1, 1), points, VoxelKey::RootKey()); @@ -616,7 +616,7 @@ TEST_CASE("Writer Pages", "[Writer]") Writer writer(out_stream, {6}); auto header = *writer.CopcConfig()->LasHeader(); - las::Points points(header.PointFormatId(), header.Scale(), header.Offset()); + las::Points points(header.PointFormatId()); points.AddPoint(points.CreatePoint()); writer.AddNode(VoxelKey(1, 1, 1, 1), points, VoxelKey(1, 1, 1, 1)); @@ -644,7 +644,7 @@ TEST_CASE("Writer Pages", "[Writer]") Writer writer(out_stream, {6}); auto header = *writer.CopcConfig()->LasHeader(); - las::Points points(header.PointFormatId(), header.Scale(), header.Offset()); + las::Points points(header.PointFormatId()); points.AddPoint(points.CreatePoint()); writer.AddNode(VoxelKey(3, 4, 4, 4), points, VoxelKey(2, 2, 2, 2)); @@ -801,7 +801,7 @@ TEST_CASE("Check Spatial Bounds", "[Writer]") auto header = *writer.CopcConfig()->LasHeader(); - las::Points points(header.PointFormatId(), header.Scale(), header.Offset()); + las::Points points(header.PointFormatId()); auto point = points.CreatePoint(); point->X(9); @@ -823,7 +823,7 @@ TEST_CASE("Check Spatial Bounds", "[Writer]") auto header = *writer.CopcConfig()->LasHeader(); - las::Points points(header.PointFormatId(), header.Scale(), header.Offset()); + las::Points points(header.PointFormatId()); auto point = points.CreatePoint(); point->X(10); @@ -845,7 +845,7 @@ TEST_CASE("Check Spatial Bounds", "[Writer]") auto header = *writer.CopcConfig()->LasHeader(); - las::Points points(header.PointFormatId(), header.Scale(), header.Offset()); + las::Points points(header.PointFormatId()); auto point = points.CreatePoint(); point->X(10); @@ -867,7 +867,7 @@ TEST_CASE("Check Spatial Bounds", "[Writer]") auto header = *writer.CopcConfig()->LasHeader(); - las::Points points(header.PointFormatId(), header.Scale(), header.Offset()); + las::Points points(header.PointFormatId()); auto point = points.CreatePoint(); point->X(0.1); From d3cd1a0d7166d0b6b76e71154107e58c71db6b1d Mon Sep 17 00:00:00 2001 From: Christopher Lee Date: Wed, 7 Sep 2022 17:33:52 -0600 Subject: [PATCH 08/15] Fix cpp examples --- example/example-laz-writer.cpp | 6 +++--- example/example-writer.cpp | 6 +++--- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/example/example-laz-writer.cpp b/example/example-laz-writer.cpp index e2d5da79..3a013788 100644 --- a/example/example-laz-writer.cpp +++ b/example/example-laz-writer.cpp @@ -35,9 +35,9 @@ las::Points RandomPoints(const las::LasHeader &header, int number_points) // The use of las::Point constructor is strongly discouraged, instead use las::Points::CreatePoint auto point = points.CreatePoint(); // point has getters/setters for all attributes - point->UnscaledX(rand_x(gen)); - point->UnscaledY(rand_y(gen)); - point->UnscaledZ(rand_z(gen)); + point->X(header.ApplyScaleX(rand_x(gen))); + point->Y(header.ApplyScaleY(rand_y(gen))); + point->Z(header.ApplyScaleZ(rand_z(gen))); points.AddPoint(point); } diff --git a/example/example-writer.cpp b/example/example-writer.cpp index 4d0c0e09..43b54c78 100644 --- a/example/example-writer.cpp +++ b/example/example-writer.cpp @@ -220,9 +220,9 @@ las::Points RandomPoints(const VoxelKey &key, const las::LasHeader &header, int // The use of las::Point constructor is strongly discouraged, instead use las::Points::CreatePoint auto point = points.CreatePoint(); // point has getters/setters for all attributes - point->UnscaledX(rand_x(gen)); - point->UnscaledY(rand_y(gen)); - point->UnscaledZ(rand_z(gen)); + point->X(header.ApplyScaleX(rand_x(gen))); + point->Y(header.ApplyScaleY(rand_y(gen))); + point->Z(header.ApplyScaleZ(rand_z(gen))); // For visualization purposes point->PointSourceId(key.d + key.x + key.y + key.z); From 27b744ff8c84053d6235cac7ad44d1f1910ed9db Mon Sep 17 00:00:00 2001 From: Christopher Lee Date: Wed, 7 Sep 2022 17:56:28 -0600 Subject: [PATCH 09/15] fix py tests --- test/point_test.py | 190 ++++++++++++++++++++------------------------ test/points_test.py | 102 ++++++------------------ test/writer_test.py | 26 +++--- 3 files changed, 123 insertions(+), 195 deletions(-) diff --git a/test/point_test.py b/test/point_test.py index abbfbf1c..91aaf0ea 100644 --- a/test/point_test.py +++ b/test/point_test.py @@ -4,11 +4,14 @@ import pytest +def pack_and_unpack(p, scale, offset): + points = copc.Points(p.point_format_id, p.EbByteSize()) + points.AddPoint(p) + return copc.Points.Unpack(points.Pack(scale, offset), p.point_format_id, p.EbByteSize(), scale, offset)[0] + def test_constructor(): point = copc.Points( point_format_id=6, - scale=copc.Vector3.DefaultScale(), - offset=copc.Vector3.DefaultOffset(), eb_byte_size=0, ).CreatePoint() @@ -16,7 +19,7 @@ def test_constructor(): assert point.HasNir() is False point_ext = copc.Points( - 8, copc.Vector3.DefaultScale(), copc.Vector3.DefaultOffset() + 8 ).CreatePoint() assert point_ext.HasRgb() is True @@ -25,15 +28,15 @@ def test_constructor(): def test_point(): point6 = copc.Points( - 6, copc.Vector3.DefaultScale(), copc.Vector3.DefaultOffset() + 6 ).CreatePoint() # Position - point6.X = 2147483647 - point6.Y = 2147483647 - point6.Z = 2147483647 - assert point6.X == 2147483647 - assert point6.Y == 2147483647 - assert point6.Z == 2147483647 + point6.x = 2147483647 + point6.y = 2147483647 + point6.z = 2147483647 + assert point6.x == 2147483647 + assert point6.y == 2147483647 + assert point6.z == 2147483647 # intensity point6.intensity = 65535 @@ -155,7 +158,7 @@ def test_point(): str(point6) point7 = copc.Points( - 7, copc.Vector3.DefaultScale(), copc.Vector3.DefaultOffset() + 7 ).CreatePoint() point7.rgb = [65535, 65535, 65535] @@ -169,7 +172,7 @@ def test_point(): assert point7.nir point8 = copc.Points( - 8, copc.Vector3.DefaultScale(), copc.Vector3.DefaultOffset() + 8 ).CreatePoint() point8.nir = 65535 @@ -179,7 +182,7 @@ def test_point(): def test_point_conversion(): point = copc.Points( - 6, copc.Vector3.DefaultScale(), copc.Vector3.DefaultOffset() + 6 ).CreatePoint() assert point.gps_time == 0 @@ -210,10 +213,10 @@ def test_point_conversion(): def test_operators_equal(): # Format 0 point = copc.Points( - 6, copc.Vector3.DefaultScale(), copc.Vector3.DefaultOffset() + 6 ).CreatePoint() point_other = copc.Points( - 6, copc.Vector3.DefaultScale(), copc.Vector3.DefaultOffset() + 6 ).CreatePoint() assert point == point_other @@ -231,19 +234,19 @@ def test_operators_equal(): # Atributes - point.X = 4 + point.x = 4 assert point != point_other - point_other.X = 4 + point_other.x = 4 assert point == point_other - point.Y = 4 + point.y = 4 assert point != point_other - point_other.Y = 4 + point_other.y = 4 assert point == point_other - point.Z = 4 + point.z = 4 assert point != point_other - point_other.Z = 4 + point_other.z = 4 assert point == point_other point.intensity = 4 @@ -339,7 +342,7 @@ def test_operators_equal(): def test_extra_byte(): point = copc.Points( - 6, copc.Vector3.DefaultScale(), copc.Vector3.DefaultOffset() + 6 ).CreatePoint() assert point.point_format_id == 6 assert point.point_record_length == 30 @@ -350,8 +353,6 @@ def test_extra_byte(): point = copc.Points( 6, - copc.Vector3.DefaultScale(), - copc.Vector3.DefaultOffset(), eb_byte_size=5, ).CreatePoint() assert point.point_format_id == 6 @@ -367,14 +368,12 @@ def test_extra_byte(): def test_operator_copy(): point = copc.Points( 8, - copc.Vector3.DefaultScale(), - copc.Vector3.DefaultOffset(), eb_byte_size=2, ).CreatePoint() - point.X = 4 - point.Y = 4 - point.Z = 4 + point.x = 4 + point.y = 4 + point.z = 4 point.gps_time = 4.0 point.red = 4 @@ -392,123 +391,102 @@ def test_scaled_xyz(): pfid = 8 # No scale and offset - point = copc.Points(pfid, scale=[1, 1, 1], offset=[0, 0, 0]).CreatePoint() - - point.X = 4 - point.Y = 4 - point.Z = 4 + point = copc.Points(pfid).CreatePoint() - assert point.x == 4 - assert point.y == 4 - assert point.z == 4 + point.x = 4 + point.y = 4.5 + point.z = -0.1 - point.x = 5 - point.y = 6 - point.z = 7 - - assert point.X == 5 - assert point.Y == 6 - assert point.Z == 7 + test_point = pack_and_unpack(point, [1,1,1], [0,0,0]) + assert test_point.x == 4 + assert test_point.y == 5 + assert test_point.z == 0 # Scale test point = copc.Points( - pfid, copc.Vector3.DefaultScale(), copc.Vector3.DefaultOffset() + pfid ).CreatePoint() - point.X = 1 - point.Y = 2 - point.Z = 3 + point.x = 0.01 + point.y = 0.02 + point.z = 0.03 + + test_point = pack_and_unpack(point, [1,1,1], [0,0,0]) + assert test_point.x == 0 + assert test_point.y == 0 + assert test_point.z == 0 - assert point.x == 0.01 - assert point.y == 0.02 - assert point.z == 0.03 + test_point = pack_and_unpack(point, [0.01,0.01,0.01], [0,0,0]) - point.x = 200 - point.y = 300 - point.z = 400 + assert test_point.x == 0.01 + assert test_point.y == 0.02 + assert test_point.z == 0.03 - assert point.X == 200 * 100 - assert point.Y == 300 * 100 - assert point.Z == 400 * 100 # Offset test scale = [1, 1, 1] offset = copc.Vector3([50001.456, 4443.123, -255.001]) - points = copc.Points(pfid, scale, offset) - point = points.CreatePoint() - - point.X = 0 - point.Y = -800 - point.Z = 3 - - assert point.x == 0 + offset.x - assert point.y == -800 + offset.y - assert point.z == 3 + offset.z + point = copc.Points(pfid).CreatePoint() point.x = 50502.888 point.y = 4002.111 point.z = -80.5 - assert point.X == 501 # 50502.888 - 50001.456 = 501.432 - assert point.Y == -441 - assert point.Z == 175 # -80.5 - -255.001 = 255.001 - 80.5 = 175 - - assert point.x == pytest.approx(50502.888, 0.000001) - assert point.y == pytest.approx(4002.111, 0.000001) - assert point.z == pytest.approx(-80.5, 0.000001) - points.AddPoint(point) + test_point = pack_and_unpack(point, scale, offset) - # scale and offset only get updated after packing - point = copc.Points.Unpack(points.Pack(), pfid, 0, scale, offset)[0] - assert point.x == pytest.approx(50502.456, 0.000001) - assert point.y == pytest.approx(4002.123, 0.000001) - assert point.z == pytest.approx(-80.001, 0.000001) + assert test_point.x == pytest.approx(50502.456, 0.000001) + assert test_point.y == pytest.approx(4002.123, 0.000001) + assert test_point.z == pytest.approx(-80.001, 0.000001) # Scale and Offset test - point = copc.Points( - pfid, scale=[0.001, 0.001, 0.001], offset=[50001.456, 4443.123, -255.001] - ).CreatePoint() + scale=[0.001, 0.001, 0.001] + offset=[50001.456, 4443.123, -255.001] + point = copc.Points(pfid).CreatePoint() + + point.x = 50502.888 + point.y = 4002.111 + point.z = -80.5 - point.X = 0 - point.Y = -800 - point.Z = 300532 + test_point = pack_and_unpack(point, scale, offset) + assert test_point.x == pytest.approx(50502.888, 0.000001) + assert test_point.y == pytest.approx(4002.111, 0.000001) + assert test_point.z == pytest.approx(-80.5, 0.000001) - assert point.x == pytest.approx(50001.456, 0.000001) - assert point.y == pytest.approx(4442.323, 0.000001) - assert point.z == pytest.approx(45.531, 0.000001) + # Change scale test + offset = [50001.456, 4443.123, -255.001] + scale = [0.001, 0.001, 0.001] + new_scale = [1,1,1] + point = copc.Points(pfid).CreatePoint() point.x = 50502.888 point.y = 4002.111 point.z = -80.5 - assert point.X == 501432 - assert point.Y == -441012 - assert point.Z == 174501 + test_point = pack_and_unpack(point, new_scale, offset) + assert test_point.x == pytest.approx(50502.456, 0.000001) + assert test_point.y == pytest.approx(4002.123, 0.000001) + assert test_point.z == pytest.approx(-80.001, 0.000001) - # (value * scale) + offset - assert point.x == pytest.approx(50502.888, 0.000001) - assert point.y == pytest.approx(4002.111, 0.000001) - assert point.z == pytest.approx(-80.5, 0.000001) # Precision checks - points = copc.Points(pfid, [0.000001, 0.000001, 0.000001], [0, 0, 0]) + points = copc.Points(pfid) point = points.CreatePoint() - + point.x = 50501132.888123 + points.AddPoint(point) with pytest.raises(RuntimeError): - point.x = 50501132.888123 - points.AddPoint(point) - points.Pack() + points.Pack([0.000001, 0.000001, 0.000001], [0, 0, 0]) - point = copc.Points(pfid, [1, 1, 1], [-8001100065, 0, 0]).CreatePoint() + points = copc.Points(pfid) + point = points.CreatePoint() + point.x = 0 + points.AddPoint(point) with pytest.raises(RuntimeError): - point.x = 0 - points.AddPoint(point) - points.Pack() + points.Pack([1, 1, 1], [-8001100065, 0, 0]) def test_within(): - point = copc.Points(6, (1, 1, 1), copc.Vector3.DefaultOffset()).CreatePoint() + point = copc.Points(6).CreatePoint() point.x = 5 point.y = 5 diff --git a/test/points_test.py b/test/points_test.py index 4bc226b9..250480ef 100644 --- a/test/points_test.py +++ b/test/points_test.py @@ -5,7 +5,7 @@ def test_points_constructor(): points = copc.Points( - 6, copc.Vector3.DefaultScale(), copc.Vector3.DefaultOffset(), 4 + 6, 4 ) assert points.point_format_id == 6 assert points.point_record_length == 34 @@ -13,26 +13,20 @@ def test_points_constructor(): point1 = copc.Points( 6, - copc.Vector3.DefaultScale(), - copc.Vector3.DefaultOffset(), eb_byte_size=4, ).CreatePoint() - point1.X = 11 - point1.Y = 11 - point1.Z = 11 + point1.x = 11.1 + point1.y = 11.2 + point1.z = 11.3 point_list = [ point1, copc.Points( 6, - copc.Vector3.DefaultScale(), - copc.Vector3.DefaultOffset(), eb_byte_size=4, ).CreatePoint(), copc.Points( 6, - copc.Vector3.DefaultScale(), - copc.Vector3.DefaultOffset(), eb_byte_size=4, ).CreatePoint(), ] @@ -42,54 +36,49 @@ def test_points_constructor(): assert points.point_record_length == 34 for point in points: assert point.point_format_id == 6 - assert points[0].Y == 11 - assert points[0].Z == 11 + assert points[0].x == 11.1 + assert points[0].y == 11.2 + assert points[0].z == 11.3 str(points) def test_adding_point_to_points(): points = copc.Points( - 6, copc.Vector3.DefaultScale(), copc.Vector3.DefaultOffset(), 0 + 6, 0 ) point = copc.Points( 6, - copc.Vector3.DefaultScale(), - copc.Vector3.DefaultOffset(), eb_byte_size=0, ).CreatePoint() - point.X = 11 - point.Y = 11 - point.Z = 11 + point.x = 11.1 + point.y = 11.2 + point.z = 11.3 points.AddPoint(point) assert len(points) == 1 - assert points[0].X == 11 - assert points[0].Y == 11 - assert points[0].Z == 11 + assert points[0].x == 11.1 + assert points[0].y == 11.2 + assert points[0].z == 11.3 point = copc.Points( 6, - copc.Vector3.DefaultScale(), - copc.Vector3.DefaultOffset(), eb_byte_size=0, ).CreatePoint() - point.X = 22 - point.Y = 22 - point.Z = 22 + point.x = 22.5 + point.y = 22.6 + point.z = 22.7 points.AddPoint(point) assert len(points) == 2 - assert points[1].X == 22 - assert points[1].Y == 22 - assert points[1].Z == 22 + assert points[1].x == 22.5 + assert points[1].y == 22.6 + assert points[1].z == 22.7 # Test check on point format point = copc.Points( 7, - copc.Vector3.DefaultScale(), - copc.Vector3.DefaultOffset(), eb_byte_size=0, ).CreatePoint() with pytest.raises(RuntimeError): @@ -98,8 +87,6 @@ def test_adding_point_to_points(): # Test check on extra bytes point = copc.Points( 6, - copc.Vector3.DefaultScale(), - copc.Vector3.DefaultOffset(), eb_byte_size=1, ).CreatePoint() with pytest.raises(RuntimeError): @@ -111,8 +98,6 @@ def test_adding_points_to_points(): [ copc.Points( 6, - copc.Vector3.DefaultScale(), - copc.Vector3.DefaultOffset(), eb_byte_size=4, ).CreatePoint() for _ in range(10) @@ -122,8 +107,6 @@ def test_adding_points_to_points(): [ copc.Points( 6, - copc.Vector3.DefaultScale(), - copc.Vector3.DefaultOffset(), eb_byte_size=4, ).CreatePoint() for _ in range(10) @@ -139,8 +122,6 @@ def test_adding_points_to_points(): [ copc.Points( 7, - copc.Vector3.DefaultScale(), - copc.Vector3.DefaultOffset(), eb_byte_size=4, ).CreatePoint() for _ in range(10) @@ -154,8 +135,6 @@ def test_adding_points_to_points(): [ copc.Points( 6, - copc.Vector3.DefaultScale(), - copc.Vector3.DefaultOffset(), eb_byte_size=1, ).CreatePoint() for _ in range(10) @@ -170,8 +149,6 @@ def test_points_format_conversion(): [ copc.Points( 6, - copc.Vector3.DefaultScale(), - copc.Vector3.DefaultOffset(), eb_byte_size=4, ).CreatePoint() for _ in range(10) @@ -192,7 +169,7 @@ def test_points_format_conversion(): def test_points_iterator(): points = copc.Points( - 6, copc.Vector3.DefaultScale(), copc.Vector3.DefaultOffset(), 4 + 6, 4 ) # generate points @@ -213,7 +190,7 @@ def test_points_iterator(): def test_points_group_accessors(): points = copc.Points( - 7, copc.Vector3.DefaultScale(), copc.Vector3.DefaultOffset(), 4 + 7, 4 ) # generate points @@ -237,18 +214,6 @@ def test_points_group_accessors(): assert points.x[i] == i assert points.y[i] == i * 3 assert points.z[i] == i - 80 - assert ( - points.X[i] - == (i - copc.Vector3.DefaultOffset().x) / copc.Vector3.DefaultScale().x - ) - assert ( - points.Y[i] - == (i * 3 - copc.Vector3.DefaultOffset().y) / copc.Vector3.DefaultScale().y - ) - assert ( - points.Z[i] - == (i - 80 - copc.Vector3.DefaultOffset().z) / copc.Vector3.DefaultScale().z - ) assert points.classification[i] == i * 255 // num_points assert points.point_source_id[i] == i * 255 // num_points assert points.red[i] == i * 4 @@ -290,21 +255,6 @@ def test_points_group_accessors(): assert p.y == i + 800 assert p.z == i * 4 - assert ( - p.X - == (i * 50 + 8 - copc.Vector3.DefaultOffset().x) - / copc.Vector3.DefaultScale().x - ) - assert ( - p.Y - == (i + 800 - copc.Vector3.DefaultOffset().y) - / copc.Vector3.DefaultScale().y - ) - assert ( - p.Z - == (i * 4 - copc.Vector3.DefaultOffset().z) / copc.Vector3.DefaultScale().z - ) - # test negative indices last_point = points[-1] assert last_point.x == 1 @@ -314,7 +264,7 @@ def test_points_group_accessors(): def test_within(): - points = copc.Points(6, (1, 1, 1), copc.Vector3.DefaultOffset()) + points = copc.Points(6) # generate points for i in range(2000): @@ -337,7 +287,7 @@ def test_within(): def test_get_within(): - points = copc.Points(6, (1, 1, 1), copc.Vector3.DefaultOffset()) + points = copc.Points(6) # generate points for i in range(2000): @@ -354,7 +304,7 @@ def test_get_within(): def test_points_accessors(): points = copc.Points( - 7, copc.Vector3.DefaultScale(), copc.Vector3.DefaultOffset(), 4 + 7, 4 ) # generate points @@ -412,7 +362,7 @@ def test_points_accessors(): def test_points_indexer_setter(): points = copc.Points( - 6, copc.Vector3.DefaultScale(), copc.Vector3.DefaultOffset(), 4 + 6, 4 ) # generate points diff --git a/test/writer_test.py b/test/writer_test.py index 2accac22..1ba295b6 100644 --- a/test/writer_test.py +++ b/test/writer_test.py @@ -237,7 +237,7 @@ def test_writer_pages(): # Root Page header = writer.copc_config.las_header - points = copc.Points(header.point_format_id, header.scale, header.offset) + points = copc.Points(header.point_format_id) points.AddPoint(points.CreatePoint()) # Add a node with root key as page writer.AddNode((1, 1, 1, 1), points, copc.VoxelKey.RootKey()) @@ -253,7 +253,7 @@ def test_writer_pages(): writer = copc.FileWriter(file_path, copc.CopcConfigWriter(6)) header = writer.copc_config.las_header - points = copc.Points(header.point_format_id, header.scale, header.offset) + points = copc.Points(header.point_format_id) points.AddPoint(points.CreatePoint()) writer.AddNode((1, 1, 1, 1), points, page_key=(1, 1, 1, 1)) @@ -279,7 +279,7 @@ def test_writer_pages(): writer = copc.FileWriter(file_path, copc.CopcConfigWriter(6)) header = writer.copc_config.las_header - points = copc.Points(header.point_format_id, header.scale, header.offset) + points = copc.Points(header.point_format_id) points.AddPoint(points.CreatePoint()) writer.AddNode((3, 4, 4, 4), points, page_key=(2, 2, 2, 2)) @@ -405,9 +405,9 @@ def test_writer_copy_and_update(): new_points = copc.Points(writer.copc_config.las_header) new_point = new_points.CreatePoint() - new_point.X = 10 - new_point.Y = 15 - new_point.Z = 20 + new_point.x = 10 + new_point.y = 15 + new_point.z = 20 new_point.gps_time = 1.5 new_point.red = 25 new_point.nir = 30 @@ -441,9 +441,9 @@ def test_writer_copy_and_update(): # Check that the written point is read correctly points = reader.GetPoints(copc.VoxelKey.RootKey()) assert len(points) == 1 - assert points[0].X == 10 - assert points[0].Y == 15 - assert points[0].Z == 20 + assert points[0].x == 10 + assert points[0].y == 15 + assert points[0].z == 20 assert points[0].gps_time == 1.5 assert points[0].red == 25 assert points[0].nir == 30 @@ -706,7 +706,7 @@ def test_check_spatial_bounds(): ## Checks on las header bounds - points = copc.Points(header.point_format_id, header.scale, header.offset) + points = copc.Points(header.point_format_id) point = points.CreatePoint() # point has getters/setters for all attributes @@ -728,7 +728,7 @@ def test_check_spatial_bounds(): header = writer.copc_config.las_header - points = copc.Points(header.point_format_id, header.scale, header.offset) + points = copc.Points(header.point_format_id) point = points.CreatePoint() point.x = 10 @@ -748,7 +748,7 @@ def test_check_spatial_bounds(): header = writer.copc_config.las_header - points = copc.Points(header.point_format_id, header.scale, header.offset) + points = copc.Points(header.point_format_id) point = points.CreatePoint() point.x = 10 @@ -767,7 +767,7 @@ def test_check_spatial_bounds(): writer = copc.FileWriter(file_path, cfg) header = writer.copc_config.las_header - points = copc.Points(header.point_format_id, header.scale, header.offset) + points = copc.Points(header.point_format_id) point = points.CreatePoint() point.x = 0.1 From b2501e8f64d70b3a2488f8449ce6fd7c6029760d Mon Sep 17 00:00:00 2001 From: Christopher Lee Date: Wed, 7 Sep 2022 17:58:39 -0600 Subject: [PATCH 10/15] fix py examples --- example/example_writer.py | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/example/example_writer.py b/example/example_writer.py index 224db993..c5d443dd 100644 --- a/example/example_writer.py +++ b/example/example_writer.py @@ -212,18 +212,18 @@ def RandomPoints(key, las_header, number_points): # Create a point with a given point format point = points.CreatePoint() # point has getters/setters for all attributes - point.X = random.randint( + point.x = las_header.ApplyScaleX(random.randint( las_header.RemoveScaleX(max(las_header.min.x, minx)), las_header.RemoveScaleX(min(las_header.max.x, minx + step)), - ) - point.Y = random.randint( + )) + point.y = las_header.ApplyScaleY(random.randint( las_header.RemoveScaleY(max(las_header.min.y, miny)), las_header.RemoveScaleY(min(las_header.max.y, miny + step)), - ) - point.Z = random.randint( + )) + point.z = las_header.ApplyScaleZ(random.randint( las_header.RemoveScaleZ(max(las_header.min.z, minz)), las_header.RemoveScaleZ(min(las_header.max.z, minz + step)), - ) + )) # For visualization purposes point.point_source_id = key.d + key.x + key.y + key.z From 9fcd60eab80783542dbf606d392622e9dd8ec085 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Thu, 8 Sep 2022 00:00:31 +0000 Subject: [PATCH 11/15] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- cpp/include/copc-lib/las/point.hpp | 3 +- cpp/include/copc-lib/las/points.hpp | 11 ++---- cpp/src/las/point.cpp | 16 +++------ cpp/src/las/points.cpp | 25 +++++-------- example/example_writer.py | 30 +++++++++------- test/point_test.py | 55 ++++++++++------------------- test/points_test.cpp | 15 +++----- test/points_test.py | 24 ++++--------- 8 files changed, 66 insertions(+), 113 deletions(-) diff --git a/cpp/include/copc-lib/las/point.hpp b/cpp/include/copc-lib/las/point.hpp index c8aa1db6..a8dd05c6 100644 --- a/cpp/include/copc-lib/las/point.hpp +++ b/cpp/include/copc-lib/las/point.hpp @@ -218,8 +218,7 @@ class Point static std::shared_ptr Unpack(std::istream &in_stream, const int8_t &point_format_id, const Vector3 &scale, const Vector3 &offset, const uint16_t &eb_byte_size); - void Pack(std::ostream &out_stream,const Vector3 &scale, - const Vector3 &offset) const; + void Pack(std::ostream &out_stream, const Vector3 &scale, const Vector3 &offset) const; void ToPointFormat(const int8_t &point_format_id); protected: diff --git a/cpp/include/copc-lib/las/points.hpp b/cpp/include/copc-lib/las/points.hpp index 514ea884..fa1c0767 100644 --- a/cpp/include/copc-lib/las/points.hpp +++ b/cpp/include/copc-lib/las/points.hpp @@ -46,18 +46,13 @@ class Points void AddPoints(std::vector> points); // Point functions - std::shared_ptr CreatePoint() - { - return std::make_shared(point_format_id_, EbByteSize()); - } + std::shared_ptr CreatePoint() { return std::make_shared(point_format_id_, EbByteSize()); } void ToPointFormat(const int8_t &point_format_id); // Pack/unpack std::vector Pack(const LasHeader &header) const; - std::vector Pack(const Vector3 &scale, - const Vector3 &offset) const; - void Pack(std::ostream &out_stream, const Vector3 &scale, - const Vector3 &offset) const; + std::vector Pack(const Vector3 &scale, const Vector3 &offset) const; + void Pack(std::ostream &out_stream, const Vector3 &scale, const Vector3 &offset) const; void Pack(std::ostream &out_stream, const LasHeader &header) const; static Points Unpack(const std::vector &point_data, const int8_t &point_format_id, const uint16_t &eb_byte_size, const Vector3 &scale, const Vector3 &offset); diff --git a/cpp/src/las/point.cpp b/cpp/src/las/point.cpp index f383f3c8..59610fe1 100644 --- a/cpp/src/las/point.cpp +++ b/cpp/src/las/point.cpp @@ -3,8 +3,7 @@ namespace copc::las { -Point::Point(const int8_t &point_format_id, const uint16_t &eb_byte_size) - : point_format_id_(point_format_id) +Point::Point(const int8_t &point_format_id, const uint16_t &eb_byte_size) : point_format_id_(point_format_id) { if (point_format_id < 6 || point_format_id > 8) throw std::runtime_error("Point: Point format must be 6-8"); @@ -17,10 +16,7 @@ Point::Point(const int8_t &point_format_id, const uint16_t &eb_byte_size) extra_bytes_.resize(eb_byte_size, 0); } -Point::Point(const LasHeader &header) - : Point(header.PointFormatId(), header.EbByteSize()) -{ -} +Point::Point(const LasHeader &header) : Point(header.PointFormatId(), header.EbByteSize()) {} Point::Point(const Point &other) : Point(other.point_format_id_, other.EbByteSize()) { @@ -57,9 +53,8 @@ bool Point::operator==(const Point &other) const { if (point_format_id_ != other.point_format_id_ || point_record_length_ != other.point_record_length_) return false; - if (!AreClose(X(), other.X(), 0.01) || - !AreClose(Y(), other.Y(), 0.01) || - !AreClose(Z(), other.Z(), 0.01) || intensity_ != other.Intensity()) + if (!AreClose(X(), other.X(), 0.01) || !AreClose(Y(), other.Y(), 0.01) || !AreClose(Z(), other.Z(), 0.01) || + intensity_ != other.Intensity()) return false; if (returns_ != other.ReturnsBitField()) return false; @@ -116,8 +111,7 @@ std::shared_ptr Point::Unpack(std::istream &in_stream, const int8_t &poin return p; } -void Point::Pack(std::ostream &out_stream,const Vector3 &scale, - const Vector3 &offset) const +void Point::Pack(std::ostream &out_stream, const Vector3 &scale, const Vector3 &offset) const { // Point pack(RemoveScale(x_scaled_, scale.x, offset.x), out_stream); diff --git a/cpp/src/las/points.cpp b/cpp/src/las/points.cpp index a85ecaf6..57e34b1c 100644 --- a/cpp/src/las/points.cpp +++ b/cpp/src/las/points.cpp @@ -7,8 +7,7 @@ namespace copc::las { -Points::Points(const int8_t &point_format_id, const uint16_t &eb_byte_size) - : point_format_id_(point_format_id) +Points::Points(const int8_t &point_format_id, const uint16_t &eb_byte_size) : point_format_id_(point_format_id) { if (point_format_id < 0 || point_format_id > 10) throw std::runtime_error("Point format must be 0-10."); @@ -16,10 +15,7 @@ Points::Points(const int8_t &point_format_id, const uint16_t &eb_byte_size) point_record_length_ = PointByteSize(point_format_id, eb_byte_size); } -Points::Points(const LasHeader &header) - : Points(header.PointFormatId(), header.EbByteSize()) -{ -} +Points::Points(const LasHeader &header) : Points(header.PointFormatId(), header.EbByteSize()) {} Points::Points(const std::vector> &points) { @@ -101,23 +97,20 @@ Points Points::Unpack(const std::vector &point_data, const int8_t &point_f return points; } -void Points::Pack(std::ostream &out_stream, const LasHeader &header) const -{ Pack(out_stream, header.Scale(), header.Offset()); } +void Points::Pack(std::ostream &out_stream, const LasHeader &header) const +{ + Pack(out_stream, header.Scale(), header.Offset()); +} -void Points::Pack(std::ostream &out_stream, const Vector3 &scale, - const Vector3 &offset) const +void Points::Pack(std::ostream &out_stream, const Vector3 &scale, const Vector3 &offset) const { for (const auto &point : points_) point->Pack(out_stream, scale, offset); } -std::vector Points::Pack(const LasHeader &header) const -{ - return Pack(header.Scale(), header.Offset()); -} +std::vector Points::Pack(const LasHeader &header) const { return Pack(header.Scale(), header.Offset()); } -std::vector Points::Pack(const Vector3 &scale, - const Vector3 &offset) const +std::vector Points::Pack(const Vector3 &scale, const Vector3 &offset) const { std::stringstream out; Pack(out, scale, offset); diff --git a/example/example_writer.py b/example/example_writer.py index c5d443dd..da092c4a 100644 --- a/example/example_writer.py +++ b/example/example_writer.py @@ -212,18 +212,24 @@ def RandomPoints(key, las_header, number_points): # Create a point with a given point format point = points.CreatePoint() # point has getters/setters for all attributes - point.x = las_header.ApplyScaleX(random.randint( - las_header.RemoveScaleX(max(las_header.min.x, minx)), - las_header.RemoveScaleX(min(las_header.max.x, minx + step)), - )) - point.y = las_header.ApplyScaleY(random.randint( - las_header.RemoveScaleY(max(las_header.min.y, miny)), - las_header.RemoveScaleY(min(las_header.max.y, miny + step)), - )) - point.z = las_header.ApplyScaleZ(random.randint( - las_header.RemoveScaleZ(max(las_header.min.z, minz)), - las_header.RemoveScaleZ(min(las_header.max.z, minz + step)), - )) + point.x = las_header.ApplyScaleX( + random.randint( + las_header.RemoveScaleX(max(las_header.min.x, minx)), + las_header.RemoveScaleX(min(las_header.max.x, minx + step)), + ) + ) + point.y = las_header.ApplyScaleY( + random.randint( + las_header.RemoveScaleY(max(las_header.min.y, miny)), + las_header.RemoveScaleY(min(las_header.max.y, miny + step)), + ) + ) + point.z = las_header.ApplyScaleZ( + random.randint( + las_header.RemoveScaleZ(max(las_header.min.z, minz)), + las_header.RemoveScaleZ(min(las_header.max.z, minz + step)), + ) + ) # For visualization purposes point.point_source_id = key.d + key.x + key.y + key.z diff --git a/test/point_test.py b/test/point_test.py index 91aaf0ea..7e251e6d 100644 --- a/test/point_test.py +++ b/test/point_test.py @@ -7,7 +7,10 @@ def pack_and_unpack(p, scale, offset): points = copc.Points(p.point_format_id, p.EbByteSize()) points.AddPoint(p) - return copc.Points.Unpack(points.Pack(scale, offset), p.point_format_id, p.EbByteSize(), scale, offset)[0] + return copc.Points.Unpack( + points.Pack(scale, offset), p.point_format_id, p.EbByteSize(), scale, offset + )[0] + def test_constructor(): point = copc.Points( @@ -18,18 +21,14 @@ def test_constructor(): assert point.HasRgb() is False assert point.HasNir() is False - point_ext = copc.Points( - 8 - ).CreatePoint() + point_ext = copc.Points(8).CreatePoint() assert point_ext.HasRgb() is True assert point_ext.HasNir() is True def test_point(): - point6 = copc.Points( - 6 - ).CreatePoint() + point6 = copc.Points(6).CreatePoint() # Position point6.x = 2147483647 point6.y = 2147483647 @@ -157,9 +156,7 @@ def test_point(): # ToString str(point6) - point7 = copc.Points( - 7 - ).CreatePoint() + point7 = copc.Points(7).CreatePoint() point7.rgb = [65535, 65535, 65535] assert point7.red == 65535 @@ -171,9 +168,7 @@ def test_point(): point7.nir = 65535 assert point7.nir - point8 = copc.Points( - 8 - ).CreatePoint() + point8 = copc.Points(8).CreatePoint() point8.nir = 65535 assert point8.nir == 65535 @@ -181,9 +176,7 @@ def test_point(): def test_point_conversion(): - point = copc.Points( - 6 - ).CreatePoint() + point = copc.Points(6).CreatePoint() assert point.gps_time == 0 assert point.scanner_channel == 0 @@ -212,12 +205,8 @@ def test_point_conversion(): def test_operators_equal(): # Format 0 - point = copc.Points( - 6 - ).CreatePoint() - point_other = copc.Points( - 6 - ).CreatePoint() + point = copc.Points(6).CreatePoint() + point_other = copc.Points(6).CreatePoint() assert point == point_other # Format 7 @@ -341,9 +330,7 @@ def test_operators_equal(): def test_extra_byte(): - point = copc.Points( - 6 - ).CreatePoint() + point = copc.Points(6).CreatePoint() assert point.point_format_id == 6 assert point.point_record_length == 30 with pytest.raises(RuntimeError): @@ -397,26 +384,24 @@ def test_scaled_xyz(): point.y = 4.5 point.z = -0.1 - test_point = pack_and_unpack(point, [1,1,1], [0,0,0]) + test_point = pack_and_unpack(point, [1, 1, 1], [0, 0, 0]) assert test_point.x == 4 assert test_point.y == 5 assert test_point.z == 0 # Scale test - point = copc.Points( - pfid - ).CreatePoint() + point = copc.Points(pfid).CreatePoint() point.x = 0.01 point.y = 0.02 point.z = 0.03 - test_point = pack_and_unpack(point, [1,1,1], [0,0,0]) + test_point = pack_and_unpack(point, [1, 1, 1], [0, 0, 0]) assert test_point.x == 0 assert test_point.y == 0 assert test_point.z == 0 - test_point = pack_and_unpack(point, [0.01,0.01,0.01], [0,0,0]) + test_point = pack_and_unpack(point, [0.01, 0.01, 0.01], [0, 0, 0]) assert test_point.x == 0.01 assert test_point.y == 0.02 @@ -439,8 +424,8 @@ def test_scaled_xyz(): assert test_point.z == pytest.approx(-80.001, 0.000001) # Scale and Offset test - scale=[0.001, 0.001, 0.001] - offset=[50001.456, 4443.123, -255.001] + scale = [0.001, 0.001, 0.001] + offset = [50001.456, 4443.123, -255.001] point = copc.Points(pfid).CreatePoint() point.x = 50502.888 @@ -455,7 +440,7 @@ def test_scaled_xyz(): # Change scale test offset = [50001.456, 4443.123, -255.001] scale = [0.001, 0.001, 0.001] - new_scale = [1,1,1] + new_scale = [1, 1, 1] point = copc.Points(pfid).CreatePoint() point.x = 50502.888 @@ -467,7 +452,6 @@ def test_scaled_xyz(): assert test_point.y == pytest.approx(4002.123, 0.000001) assert test_point.z == pytest.approx(-80.001, 0.000001) - # Precision checks points = copc.Points(pfid) point = points.CreatePoint() @@ -476,7 +460,6 @@ def test_scaled_xyz(): with pytest.raises(RuntimeError): points.Pack([0.000001, 0.000001, 0.000001], [0, 0, 0]) - points = copc.Points(pfid) point = points.CreatePoint() point.x = 0 diff --git a/test/points_test.cpp b/test/points_test.cpp index 7006395c..d186535b 100644 --- a/test/points_test.cpp +++ b/test/points_test.cpp @@ -81,30 +81,25 @@ TEST_CASE("Points tests", "[Point]") SECTION("Adding Points to Points") { - auto points = Points(std::vector>( - 10, std::make_shared(6, 4))); - auto points_other = Points(std::vector>( - 10, std::make_shared(6, 4))); + auto points = Points(std::vector>(10, std::make_shared(6, 4))); + auto points_other = Points(std::vector>(10, std::make_shared(6, 4))); points.AddPoints(points_other); REQUIRE(points.Get().size() == 20); // Test check on point format - points_other = Points(std::vector>( - 10, std::make_shared(7, 4))); + points_other = Points(std::vector>(10, std::make_shared(7, 4))); REQUIRE_THROWS(points.AddPoints(points_other)); // Test check on extra bytes - points_other = Points(std::vector>( - 10, std::make_shared(6, 1))); + points_other = Points(std::vector>(10, std::make_shared(6, 1))); REQUIRE_THROWS(points.AddPoints(points_other)); } SECTION("Points format conversion") { - auto points = Points(std::vector>( - 10, std::make_shared(6, 4))); + auto points = Points(std::vector>(10, std::make_shared(6, 4))); points.ToPointFormat(7); REQUIRE(points.PointFormatId() == 7); diff --git a/test/points_test.py b/test/points_test.py index 250480ef..4ff74a96 100644 --- a/test/points_test.py +++ b/test/points_test.py @@ -4,9 +4,7 @@ def test_points_constructor(): - points = copc.Points( - 6, 4 - ) + points = copc.Points(6, 4) assert points.point_format_id == 6 assert points.point_record_length == 34 assert len(points) == 0 @@ -44,9 +42,7 @@ def test_points_constructor(): def test_adding_point_to_points(): - points = copc.Points( - 6, 0 - ) + points = copc.Points(6, 0) point = copc.Points( 6, eb_byte_size=0, @@ -168,9 +164,7 @@ def test_points_format_conversion(): def test_points_iterator(): - points = copc.Points( - 6, 4 - ) + points = copc.Points(6, 4) # generate points num_points = 2000 @@ -189,9 +183,7 @@ def test_points_iterator(): def test_points_group_accessors(): - points = copc.Points( - 7, 4 - ) + points = copc.Points(7, 4) # generate points num_points = 2000 @@ -303,9 +295,7 @@ def test_get_within(): def test_points_accessors(): - points = copc.Points( - 7, 4 - ) + points = copc.Points(7, 4) # generate points num_points = 2000 @@ -361,9 +351,7 @@ def test_points_accessors(): def test_points_indexer_setter(): - points = copc.Points( - 6, 4 - ) + points = copc.Points(6, 4) # generate points num_points = 2000 From f6e1518f684ed42daef313397758c0ddb12a26bf Mon Sep 17 00:00:00 2001 From: Christopher Lee Date: Thu, 8 Sep 2022 12:08:15 -0600 Subject: [PATCH 12/15] PR Review --- cpp/src/io/copc_writer_public.cpp | 2 +- cpp/src/las/point.cpp | 2 +- example/example_writer.py | 24 +++++++++--------------- 3 files changed, 11 insertions(+), 17 deletions(-) diff --git a/cpp/src/io/copc_writer_public.cpp b/cpp/src/io/copc_writer_public.cpp index b482f43c..5d58f09b 100644 --- a/cpp/src/io/copc_writer_public.cpp +++ b/cpp/src/io/copc_writer_public.cpp @@ -107,7 +107,7 @@ Node Writer::AddNode(const VoxelKey &key, const las::Points &points, const Voxel points.PointRecordLength() != config_->LasHeader()->PointRecordLength()) throw std::runtime_error("Writer::AddNode: New points must be of same format and size."); - std::vector uncompressed_data = points.Pack(config_->LasHeader()->Scale(), config_->LasHeader()->Offset()); + std::vector uncompressed_data = points.Pack(config_->LasHeader()); return AddNode(key, uncompressed_data, page_key); } diff --git a/cpp/src/las/point.cpp b/cpp/src/las/point.cpp index 59610fe1..d8a34509 100644 --- a/cpp/src/las/point.cpp +++ b/cpp/src/las/point.cpp @@ -53,7 +53,7 @@ bool Point::operator==(const Point &other) const { if (point_format_id_ != other.point_format_id_ || point_record_length_ != other.point_record_length_) return false; - if (!AreClose(X(), other.X(), 0.01) || !AreClose(Y(), other.Y(), 0.01) || !AreClose(Z(), other.Z(), 0.01) || + if (!AreClose(X(), other.X(), 0.000001) || !AreClose(Y(), other.Y(), 0.000001) || !AreClose(Z(), other.Z(), 0.000001) || intensity_ != other.Intensity()) return false; if (returns_ != other.ReturnsBitField()) diff --git a/example/example_writer.py b/example/example_writer.py index da092c4a..bc455ba4 100644 --- a/example/example_writer.py +++ b/example/example_writer.py @@ -212,24 +212,18 @@ def RandomPoints(key, las_header, number_points): # Create a point with a given point format point = points.CreatePoint() # point has getters/setters for all attributes - point.x = las_header.ApplyScaleX( - random.randint( - las_header.RemoveScaleX(max(las_header.min.x, minx)), - las_header.RemoveScaleX(min(las_header.max.x, minx + step)), + point.x = random.uniform( + max(las_header.min.x, minx), + min(las_header.max.x, minx + step), ) - ) - point.y = las_header.ApplyScaleY( - random.randint( - las_header.RemoveScaleY(max(las_header.min.y, miny)), - las_header.RemoveScaleY(min(las_header.max.y, miny + step)), + point.y = random.uniform( + max(las_header.min.y, miny), + min(las_header.max.y, miny + step), ) - ) - point.z = las_header.ApplyScaleZ( - random.randint( - las_header.RemoveScaleZ(max(las_header.min.z, minz)), - las_header.RemoveScaleZ(min(las_header.max.z, minz + step)), + point.z = random.uniform( + max(las_header.min.z, minz), + min(las_header.max.z, minz + step), ) - ) # For visualization purposes point.point_source_id = key.d + key.x + key.y + key.z From 9cb5aa2b65f27f88ed8a7d93701b7edd90c51709 Mon Sep 17 00:00:00 2001 From: Christopher Lee Date: Thu, 8 Sep 2022 12:10:45 -0600 Subject: [PATCH 13/15] Changelog --- CHANGELOG.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 2e8b955e..c377cefa 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,9 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] +### Changed +- **\[Python/C++\]** Point and Points objects no longer depend on an internal scale or offset. XYZ coordinates are stored as doubles internally, and converted into integers using scale and offset only when packing or unpacking. + ## [2.3.1] - 2022-04-14 ### Fixed From 9864470d203c084846a8827440107c0eea6718ab Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Thu, 8 Sep 2022 18:10:57 +0000 Subject: [PATCH 14/15] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- cpp/src/las/point.cpp | 4 ++-- example/example_writer.py | 18 +++++++++--------- 2 files changed, 11 insertions(+), 11 deletions(-) diff --git a/cpp/src/las/point.cpp b/cpp/src/las/point.cpp index d8a34509..bb78b47a 100644 --- a/cpp/src/las/point.cpp +++ b/cpp/src/las/point.cpp @@ -53,8 +53,8 @@ bool Point::operator==(const Point &other) const { if (point_format_id_ != other.point_format_id_ || point_record_length_ != other.point_record_length_) return false; - if (!AreClose(X(), other.X(), 0.000001) || !AreClose(Y(), other.Y(), 0.000001) || !AreClose(Z(), other.Z(), 0.000001) || - intensity_ != other.Intensity()) + if (!AreClose(X(), other.X(), 0.000001) || !AreClose(Y(), other.Y(), 0.000001) || + !AreClose(Z(), other.Z(), 0.000001) || intensity_ != other.Intensity()) return false; if (returns_ != other.ReturnsBitField()) return false; diff --git a/example/example_writer.py b/example/example_writer.py index bc455ba4..54ad2d91 100644 --- a/example/example_writer.py +++ b/example/example_writer.py @@ -213,17 +213,17 @@ def RandomPoints(key, las_header, number_points): point = points.CreatePoint() # point has getters/setters for all attributes point.x = random.uniform( - max(las_header.min.x, minx), - min(las_header.max.x, minx + step), - ) + max(las_header.min.x, minx), + min(las_header.max.x, minx + step), + ) point.y = random.uniform( - max(las_header.min.y, miny), - min(las_header.max.y, miny + step), - ) + max(las_header.min.y, miny), + min(las_header.max.y, miny + step), + ) point.z = random.uniform( - max(las_header.min.z, minz), - min(las_header.max.z, minz + step), - ) + max(las_header.min.z, minz), + min(las_header.max.z, minz + step), + ) # For visualization purposes point.point_source_id = key.d + key.x + key.y + key.z From 1778c91105f83483bd6899aa5c556145a497f4ca Mon Sep 17 00:00:00 2001 From: Christopher Lee Date: Thu, 8 Sep 2022 12:18:40 -0600 Subject: [PATCH 15/15] fix --- cpp/src/io/copc_writer_public.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cpp/src/io/copc_writer_public.cpp b/cpp/src/io/copc_writer_public.cpp index 5d58f09b..ef33802f 100644 --- a/cpp/src/io/copc_writer_public.cpp +++ b/cpp/src/io/copc_writer_public.cpp @@ -107,7 +107,7 @@ Node Writer::AddNode(const VoxelKey &key, const las::Points &points, const Voxel points.PointRecordLength() != config_->LasHeader()->PointRecordLength()) throw std::runtime_error("Writer::AddNode: New points must be of same format and size."); - std::vector uncompressed_data = points.Pack(config_->LasHeader()); + std::vector uncompressed_data = points.Pack(*config_->LasHeader()); return AddNode(key, uncompressed_data, page_key); }