Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Python Shared Pointers #41

Merged
merged 15 commits into from
Sep 22, 2021
2 changes: 1 addition & 1 deletion example/example-reader.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ void ReaderExample()
cout << endl << "First 5 points: " << endl;
for (int i = 0; i < 5; i++)
{
cout << node_points.Get(i).ToString() << endl;
cout << node_points.Get(i)->ToString() << endl;
}
}

Expand Down
2 changes: 1 addition & 1 deletion example/example-reader.py
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ def reader_example():

print("First 5 points:")
for i in range(5):
print(node_points.Get(i))
print(node_points[i])
CCInc marked this conversation as resolved.
Show resolved Hide resolved

# We can also get the raw compressed data if we want to decompress it ourselves:

Expand Down
10 changes: 5 additions & 5 deletions example/example-writer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -109,13 +109,13 @@ las::Points RandomPoints(VoxelKey key, int8_t point_format_id)
{
// Create a point with a given point format
// The use of las::Point constructor is strongly discouraged, instead use las::Points::CreatePoint
las::Point point = 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->UnscaledX(rand_x(gen));
point->UnscaledY(rand_y(gen));
point->UnscaledZ(rand_z(gen));
// For visualization purposes
point.PointSourceID(key.d + key.x + key.y + key.d);
point->PointSourceID(key.d + key.x + key.y + key.d);

points.AddPoint(point);
}
Expand Down
4 changes: 2 additions & 2 deletions include/copc-lib/las/point.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -437,8 +437,8 @@ class Point
bool operator!=(const Point &other) const { return !(*this == other); };
std::string ToString() const;

static Point Unpack(std::istream &in_stream, const int8_t &point_format_id, const Vector3 &scale,
const Vector3 &offset, const uint16_t &num_extra_bytes);
static std::shared_ptr<Point> Unpack(std::istream &in_stream, const int8_t &point_format_id, const Vector3 &scale,
const Vector3 &offset, const uint16_t &num_extra_bytes);
void Pack(std::ostream &out_stream) const;
void ToPointFormat(const int8_t &point_format_id);

Expand Down
37 changes: 24 additions & 13 deletions include/copc-lib/las/points.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -21,27 +21,36 @@ class Points
const uint16_t &num_extra_bytes = 0);
Points(const LasHeader &header);
// Will create Points object given a points vector
Points(const std::vector<Point> &points);
Points(const std::vector<std::shared_ptr<Point>> &points);

// Getters
int8_t PointFormatID() const { return point_format_id_; }
uint32_t PointRecordLength() const { return point_record_length_; }
uint32_t NumExtraBytes() const { return ComputeNumExtraBytes(point_format_id_, point_record_length_); }

// Vector functions
std::vector<Point> Get() { return points_; }
Point Get(const size_t &idx) { return points_[idx]; }
std::vector<std::shared_ptr<Point>> Get() { return points_; }
size_t Size() const { return points_.size(); }
void Reserve(const size_t &num) { points_.reserve(num); }

std::shared_ptr<Point> Get(const size_t &idx) { return points_[idx]; }
std::shared_ptr<Point> &operator[](size_t i) { return points_[i]; }
const std::shared_ptr<Point> &operator[](size_t i) const { return points_[i]; }

const std::vector<std::shared_ptr<Point>>::const_iterator begin() const { return points_.begin(); }
const std::vector<std::shared_ptr<Point>>::const_iterator end() const { return points_.end(); }

// Add points functions
void AddPoint(const Point &point);
void AddPoint(const std::shared_ptr<Point> &point);
void AddPoints(Points points);
// TODO[Leo]: Add this to tests
void AddPoints(std::vector<las::Point> points);
void AddPoints(std::vector<std::shared_ptr<Point>> points);

// Point functions
las::Point CreatePoint() { return las::Point(point_format_id_, scale_, offset_, NumExtraBytes()); }
std::shared_ptr<Point> CreatePoint()
{
return std::make_shared<Point>(point_format_id_, scale_, offset_, NumExtraBytes());
}
void ToPointFormat(const int8_t &point_format_id);

