Skip to content

Commit a69ca4e

Browse files
leo-stanclee-ai
andauthored
FEAT-865: LAZ writer (#104)
* Fix precommit bug with black. * Fix precommit unauthenticated git protocol error. * Rename elements to prepare for LAZ writer. * Add scaffolding for LAZ writer. * Update LAZ writer init function. * Implement LazConfig and LazConfigWriter. * Fixing LazConfig tests. * Start to implement BaseWriter class. * Finish implementation of LAZ base writer. * Prototype LAZ writer. * Finish and test LAZ writer. * Hide base writer header file. * Implement LasHeader UpdateBounds. * Typo. * Rename LasHeader::UpdateBounds to CheckAndUpdateBounds and small clean-ups. * Revert "Rename LasHeader::UpdateBounds to CheckAndUpdateBounds and small clean-ups." This reverts commit a97719c. * Fix bug with laz writer VLRs. * Refactor OffsetToPointData. * Fix OffsetToPointData. * Implement pointer casting between laz and copc config classes to avoid code duplication. * Small changes from PR review. * Clean-up. * Refactor file writing into a base class. * Refactor WriteChunk into BaseWriter to remove code duplication. * Clean-up. * Clean-up. * Clean-up. * Miscellaneous improvements and clean-up. * Miscellaneous improvements and clean-up. * Fix seekg types. * Rename CheckAndUpdateBounds and add SetGpsTimeBit. * Refactor header space fill to BaseWriter and rename LasHeader::SIZE_BYTES to LasHeader::HEADER_SIZE_BYTES. * Fix github test runs. * Update LasHeader GpsTime type bit tests. * Revert "Update LasHeader GpsTime type bit tests." This reverts commit 187dbb1. * Revert "Refactor header space fill to BaseWriter and rename LasHeader::SIZE_BYTES to LasHeader::HEADER_SIZE_BYTES." This reverts commit e843c4d. * Revert "Rename CheckAndUpdateBounds and add SetGpsTimeBit." This reverts commit 18ec87b. * Revert "Revert "Refactor header space fill to BaseWriter and rename LasHeader::SIZE_BYTES to LasHeader::HEADER_SIZE_BYTES."" This reverts commit d404323. * Fix refactoring of std::fill_n. * Revert "Revert "Rename CheckAndUpdateBounds and add SetGpsTimeBit."" This reverts commit 7f8309c. * Fix tests after CheckAndUpdateBounds name change. * Revert "Revert "Update LasHeader GpsTime type bit tests."" This reverts commit 94fc920. * Fix return type of LasHeader::ApplyInverseScale. * Fix return type of LasHeader::ApplyInverseScale. * Fix bug in filepath in writer_test.py. * Remove remaining static_cast<long>. * Revert fill_n changes. * Change type of LasHeader::RemoveScale from int64 to in32. * Fix IsCopc typos. Co-authored-by: Christopher Lee <[email protected]>
1 parent fb44ed1 commit a69ca4e

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

53 files changed

+1547
-610
lines changed

CHANGELOG.md

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,19 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
77

88
## [Unreleased]
99

10+
### Added
11+
- **\[C++\]** Add `LazConfig` and `LazConfigWriter` classes as parent class to `CopcConfig` to handle LAZ files.
12+
- **\[C++\]** Add `LazWriter` and `LazFileWriter` classes to write LAZ files.
13+
- **\[C++\]** Add `example-laz-writer.cpp` to show how to use the LAZ writer.
14+
- **\[Python/C++\]** Add `CheckAndUpdateBounds` to `LasHeader` to check values in a `Point` and update the bounds if necessary.
15+
- **\[Python/C++\]** Add `SetGpsTimeBit` to `LasHeader` to easily set the bit value to 1.
16+
17+
### Changed
18+
- **\[Python/C++\]** Rename `LasHeader::ApplyInverseScale` to `LasHeader::RemoveScale` to be consistent with `Point` class.
19+
20+
### Fixed
21+
- **\[Python/C++\]** Change return type of `LasHeader::ApplyInverseScale` from `double` to `int32_t`.
22+
1023
## [2.2.3] - 2022-02-02
1124

1225
### Fixed

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -82,7 +82,7 @@ add_executable(funlib fun-main.cpp)
8282
target_link_libraries(funlib COPCLIB::copc-lib LAZPERF::lazperf)
8383
```
8484

85-
The primary public interface will be your [FileReader](./cpp/include/copc-lib/io/reader.hpp) and [FileWriter](./cpp/include/copc-lib/io/writer.hpp) objects. Check the headers and [example files](./example) for documentation.
85+
The primary public interface will be your [FileReader](./cpp/include/copc-lib/io/copc_reader.hpp) and [FileWriter](./cpp/include/copc-lib/io/copc_writer.hpp) objects. Check the headers and [example files](./example) for documentation.
8686

8787
```cpp
8888
#include <iostream>

cpp/CMakeLists.txt

Lines changed: 16 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -4,21 +4,24 @@ set(LIBRARY_TARGET_NAME copc-lib)
44
set(${LIBRARY_TARGET_NAME}_HDR
55
include/${LIBRARY_TARGET_NAME}/copc/info.hpp
66
include/${LIBRARY_TARGET_NAME}/copc/extents.hpp
7-
include/${LIBRARY_TARGET_NAME}/copc/config.hpp
7+
include/${LIBRARY_TARGET_NAME}/copc/copc_config.hpp
88
include/${LIBRARY_TARGET_NAME}/geometry/box.hpp
99
include/${LIBRARY_TARGET_NAME}/geometry/vector3.hpp
1010
include/${LIBRARY_TARGET_NAME}/hierarchy/entry.hpp
1111
include/${LIBRARY_TARGET_NAME}/hierarchy/key.hpp
1212
include/${LIBRARY_TARGET_NAME}/hierarchy/node.hpp
1313
include/${LIBRARY_TARGET_NAME}/hierarchy/page.hpp
14-
include/${LIBRARY_TARGET_NAME}/io/base_io.hpp
15-
include/${LIBRARY_TARGET_NAME}/io/reader.hpp
16-
include/${LIBRARY_TARGET_NAME}/io/writer.hpp
14+
include/${LIBRARY_TARGET_NAME}/io/copc_base_io.hpp
15+
include/${LIBRARY_TARGET_NAME}/io/copc_reader.hpp
16+
include/${LIBRARY_TARGET_NAME}/io/copc_writer.hpp
17+
include/${LIBRARY_TARGET_NAME}/io/laz_writer.hpp
1718
include/${LIBRARY_TARGET_NAME}/las/header.hpp
19+
include/${LIBRARY_TARGET_NAME}/io/laz_base_writer.hpp
1820
include/${LIBRARY_TARGET_NAME}/las/point.hpp
1921
include/${LIBRARY_TARGET_NAME}/las/points.hpp
2022
include/${LIBRARY_TARGET_NAME}/las/utils.hpp
2123
include/${LIBRARY_TARGET_NAME}/las/vlr.hpp
24+
include/${LIBRARY_TARGET_NAME}/las/laz_config.hpp
2225
include/${LIBRARY_TARGET_NAME}/laz/compressor.hpp
2326
include/${LIBRARY_TARGET_NAME}/laz/decompressor.hpp
2427
)
@@ -27,22 +30,25 @@ set(${LIBRARY_TARGET_NAME}_HDR
2730
set(${LIBRARY_TARGET_NAME}_SRC
2831
include/${LIBRARY_TARGET_NAME}/hierarchy/internal/page.hpp
2932
include/${LIBRARY_TARGET_NAME}/hierarchy/internal/hierarchy.hpp
30-
include/${LIBRARY_TARGET_NAME}/io/internal/writer_internal.hpp
33+
include/${LIBRARY_TARGET_NAME}/io/internal/copc_writer_internal.hpp
3134
src/copc/info.cpp
3235
src/copc/extents.cpp
33-
src/copc/config.cpp
36+
src/copc/copc_config.cpp
3437
src/geometry/box.cpp
3538
src/hierarchy/key.cpp
3639
src/hierarchy/page.cpp
37-
src/io/base_io.cpp
38-
src/io/reader.cpp
39-
src/io/writer_internal.cpp
40-
src/io/writer_public.cpp
40+
src/io/copc_base_io.cpp
41+
src/io/copc_reader.cpp
42+
src/io/copc_writer_internal.cpp
43+
src/io/copc_writer_public.cpp
44+
src/io/laz_base_writer.cpp
45+
src/io/laz_writer.cpp
4146
src/las/header.cpp
4247
src/las/point.cpp
4348
src/las/points.cpp
4449
src/las/utils.cpp
4550
src/las/vlr.cpp
51+
src/las/laz_config.cpp
4652
)
4753

4854
# Compile static library for pip wheels

cpp/include/copc-lib/copc/config.hpp renamed to cpp/include/copc-lib/copc/copc_config.hpp

Lines changed: 4 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -7,42 +7,32 @@
77
#include "copc-lib/copc/extents.hpp"
88
#include "copc-lib/copc/info.hpp"
99
#include "copc-lib/las/header.hpp"
10+
#include "copc-lib/las/laz_config.hpp"
1011
#include "copc-lib/las/utils.hpp"
1112
#include "copc-lib/las/vlr.hpp"
1213

1314
namespace copc
1415
{
15-
const int COPC_OFFSET = 429;
1616

17-
class CopcConfig
17+
class CopcConfig : public las::LazConfig
1818
{
1919
public:
2020
CopcConfig() = default;
2121
CopcConfig(const las::LasHeader &header, const CopcInfo &copc_info, const CopcExtents &copc_extents,
2222
const std::string &wkt, const las::EbVlr &extra_bytes_vlr)
23-
: header_(std::make_shared<las::LasHeader>(header)), copc_info_(std::make_shared<copc::CopcInfo>(copc_info)),
24-
copc_extents_(std::make_shared<copc::CopcExtents>(copc_extents)), wkt_(wkt),
25-
eb_vlr_(std::make_shared<las::EbVlr>(extra_bytes_vlr)){};
26-
27-
virtual las::LasHeader LasHeader() const { return *header_; }
23+
: LazConfig(header, wkt, extra_bytes_vlr), copc_info_(std::make_shared<copc::CopcInfo>(copc_info)),
24+
copc_extents_(std::make_shared<copc::CopcExtents>(copc_extents)){};
2825

2926
virtual copc::CopcInfo CopcInfo() const { return *copc_info_; }
3027

3128
virtual copc::CopcExtents CopcExtents() const { return *copc_extents_; }
3229

33-
std::string Wkt() const { return wkt_; }
34-
35-
las::EbVlr ExtraBytesVlr() const { return *eb_vlr_; }
36-
3730
protected:
3831
CopcConfig(const int8_t &point_format_id, const Vector3 &scale, const Vector3 &offset, const std::string &wkt,
3932
const las::EbVlr &extra_bytes_vlr, bool has_extended_stats);
4033

41-
std::shared_ptr<las::LasHeader> header_;
4234
std::shared_ptr<copc::CopcInfo> copc_info_;
4335
std::shared_ptr<copc::CopcExtents> copc_extents_;
44-
std::string wkt_;
45-
std::shared_ptr<las::EbVlr> eb_vlr_;
4636
};
4737

4838
class CopcConfigWriter : public CopcConfig

cpp/include/copc-lib/copc/extents.hpp

Lines changed: 22 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
#define COPCLIB_COPC_EXTENTS_H_
33

44
#include <string>
5+
#include <utility>
56
#include <vector>
67

78
#include <lazperf/vlr.hpp>
@@ -129,43 +130,49 @@ class CopcExtents
129130
}
130131

131132
// Setters for python bindings
132-
void Intensity(std::shared_ptr<CopcExtent> intensity) { extents_[0] = intensity; }
133-
void ReturnNumber(std::shared_ptr<CopcExtent> return_number) { extents_[1] = return_number; }
134-
void NumberOfReturns(std::shared_ptr<CopcExtent> number_of_returns) { extents_[2] = number_of_returns; }
135-
void ScannerChannel(std::shared_ptr<CopcExtent> scanner_channel) { extents_[3] = scanner_channel; }
136-
void ScanDirectionFlag(std::shared_ptr<CopcExtent> scan_direction_flag) { extents_[4] = scan_direction_flag; }
137-
void EdgeOfFlightLine(std::shared_ptr<CopcExtent> edge_of_flight_line) { extents_[5] = edge_of_flight_line; }
138-
void Classification(std::shared_ptr<CopcExtent> classification) { extents_[6] = classification; }
139-
void UserData(std::shared_ptr<CopcExtent> user_data) { extents_[7] = user_data; }
140-
void ScanAngle(std::shared_ptr<CopcExtent> scan_angle) { extents_[8] = scan_angle; }
141-
void PointSourceId(std::shared_ptr<CopcExtent> point_source_id) { extents_[9] = point_source_id; }
142-
void GpsTime(std::shared_ptr<CopcExtent> gps_time) { extents_[10] = gps_time; }
133+
void Intensity(std::shared_ptr<CopcExtent> intensity) { extents_[0] = std::move(intensity); }
134+
void ReturnNumber(std::shared_ptr<CopcExtent> return_number) { extents_[1] = std::move(return_number); }
135+
void NumberOfReturns(std::shared_ptr<CopcExtent> number_of_returns) { extents_[2] = std::move(number_of_returns); }
136+
void ScannerChannel(std::shared_ptr<CopcExtent> scanner_channel) { extents_[3] = std::move(scanner_channel); }
137+
void ScanDirectionFlag(std::shared_ptr<CopcExtent> scan_direction_flag)
138+
{
139+
extents_[4] = std::move(scan_direction_flag);
140+
}
141+
void EdgeOfFlightLine(std::shared_ptr<CopcExtent> edge_of_flight_line)
142+
{
143+
extents_[5] = std::move(edge_of_flight_line);
144+
}
145+
void Classification(std::shared_ptr<CopcExtent> classification) { extents_[6] = std::move(classification); }
146+
void UserData(std::shared_ptr<CopcExtent> user_data) { extents_[7] = std::move(user_data); }
147+
void ScanAngle(std::shared_ptr<CopcExtent> scan_angle) { extents_[8] = std::move(scan_angle); }
148+
void PointSourceId(std::shared_ptr<CopcExtent> point_source_id) { extents_[9] = std::move(point_source_id); }
149+
void GpsTime(std::shared_ptr<CopcExtent> gps_time) { extents_[10] = std::move(gps_time); }
143150
void Red(std::shared_ptr<CopcExtent> red)
144151
{
145152
if (point_format_id_ > 6)
146-
extents_[1] = red;
153+
extents_[1] = std::move(red);
147154
else
148155
throw std::runtime_error("CopcExtents::Red: This point format does not have Red");
149156
}
150157
void Green(std::shared_ptr<CopcExtent> green)
151158
{
152159
if (point_format_id_ > 6)
153-
extents_[12] = green;
160+
extents_[12] = std::move(green);
154161
else
155162
throw std::runtime_error("CopcExtents::Green: This point format does not have Green");
156163
}
157164
void Blue(std::shared_ptr<CopcExtent> blue)
158165
{
159166
if (point_format_id_ > 6)
160-
extents_[13] = blue;
167+
extents_[13] = std::move(blue);
161168
else
162169
throw std::runtime_error("CopcExtents::Blue: This point format does not have Blue");
163170
}
164171

165172
void Nir(std::shared_ptr<CopcExtent> nir)
166173
{
167174
if (point_format_id_ == 8)
168-
extents_[14] = nir;
175+
extents_[14] = std::move(nir);
169176
else
170177
throw std::runtime_error("CopcExtents::NIR: This point format does not have NIR");
171178
}

cpp/include/copc-lib/copc/info.hpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,9 @@ namespace copc
1111
class CopcInfo
1212
{
1313
public:
14+
static const int VLR_OFFSET = 375; // COPC Info VLR must be the first VLR after the LAS header block
15+
static const int VLR_SIZE_BYTES = 160; // COPC Info VLR payload is 160 bytes, https://copc.io/
16+
1417
CopcInfo() = default;
1518

1619
CopcInfo(const lazperf::copc_info_vlr &copc_info_vlr);

cpp/include/copc-lib/hierarchy/entry.hpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ class Entry
1717
static const int ENTRY_SIZE = 32;
1818

1919
Entry() : offset(-1), byte_size(-1), key(VoxelKey::InvalidKey()), point_count(-1){};
20-
Entry(VoxelKey key, int64_t offset, int32_t size, int32_t point_count)
20+
Entry(VoxelKey key, uint64_t offset, int32_t size, int32_t point_count)
2121
: offset(offset), byte_size(size), key(key), point_count(point_count){};
2222

2323
virtual bool IsValid() const { return offset >= 0 && byte_size >= 0 && key.IsValid(); }

cpp/include/copc-lib/hierarchy/internal/page.hpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33

44
#include <set>
55
#include <unordered_map>
6+
#include <utility>
67

78
#include "copc-lib/hierarchy/page.hpp"
89

@@ -13,7 +14,7 @@ class PageInternal;
1314
class PageInternal : public Page
1415
{
1516
public:
16-
PageInternal(Entry e) : Page(e){};
17+
PageInternal(Entry e) : Page(std::move(e)){};
1718
PageInternal(VoxelKey key, int64_t offset, int32_t byte_size) : Page(key, offset, byte_size){};
1819
PageInternal(VoxelKey key) : Page(key, -1, -1){};
1920

cpp/include/copc-lib/hierarchy/page.hpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33

44
#include <istream>
55
#include <memory>
6+
#include <utility>
67

78
#include "copc-lib/hierarchy/entry.hpp"
89
#include "copc-lib/hierarchy/node.hpp"
@@ -13,7 +14,7 @@ class Page;
1314
class Page : public Entry
1415
{
1516
public:
16-
Page(Entry e) : Entry(e){};
17+
Page(Entry e) : Entry(std::move(e)){};
1718
Page(VoxelKey key, int64_t offset, int32_t byte_size) : Entry(key, offset, byte_size, -1){};
1819

1920
// If a page is "loaded" it doesn't matter the offset/size

cpp/include/copc-lib/io/base_io.hpp renamed to cpp/include/copc-lib/io/copc_base_io.hpp

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
1-
#ifndef COPCLIB_IO_BASE_H_
2-
#define COPCLIB_IO_BASE_H_
1+
#ifndef COPCLIB_IO_COPC_BASE_IO_H_
2+
#define COPCLIB_IO_COPC_BASE_IO_H_
33

4-
#include "copc-lib/copc/config.hpp"
4+
#include "copc-lib/copc/copc_config.hpp"
55
#include "copc-lib/copc/extents.hpp"
66
#include "copc-lib/copc/info.hpp"
77
#include "copc-lib/hierarchy/node.hpp"
@@ -34,4 +34,4 @@ class BaseIO
3434
};
3535

3636
} // namespace copc
37-
#endif // COPCLIB_IO_BASE_H_
37+
#endif // COPCLIB_IO_COPC_BASE_IO_H_

cpp/include/copc-lib/io/reader.hpp renamed to cpp/include/copc-lib/io/copc_reader.hpp

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,14 @@
1-
#ifndef COPCLIB_IO_READER_H_
2-
#define COPCLIB_IO_READER_H_
1+
#ifndef COPCLIB_IO_COPC_READER_H_
2+
#define COPCLIB_IO_COPC_READER_H_
33

44
#include <istream>
55
#include <limits>
66
#include <map>
77
#include <string>
88

9-
#include "copc-lib/copc/config.hpp"
9+
#include "copc-lib/copc/copc_config.hpp"
1010
#include "copc-lib/hierarchy/key.hpp"
11-
#include "copc-lib/io/base_io.hpp"
11+
#include "copc-lib/io/copc_base_io.hpp"
1212
#include "copc-lib/las/points.hpp"
1313
#include "copc-lib/las/vlr.hpp"
1414

@@ -84,7 +84,7 @@ class Reader : public BaseIO
8484
static uint64_t FetchVlr(const std::map<uint64_t, las::VlrHeader> &vlrs, const std::string &user_id,
8585
uint16_t record_id);
8686
// Finds and loads the COPC vlr
87-
CopcInfo ReadCopcInfoVlr();
87+
CopcInfo ReadCopcInfoVlr(std::map<uint64_t, las::VlrHeader> &vlrs);
8888
// Finds and loads the COPC vlr
8989
CopcExtents ReadCopcExtentsVlr(std::map<uint64_t, las::VlrHeader> &vlrs, const las::EbVlr &eb_vlr) const;
9090
// Finds and loads the WKT vlr
@@ -126,4 +126,4 @@ class FileReader : public Reader
126126
};
127127

128128
} // namespace copc
129-
#endif // COPCLIB_IO_READER_H_
129+
#endif // COPCLIB_IO_COPC_READER_H_

0 commit comments

Comments
 (0)