TEST(LasWriterTest, all_extra_dims) { Options readerOps; readerOps.add("filename", Support::datapath("bpf/simple-extra.bpf")); BpfReader reader; reader.setOptions(readerOps); FileUtils::deleteFile(Support::temppath("simple.las")); Options writerOps; writerOps.add("extra_dims", "all"); writerOps.add("filename", Support::temppath("simple.las")); writerOps.add("minor_version", 4); LasWriter writer; writer.setInput(reader); writer.setOptions(writerOps); PointTable table; writer.prepare(table); writer.execute(table); Options ops; ops.add("filename", Support::temppath("simple.las")); LasReader r; r.setOptions(ops); PointTable t2; r.prepare(t2); Dimension::Id foo = t2.layout()->findDim("Foo"); Dimension::Id bar = t2.layout()->findDim("Bar"); Dimension::Id baz = t2.layout()->findDim("Baz"); PointViewSet s = r.execute(t2); EXPECT_EQ(s.size(), 1u); PointViewPtr v = *s.begin(); // We test for floats instead of doubles because when X, Y and Z // get written, they are written scaled, which loses precision. The // foo, bar and baz values are written as full-precision doubles. for (PointId i = 0; i < v->size(); ++i) { using namespace Dimension; ASSERT_FLOAT_EQ(v->getFieldAs<float>(Id::X, i), v->getFieldAs<float>(foo, i)); ASSERT_FLOAT_EQ(v->getFieldAs<float>(Id::Y, i), v->getFieldAs<float>(bar, i)); ASSERT_FLOAT_EQ(v->getFieldAs<float>(Id::Z, i), v->getFieldAs<float>(baz, i)); } }
TEST(ChipperTest, test_construction) { PointTable table; Options ops1; std::string filename(Support::datapath("las/1.2-with-color.las")); ops1.add("filename", filename); LasReader reader; reader.setOptions(ops1); { // need to scope the writer, so that's it dtor can use the stream Options options; Option capacity("capacity", 15, "capacity"); options.add(capacity); ChipperFilter chipper; chipper.setInput(reader); chipper.setOptions(options); chipper.prepare(table); PointViewSet viewSet = chipper.execute(table); EXPECT_EQ(viewSet.size(), 71u); std::vector<PointViewPtr> views; for (auto it = viewSet.begin(); it != viewSet.end(); ++it) views.push_back(*it); auto sorter = [](PointViewPtr p1, PointViewPtr p2) { //This is super inefficient, but we're doing tests. BOX3D b1 = p1->calculateBounds(); BOX3D b2 = p2->calculateBounds(); return b1.minx < b2.minx ? true : b1.minx > b2.minx ? false : b1.miny < b2.miny; }; std::sort(views.begin(), views.end(), sorter); auto view = views[2]; auto bounds = view->calculateBounds(); EXPECT_NEAR(bounds.minx, 635674.05, 0.05); EXPECT_NEAR(bounds.maxx, 635993.93, 0.05); EXPECT_NEAR(bounds.miny, 848992.45, 0.05); EXPECT_NEAR(bounds.maxy, 849427.07, 0.05); for (size_t i = 0; i < views.size(); ++i) EXPECT_EQ(views[i]->size(), 15u); } }
TEST(SplitterTest, test_buffer) { Options readerOptions; readerOptions.add("filename", Support::datapath("las/1.2-with-color.las")); LasReader reader; reader.setOptions(readerOptions); Options splitterOptions; splitterOptions.add("length", 1000); splitterOptions.add("buffer", 20); SplitterFilter splitter; splitter.setOptions(splitterOptions); splitter.setInput(reader); PointTable table; splitter.prepare(table); PointViewSet viewSet = splitter.execute(table); std::vector<PointViewPtr> views; std::map<PointViewPtr, BOX2D> bounds; for (auto it = viewSet.begin(); it != viewSet.end(); ++it) { BOX2D b; PointViewPtr v = *it; v->calculateBounds(b); EXPECT_TRUE(b.maxx - b.minx <= 1040); EXPECT_TRUE(b.maxy - b.miny <= 1040); bounds[v] = b; views.push_back(v); } auto sorter = [&bounds](PointViewPtr p1, PointViewPtr p2) { BOX2D b1 = bounds[p1]; BOX2D b2 = bounds[p2]; return b1.minx < b2.minx ? true : b1.minx > b2.minx ? false : b1.miny < b2.miny; }; std::sort(views.begin(), views.end(), sorter); EXPECT_EQ(views.size(), 24u); size_t counts[] = {26, 26, 3, 28, 27, 13, 14, 65, 80, 47, 80, 89, 94, 77, 5, 79, 65, 34, 63, 67, 74, 69, 36, 5}; size_t i = 0; for (PointViewPtr view : views) EXPECT_EQ(view->size(), counts[i++]); }
TEST(FerryFilterTest, test_ferry_invalid) { Options ops1; ops1.add("filename", Support::datapath("las/1.2-with-color.las")); LasReader reader; reader.setOptions(ops1); Options op1; op1.add("dimensions", "X=X"); FerryFilter f1; f1.setInput(reader); f1.setOptions(op1); PointTable table; // Make sure we can't ferry to ourselves. EXPECT_THROW(f1.prepare(table), pdal_error); Options op2; op2.add("dimension", "X=NewX"); FerryFilter f2; f2.setInput(reader); f2.setOptions(op2); // Make sure we reject old option name. EXPECT_THROW(f2.prepare(table), pdal_error); Options op3; op3.add("dimensions", "NewX = X"); FerryFilter f3; f3.setInput(reader); f3.setOptions(op3); // Make sure we reject bad source dimension. EXPECT_THROW(f3.prepare(table), pdal_error); Options op4; op4.add("dimensions", "X = Y, X = NewZ = NewQ"); FerryFilter f4; f4.setInput(reader); f4.setOptions(op4); // Make sure we reject bad option format. EXPECT_THROW(f4.prepare(table), pdal_error); }
// Compare the source LAS file with the extracted OCI data. // Candidate is the OCI reader's view. void compare(const PointViewPtr candidate, std::string filename) { Options options; Option fn("filename", filename); options.add(fn); PointTable table; LasReader reader; reader.setOptions(options); reader.prepare(table); PointViewSet viewSet = reader.execute(table); EXPECT_EQ(viewSet.size(), 1u); PointViewPtr source = *viewSet.begin(); EXPECT_EQ(source->size(), candidate->size()); PointId limit = std::min(source->size(), candidate->size()); for (PointId i = 0; i < limit; ++i) { using namespace Dimension; int32_t sx = source->getFieldAs<int32_t>(Id::X, i); int32_t sy = source->getFieldAs<int32_t>(Id::Y, i); int32_t sz = source->getFieldAs<int32_t>(Id::Z, i); uint16_t sintensity = source->getFieldAs<uint16_t>(Id::Intensity, i); uint16_t sred = source->getFieldAs<uint16_t>(Id::Red, i); uint16_t sgreen = source->getFieldAs<uint16_t>(Id::Green, i); uint16_t sblue = source->getFieldAs<uint16_t>(Id::Blue, i); int32_t cx = candidate->getFieldAs<int32_t>(Id::X, i); int32_t cy = candidate->getFieldAs<int32_t>(Id::Y, i); int32_t cz = candidate->getFieldAs<int32_t>(Id::Z, i); uint16_t cintensity = candidate->getFieldAs<uint16_t>(Id::Intensity, i); uint16_t cred = candidate->getFieldAs<uint16_t>(Id::Red, i); uint16_t cgreen = candidate->getFieldAs<uint16_t>(Id::Green, i); uint16_t cblue = candidate->getFieldAs<uint16_t>(Id::Blue, i); EXPECT_EQ(sx, cx); EXPECT_EQ(sy, cy); EXPECT_EQ(sz, cz); EXPECT_EQ(sintensity, cintensity); EXPECT_EQ(sred, cred); EXPECT_EQ(sgreen, cgreen); EXPECT_EQ(sblue, cblue); } }
// The header of 1.2-with-color-clipped says that it has 1065 points, // but it really only has 1064. TEST(LasReaderTest, LasHeaderIncorrentPointcount) { PointTable table; Options readOps; readOps.add("filename", Support::datapath("las/1.2-with-color-clipped.las")); LasReader reader; reader.setOptions(readOps); reader.prepare(table); PointViewSet viewSet = reader.execute(table); PointViewPtr view = *viewSet.begin(); EXPECT_EQ(1064u, view->size()); }
TEST(LasWriterTest, auto_offset) { using namespace Dimension; const std::string FILENAME(Support::temppath("offset_test.las")); PointTable table; table.layout()->registerDim(Id::X); BufferReader bufferReader; PointViewPtr view(new PointView(table)); view->setField(Id::X, 0, 125000.00); view->setField(Id::X, 1, 74529.00); view->setField(Id::X, 2, 523523.02); bufferReader.addView(view); Options writerOps; writerOps.add("filename", FILENAME); writerOps.add("offset_x", "auto"); writerOps.add("scale_x", "auto"); LasWriter writer; writer.setOptions(writerOps); writer.setInput(bufferReader); writer.prepare(table); writer.execute(table); Options readerOps; readerOps.add("filename", FILENAME); PointTable readTable; LasReader reader; reader.setOptions(readerOps); reader.prepare(readTable); EXPECT_DOUBLE_EQ(74529.00, reader.header().offsetX()); PointViewSet viewSet = reader.execute(readTable); EXPECT_EQ(viewSet.size(), 1u); view = *viewSet.begin(); EXPECT_EQ(view->size(), 3u); EXPECT_NEAR(125000.00, view->getFieldAs<double>(Id::X, 0), .0001); EXPECT_NEAR(74529.00, view->getFieldAs<double>(Id::X, 1), .0001); EXPECT_NEAR(523523.02, view->getFieldAs<double>(Id::X, 2), .0001); FileUtils::deleteFile(FILENAME); }
TEST(LasReaderTest, EmptyGeotiffVlr) { PointTable table; Options readOps; readOps.add("filename", Support::datapath("las/1.2-empty-geotiff-vlrs.las")); LasReader reader; reader.setOptions(readOps); reader.prepare(table); PointViewSet viewSet = reader.execute(table); PointViewPtr view = *viewSet.begin(); EXPECT_EQ(43u, view->size()); }
void writeData(Orientation orient, bool scaling, bool compression = false) { Options options; options.add("capacity", 10000); options.add("connection", std::string(connectString)); options.add("debug", "true"); options.add("block_table_name", blockTableName); options.add("base_table_name", baseTableName); options.add("cloud_column_name", "CLOUD"); options.add("srid", 26910); options.add("disable_cloud_trigger", true); options.add("store_dimensional_orientation", orient == Orientation::DimensionMajor); if (scaling) { options.add("offset_x", "auto"); options.add("offset_y", "auto"); options.add("offset_z", "auto"); options.add("scale_x", 1e-6); options.add("scale_y", 1e-6); options.add("scale_z", 1e-6); } if (compression) options.add("compression", true); PointTable table; Options readerOps; readerOps.add("filename", Support::datapath("autzen/autzen-utm.las")); StageFactory f; LasReader reader; reader.setOptions(readerOps); SplitFilter split; split.setInput(reader); Stage* writer(f.createStage("writers.oci")); EXPECT_TRUE(writer); writer->setOptions(options); writer->setInput(split); writer->prepare(table); writer->execute(table); }
// Test that data from three input views gets written to separate output files. TEST(LasWriterTest, flex) { std::array<std::string, 3> outname = {{ "test_1.las", "test_2.las", "test_3.las" }}; Options readerOps; readerOps.add("filename", Support::datapath("las/simple.las")); PointTable table; LasReader reader; reader.setOptions(readerOps); reader.prepare(table); PointViewSet views = reader.execute(table); PointViewPtr v = *(views.begin()); PointViewPtr v1(new PointView(table)); PointViewPtr v2(new PointView(table)); PointViewPtr v3(new PointView(table)); std::vector<PointViewPtr> vs; vs.push_back(v1); vs.push_back(v2); vs.push_back(v3); for (PointId i = 0; i < v->size(); ++i) vs[i % 3]->appendPoint(*v, i); for (size_t i = 0; i < outname.size(); ++i) FileUtils::deleteFile(Support::temppath(outname[i])); BufferReader reader2; reader2.addView(v1); reader2.addView(v2); reader2.addView(v3); Options writerOps; writerOps.add("filename", Support::temppath("test_#.las")); LasWriter writer; writer.setOptions(writerOps); writer.setInput(reader2); writer.prepare(table); writer.execute(table); for (size_t i = 0; i < outname.size(); ++i) { std::string filename = Support::temppath(outname[i]); EXPECT_TRUE(FileUtils::fileExists(filename)); Options ops; ops.add("filename", filename); LasReader r; r.setOptions(ops); EXPECT_EQ(r.preview().m_pointCount, 355u); } }
TEST(LasWriterTest, pdal_add_vlr) { PointTable table; std::string infile(Support::datapath("las/1.2-with-color.las")); std::string outfile(Support::temppath("simple.las")); // remove file from earlier run, if needed FileUtils::deleteFile(outfile); Options readerOpts; readerOpts.add("filename", infile); std::string vlr( " [ { \"description\": \"A description under 32 bytes\", \"record_id\": 42, \"user_id\": \"hobu\", \"data\": \"dGhpcyBpcyBzb21lIHRleHQ=\" }, { \"description\": \"A description under 32 bytes\", \"record_id\": 43, \"user_id\": \"hobu\", \"data\": \"dGhpcyBpcyBzb21lIG1vcmUgdGV4dA==\" } ]"); Options writerOpts; writerOpts.add("vlrs", vlr); writerOpts.add("filename", outfile); LasReader reader; reader.setOptions(readerOpts); LasWriter writer; writer.setOptions(writerOpts); writer.setInput(reader); writer.prepare(table); writer.execute(table); PointTable t2; Options readerOpts2; readerOpts2.add("filename", outfile); LasReader reader2; reader2.setOptions(readerOpts2); reader2.prepare(t2); reader2.execute(t2); MetadataNode forward = reader2.getMetadata(); auto pred = [](MetadataNode temp) { return Utils::startsWith(temp.name(), "vlr_"); }; MetadataNodeList nodes = forward.findChildren(pred); EXPECT_EQ(nodes.size(), 2UL); }
TEST(LasReaderTest, header) { PointTable table; Options ops; ops.add("filename", Support::datapath("las/simple.las")); LasReader reader; reader.setOptions(ops); reader.prepare(table); // This tests the copy ctor, too. LasHeader h = reader.header(); EXPECT_EQ(h.fileSignature(), "LASF"); EXPECT_EQ(h.fileSourceId(), 0); EXPECT_TRUE(h.projectId().isNull()); EXPECT_EQ(h.versionMajor(), 1); EXPECT_EQ(h.versionMinor(), 2); EXPECT_EQ(h.creationDOY(), 0); EXPECT_EQ(h.creationYear(), 0); EXPECT_EQ(h.vlrOffset(), 227); EXPECT_EQ(h.pointFormat(), 3); EXPECT_EQ(h.pointCount(), 1065u); EXPECT_DOUBLE_EQ(h.scaleX(), .01); EXPECT_DOUBLE_EQ(h.scaleY(), .01); EXPECT_DOUBLE_EQ(h.scaleZ(), .01); EXPECT_DOUBLE_EQ(h.offsetX(), 0); EXPECT_DOUBLE_EQ(h.offsetY(), 0); EXPECT_DOUBLE_EQ(h.offsetZ(), 0); EXPECT_DOUBLE_EQ(h.maxX(), 638982.55); EXPECT_DOUBLE_EQ(h.maxY(), 853535.43); EXPECT_DOUBLE_EQ(h.maxZ(), 586.38); EXPECT_DOUBLE_EQ(h.minX(), 635619.85); EXPECT_DOUBLE_EQ(h.minY(), 848899.70); EXPECT_DOUBLE_EQ(h.minZ(), 406.59); EXPECT_EQ(h.compressed(), false); EXPECT_EQ(h.compressionInfo(), ""); EXPECT_EQ(h.pointCountByReturn(0), 925u); EXPECT_EQ(h.pointCountByReturn(1), 114u); EXPECT_EQ(h.pointCountByReturn(2), 21u); EXPECT_EQ(h.pointCountByReturn(3), 5u); EXPECT_EQ(h.pointCountByReturn(4), 0u); }
TEST(LasWriterTest, forwardvlr) { Options readerOps1; readerOps1.add("filename", Support::datapath("las/lots_of_vlr.las")); LasReader r1; r1.addOptions(readerOps1); std::string testfile = Support::temppath("tmp.las"); FileUtils::deleteFile(testfile); Options writerOps; writerOps.add("forward", "vlr"); writerOps.add("filename", testfile); LasWriter w; w.setInput(r1); w.addOptions(writerOps); PointTable t; w.prepare(t); w.execute(t); Options readerOps; readerOps.add("filename", testfile); LasReader r; r.setOptions(readerOps); PointTable t2; r.prepare(t2); r.execute(t2); MetadataNode forward = t2.privateMetadata("lasforward"); auto pred = [](MetadataNode temp) { return Utils::startsWith(temp.name(), "vlr_"); }; MetadataNodeList nodes = forward.findChildren(pred); EXPECT_EQ(nodes.size(), 388UL); }
// Test reprojecting UTM 15 to DD with a filter TEST(ReprojectionFilterTest, stream_test_1) { const char* epsg4326_wkt = "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\"]]"; Options ops1; ops1.add("filename", Support::datapath("las/utm15.las")); LasReader reader; reader.setOptions(ops1); Options options; options.add("out_srs", epsg4326_wkt); ReprojectionFilter reprojectionFilter; reprojectionFilter.setOptions(options); reprojectionFilter.setInput(reader); auto cb = [](PointRef& point) { static int i = 0; const double x = -93.351563; const double y = 41.577148; const double z = 16.000000; if (i == 0) { EXPECT_FLOAT_EQ(point.getFieldAs<float>(Dimension::Id::X), x); EXPECT_FLOAT_EQ(point.getFieldAs<float>(Dimension::Id::Y), y); EXPECT_FLOAT_EQ(point.getFieldAs<float>(Dimension::Id::Z), z); } ++i; return true; }; StreamCallbackFilter stream; stream.setCallback(cb); stream.setInput(reprojectionFilter); FixedPointTable table(20); stream.prepare(table); stream.execute(table); }
TEST(CropFilterTest, test_crop_polygon_reprojection) { Options options; options.add("spatialreference", Support::datapath("autzen/autzen-srs.wkt")); options.add("out_srs", "EPSG:4326"); options.add("x_dim", std::string("readers.las.X")); options.add("y_dim", std::string("readers.las.Y")); options.add("z_dim", std::string("readers.las.Z")); options.add("scale_x", 0.0000001f); options.add("scale_y", 0.0000001f); options.add("filename", Support::datapath("las/1.2-with-color.las")); std::istream* wkt_stream = FileUtils::openFile( Support::datapath("autzen/autzen-selection-dd.wkt")); std::stringstream strbuf; strbuf << wkt_stream->rdbuf(); std::string wkt(strbuf.str()); Option polygon("polygon", wkt); options.add(polygon); LasReader reader; reader.setOptions(options); ReprojectionFilter reprojection; reprojection.setOptions(options); reprojection.setInput(reader); CropFilter crop; crop.setOptions(options); crop.setInput(reprojection); PointTable table; PointViewPtr view(new PointView(table)); crop.prepare(table); PointViewSet viewSet = crop.execute(table); EXPECT_EQ(viewSet.size(), 1u); view = *viewSet.begin(); EXPECT_EQ(view->size(), 47u); FileUtils::closeFile(wkt_stream); }
TEST(LasReaderTest, inspect) { Options ops; ops.add("filename", Support::datapath("las/epsg_4326.las")); LasReader reader; reader.setOptions(ops); QuickInfo qi = reader.preview(); std::string testWkt = "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\"]]"; #ifdef PDAL_HAVE_LIBGEOTIFF EXPECT_EQ(qi.m_srs.getWKT(), testWkt); #endif // PDAL_HAVE_LIBGEOTIFF EXPECT_EQ(qi.m_pointCount, 5380u); BOX3D bounds(-94.683465399999989, 31.0367341, 39.081000199999998, -94.660631099999989, 31.047329099999999, 78.119000200000002); EXPECT_EQ(qi.m_bounds, bounds); const char *dims[] = { "Classification", "EdgeOfFlightLine", "Intensity", "NumberOfReturns", "PointSourceId", "ReturnNumber", "ScanAngleRank", "ScanDirectionFlag", "UserData", "X", "Y", "Z" }; std::sort(qi.m_dimNames.begin(), qi.m_dimNames.end()); EXPECT_TRUE(CheckEqualCollections(qi.m_dimNames.begin(), qi.m_dimNames.end(), std::begin(dims))); }
TEST(LasReaderTest, test_vlr) { PointTable table; Options ops1; ops1.add("filename", Support::datapath("las/lots_of_vlr.las")); LasReader reader; reader.setOptions(ops1); reader.prepare(table); reader.execute(table); MetadataNode root = reader.getMetadata(); for (size_t i = 0; i < 390; ++i) { std::string name("vlr_"); name += std::to_string(i); MetadataNode m = root.findChild(name); EXPECT_TRUE(!m.value().empty()) << "No node " << i; } }
TEST(LasReaderTest, callback) { PointTable table; point_count_t count = 0; Options ops; ops.add("filename", Support::datapath("las/simple.las")); Reader::PointReadFunc cb = [&count](PointView& view, PointId id) { count++; }; LasReader reader; reader.setOptions(ops); reader.setReadCb(cb); reader.prepare(table); reader.execute(table); EXPECT_EQ(count, (point_count_t)1065); }
TEST(LasReaderTest, test_sequential) { PointTable table; Options ops1; ops1.add("filename", Support::datapath("las/1.2-with-color.las")); ops1.add("count", 103); LasReader reader; reader.setOptions(ops1); reader.prepare(table); PointViewSet viewSet = reader.execute(table); EXPECT_EQ(viewSet.size(), 1u); PointViewPtr view = *viewSet.begin(); Support::check_p0_p1_p2(*view); PointViewPtr view2 = view->makeNew(); view2->appendPoint(*view, 100); view2->appendPoint(*view, 101); view2->appendPoint(*view, 102); Support::check_p100_p101_p102(*view2); }
TEST(LasReaderTest, test_sequential) { PointContext ctx; Options ops1; ops1.add("filename", Support::datapath("las/1.2-with-color.las")); ops1.add("count", 103); LasReader reader; reader.setOptions(ops1); reader.prepare(ctx); PointBufferSet pbSet = reader.execute(ctx); EXPECT_EQ(pbSet.size(), 1u); PointBufferPtr buf = *pbSet.begin(); Support::check_p0_p1_p2(*buf); PointBufferPtr buf2 = buf->makeNew(); buf2->appendPoint(*buf, 100); buf2->appendPoint(*buf, 101); buf2->appendPoint(*buf, 102); Support::check_p100_p101_p102(*buf2); }
TEST(LasWriterTest, fix1063_1064_1065) { std::string outfile = Support::temppath("out.las"); std::string infile = Support::datapath("las/test1_4.las"); FileUtils::deleteFile(outfile); std::string cmd = "pdal translate --writers.las.forward=all " "--writers.las.a_srs=\"EPSG:4326\" " + infile + " " + outfile; std::string output; Utils::run_shell_command(Support::binpath(cmd), output); Options o; o.add("filename", outfile); LasReader r; r.setOptions(o); PointTable t; r.prepare(t); PointViewSet s = r.execute(t); EXPECT_EQ(s.size(), 1u); PointViewPtr v = *s.begin(); EXPECT_EQ(v->size(), 1000u); // https://github.com/PDAL/PDAL/issues/1063 for (PointId idx = 0; idx < v->size(); ++idx) EXPECT_EQ(8, v->getFieldAs<int>(Dimension::Id::ClassFlags, idx)); // https://github.com/PDAL/PDAL/issues/1064 MetadataNode m = r.getMetadata(); m = m.findChild("global_encoding"); EXPECT_EQ(17, m.value<int>()); // https://github.com/PDAL/PDAL/issues/1065 SpatialReference ref = v->spatialReference(); std::string wkt = "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\"]]"; EXPECT_EQ(ref.getWKT(), wkt); }
static void test_a_format(const std::string& file, uint8_t majorVersion, uint8_t minorVersion, int pointFormat, double xref, double yref, double zref, double tref, uint16_t rref, uint16_t gref, uint16_t bref) { PointTable table; Options ops1; ops1.add("filename", Support::datapath(file)); ops1.add("count", 1); LasReader reader; reader.setOptions(ops1); reader.prepare(table); EXPECT_EQ(reader.header().pointFormat(), pointFormat); EXPECT_EQ(reader.header().versionMajor(), majorVersion); EXPECT_EQ(reader.header().versionMinor(), minorVersion); PointViewSet viewSet = reader.execute(table); EXPECT_EQ(viewSet.size(), 1u); PointViewPtr view = *viewSet.begin(); EXPECT_EQ(view->size(), 1u); Support::check_pN(*view, 0, xref, yref, zref, tref, rref, gref, bref); }
TEST(LasWriterTest, srs) { Options readerOps; readerOps.add("filename", Support::datapath("las/utm15.las")); LasReader reader; reader.setOptions(readerOps); Options writerOps; writerOps.add("filename", Support::temppath("out.las")); LasWriter writer; writer.setInput(reader); writer.setOptions(writerOps); PointTable table; writer.prepare(table); writer.execute(table); LasTester tester; SpatialReference srs = tester.srs(writer); EXPECT_EQ(srs, SpatialReference("EPSG:26915")); }
TEST(LasWriterTest, pdal_metadata) { PointTable table; std::string infile(Support::datapath("las/1.2-with-color.las")); std::string outfile(Support::temppath("simple.las")); // remove file from earlier run, if needed FileUtils::deleteFile(outfile); Options readerOpts; readerOpts.add("filename", infile); Options writerOpts; writerOpts.add("pdal_metadata", true); writerOpts.add("filename", outfile); LasReader reader; reader.setOptions(readerOpts); LasWriter writer; writer.setOptions(writerOpts); writer.setInput(reader); writer.prepare(table); writer.execute(table); PointTable t2; Options readerOpts2; readerOpts2.add("filename", outfile); LasReader reader2; reader2.setOptions(readerOpts2); reader2.prepare(t2); reader2.execute(t2); EXPECT_EQ(reader2.getMetadata().children("pdal_metadata").size(), 1UL); EXPECT_EQ(reader2.getMetadata().children("pdal_pipeline").size(), 1UL); }
TEST(LasWriterTest, streamhashwrite) { std::string infile(Support::datapath("las/autzen_trim.las")); std::string outfile(Support::temppath("trimtest#.las")); FileUtils::deleteFile(outfile); Options ops1; ops1.add("filename", infile); LasReader r; r.setOptions(ops1); Options ops2; ops2.add("filename", outfile); LasWriter w; w.setOptions(ops2); w.setInput(r); FixedPointTable t(100); EXPECT_THROW(w.prepare(t), pdal_error); }
// Test reprojecting UTM 15 to DD with a filter TEST(ReprojectionFilterTest, ReprojectionFilterTest_test_1) { const char* epsg4326_wkt = "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\"]]"; PointTable table; const double postX = -93.351563; const double postY = 41.577148; const double postZ = 16.000000; { const SpatialReference out_ref(epsg4326_wkt); Options ops1; ops1.add("filename", Support::datapath("las/utm15.las")); LasReader reader; reader.setOptions(ops1); Options options; options.add("out_srs", out_ref.getWKT()); ReprojectionFilter reprojectionFilter; reprojectionFilter.setOptions(options); reprojectionFilter.setInput(reader); reprojectionFilter.prepare(table); PointViewSet viewSet = reprojectionFilter.execute(table); EXPECT_EQ(viewSet.size(), 1u); PointViewPtr view = *viewSet.begin(); double x, y, z; getPoint(*view.get(), x, y, z); EXPECT_FLOAT_EQ(x, postX); EXPECT_FLOAT_EQ(y, postY); EXPECT_FLOAT_EQ(z, postZ); } }
TEST(CropFilterTest, test_crop_polygon) { #ifdef PDAL_HAVE_GEOS Options ops1; ops1.add("filename", Support::datapath("las/1.2-with-color.las")); LasReader reader; reader.setOptions(ops1); Options options; Option debug("debug", true, ""); Option verbose("verbose", 9, ""); std::istream* wkt_stream = FileUtils::openFile(Support::datapath("autzen/autzen-selection.wkt")); std::stringstream strbuf; strbuf << wkt_stream->rdbuf(); std::string wkt(strbuf.str()); Option polygon("polygon", wkt, ""); options.add(polygon); CropFilter crop; crop.setInput(reader); crop.setOptions(options); PointTable table; crop.prepare(table); PointViewSet viewSet = crop.execute(table); EXPECT_EQ(viewSet.size(), 1u); PointViewPtr view = *viewSet.begin(); EXPECT_EQ(view->size(), 47u); FileUtils::closeFile(wkt_stream); #endif }
void compareTextLas(const std::string& textFilename, const std::string& lasFilename) { TextReader t; Options to; to.add("filename", textFilename); t.setOptions(to); LasReader l; Options lo; lo.add("filename", lasFilename); l.setOptions(lo); PointTable tt; t.prepare(tt); PointViewSet ts = t.execute(tt); EXPECT_EQ(ts.size(), 1U); PointViewPtr tv = *ts.begin(); PointTable lt; l.prepare(lt); PointViewSet ls = l.execute(lt); EXPECT_EQ(ls.size(), 1U); PointViewPtr lv = *ls.begin(); EXPECT_EQ(tv->size(), lv->size()); // Validate some point data. for (PointId i = 0; i < lv->size(); ++i) { EXPECT_DOUBLE_EQ(tv->getFieldAs<double>(Dimension::Id::X, i), lv->getFieldAs<double>(Dimension::Id::X, i)); EXPECT_DOUBLE_EQ(tv->getFieldAs<double>(Dimension::Id::Y, i), lv->getFieldAs<double>(Dimension::Id::Y, i)); EXPECT_DOUBLE_EQ(tv->getFieldAs<double>(Dimension::Id::Z, i), lv->getFieldAs<double>(Dimension::Id::Z, i)); } }
TEST(Random, extra_ops) { std::string outfile(Support::temppath("out.las")); const std::string cmd = appName() + " --count=100 --writers.las.minor_version=3 " + outfile; FileUtils::deleteFile(outfile); std::string output; Utils::run_shell_command(cmd, output); Options o; o.add("filename", outfile); PointTable t; LasReader r; r.setOptions(o); r.prepare(t); MetadataNode n = r.getMetadata(); EXPECT_EQ(n.findChild("minor_version").value<uint8_t>(), 3); }
TEST(RangeFilterTest, nan) { LasReader reader; Options options; options.add("filename", Support::datapath("las/gps-time-nan.las")); reader.setOptions(options); Options rangeOptions; rangeOptions.add("limits", "GpsTime[-1:1]"); RangeFilter filter; filter.setOptions(rangeOptions); filter.setInput(reader); PointTable table; filter.prepare(table); PointViewSet viewSet = filter.execute(table); PointViewPtr view = *viewSet.begin(); EXPECT_EQ(1u, viewSet.size()); EXPECT_EQ(0u, view->size()); }