1 /******************************************************************************
2 * Copyright (c) 2011, Michael P. Gerlek (mpg@flaxen.com)
3 *
4 * All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following
8 * conditions are met:
9 *
10 * * Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * * Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in
14 * the documentation and/or other materials provided
15 * with the distribution.
16 * * Neither the name of Hobu, Inc. or Flaxen Geo Consulting nor the
17 * names of its contributors may be used to endorse or promote
18 * products derived from this software without specific prior
19 * written permission.
20 *
21 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
22 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
23 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
24 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
25 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
26 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
27 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
28 * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
29 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
30 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
31 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
32 * OF SUCH DAMAGE.
33 ****************************************************************************/
34
35 #include <pdal/pdal_test_main.hpp>
36
37 #include <pdal/PointTable.hpp>
38 #include <io/LasReader.hpp>
39 #include "Support.hpp"
40
41 namespace pdal
42 {
43
TEST(PointTable,resolveType)44 TEST(PointTable, resolveType)
45 {
46 using namespace Dimension;
47
48 PointTable table;
49 PointLayoutPtr layout(table.layout());
50
51 // Start with a default-defined dimension.
52 layout->registerDim(Id::X);
53 EXPECT_EQ(layout->dimSize(Id::X), 8u);
54 EXPECT_EQ(layout->dimType(Id::X), Type::Double);
55
56 layout->registerDim(Id::X, Type::Signed32);
57 EXPECT_EQ(layout->dimSize(Id::X), 8u);
58 EXPECT_EQ(layout->dimType(Id::X), Type::Double);
59
60 layout->registerDim(Dimension::Id::X, Type::Unsigned8);
61 EXPECT_EQ(layout->dimSize(Id::X), 8u);
62 EXPECT_EQ(layout->dimType(Id::X), Type::Double);
63
64 /// Build as we go.
65 layout->registerDim(Id::Intensity, Type::Unsigned8);
66 EXPECT_EQ(layout->dimSize(Id::Intensity), 1u);
67 EXPECT_EQ(layout->dimType(Id::Intensity), Type::Unsigned8);
68
69 layout->registerDim(Id::Intensity, Type::Unsigned8);
70 EXPECT_EQ(layout->dimSize(Id::Intensity), 1u);
71 EXPECT_EQ(layout->dimType(Id::Intensity), Type::Unsigned8);
72
73 layout->registerDim(Id::Intensity, Type::Signed8);
74 // Signed 8 and Unsigned 8 should yield signed 16.
75 EXPECT_EQ(layout->dimSize(Id::Intensity), 2u);
76 EXPECT_EQ(layout->dimType(Id::Intensity), Type::Signed16);
77
78 layout->registerDim(Id::Intensity, Type::Signed16);
79 EXPECT_EQ(layout->dimSize(Id::Intensity), 2u);
80 EXPECT_EQ(layout->dimType(Id::Intensity), Type::Signed16);
81
82 layout->registerDim(Id::Intensity, Type::Float);
83 EXPECT_EQ(layout->dimSize(Id::Intensity), 4u);
84 EXPECT_EQ(layout->dimType(Id::Intensity), Type::Float);
85
86 layout->registerDim(Id::Intensity, Type::Double);
87 EXPECT_EQ(layout->dimSize(Id::Intensity), 8u);
88 EXPECT_EQ(layout->dimType(Id::Intensity), Type::Double);
89
90 ///
91 layout->registerDim(Id::Red, Type::Unsigned16);
92 EXPECT_EQ(layout->dimSize(Id::Red), 2u);
93 EXPECT_EQ(layout->dimType(Id::Red), Type::Unsigned16);
94
95 layout->registerDim(Id::Red, Type::Signed8);
96 EXPECT_EQ(layout->dimSize(Id::Red), 4u);
97 EXPECT_EQ(layout->dimType(Id::Red), Type::Signed32);
98
99 layout->registerDim(Id::Red, Type::Signed16);
100 EXPECT_EQ(layout->dimSize(Id::Red), 4u);
101 EXPECT_EQ(layout->dimType(Id::Red), Type::Signed32);
102
103 layout->registerDim(Id::Red, Type::Double);
104 EXPECT_EQ(layout->dimSize(Id::Red), 8u);
105 EXPECT_EQ(layout->dimType(Id::Red), Type::Double);
106 }
107
TEST(PointTable,userView)108 TEST(PointTable, userView)
109 {
110 class UserTable : public PointTable
111 {
112 private:
113 double m_x;
114 double m_y;
115 double m_z;
116
117 public:
118 PointId addPoint()
119 { return 0; }
120 char *getPoint(PointId idx)
121 { return NULL; }
122 void setFieldInternal(Dimension::Id id, PointId idx,
123 const void *value)
124 {
125 if (id == Dimension::Id::X)
126 m_x = *(const double *)value;
127 else if (id == Dimension::Id::Y)
128 m_y = *(const double *)value;
129 else if (id == Dimension::Id::Z)
130 m_z = *(const double *)value;
131 }
132 void getFieldInternal(Dimension::Id id, PointId idx,
133 void *value) const
134 {
135 if (id == Dimension::Id::X)
136 *(double *)value = m_x;
137 else if (id == Dimension::Id::Y)
138 *(double *)value = m_y;
139 else if (id == Dimension::Id::Z)
140 *(double *)value = m_z;
141 }
142 };
143
144 LasReader reader;
145
146 Options opts;
147 opts.add("filename", Support::datapath("las/simple.las"));
148 opts.add("count", 100);
149
150 reader.setOptions(opts);
151
152 PointTable defTable;
153 reader.prepare(defTable);
154 PointViewSet viewSet = reader.execute(defTable);
155 PointViewPtr defView = *viewSet.begin();
156
157 bool called(false);
158 auto readCb = [defView, &called](PointView& customView, PointId id)
159 {
160 called = true;
161 double xDef = defView->getFieldAs<double>(Dimension::Id::X, id);
162 double yDef = defView->getFieldAs<double>(Dimension::Id::Y, id);
163 double zDef = defView->getFieldAs<double>(Dimension::Id::Z, id);
164
165 double x = customView.getFieldAs<double>(Dimension::Id::X, id);
166 double y = customView.getFieldAs<double>(Dimension::Id::Y, id);
167 double z = customView.getFieldAs<double>(Dimension::Id::Z, id);
168
169 EXPECT_DOUBLE_EQ(xDef, x);
170 EXPECT_DOUBLE_EQ(yDef, y);
171 EXPECT_DOUBLE_EQ(zDef, z);
172 };
173
174 reader.setReadCb(readCb);
175 UserTable table;
176
177 reader.prepare(table);
178 reader.execute(table);
179 EXPECT_TRUE(called);
180 }
181
TEST(PointTable,srs)182 TEST(PointTable, srs)
183 {
184 SpatialReference srs1("GEOGCS[\"WGS 84\",DATUM[\"WGS_1984\",SPHEROID[\"WGS 84\",6378137,298.257223563,AUTHORITY[\"EPSG\",\"7030\"]],AUTHORITY[\"EPSG\",\"6326\"]],PRIMEM[\"Greenwich\",0,AUTHORITY[\"EPSG\",\"8901\"]],UNIT[\"degree\",0.0174532925199433,AUTHORITY[\"EPSG\",\"9122\"]],AUTHORITY[\"EPSG\",\"4326\"]]");
185
186 SpatialReference srs2("PROJCS[\"WGS 84 / UTM zone 17N\",GEOGCS[\"WGS 84\",DATUM[\"WGS_1984\",SPHEROID[\"WGS 84\",6378137,298.257223563,AUTHORITY[\"EPSG\",\"7030\"]],AUTHORITY[\"EPSG\",\"6326\"]],PRIMEM[\"Greenwich\",0],UNIT[\"degree\",0.0174532925199433],AUTHORITY[\"EPSG\",\"4326\"]],PROJECTION[\"Transverse_Mercator\"],PARAMETER[\"latitude_of_origin\",0],PARAMETER[\"central_meridian\",-81],PARAMETER[\"scale_factor\",0.9996],PARAMETER[\"false_easting\",500000],PARAMETER[\"false_northing\",0],UNIT[\"metre\",1,AUTHORITY[\"EPSG\",\"9001\"]],AUTHORITY[\"EPSG\",\"32617\"]]");
187
188 PointTable table;
189
190 table.addSpatialReference(srs1);
191 table.addSpatialReference(srs1);
192 EXPECT_TRUE(table.spatialReferenceUnique());
193 EXPECT_EQ(table.anySpatialReference(), srs1);
194
195 table.addSpatialReference(srs2);
196 EXPECT_FALSE(table.spatialReferenceUnique());
197 EXPECT_EQ(table.anySpatialReference(), srs2);
198 EXPECT_EQ(table.m_spatialRefs.size(), 2u);
199
200 table.addSpatialReference(srs1);
201 EXPECT_FALSE(table.spatialReferenceUnique());
202 EXPECT_EQ(table.anySpatialReference(), srs1);
203 EXPECT_EQ(table.m_spatialRefs.size(), 2u);
204 }
205
simpleTest(PointTableRef table)206 void simpleTest(PointTableRef table)
207 {
208 PointLayoutPtr layout = table.layout();
209
210 layout->registerDim(Dimension::Id::X);
211 layout->registerDim(Dimension::Id::Y);
212 layout->registerDim(Dimension::Id::Z);
213 layout->registerDim(Dimension::Id::Intensity);
214 layout->registerDim(Dimension::Id::Blue);
215
216 PointView v(table);
217 for (PointId id = 0; id < 10000; id++)
218 {
219 if (id % 200 < 100)
220 {
221 v.setField(Dimension::Id::X, id, id);
222 v.setField(Dimension::Id::Y, id, id + 1);
223 v.setField(Dimension::Id::Z, id, id + 2);
224 v.setField(Dimension::Id::Intensity, id, (id * 100) % 6523);
225 }
226 else
227 v.setField(Dimension::Id::Blue, id, 0);
228 }
229
230 for (PointId id = 0; id < 10000; id++)
231 {
232 if (id % 200 < 100)
233 {
234 EXPECT_EQ(id, v.getFieldAs<PointId>(Dimension::Id::X, id));
235 EXPECT_EQ(id + 1, v.getFieldAs<PointId>(Dimension::Id::Y, id));
236 EXPECT_EQ(id + 2, v.getFieldAs<PointId>(Dimension::Id::Z, id));
237 EXPECT_EQ((id * 100) % 6523,
238 v.getFieldAs<PointId>(Dimension::Id::Intensity, id));
239 }
240 else
241 {
242 EXPECT_EQ(0U, v.getFieldAs<PointId>(Dimension::Id::X, id));
243 EXPECT_EQ(0U, v.getFieldAs<PointId>(Dimension::Id::Y, id));
244 EXPECT_EQ(0U, v.getFieldAs<PointId>(Dimension::Id::Z, id));
245 EXPECT_EQ(0U, v.getFieldAs<PointId>(Dimension::Id::Intensity, id));
246 }
247 }
248 }
249
250
TEST(PointTable,simple)251 TEST(PointTable, simple)
252 {
253 PointTable t;
254 simpleTest(t);
255 }
256
TEST(PointTable,layoutLimit)257 TEST(PointTable, layoutLimit)
258 {
259 PointTable t;
260 PointLayoutPtr layout = t.layout();
261 layout->setAllowedDims({ "X", "Z"});
262
263 layout->registerDim(Dimension::Id::X);
264 layout->registerDim(Dimension::Id::Y);
265 layout->registerDim(Dimension::Id::Z);
266 layout->registerDim(Dimension::Id::Intensity);
267 layout->registerDim(Dimension::Id::Blue);
268 t.finalize();
269
270 PointView v(t);
271 for (PointId id = 0; id < 1000; id++)
272 {
273 if (id % 200 < 100)
274 {
275 v.setField(Dimension::Id::X, id, id);
276 v.setField(Dimension::Id::Y, id, id + 1);
277 v.setField(Dimension::Id::Z, id, id + 2);
278 v.setField(Dimension::Id::Intensity, id, (id * 100) % 6523);
279 }
280 else
281 {
282 v.setField(Dimension::Id::X, id, 0);
283 v.setField(Dimension::Id::Blue, id, id);
284 }
285 }
286
287 for (PointId id = 0; id < 1000; id++)
288 {
289 if (id % 200 < 100)
290 {
291 EXPECT_EQ(id, v.getFieldAs<PointId>(Dimension::Id::X, id));
292 EXPECT_EQ(id + 1, v.getFieldAs<PointId>(Dimension::Id::Y, id));
293 EXPECT_EQ(id + 2, v.getFieldAs<PointId>(Dimension::Id::Z, id));
294 }
295 else
296 {
297 EXPECT_EQ(0U, v.getFieldAs<PointId>(Dimension::Id::X, id));
298 EXPECT_EQ(0U, v.getFieldAs<PointId>(Dimension::Id::Y, id));
299 EXPECT_EQ(0U, v.getFieldAs<PointId>(Dimension::Id::Z, id));
300 }
301 EXPECT_EQ(0U, v.getFieldAs<PointId>(Dimension::Id::Intensity, id));
302 EXPECT_EQ(0U, v.getFieldAs<PointId>(Dimension::Id::Blue, id));
303 }
304 }
305
306 } // namespace
307