// Pack/unpack
Expand All @@ -58,7 +67,7 @@ class Points
{
std::vector<double> out;
out.resize(Size());
std::transform(points_.begin(), points_.end(), out.begin(), [](Point p) { return p.X(); });
std::transform(points_.begin(), points_.end(), out.begin(), [](std::shared_ptr<Point> p) { return p->X(); });
return out;
}
void X(const std::vector<double> &in)
Expand All @@ -67,14 +76,15 @@ class Points
throw std::runtime_error("X setter array must be same size as Points array!");

for (unsigned i = 0; i < points_.size(); ++i)
points_[i].X(in[i]);
points_[i]->X(in[i]);
}

std::vector<double> Y() const
{
std::vector<double> out;
out.resize(Size());
std::transform(points_.begin(), points_.end(), out.begin(), [](const Point &p) { return p.Y(); });
std::transform(points_.begin(), points_.end(), out.begin(),
[](const std::shared_ptr<Point> &p) { return p->Y(); });
return out;
}
void Y(const std::vector<double> &in)
Expand All @@ -83,14 +93,15 @@ class Points
throw std::runtime_error("Y setter array must be same size as Points array!");

for (unsigned i = 0; i < points_.size(); ++i)
points_[i].Y(in[i]);
points_[i]->Y(in[i]);
}

std::vector<double> Z() const
{
std::vector<double> out;
out.resize(Size());
std::transform(points_.begin(), points_.end(), out.begin(), [](const Point &p) { return p.Z(); });
std::transform(points_.begin(), points_.end(), out.begin(),
[](const std::shared_ptr<Point> &p) { return p->Z(); });
return out;
}
void Z(const std::vector<double> &in)
Expand All @@ -99,11 +110,11 @@ class Points
throw std::runtime_error("Z setter array must be same size as Points array!");

for (unsigned i = 0; i < points_.size(); ++i)
points_[i].Z(in[i]);
points_[i]->Z(in[i]);
}

private:
std::vector<Point> points_;
std::vector<std::shared_ptr<Point>> points_;
int8_t point_format_id_;
uint32_t point_record_length_;
Vector3 scale_;
Expand Down
5 changes: 5 additions & 0 deletions pyproject.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
[tool.pytest.ini_options]
minversion = "6.0"
testpaths = [
"test"
]
CCInc marked this conversation as resolved.
Show resolved Hide resolved
31 changes: 24 additions & 7 deletions python/bindings.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ PYBIND11_MODULE(copclib, m)
.def("ChildOf", &VoxelKey::ChildOf, py::arg("parent_key"))
.def("__str__", &VoxelKey::ToString)
.def("__repr__", &VoxelKey::ToString);
py::implicitly_convertible<py::tuple, VoxelKey>();
CCInc marked this conversation as resolved.
Show resolved Hide resolved

py::class_<Node>(m, "Node")
.def(py::init<>())
Expand Down Expand Up @@ -79,10 +80,9 @@ PYBIND11_MODULE(copclib, m)
.def(py::self == py::self)
.def("__str__", &Vector3::ToString)
.def("__repr__", &Vector3::ToString);

py::implicitly_convertible<py::list, Vector3>();

