Skip to content

Commit 08b83dd

Browse files
authored
Merge pull request #378 from potree/extra_attributes
Extra attributes
2 parents 685ef56 + f77c87b commit 08b83dd

16 files changed

+416
-85
lines changed

PotreeConverter/include/BINPointWriter.hpp

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,7 @@ class BINPointWriter : public PointWriter{
5151
close();
5252
}
5353

54-
void write(const Point &point){
54+
void write(Point &point){
5555
for(int i = 0; i < attributes.size(); i++){
5656

5757
PointAttribute attribute = attributes[i];
@@ -129,6 +129,8 @@ class BINPointWriter : public PointWriter{
129129
}
130130
}
131131

132+
writer->write(reinterpret_cast<const char*>(point.extraBytes.data()), point.extraBytes.size());
133+
132134
numPoints++;
133135
}
134136

PotreeConverter/include/CloudJS.hpp

Lines changed: 13 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -124,43 +124,19 @@ class CloudJS{
124124
Value version(this->version.c_str(), (rapidjson::SizeType)this->version.size());
125125
Value octreeDir("data");
126126
Value projection(this->projection.c_str(), (rapidjson::SizeType)this->projection.size());
127+
127128
Value boundingBox(rapidjson::kObjectType);
128129
{
129-
//Value min(rapidjson::kArrayType);
130-
//min.PushBack(this->boundingBox.min.x, d.GetAllocator());
131-
//min.PushBack(this->boundingBox.min.y, d.GetAllocator());
132-
//min.PushBack(this->boundingBox.min.z, d.GetAllocator());
133-
//
134-
//Value max(rapidjson::kArrayType);
135-
//max.PushBack(this->boundingBox.max.x, d.GetAllocator());
136-
//max.PushBack(this->boundingBox.max.y, d.GetAllocator());
137-
//max.PushBack(this->boundingBox.max.z, d.GetAllocator());
138-
//
139-
//boundingBox.AddMember("min", min, d.GetAllocator());
140-
//boundingBox.AddMember("max", max, d.GetAllocator());
141-
142130
boundingBox.AddMember("lx", this->boundingBox.min.x, d.GetAllocator());
143131
boundingBox.AddMember("ly", this->boundingBox.min.y, d.GetAllocator());
144132
boundingBox.AddMember("lz", this->boundingBox.min.z, d.GetAllocator());
145133
boundingBox.AddMember("ux", this->boundingBox.max.x, d.GetAllocator());
146134
boundingBox.AddMember("uy", this->boundingBox.max.y, d.GetAllocator());
147135
boundingBox.AddMember("uz", this->boundingBox.max.z, d.GetAllocator());
148136
}
137+
149138
Value tightBoundingBox(rapidjson::kObjectType);
150139
{
151-
//Value min(rapidjson::kArrayType);
152-
//min.PushBack(this->tightBoundingBox.min.x, d.GetAllocator());
153-
//min.PushBack(this->tightBoundingBox.min.y, d.GetAllocator());
154-
//min.PushBack(this->tightBoundingBox.min.z, d.GetAllocator());
155-
//
156-
//Value max(rapidjson::kArrayType);
157-
//max.PushBack(this->tightBoundingBox.max.x, d.GetAllocator());
158-
//max.PushBack(this->tightBoundingBox.max.y, d.GetAllocator());
159-
//max.PushBack(this->tightBoundingBox.max.z, d.GetAllocator());
160-
//
161-
//tightBoundingBox.AddMember("min", min, d.GetAllocator());
162-
//tightBoundingBox.AddMember("max", max, d.GetAllocator());
163-
164140
tightBoundingBox.AddMember("lx", this->tightBoundingBox.min.x, d.GetAllocator());
165141
tightBoundingBox.AddMember("ly", this->tightBoundingBox.min.y, d.GetAllocator());
166142
tightBoundingBox.AddMember("lz", this->tightBoundingBox.min.z, d.GetAllocator());
@@ -174,8 +150,17 @@ class CloudJS{
174150
pointAttributes.SetArray();
175151
for(int i = 0; i < this->pointAttributes.size(); i++){
176152
PointAttribute attribute = this->pointAttributes[i];
177-
Value str(attribute.name.c_str(), d.GetAllocator());
178-
pointAttributes.PushBack(str, d.GetAllocator());
153+
154+
155+
Value vAttribute(rapidjson::kObjectType);
156+
vAttribute.AddMember("name", Value(attribute.name.c_str(), d.GetAllocator()), d.GetAllocator());
157+
vAttribute.AddMember("size", attribute.byteSize, d.GetAllocator());
158+
vAttribute.AddMember("elements", attribute.numElements, d.GetAllocator());
159+
vAttribute.AddMember("elementSize", attribute.byteSize / attribute.numElements, d.GetAllocator());
160+
vAttribute.AddMember("type", Value(attribute.type.c_str(), d.GetAllocator()), d.GetAllocator());
161+
vAttribute.AddMember("description", Value(attribute.description.c_str(), d.GetAllocator()), d.GetAllocator());
162+
163+
pointAttributes.PushBack(vAttribute, d.GetAllocator());
179164
}
180165
}else if(outputFormat == OutputFormat::LAS){
181166
pointAttributes = "LAS";
Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
1+
2+
#pragma once
3+
4+
#include <unordered_map>
5+
6+
using std::unordered_map;
7+
8+
// see LAS spec 1.4
9+
// https://www.asprs.org/wp-content/uploads/2010/12/LAS_1_4_r13.pdf
10+
// total of 192 bytes
11+
struct ExtraBytesRecord {
12+
unsigned char reserved[2];
13+
unsigned char data_type;
14+
unsigned char options;
15+
char name[32];
16+
unsigned char unused[4];
17+
int64_t no_data[3]; // 24 = 3*8 bytes // hack: not really int, can be double too
18+
int64_t min[3]; // 24 = 3*8 bytes // hack: not really int, can be double too
19+
int64_t max[3]; // 24 = 3*8 bytes // hack: not really int, can be double too
20+
double scale[3];
21+
double offset[3];
22+
char description[32];
23+
};
24+
25+
struct ExtraType {
26+
string type = "";
27+
int size = 0;
28+
int numElements = 0;
29+
};
30+
31+
//ExtraType extraTypeFromID(int id) {
32+
// if (id == 0) {
33+
// return ExtraType{ "undefined", 0, 1 };
34+
// }else if (id == 1) {
35+
// return ExtraType{ "uint8", 1, 1 };
36+
// }else if (id == 2) {
37+
// return ExtraType{ "int8", 1, 1 };
38+
// }else if (id == 3) {
39+
// return ExtraType{ "uint16", 2, 1 };
40+
// }else if (id == 4) {
41+
// return ExtraType{ "int16", 2, 1 };
42+
// }else if (id == 5) {
43+
// return ExtraType{ "uint32", 4, 1 };
44+
// }else if (id == 6) {
45+
// return ExtraType{ "int32", 4, 1 };
46+
// }else if (id == 7) {
47+
// return ExtraType{ "uint64", 8, 1 };
48+
// }else if (id == 8) {
49+
// return ExtraType{ "int64", 8, 1 };
50+
// }else if (id == 9) {
51+
// return ExtraType{ "float", 4, 1 };
52+
// }else if (id == 10) {
53+
// return ExtraType{ "double", 8, 1 };
54+
// }
55+
//
56+
// cout << "ERROR: unsupported extra type: " << id << endl;
57+
// exit(123);
58+
//}
59+
60+
const unordered_map<unsigned char, ExtraType> typeToExtraType = {
61+
{0, ExtraType{"undefined", 0, 1}},
62+
{1, ExtraType{"uint8", 1, 1}},
63+
{2, ExtraType{"int8", 1, 1}},
64+
{3, ExtraType{"uint16", 2, 1}},
65+
{4, ExtraType{"int16", 2, 1}},
66+
{5, ExtraType{"uint32", 4, 1}},
67+
{6, ExtraType{"int32", 4, 1}},
68+
{7, ExtraType{"uint64", 8, 1}},
69+
{8, ExtraType{"int64", 8, 1}},
70+
{9, ExtraType{"float", 4, 1}},
71+
{10, ExtraType{"double", 8, 1}},
72+
};
73+
74+
75+
76+

PotreeConverter/include/LASPointReader.h

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
#include "Point.h"
1313
#include "PointReader.h"
1414
#include "stuff.h"
15+
#include "ExtraBytes.hpp"
1516

1617
using std::string;
1718

@@ -54,6 +55,7 @@ class LIBLASReader{
5455

5556
laszip_BOOL request_reader = 1;
5657
laszip_request_compatibility_mode(laszip_reader, request_reader);
58+
5759

5860
{// read first x points to find if color is 1 or 2 bytes
5961
laszip_BOOL is_compressed = iEndsWith(path, ".laz") ? 1 : 0;
@@ -66,7 +68,7 @@ class LIBLASReader{
6668
laszip_get_point_pointer(laszip_reader, &point);
6769

6870
colorScale = 1;
69-
for(int i = 0; i < 100000 && i < npoints; i++){
71+
for(int i = 0; i < 100'000 && i < npoints; i++){
7072
laszip_read_point(laszip_reader);
7173

7274
auto r = point->rgb[0];
@@ -124,6 +126,10 @@ class LIBLASReader{
124126
p.pointSourceID = point->point_source_ID;
125127
p.gpsTime = point->gps_time;
126128

129+
if (point->num_extra_bytes > 0) {
130+
p.extraBytes = vector<uint8_t>(point->extra_bytes, point->extra_bytes + point->num_extra_bytes);
131+
}
132+
127133
return p;
128134
}
129135
void close(){
@@ -133,7 +139,6 @@ class LIBLASReader{
133139
AABB getAABB();
134140
};
135141

136-
137142
class LASPointReader : public PointReader{
138143
private:
139144
AABB aabb;

PotreeConverter/include/LASPointWriter.hpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -78,7 +78,7 @@ class LASPointWriter : public PointWriter{
7878
close();
7979
}
8080

81-
void write(const Point &point);
81+
void write(Point &point);
8282

8383
void close(){
8484

PotreeConverter/include/Point.h

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,10 @@
55
#include "Vector3.h"
66

77
#include <iostream>
8+
#include <vector>
89

910
using std::ostream;
11+
using std::vector;
1012

1113
namespace Potree{
1214

@@ -22,7 +24,7 @@ class Point{
2224
unsigned char numberOfReturns = 0;
2325
unsigned short pointSourceID = 0;
2426
double gpsTime = 0.0;
25-
27+
vector<uint8_t> extraBytes;
2628

2729
Point() = default;
2830

PotreeConverter/include/PointAttributes.hpp

Lines changed: 30 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,12 +5,38 @@
55

66
#include <string>
77
#include <vector>
8+
#include <unordered_map>
89

910
using std::string;
1011
using std::vector;
12+
using std::unordered_map;
1113

1214
namespace Potree{
1315

16+
#define ATTRIBUTE_TYPE_INT8 "int8"
17+
#define ATTRIBUTE_TYPE_INT16 "int16"
18+
#define ATTRIBUTE_TYPE_INT32 "int32"
19+
#define ATTRIBUTE_TYPE_INT64 "int64"
20+
#define ATTRIBUTE_TYPE_UINT8 "uint8"
21+
#define ATTRIBUTE_TYPE_UINT16 "uint16"
22+
#define ATTRIBUTE_TYPE_UINT32 "uint32"
23+
#define ATTRIBUTE_TYPE_UINT64 "uint64"
24+
#define ATTRIBUTE_TYPE_FLOAT "float"
25+
#define ATTRIBUTE_TYPE_DOUBLE "double"
26+
27+
const unordered_map<string, int> attributeTypeSize = {
28+
{ATTRIBUTE_TYPE_INT8, 1},
29+
{ATTRIBUTE_TYPE_INT16, 2},
30+
{ATTRIBUTE_TYPE_INT32, 4},
31+
{ATTRIBUTE_TYPE_INT64, 8},
32+
{ATTRIBUTE_TYPE_UINT8, 1},
33+
{ATTRIBUTE_TYPE_UINT16, 2},
34+
{ATTRIBUTE_TYPE_UINT32, 4},
35+
{ATTRIBUTE_TYPE_UINT64, 8},
36+
{ATTRIBUTE_TYPE_FLOAT, 4},
37+
{ATTRIBUTE_TYPE_DOUBLE, 8}
38+
};
39+
1440
class PointAttribute{
1541
public:
1642
static const PointAttribute POSITION_CARTESIAN;
@@ -27,12 +53,15 @@ class PointAttribute{
2753

2854
int ordinal;
2955
string name;
56+
string description;
57+
string type;
3058
int numElements;
3159
int byteSize;
3260

33-
PointAttribute(int ordinal, string name, int numElements, int byteSize){
61+
PointAttribute(int ordinal, string name, string type, int numElements, int byteSize){
3462
this->ordinal = ordinal;
3563
this->name = name;
64+
this->type = type;
3665
this->numElements = numElements;
3766
this->byteSize = byteSize;
3867
}

PotreeConverter/include/PointWriter.hpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ class PointWriter{
1919

2020
virtual ~PointWriter(){};
2121

22-
virtual void write(const Point &point) = 0;
22+
virtual void write(Point &point) = 0;
2323

2424
virtual void close() = 0;
2525

PotreeConverter/include/PotreeConverter.h

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,11 @@ namespace Potree{
1919

2020
class SparseGrid;
2121

22+
struct FileInfos {
23+
AABB aabb;
24+
uint64_t numPoints = 0;
25+
};
26+
2227
class PotreeConverter{
2328

2429
private:
@@ -30,7 +35,7 @@ class PotreeConverter{
3035

3136
PointReader *createPointReader(string source, PointAttributes pointAttributes);
3237
void prepare();
33-
AABB calculateAABB();
38+
FileInfos computeInfos();
3439
void generatePage(string name);
3540

3641
public:

PotreeConverter/include/Vector3.h

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,8 @@
44

55
#include <math.h>
66
#include <iostream>
7+
#include <iomanip>
8+
#include <sstream>
79

810
using std::ostream;
911
#ifndef _MSC_VER
@@ -79,7 +81,12 @@ class Vector3{
7981
}
8082

8183
friend ostream &operator<<( ostream &output, const Vector3<T> &value ){
82-
output << "[" << value.x << ", " << value.y << ", " << value.z << "]" ;
84+
std::stringstream ss;
85+
ss << std::setprecision(6) << std::fixed;
86+
ss << "[" << value.x << ", " << value.y << ", " << value.z << "]";
87+
88+
output << ss.str();
89+
8390
return output;
8491
}
8592
};

0 commit comments

Comments
 (0)