void InfoKernel::dump(MetadataNode& root) { if (m_showSchema) root.add(m_manager->pointTable().toMetadata().clone("schema")); if (m_PointCloudSchemaOutput.size() > 0) { #ifdef PDAL_HAVE_LIBXML2 XMLSchema schema(m_manager->pointTable().layout()); std::ostream *out = FileUtils::createFile(m_PointCloudSchemaOutput); std::string xml(schema.xml()); out->write(xml.c_str(), xml.size()); FileUtils::closeFile(out); #else std::cerr << "libxml2 support not enabled, no schema is produced" << std::endl; #endif } if (m_showStats) root.add(m_statsStage->getMetadata().clone("stats")); if (m_pipelineFile.size() > 0) PipelineWriter::writePipeline(m_manager->getStage(), m_pipelineFile); if (m_pointIndexes.size()) { PointViewSet viewSet = m_manager->views(); assert(viewSet.size() == 1); root.add(dumpPoints(*viewSet.begin()).clone("points")); } if (m_queryPoint.size()) { PointViewSet viewSet = m_manager->views(); assert(viewSet.size() == 1); root.add(dumpQuery(*viewSet.begin())); } if (m_showMetadata) { // If we have a reader cached, this means we // weren't reading a pipeline file directly. In that // case, use the metadata from the reader (old behavior). // Otherwise, return the full metadata of the entire pipeline if (m_reader) root.add(m_reader->getMetadata().clone("metadata")); else root.add(m_manager->getMetadata().clone("metadata")); } if (m_boundary) { PointViewSet viewSet = m_manager->views(); assert(viewSet.size() == 1); root.add(m_hexbinStage->getMetadata().clone("boundary")); } }
TEST_F(PredicateFilterTest, PredicateFilterTest_test_programmable_4) { StageFactory f; // test the point counters in the Predicate's iterator BOX3D bounds(0.0, 0.0, 0.0, 2.0, 2.0, 2.0); Options readerOpts; readerOpts.add("bounds", bounds); readerOpts.add("count", 1000); readerOpts.add("mode", "ramp"); FauxReader reader; reader.setOptions(readerOpts); const Option source("source", // "Y > 0.5" "import numpy as np\n" "def yow2(ins,outs):\n" " Y = ins['Y']\n" " Mask = np.greater(Y, 0.5)\n" " #print Mask\n" " outs['Mask'] = Mask\n" " return True\n" ); const Option module("module", "MyModule1"); const Option function("function", "yow2"); Options opts; opts.add(source); opts.add(module); opts.add(function); Stage* filter(f.createStage("filters.python")); filter->setOptions(opts); filter->setInput(reader); PointTable table; PointViewPtr buf(new PointView(table)); filter->prepare(table); StageWrapper::ready(reader, table); PointViewSet viewSet = StageWrapper::run(reader, buf); StageWrapper::done(reader, table); EXPECT_EQ(viewSet.size(), 1u); buf = *viewSet.begin(); EXPECT_EQ(buf->size(), 1000u); StageWrapper::ready(*filter, table); viewSet = StageWrapper::run(*filter, buf); StageWrapper::done(*filter, table); EXPECT_EQ(viewSet.size(), 1u); buf = *viewSet.begin(); EXPECT_EQ(buf->size(), 750u); }
int DiffKernel::execute() { PointTable sourceTable; Stage& source = makeReader(m_sourceFile, m_driverOverride); source.prepare(sourceTable); PointViewSet sourceSet = source.execute(sourceTable); MetadataNode errors; PointTable candidateTable; Stage& candidate = makeReader(m_candidateFile, m_driverOverride); candidate.prepare(candidateTable); PointViewSet candidateSet = candidate.execute(candidateTable); assert(sourceSet.size() == 1); assert(candidateSet.size() == 1); PointViewPtr sourceView = *sourceSet.begin(); PointViewPtr candidateView = *candidateSet.begin(); if (candidateView->size() != sourceView->size()) { std::ostringstream oss; oss << "Source and candidate files do not have the same point count"; errors.add("count.error", oss.str()); errors.add("count.candidate", candidateView->size()); errors.add("count.source", sourceView->size()); } MetadataNode source_metadata = sourceTable.metadata(); MetadataNode candidate_metadata = candidateTable.metadata(); if (source_metadata != candidate_metadata) { std::ostringstream oss; oss << "Source and candidate files do not have the same metadata count"; errors.add("metadata.error", oss.str()); errors.add(source_metadata); errors.add(candidate_metadata); } if (candidateTable.layout()->dims().size() != sourceTable.layout()->dims().size()) { std::ostringstream oss; oss << "Source and candidate files do not have the same " "number of dimensions"; } return 0; }
TEST(Ilvis2ReaderTest, testReadHigh) { Option filename("filename", Support::datapath("ilvis2/ILVIS2_TEST_FILE.TXT")); Options options(filename); options.add("mapping","high"); std::shared_ptr<Ilvis2Reader> reader(new Ilvis2Reader); reader->setOptions(options); PointTable table; reader->prepare(table); PointViewSet viewSet = reader->execute(table); EXPECT_EQ(viewSet.size(), 1u); PointViewPtr view = *viewSet.begin(); EXPECT_EQ(view->size(), 3u); checkPoint(*view.get(), 0, 42504.48313, 78.307672,-58.785213,1956.777 ); checkPoint(*view.get(), 1, 42504.48512, 78.307592, 101.215097, 1956.588 ); checkPoint(*view.get(), 2, 42504.48712, 78.307512, -58.78459, 2956.667 ); }
TEST(DecimationFilterTest, DecimationFilterTest_test1) { BOX3D srcBounds(0.0, 0.0, 0.0, 100.0, 100.0, 100.0); Options ops; ops.add("bounds", srcBounds); ops.add("mode", "random"); ops.add("num_points", 30); FauxReader reader; reader.setOptions(ops); Options decimationOps; decimationOps.add("step", 10); DecimationFilter filter; filter.setOptions(decimationOps); filter.setInput(reader); PointTable table; filter.prepare(table); PointViewSet viewSet = filter.execute(table); EXPECT_EQ(viewSet.size(), 1u); PointViewPtr view = *viewSet.begin(); EXPECT_EQ(view->size(), 3u); uint64_t t0 = view->getFieldAs<uint64_t>(Dimension::Id::OffsetTime, 0); uint64_t t1 = view->getFieldAs<uint64_t>(Dimension::Id::OffsetTime, 1); uint64_t t2 = view->getFieldAs<uint64_t>(Dimension::Id::OffsetTime, 2); EXPECT_EQ(t0, 0u); EXPECT_EQ(t1, 10u); EXPECT_EQ(t2, 20u); }
TEST(CropFilterTest, test_crop) { BOX3D srcBounds(0.0, 0.0, 0.0, 10.0, 100.0, 1000.0); Options opts; opts.add("bounds", srcBounds); opts.add("num_points", 1000); opts.add("mode", "ramp"); FauxReader reader; reader.setOptions(opts); // crop the window to 1/3rd the size in each dimension BOX2D dstBounds(3.33333, 33.33333, 6.66666, 66.66666); Options cropOpts; cropOpts.add("bounds", dstBounds); CropFilter filter; filter.setOptions(cropOpts); filter.setInput(reader); Options statOpts; StatsFilter stats; stats.setOptions(statOpts); stats.setInput(filter); PointTable table; stats.prepare(table); PointViewSet viewSet = stats.execute(table); EXPECT_EQ(viewSet.size(), 1u); PointViewPtr buf = *viewSet.begin(); const stats::Summary& statsX = stats.getStats(Dimension::Id::X); const stats::Summary& statsY = stats.getStats(Dimension::Id::Y); const stats::Summary& statsZ = stats.getStats(Dimension::Id::Z); EXPECT_EQ(buf->size(), 333u); const double minX = statsX.minimum(); const double minY = statsY.minimum(); const double minZ = statsZ.minimum(); const double maxX = statsX.maximum(); const double maxY = statsY.maximum(); const double maxZ = statsZ.maximum(); const double avgX = statsX.average(); const double avgY = statsY.average(); const double avgZ = statsZ.average(); const double delX = 10.0 / 999.0 * 100.0; const double delY = 100.0 / 999.0 * 100.0; const double delZ = 1000.0 / 999.0 * 100.0; EXPECT_NEAR(minX, 3.33333, delX); EXPECT_NEAR(minY, 33.33333, delY); EXPECT_NEAR(minZ, 333.33333, delZ); EXPECT_NEAR(maxX, 6.66666, delX); EXPECT_NEAR(maxY, 66.66666, delY); EXPECT_NEAR(maxZ, 666.66666, delZ); EXPECT_NEAR(avgX, 5.00000, delX); EXPECT_NEAR(avgY, 50.00000, delY); EXPECT_NEAR(avgZ, 500.00000, delZ); }
TEST(QFITReaderTest, test_10_word) { Options options; options.add("filename", Support::datapath("qfit/10-word.qi"), "Input filename for reader to use"); options.add("flip_coordinates", false, "Flip coordinates from 0-360 to -180-180"); options.add("scale_z", 0.001f, "Z scale from mm to m"); options.add("count", 3); std::shared_ptr<QfitReader> reader(new QfitReader); reader->setOptions(options); EXPECT_EQ(reader->getName(), "readers.qfit"); PointTable table; reader->prepare(table); PointViewSet viewSet = reader->execute(table); EXPECT_EQ(viewSet.size(), 1u); PointViewPtr view = *viewSet.begin(); EXPECT_EQ(view->size(), 3u); Check_Point(*view, 0, 221.826822, 59.205160, 32.0900, 0); Check_Point(*view, 1, 221.826740, 59.205161, 32.0190, 0); Check_Point(*view, 2, 221.826658, 59.205164, 32.0000, 0); }
void readData() { std::ostringstream oss; oss << "SELECT l.\"OBJ_ID\", l.\"BLK_ID\", l.\"BLK_EXTENT\", " << "l.\"BLK_DOMAIN\", l.\"PCBLK_MIN_RES\", l.\"PCBLK_MAX_RES\", " << "l.\"NUM_POINTS\", l.\"NUM_UNSORTED_POINTS\", l.\"PT_SORT_DIM\", " << "l.\"POINTS\", b.cloud " "FROM PDAL_TEST_BLOCKS l, PDAL_TEST_BASE b " "WHERE b.id = l.obj_id ORDER BY l.blk_id "; Options options = readerOptions(); options.add("query", oss.str()); StageFactory f; Stage* reader(f.createStage("readers.oci")); EXPECT_TRUE(reader); reader->setOptions(options); PointTable table; reader->prepare(table); PointViewSet viewSet = reader->execute(table); EXPECT_EQ(viewSet.size(), 1u); PointViewPtr view = *viewSet.begin(); EXPECT_EQ(view->size(), 1065u); compare(view, Support::datapath("autzen/autzen-utm.las")); }
TEST(RandomizeFilterTest, simple) { // This isn't a real test. It's just here to allow easy debugging. point_count_t count = 1000; Options readerOps; readerOps.add("bounds", BOX3D(1, 1, 1, (double)count, (double)count, (double)count)); readerOps.add("mode", "ramp"); readerOps.add("count", count); FauxReader r; r.setOptions(readerOps); RandomizeFilter f; f.setInput(r); PointTable t; f.prepare(t); PointViewSet s = f.execute(t); EXPECT_EQ(s.size(), 1u); PointViewPtr v = *s.begin(); EXPECT_EQ(v->size(), (size_t)count); /** for (PointId i = 0; i < count; i++) std::cerr << "X[" << i << "] = " << v->getFieldAs<double>(Dimension::Id::X, i) << "!\n"; **/ }
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(RangeFilterTest, negation) { BOX3D srcBounds(0.0, 0.0, 1.0, 0.0, 0.0, 10.0); Options ops; ops.add("bounds", srcBounds); ops.add("mode", "ramp"); ops.add("count", 10); StageFactory f; FauxReader reader; reader.setOptions(ops); Options rangeOps; rangeOps.add("limits", "Z![2:5]"); RangeFilter filter; filter.setOptions(rangeOps); filter.setInput(reader); PointTable table; filter.prepare(table); PointViewSet viewSet = filter.execute(table); PointViewPtr view = *viewSet.begin(); EXPECT_EQ(1u, viewSet.size()); EXPECT_EQ(6u, view->size()); EXPECT_FLOAT_EQ(1.0, view->getFieldAs<double>(Dimension::Id::Z, 0)); EXPECT_FLOAT_EQ(6.0, view->getFieldAs<double>(Dimension::Id::Z, 1)); EXPECT_FLOAT_EQ(7.0, view->getFieldAs<double>(Dimension::Id::Z, 2)); EXPECT_FLOAT_EQ(8.0, view->getFieldAs<double>(Dimension::Id::Z, 3)); EXPECT_FLOAT_EQ(9.0, view->getFieldAs<double>(Dimension::Id::Z, 4)); EXPECT_FLOAT_EQ(10.0, view->getFieldAs<double>(Dimension::Id::Z, 5)); }
TEST(RangeFilterTest, multipleDimensions) { BOX3D srcBounds(0.0, 1.0, 1.0, 0.0, 10.0, 10.0); Options ops; ops.add("bounds", srcBounds); ops.add("mode", "ramp"); ops.add("count", 10); FauxReader reader; reader.setOptions(ops); Options rangeOps; rangeOps.add("limits", "Y[4.00e0:+6]"); rangeOps.add("limits", "Z[4:6]"); RangeFilter filter; filter.setOptions(rangeOps); filter.setInput(reader); PointTable table; filter.prepare(table); PointViewSet viewSet = filter.execute(table); PointViewPtr view = *viewSet.begin(); EXPECT_EQ(1u, viewSet.size()); EXPECT_EQ(3u, view->size()); EXPECT_FLOAT_EQ(4.0, view->getFieldAs<double>(Dimension::Id::Y, 0)); EXPECT_FLOAT_EQ(5.0, view->getFieldAs<double>(Dimension::Id::Y, 1)); EXPECT_FLOAT_EQ(6.0, view->getFieldAs<double>(Dimension::Id::Y, 2)); EXPECT_FLOAT_EQ(4.0, view->getFieldAs<double>(Dimension::Id::Z, 0)); EXPECT_FLOAT_EQ(5.0, view->getFieldAs<double>(Dimension::Id::Z, 1)); EXPECT_FLOAT_EQ(6.0, view->getFieldAs<double>(Dimension::Id::Z, 2)); }
TEST(RangeFilterTest, negativeValues) { BOX3D srcBounds(0.0, 0.0, -10.0, 0.0, 0.0, 10.0); Options ops; ops.add("bounds", srcBounds); ops.add("mode", "ramp"); ops.add("count", 21); FauxReader reader; reader.setOptions(ops); Options rangeOps; rangeOps.add("limits", "Z[-1:1)"); RangeFilter filter; filter.setOptions(rangeOps); filter.setInput(reader); PointTable table; filter.prepare(table); PointViewSet viewSet = filter.execute(table); PointViewPtr view = *viewSet.begin(); EXPECT_EQ(1u, viewSet.size()); EXPECT_EQ(2u, view->size()); EXPECT_FLOAT_EQ(-1.0, view->getFieldAs<double>(Dimension::Id::Z, 0)); EXPECT_FLOAT_EQ(0.0, view->getFieldAs<double>(Dimension::Id::Z, 1)); }
TEST(FerryFilterTest, test_ferry_copy_xml) { PipelineManager mgr; mgr.readPipeline(Support::configuredpath("filters/ferry.xml")); mgr.execute(); ConstPointTableRef table(mgr.pointTable()); PointViewSet viewSet = mgr.views(); EXPECT_EQ(viewSet.size(), 1u); PointViewPtr view = *viewSet.begin(); EXPECT_EQ(view->size(), 1065u); Dimension::Id::Enum state_plane_x = table.layout()->findDim("StatePlaneX"); Dimension::Id::Enum state_plane_y = table.layout()->findDim("StatePlaneY"); double lon = view->getFieldAs<double>(Dimension::Id::X, 0); double lat = view->getFieldAs<double>(Dimension::Id::Y, 0); double x = view->getFieldAs<double>(state_plane_x, 0); double y = view->getFieldAs<double>(state_plane_y, 0); EXPECT_DOUBLE_EQ(-117.2501328350574, lon); EXPECT_DOUBLE_EQ(49.341077824192915, lat); EXPECT_DOUBLE_EQ(637012.24, x); EXPECT_DOUBLE_EQ(849028.31, y); }
TEST(RangeFilterTest, simple_logic) { Options ops; ops.add("bounds", BOX3D(1, 101, 201, 10, 110, 210)); ops.add("mode", "ramp"); ops.add("count", 10); FauxReader reader; reader.setOptions(ops); Options rangeOps; rangeOps.add("limits", "Y[108:109], X[2:5], Z[1:1000], X[7:9], Y[103:105]"); RangeFilter filter; filter.setOptions(rangeOps); filter.setInput(reader); PointTable table; filter.prepare(table); PointViewSet viewSet = filter.execute(table); PointViewPtr view = *viewSet.begin(); EXPECT_EQ(1u, viewSet.size()); EXPECT_EQ(5u, view->size()); EXPECT_EQ(view->getFieldAs<int>(Dimension::Id::X, 0), 3); EXPECT_EQ(view->getFieldAs<int>(Dimension::Id::X, 1), 4); EXPECT_EQ(view->getFieldAs<int>(Dimension::Id::X, 2), 5); EXPECT_EQ(view->getFieldAs<int>(Dimension::Id::X, 3), 8); EXPECT_EQ(view->getFieldAs<int>(Dimension::Id::X, 4), 9); }
void InfoKernel::dump(MetadataNode& root) { if (m_showSchema) root.add(Utils::toMetadata(m_manager->pointTable()).clone("schema")); if (m_PointCloudSchemaOutput.size() > 0) { #ifdef PDAL_HAVE_LIBXML2 XMLSchema schema(m_manager->pointTable().layout()); std::ostream *out = FileUtils::createFile(m_PointCloudSchemaOutput); std::string xml(schema.xml()); out->write(xml.c_str(), xml.size()); FileUtils::closeFile(out); #else std::cerr << "libxml2 support not enabled, no schema is produced" << std::endl; #endif } if (m_showStats) root.add(m_statsStage->getMetadata().clone("stats")); if (m_pipelineFile.size() > 0) PipelineWriter::writePipeline(m_manager->getStage(), m_pipelineFile); if (m_pointIndexes.size()) { PointViewSet viewSet = m_manager->views(); assert(viewSet.size() == 1); root.add(dumpPoints(*viewSet.begin()).clone("points")); } if (m_queryPoint.size()) { PointViewSet viewSet = m_manager->views(); assert(viewSet.size() == 1); root.add(dumpQuery(*viewSet.begin())); } if (m_showMetadata) root.add(m_reader->getMetadata().clone("metadata")); if (m_boundary) { PointViewSet viewSet = m_manager->views(); assert(viewSet.size() == 1); root.add(m_hexbinStage->getMetadata().clone("boundary")); } }
TEST_F(PredicateFilterTest, PredicateFilterTest_test_programmable) { StageFactory f; BOX3D bounds(0.0, 0.0, 0.0, 2.0, 2.0, 2.0); Options readerOps; readerOps.add("bounds", bounds); readerOps.add("count", 1000); readerOps.add("mode", "ramp"); FauxReader reader; reader.setOptions(readerOps); // keep all points where x less than 1.0 const Option source("source", // "X < 1.0" "import numpy as np\n" "def yow1(ins,outs):\n" " X = ins['X']\n" " Mask = np.less(X, 1.0)\n" " #print X\n" " #print Mask\n" " outs['Mask'] = Mask\n" " return True\n" ); const Option module("module", "MyModule1"); const Option function("function", "yow1"); Options opts; opts.add(source); opts.add(module); opts.add(function); Stage* filter(f.createStage("filters.python")); filter->setOptions(opts); filter->setInput(reader); Options statOpts; std::unique_ptr<StatsFilter> stats(new StatsFilter); stats->setOptions(statOpts); stats->setInput(*filter); PointTable table; stats->prepare(table); PointViewSet viewSet = stats->execute(table); EXPECT_EQ(viewSet.size(), 1u); const stats::Summary& statsX = stats->getStats(Dimension::Id::X); const stats::Summary& statsY = stats->getStats(Dimension::Id::Y); const stats::Summary& statsZ = stats->getStats(Dimension::Id::Z); EXPECT_TRUE(Utils::compare_approx(statsX.minimum(), 0.0, 0.01)); EXPECT_TRUE(Utils::compare_approx(statsY.minimum(), 0.0, 0.01)); EXPECT_TRUE(Utils::compare_approx(statsZ.minimum(), 0.0, 0.01)); EXPECT_TRUE(Utils::compare_approx(statsX.maximum(), 1.0, 0.01)); EXPECT_TRUE(Utils::compare_approx(statsY.maximum(), 1.0, 0.01)); EXPECT_TRUE(Utils::compare_approx(statsZ.maximum(), 1.0, 0.01)); }
void testReadWrite(bool compression, bool scaling) { FileUtils::deleteFile(tempFilename); Options writerOptions = getWriterOptions(); if (scaling) { writerOptions.add("scale_x", 0.01); writerOptions.add("scale_y", 0.01); } writerOptions.add("compression", compression); StageFactory f; { std::cerr << "*** Writing data!\n"; Options lasReadOpts; lasReadOpts.add("filename", Support::datapath("las/1.2-with-color.las")); lasReadOpts.add("count", 11); LasReader reader; reader.setOptions(lasReadOpts); Stage* sqliteWriter(f.createStage("writers.sqlite")); sqliteWriter->setOptions(writerOptions); sqliteWriter->setInput(reader); PointTable table; sqliteWriter->prepare(table); sqliteWriter->execute(table); } { Stage* sqliteReader(f.createStage("readers.sqlite")); sqliteReader->setOptions(getReaderOptions()); PointTable table2; sqliteReader->prepare(table2); PointViewSet viewSet = sqliteReader->execute(table2); EXPECT_EQ(viewSet.size(), 1U); PointViewPtr view = *viewSet.begin(); using namespace Dimension; uint16_t reds[] = {68, 54, 112, 178, 134, 99, 90, 106, 106, 100, 64}; for (PointId idx = 0; idx < 11; idx++) { uint16_t r = view->getFieldAs<uint16_t>(Id::Red, idx); EXPECT_EQ(r, reds[idx]); } int32_t x = view->getFieldAs<int32_t>(Id::X, 10); EXPECT_EQ(x, 636038); double xd = view->getFieldAs<double>(Id::X, 10); EXPECT_FLOAT_EQ(xd, 636037.53); } // FileUtils::deleteFile(tempFilename); }
PointViewPtr DeltaKernel::loadSet(const std::string& filename, PointTable& table) { Stage& reader = makeReader(filename, m_driverOverride); reader.prepare(table); PointViewSet viewSet = reader.execute(table); assert(viewSet.size() == 1); return *viewSet.begin(); }
TEST(PredicateFilterTest, PredicateFilterTest_test2) { StageFactory f; // same as above, but with 'Y >' instead of 'X <' BOX3D bounds(0.0, 0.0, 0.0, 2.0, 2.0, 2.0); Options readerOps; readerOps.add("bounds", bounds); readerOps.add("num_points", 1000); readerOps.add("mode", "ramp"); FauxReader reader; reader.setOptions(readerOps); Option source("source", // "Y > 1.0" "import numpy as np\n" "def yow2(ins,outs):\n" " Y = ins['Y']\n" " Mask = np.greater(Y, 1.0)\n" " #print Mask\n" " outs['Mask'] = Mask\n" " return True\n" ); Option module("module", "MyModule1"); Option function("function", "yow2"); Options opts; opts.add(source); opts.add(module); opts.add(function); std::unique_ptr<Stage> filter(f.createStage("filters.predicate")); filter->setOptions(opts); filter->setInput(reader); Options statOpts; std::unique_ptr<StatsFilter> stats(new StatsFilter); stats->setOptions(statOpts); stats->setInput(*filter); PointTable table; stats->prepare(table); PointViewSet viewSet = stats->execute(table); EXPECT_EQ(viewSet.size(), 1u); const stats::Summary& statsX = stats->getStats(Dimension::Id::X); const stats::Summary& statsY = stats->getStats(Dimension::Id::Y); const stats::Summary& statsZ = stats->getStats(Dimension::Id::Z); EXPECT_TRUE(Utils::compare_approx<double>(statsX.minimum(), 1.0, 0.01)); EXPECT_TRUE(Utils::compare_approx<double>(statsY.minimum(), 1.0, 0.01)); EXPECT_TRUE(Utils::compare_approx<double>(statsZ.minimum(), 1.0, 0.01)); EXPECT_TRUE(Utils::compare_approx<double>(statsX.maximum(), 2.0, 0.01)); EXPECT_TRUE(Utils::compare_approx<double>(statsY.maximum(), 2.0, 0.01)); EXPECT_TRUE(Utils::compare_approx<double>(statsZ.maximum(), 2.0, 0.01)); }
// LAZ files are normally written in chunks of 50,000, so a file of size // 110,000 ensures we read some whole chunks and a partial. TEST(LasReaderTest, lazperf) { Options ops1; ops1.add("filename", Support::datapath("laz/autzen_trim.laz")); ops1.add("compression", "lazperf"); LasReader lazReader; lazReader.setOptions(ops1); PointTable t1; lazReader.prepare(t1); PointViewSet pbSet = lazReader.execute(t1); EXPECT_EQ(pbSet.size(), 1UL); PointViewPtr view1 = *pbSet.begin(); EXPECT_EQ(view1->size(), (point_count_t)110000); Options ops2; ops2.add("filename", Support::datapath("las/autzen_trim.las")); LasReader lasReader; lasReader.setOptions(ops2); PointTable t2; lasReader.prepare(t2); pbSet = lasReader.execute(t2); EXPECT_EQ(pbSet.size(), 1UL); PointViewPtr view2 = *pbSet.begin(); EXPECT_EQ(view2->size(), (point_count_t)110000); DimTypeList dims = view1->dimTypes(); size_t pointSize = view1->pointSize(); EXPECT_EQ(view1->pointSize(), view2->pointSize()); // Validate some point data. std::unique_ptr<char> buf1(new char[pointSize]); std::unique_ptr<char> buf2(new char[pointSize]); for (PointId i = 0; i < 110000; i += 100) { view1->getPackedPoint(dims, i, buf1.get()); view2->getPackedPoint(dims, i, buf2.get()); EXPECT_EQ(memcmp(buf1.get(), buf2.get(), pointSize), 0); } }
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(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)); } }
// This test make sure bounds are correct by using known and calculable counts. TEST(SplitterTest, test_buffer2) { Options readerOptions; readerOptions.add("mode", "grid"); readerOptions.add("bounds", BOX3D(0, 0, 0, 1000, 1000, 0)); FauxReader reader; reader.setOptions(readerOptions); Options splitterOptions; splitterOptions.add("length", 300); splitterOptions.add("origin_x", 500); splitterOptions.add("origin_y", 500); splitterOptions.add("buffer", 25); SplitterFilter splitter; splitter.setOptions(splitterOptions); splitter.setInput(reader); PointTable table; splitter.prepare(table); PointViewSet s = splitter.execute(table); EXPECT_EQ(s.size(), 16U); std::vector<PointViewPtr> vvec; std::map<PointViewPtr, BOX2D> bounds; for (PointViewPtr v : s) { BOX2D b; v->calculateBounds(b); bounds[v] = b; vvec.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(vvec.begin(), vvec.end(), sorter); size_t counts[] = { 50625, 78525, 78525, 50400, 78525, 121801, 121801, 78176, 78525, 121801, 121801, 78176, 50400, 78176, 78176, 50176 }; size_t i = 0; for (PointViewPtr v : vvec) EXPECT_EQ(v->size(), counts[i++]); }
TEST_F(PythonFilterTest, add_dimension) { StageFactory f; BOX3D bounds(0.0, 0.0, 0.0, 1.0, 1.0, 1.0); Options ops; ops.add("bounds", bounds); ops.add("count", 10); ops.add("mode", "ramp"); FauxReader reader; reader.setOptions(ops); Option source("source", "import numpy\n" "def myfunc(ins,outs):\n" " outs['AddedIntensity'] = np.zeros(ins['X'].size, dtype=numpy.double) + 1\n" " outs['AddedPointSourceId'] = np.zeros(ins['X'].size, dtype=numpy.double) + 2\n" " return True\n" ); Option module("module", "MyModule"); Option function("function", "myfunc"); Option intensity("add_dimension", "AddedIntensity"); Option scanDirection("add_dimension", "AddedPointSourceId"); Options opts; opts.add(source); opts.add(module); opts.add(function); opts.add(intensity); opts.add(scanDirection); Stage* filter(f.createStage("filters.python")); filter->setOptions(opts); filter->setInput(reader); PointTable table; filter->prepare(table); PointViewSet viewSet = filter->execute(table); EXPECT_EQ(viewSet.size(), 1u); PointViewPtr view = *viewSet.begin(); PointLayoutPtr layout(table.layout()); Dimension::Id int_id = layout->findDim("AddedIntensity"); Dimension::Id psid_id = layout->findDim("AddedPointSourceId"); for (unsigned int i = 0; i < view->size(); ++i) { EXPECT_EQ(view->getFieldAs<uint16_t>(int_id, i), 1); EXPECT_EQ(view->getFieldAs<uint16_t>(psid_id, i), 2); } }
TEST(OldPCLBlockTests, PMF) { StageFactory f; Options ro; ro.add("filename", Support::datapath("autzen/autzen-point-format-3.las")); Stage* r(f.createStage("readers.las")); EXPECT_TRUE(r); r->setOptions(ro); Options ao; ao.add("assignment", "Classification[:]=0"); Stage* assign(f.createStage("filters.assign")); EXPECT_TRUE(assign); assign->setOptions(ao); assign->setInput(*r); Options fo; fo.add("max_window_size", 33.0); fo.add("cell_size", 10.0); fo.add("slope", 1.0); fo.add("initial_distance", 0.15); fo.add("max_distance", 2.5); fo.add("returns", "first"); fo.add("returns", "intermediate"); fo.add("returns", "last"); fo.add("returns", "only"); Stage* outlier(f.createStage("filters.pmf")); EXPECT_TRUE(outlier); outlier->setOptions(fo); outlier->setInput(*assign); Options rangeOpts; rangeOpts.add("limits", "Classification[2:2]"); Stage* range(f.createStage("filters.range")); EXPECT_TRUE(range); range->setOptions(rangeOpts); range->setInput(*outlier); PointTable table; range->prepare(table); PointViewSet viewSet = range->execute(table); EXPECT_EQ(1u, viewSet.size()); PointViewPtr view = *viewSet.begin(); EXPECT_EQ(79u, view->size()); }
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_F(PythonFilterTest, metadata) { StageFactory f; BOX3D bounds(0.0, 0.0, 0.0, 1.0, 1.0, 1.0); Options ops; ops.add("bounds", bounds); ops.add("count", 10); ops.add("mode", "ramp"); FauxReader reader; reader.setOptions(ops); Option source("source", "import numpy\n" "import sys\n" "import redirector\n" "def myfunc(ins,outs):\n" " global metadata\n" " #print('before', globals(), file=sys.stderr,)\n" " metadata = {'name': 'root', 'value': 'a string', 'type': 'string', 'description': 'a description', 'children': [{'name': 'filters.python', 'value': 52, 'type': 'integer', 'description': 'a filter description', 'children': []}, {'name': 'readers.faux', 'value': 'another string', 'type': 'string', 'description': 'a reader description', 'children': []}]}\n" " # print ('schema', schema, file=sys.stderr,)\n" " return True\n" ); Option module("module", "MyModule"); Option function("function", "myfunc"); Options opts; opts.add(source); opts.add(module); opts.add(function); Stage* filter(f.createStage("filters.python")); filter->setOptions(opts); filter->setInput(reader); PointTable table; filter->prepare(table); PointViewSet viewSet = filter->execute(table); EXPECT_EQ(viewSet.size(), 1u); PointViewPtr view = *viewSet.begin(); PointLayoutPtr layout(table.layout()); MetadataNode m = table.metadata(); m = m.findChild("filters.python"); MetadataNodeList l = m.children(); EXPECT_EQ(l.size(), 3u); EXPECT_EQ(l[0].name(), "filters.python"); EXPECT_EQ(l[0].value(), "52"); EXPECT_EQ(l[0].description(), "a filter description"); }
TEST(MergeTest, test4) { using namespace pdal; PipelineManager mgr; mgr.readPipeline(Support::configuredpath("filters/merge.json")); mgr.execute(); PointViewSet viewSet = mgr.views(); EXPECT_EQ(1u, viewSet.size()); PointViewPtr view = *viewSet.begin(); EXPECT_EQ(2130u, view->size()); }
TEST(IcebridgeReaderTest, testRead) { StageFactory f; Stage* reader(f.createStage("readers.icebridge")); EXPECT_TRUE(reader); Option filename("filename", getFilePath(), ""); Options options(filename); reader->setOptions(options); PointTable table; reader->prepare(table); PointViewSet viewSet = reader->execute(table); EXPECT_EQ(viewSet.size(), 1u); PointViewPtr view = *viewSet.begin(); EXPECT_EQ(view->size(), 2u); checkPoint( *view, 0, 141437548, // time 82.605319, // latitude -58.593811, // longitude 18.678, // elevation 2408, // xmtSig 181, // rcvSig 49.91, // azimuth -4.376, // pitch 0.608, // roll 2.9, // gpsPdop 20.0, // pulseWidth 0.0); // relTime checkPoint( *view, 1, 141437548, // time 82.605287, // latitude -58.593811, // longitude 18.688, // elevation 2642, // xmtSig 173, // rcvSig 52.006, // azimuth -4.376, // pitch 0.609, // roll 2.9, // gpsPdop 17.0, // pulseWidth 0.0); // relTime }