py::class_<las::Point>(m, "Point")
py::class_<las::Point, std::shared_ptr<las::Point>>(m, "Point")
.def_property("X", py::overload_cast<>(&las::Point::X, py::const_),
py::overload_cast<const double &>(&las::Point::X))
.def_property("Y", py::overload_cast<>(&las::Point::Y, py::const_),
Expand Down Expand Up @@ -172,7 +172,7 @@ PYBIND11_MODULE(copclib, m)
py::class_<las::Points>(m, "Points")
.def(py::init<const uint8_t &, const Vector3 &, const Vector3 &, const uint16_t &>(),
py::arg("point_format_id"), py::arg("scale"), py::arg("offset"), py::arg("num_extra_bytes") = 0)
.def(py::init<const std::vector<las::Point> &>(), py::arg("points"))
.def(py::init<const std::vector<std::shared_ptr<las::Point>> &>(), py::arg("points"))
.def(py::init<const las::LasHeader &>())
.def_property("X", py::overload_cast<>(&las::Points::X, py::const_),
py::overload_cast<const std::vector<double> &>(&las::Points::X))
Expand All @@ -183,18 +183,35 @@ PYBIND11_MODULE(copclib, m)
.def_property_readonly("PointFormatID", &las::Points::PointFormatID)
.def_property_readonly("PointRecordLength", &las::Points::PointRecordLength)
.def_property_readonly("NumExtraBytes", &las::Points::NumExtraBytes)
.def("Get", py::overload_cast<>(&las::Points::Get))
.def("Get", py::overload_cast<const size_t &>(&las::Points::Get), py::arg("idx"))
.def_property_readonly("Size", &las::Points::Size)
.def("AddPoint", &las::Points::AddPoint)
.def("AddPoints", py::overload_cast<las::Points>(&las::Points::AddPoints))
.def("AddPoints", py::overload_cast<std::vector<las::Point>>(&las::Points::AddPoints))
.def("AddPoints", py::overload_cast<std::vector<std::shared_ptr<las::Point>>>(&las::Points::AddPoints))
.def("CreatePoint", &las::Points::CreatePoint)
.def("ToPointFormat", &las::Points::ToPointFormat, py::arg("point_format_id"))
.def("Pack", py::overload_cast<>(&las::Points::Pack))
.def("Unpack", py::overload_cast<const std::vector<char> &, const las::LasHeader &>(&las::Points::Unpack))
.def("Unpack", py::overload_cast<const std::vector<char> &, const int8_t &, const uint16_t &, const Vector3 &,
const Vector3 &>(&las::Points::Unpack))
/// Bare bones interface
.def("__getitem__",
[](const las::Points &s, size_t i) {
if (i >= s.Size())
throw py::index_error();
return s[i];
})
.def("__setitem__",
[](las::Points &s, size_t i, std::shared_ptr<las::Point> v) {
if (i >= s.Size())
throw py::index_error();
s[i] = v;
})
.def("__len__", &las::Points::Size)
/// Optional sequence protocol operations
.def(
"__iter__", [](las::Points &s) { return py::make_iterator(s.begin(), s.end()); },
py::keep_alive<0, 1>() /* Essential: keep object alive while iterator exists */)
.def("__contains__",
[](las::Points &s, std::shared_ptr<las::Point> v) { return std::find(s.begin(), s.end(), v) != s.end(); })
.def("__str__", &las::Points::ToString)
.def("__repr__", &las::Points::ToString);

Expand Down
54 changes: 27 additions & 27 deletions src/las/point.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -97,50 +97,50 @@ bool Point::operator==(const Point &other) const
return true;
}

Point Point::Unpack(std::istream &in_stream, const int8_t &point_format_id, const Vector3 &scale, const Vector3 &offset,
const uint16_t &num_extra_bytes)
std::shared_ptr<Point> Point::Unpack(std::istream &in_stream, const int8_t &point_format_id, const Vector3 &scale,
const Vector3 &offset, const uint16_t &num_extra_bytes)
{
Point p(point_format_id, scale, offset, num_extra_bytes);
std::shared_ptr<Point> p = std::make_shared<Point>(point_format_id, scale, offset, num_extra_bytes);

p.x_ = unpack<int32_t>(in_stream);
p.y_ = unpack<int32_t>(in_stream);
p.z_ = unpack<int32_t>(in_stream);
p.intensity_ = unpack<uint16_t>(in_stream);
if (p.extended_point_type_)
p->x_ = unpack<int32_t>(in_stream);
p->y_ = unpack<int32_t>(in_stream);
p->z_ = unpack<int32_t>(in_stream);
p->intensity_ = unpack<uint16_t>(in_stream);
if (p->extended_point_type_)
{
p.extended_returns_ = unpack<uint8_t>(in_stream);
p.extended_flags_ = unpack<uint8_t>(in_stream);
p.extended_classification_ = unpack<uint8_t>(in_stream);
p.user_data_ = unpack<uint8_t>(in_stream);
p.extended_scan_angle_ = unpack<int16_t>(in_stream);
p->extended_returns_ = unpack<uint8_t>(in_stream);
p->extended_flags_ = unpack<uint8_t>(in_stream);
p->extended_classification_ = unpack<uint8_t>(in_stream);
p->user_data_ = unpack<uint8_t>(in_stream);
p->extended_scan_angle_ = unpack<int16_t>(in_stream);
}
else
{
p.returns_flags_eof_ = unpack<uint8_t>(in_stream);
p.classification_ = unpack<uint8_t>(in_stream);
p.scan_angle_rank_ = unpack<int8_t>(in_stream);
p.user_data_ = unpack<uint8_t>(in_stream);
p->returns_flags_eof_ = unpack<uint8_t>(in_stream);
p->classification_ = unpack<uint8_t>(in_stream);
p->scan_angle_rank_ = unpack<int8_t>(in_stream);
p->user_data_ = unpack<uint8_t>(in_stream);
}
p.point_source_id_ = unpack<uint16_t>(in_stream);
p->point_source_id_ = unpack<uint16_t>(in_stream);

if (p.has_gps_time_)
if (p->has_gps_time_)
{
p.gps_time_ = unpack<double>(in_stream);
p->gps_time_ = unpack<double>(in_stream);
}
if (p.has_rgb_)
if (p->has_rgb_)
{
p.rgb_[0] = unpack<uint16_t>(in_stream);
p.rgb_[1] = unpack<uint16_t>(in_stream);
p.rgb_[2] = unpack<uint16_t>(in_stream);
p->rgb_[0] = unpack<uint16_t>(in_stream);
p->rgb_[1] = unpack<uint16_t>(in_stream);
p->rgb_[2] = unpack<uint16_t>(in_stream);
}
if (p.has_nir_)
if (p->has_nir_)
{
p.nir_ = unpack<uint16_t>(in_stream);
p->nir_ = unpack<uint16_t>(in_stream);
}

for (uint32_t i = 0; i < num_extra_bytes; i++)
{
p.extra_bytes_[i] = unpack<uint8_t>(in_stream);
p->extra_bytes_[i] = unpack<uint8_t>(in_stream);
}
return p;
}
Expand Down
22 changes: 11 additions & 11 deletions src/las/points.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -20,15 +20,15 @@ Points::Points(const int8_t &point_format_id, const Vector3 &scale, const Vector
Points::Points(const LasHeader &header)
: Points(header.point_format_id, header.scale, header.offset, header.NumExtraBytes()){};

Points::Points(const std::vector<Point> &points)
Points::Points(const std::vector<std::shared_ptr<Point>> &points)
{
if (points.empty())
throw std::runtime_error("Can't add empty vector of points to Points!");

point_record_length_ = points[0].PointRecordLength();
point_format_id_ = points[0].PointFormatID();
scale_ = points[0].Scale();
offset_ = points[0].Offset();
point_record_length_ = points[0]->PointRecordLength();
point_format_id_ = points[0]->PointFormatID();
scale_ = points[0]->Scale();
offset_ = points[0]->Offset();

AddPoints(points);
}
Expand All @@ -38,13 +38,13 @@ void Points::ToPointFormat(const int8_t &point_format_id)
if (point_format_id < 0 || point_format_id > 10)
throw std::runtime_error("Point format must be 0-10.");
for (auto &point : points_)
point.ToPointFormat(point_format_id);
point->ToPointFormat(point_format_id);
point_format_id_ = point_format_id;
}

void Points::AddPoint(const Point &point)
void Points::AddPoint(const std::shared_ptr<Point> &point)
{
if (point.PointFormatID() == point_format_id_ && point.PointRecordLength() == point_record_length_)
if (point->PointFormatID() == point_format_id_ && point->PointRecordLength() == point_record_length_)
points_.push_back(point);
else
throw std::runtime_error("New point must be of same format and byte_size.");
Expand All @@ -59,11 +59,11 @@ void Points::AddPoints(Points points)
points_.insert(points_.end(), point_vec.begin(), point_vec.end());
}

void Points::AddPoints(std::vector<las::Point> points)
void Points::AddPoints(std::vector<std::shared_ptr<Point>> points)
{
for (const auto &point : points)
{
if (point.PointFormatID() != point_format_id_ || point.PointRecordLength() != point_record_length_)
if (point->PointFormatID() != point_format_id_ || point->PointRecordLength() != point_record_length_)
throw std::runtime_error("New points must be of same format and byte_size.");
}

Expand Down Expand Up @@ -103,7 +103,7 @@ Points Points::Unpack(const std::vector<char> &point_data, const int8_t &point_f
void Points::Pack(std::ostream &out_stream)
{
for (const auto &point : points_)
point.Pack(out_stream);
point->Pack(out_stream);
}

std::vector<char> Points::Pack()
Expand Down
Loading