TEST(KDIndex, neighbordims) { PointTable table; PointLayoutPtr layout = table.layout(); PointView view(table); layout->registerDim(Dimension::Id::X); layout->registerDim(Dimension::Id::Z); view.setField(Dimension::Id::X, 0, 0); view.setField(Dimension::Id::Z, 0, 0); view.setField(Dimension::Id::X, 1, 1); view.setField(Dimension::Id::Z, 1, 1); EXPECT_THROW(KD2Index index(view), pdal_error); PointTable table2; PointLayoutPtr layout2 = table.layout(); PointView view2(table2); layout->registerDim(Dimension::Id::X); layout->registerDim(Dimension::Id::Y); view.setField(Dimension::Id::X, 0, 0); view.setField(Dimension::Id::Y, 0, 0); view.setField(Dimension::Id::X, 1, 1); view.setField(Dimension::Id::Y, 1, 1); EXPECT_THROW(KD3Index index(view2), pdal_error); }
TEST(NitfReaderTest, optionSrs) { StageFactory f; Options nitfOpts; nitfOpts.add("filename", Support::datapath("nitf/autzen-utm10.ntf")); std::string sr = "PROJCS[\"NAD83 / UTM zone 11N\",GEOGCS[\"NAD83\",DATUM[\"North_American_Datum_1983\",SPHEROID[\"GRS 1980\",6378137,298.257222101,AUTHORITY[\"EPSG\",\"7019\"]],TOWGS84[0,0,0,0,0,0,0],AUTHORITY[\"EPSG\",\"6269\"]],PRIMEM[\"Greenwich\",0,AUTHORITY[\"EPSG\",\"8901\"]],UNIT[\"degree\",0.0174532925199433,AUTHORITY[\"EPSG\",\"9122\"]],AUTHORITY[\"EPSG\",\"4269\"]],PROJECTION[\"Transverse_Mercator\"],PARAMETER[\"latitude_of_origin\",0],PARAMETER[\"central_meridian\",-123],PARAMETER[\"scale_factor\",0.9996],PARAMETER[\"false_easting\",500000],PARAMETER[\"false_northing\",0],UNIT[\"metre\",1,AUTHORITY[\"EPSG\",\"9001\"]],AXIS[\"Easting\",EAST],AXIS[\"Northing\",NORTH],AUTHORITY[\"EPSG\",\"26910\"]]"; nitfOpts.add("spatialreference", sr); PointTable table; Stage* nitfReader(f.createStage("readers.nitf")); EXPECT_TRUE(nitfReader); nitfReader->setOptions(nitfOpts); Options lasOpts; lasOpts.add("filename", "/dev/null"); LasWriter writer; writer.setInput(*nitfReader); writer.setOptions(lasOpts);; writer.prepare(table); PointViewSet pbSet = writer.execute(table); EXPECT_EQ(sr, nitfReader->getSpatialReference().getWKT()); EXPECT_EQ("", writer.getSpatialReference().getWKT()); EXPECT_EQ(sr, table.spatialReference().getWKT()); }
int DeltaKernel::execute() { PointTable srcTable; PointTable candTable; DimIndexMap dims; PointViewPtr srcView = loadSet(m_sourceFile, srcTable); PointViewPtr candView = loadSet(m_candidateFile, candTable); PointLayoutPtr srcLayout = srcTable.layout(); PointLayoutPtr candLayout = candTable.layout(); Dimension::IdList ids = srcLayout->dims(); for (Dimension::Id dim : ids) { std::string name = srcLayout->dimName(dim); if (!m_allDims) if (name != "X" && name != "Y" && name != "Z") continue; DimIndex d; d.m_name = name; d.m_srcId = dim; dims[name] = d; } ids = candLayout->dims(); for (Dimension::Id dim : ids) { std::string name = candLayout->dimName(dim); auto di = dims.find(name); if (di == dims.end()) continue; DimIndex& d = di->second; d.m_candId = dim; } // Remove dimensions that aren't in both the source and candidate lists. for (auto di = dims.begin(); di != dims.end();) { DimIndex& d = di->second; if (d.m_candId == Dimension::Id::Unknown) dims.erase(di++); else ++di; } // Index the candidate data. KD3Index index(*candView); index.build(); MetadataNode root; if (m_detail) root = dumpDetail(srcView, candView, index, dims); else root = dump(srcView, candView, index, dims); Utils::toJSON(root, std::cout); return 0; }
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); Options op5; op5.add("dimensions", "=Foobar"); FerryFilter f5; f5.setInput(reader); f5.setOptions(op5); f5.prepare(table); EXPECT_TRUE(table.layout()->findDim("Foobar") != Dimension::Id::Unknown); }
TEST(KDIndex, neighbors2D) { PointTable table; PointLayoutPtr layout = table.layout(); PointView view(table); layout->registerDim(Dimension::Id::X); layout->registerDim(Dimension::Id::Y); view.setField(Dimension::Id::X, 0, 0); view.setField(Dimension::Id::Y, 0, 0); view.setField(Dimension::Id::X, 1, 1); view.setField(Dimension::Id::Y, 1, 1); view.setField(Dimension::Id::X, 2, 3); view.setField(Dimension::Id::Y, 2, 3); view.setField(Dimension::Id::X, 3, 6); view.setField(Dimension::Id::Y, 3, 6); view.setField(Dimension::Id::X, 4, 10); view.setField(Dimension::Id::Y, 4, 10); KD2Index index(view); index.build(); EXPECT_EQ(index.neighbor(0, 0), 0u); EXPECT_EQ(index.neighbor(1.1, 1.1), 1u); EXPECT_EQ(index.neighbor(3.3, 3.3), 2u); EXPECT_EQ(index.neighbor(6.1, 6.1), 3u); EXPECT_EQ(index.neighbor(15, 15), 4u); std::vector<PointId> ids; ids = index.neighbors(0, 0, 5); EXPECT_EQ(ids.size(), 5u); EXPECT_EQ(ids[0], 0u); EXPECT_EQ(ids[1], 1u); EXPECT_EQ(ids[2], 2u); EXPECT_EQ(ids[3], 3u); EXPECT_EQ(ids[4], 4u); ids = index.neighbors(0, 0, 25); EXPECT_EQ(ids.size(), 5u); EXPECT_EQ(ids[0], 0u); EXPECT_EQ(ids[1], 1u); EXPECT_EQ(ids[2], 2u); EXPECT_EQ(ids[3], 3u); EXPECT_EQ(ids[4], 4u); ids = index.neighbors(3.1, 3.1, 5); EXPECT_EQ(ids.size(), 5u); EXPECT_EQ(ids[0], 2u); EXPECT_EQ(ids[1], 1u); EXPECT_EQ(ids[2], 3u); EXPECT_EQ(ids[3], 0u); EXPECT_EQ(ids[4], 4u); }
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); } }
TIndexKernel::FileInfo TIndexKernel::getFileInfo(KernelFactory& factory, const std::string& filename) { FileInfo fileInfo; PipelineManager manager; manager.commonOptions() = m_manager.commonOptions(); manager.stageOptions() = m_manager.stageOptions(); // Need to make sure options get set. Stage& reader = manager.makeReader(filename, ""); if (m_fastBoundary) { QuickInfo qi = reader.preview(); std::stringstream polygon; polygon << "POLYGON (("; polygon << qi.m_bounds.minx << " " << qi.m_bounds.miny; polygon << ", " << qi.m_bounds.maxx << " " << qi.m_bounds.miny; polygon << ", " << qi.m_bounds.maxx << " " << qi.m_bounds.maxy; polygon << ", " << qi.m_bounds.minx << " " << qi.m_bounds.maxy; polygon << ", " << qi.m_bounds.minx << " " << qi.m_bounds.miny; polygon << "))"; fileInfo.m_boundary = polygon.str(); if (!qi.m_srs.empty()) fileInfo.m_srs = qi.m_srs.getWKT(); } else { Stage& hexer = manager.makeFilter("filters.hexbin", reader); PointTable table; hexer.prepare(table); PointViewSet set = hexer.execute(table); MetadataNode m = table.metadata(); m = m.findChild("filters.hexbin:boundary"); fileInfo.m_boundary = m.value(); PointViewPtr v = *set.begin(); if (!v->spatialReference().empty()) fileInfo.m_srs = v->spatialReference().getWKT(); } FileUtils::fileTimes(filename, &fileInfo.m_ctime, &fileInfo.m_mtime); fileInfo.m_filename = filename; return fileInfo; }
TEST(SegmentationTest, BasicClustering) { using namespace Segmentation; std::vector<std::vector<PointId>> clusters; PointTable table; PointLayoutPtr layout(table.layout()); layout->registerDim(Dimension::Id::X); layout->registerDim(Dimension::Id::Y); layout->registerDim(Dimension::Id::Z); PointViewPtr src(new PointView(table)); // Single point, single cluster src->setField(Dimension::Id::X, 0, 0.0); src->setField(Dimension::Id::Y, 0, 0.0); src->setField(Dimension::Id::Z, 0, 0.0); clusters = extractClusters(*src, 1, 10, 1.0); EXPECT_EQ(1u, clusters.size()); EXPECT_EQ(1u, clusters[0].size()); // Two separate clusters, both with single point src->setField(Dimension::Id::X, 1, 10.0); src->setField(Dimension::Id::Y, 1, 10.0); src->setField(Dimension::Id::Z, 1, 10.0); clusters = extractClusters(*src, 1, 10, 1.0); EXPECT_EQ(2u, clusters.size()); EXPECT_EQ(1u, clusters[0].size()); EXPECT_EQ(1u, clusters[1].size()); // Still two clusters, one with two points src->setField(Dimension::Id::X, 2, 0.5); src->setField(Dimension::Id::Y, 2, 0.5); src->setField(Dimension::Id::Z, 2, 0.5); clusters = extractClusters(*src, 1, 10, 1.0); EXPECT_EQ(2u, clusters.size()); EXPECT_EQ(2u, clusters[0].size()); EXPECT_EQ(1u, clusters[1].size()); // Reject the cluster with only one point clusters = extractClusters(*src, 2, 10, 1.0); EXPECT_EQ(1u, clusters.size()); EXPECT_EQ(2u, clusters[0].size()); // Reject the cluster with two points clusters = extractClusters(*src, 1, 1, 1.0); EXPECT_EQ(1u, clusters.size()); EXPECT_EQ(1u, clusters[0].size()); }
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(XMLSchemaTest, copy) { using namespace pdal; std::string xml = ReadXML(TestConfig::dataPath() + "../../schemas/16-dim-schema.xml"); std::string xsd = ReadXML(TestConfig::dataPath() + "../../schemas/LAS.xsd"); XMLSchema s1(xml, xsd); PointTable table; XMLDimList dims = s1.xmlDims(); for (auto di = dims.begin(); di != dims.end(); ++di) { Dimension::Id id = table.layout()->registerOrAssignDim( di->m_name, di->m_dimType.m_type); s1.setId(di->m_name, id); } MetadataNode m; MetadataNode m1 = m.add("m1", 1u); MetadataNode m2 = m.add("m2", 1); MetadataNode m1prime = m.add("m1prime", "Some other metadata"); m1.add("uuid", Uuid()); XMLSchema s2(s1.xmlDims(), m); std::string xml_output = s2.xml(); XMLSchema s3(xml_output, xsd); XMLDimList dims3 = s3.xmlDims(); EXPECT_EQ(dims.size(), dims3.size()); auto di1 = dims.begin(); auto di3 = dims3.begin(); while (di1 != dims.end() && di3 != dims3.end()) { XMLDim& dim1 = *di1; XMLDim& dim3 = *di3; EXPECT_EQ(dim1.m_name, dim3.m_name); EXPECT_EQ(dim1.m_dimType.m_type, dim3.m_dimType.m_type); di1++; di3++; } }
TEST(KDIndex, radius3D) { PointTable table; PointLayoutPtr layout = table.layout(); PointView view(table); layout->registerDim(Dimension::Id::X); layout->registerDim(Dimension::Id::Y); layout->registerDim(Dimension::Id::Z); view.setField(Dimension::Id::X, 0, 0); view.setField(Dimension::Id::Y, 0, 0); view.setField(Dimension::Id::Z, 0, 0); view.setField(Dimension::Id::X, 1, 1); view.setField(Dimension::Id::Y, 1, 1); view.setField(Dimension::Id::Z, 1, 1); view.setField(Dimension::Id::X, 2, 3); view.setField(Dimension::Id::Y, 2, 3); view.setField(Dimension::Id::Z, 2, 3); view.setField(Dimension::Id::X, 3, 6); view.setField(Dimension::Id::Y, 3, 6); view.setField(Dimension::Id::Z, 3, 6); view.setField(Dimension::Id::X, 4, 10); view.setField(Dimension::Id::Y, 4, 10); view.setField(Dimension::Id::Z, 4, 10); KD3Index index(view); index.build(); std::vector<PointId> ids; ids = index.radius(0, 0, 0, 5.2); EXPECT_EQ(ids.size(), 3u); EXPECT_EQ(ids[0], 0u); EXPECT_EQ(ids[1], 1u); EXPECT_EQ(ids[2], 2u); ids = index.radius(3.1, 3.1, 3.1, 12.2); EXPECT_EQ(ids.size(), 5u); EXPECT_EQ(ids[0], 2u); EXPECT_EQ(ids[1], 1u); EXPECT_EQ(ids[2], 3u); EXPECT_EQ(ids[3], 0u); EXPECT_EQ(ids[4], 4u); }
TEST(PointViewTest, calcBounds) { auto set_points = [](PointViewPtr view, PointId i, double x, double y, double z) { view->setField(Dimension::Id::X, i, x); view->setField(Dimension::Id::Y, i, y); view->setField(Dimension::Id::Z, i, z); }; PointTable table; PointLayoutPtr layout(table.layout()); layout->registerDim(Dimension::Id::X); layout->registerDim(Dimension::Id::Y); layout->registerDim(Dimension::Id::Z); const double lim_min = (std::numeric_limits<double>::lowest)(); const double lim_max = (std::numeric_limits<double>::max)(); PointViewPtr b0(new PointView(table)); BOX3D box_b0; b0->calculateBounds(box_b0); check_bounds(box_b0, lim_max, lim_min, lim_max, lim_min, lim_max, lim_min); PointViewPtr b1(new PointView(table)); set_points(b1, 0, 0.0, 0.0, 0.0); set_points(b1, 1, 2.0, 2.0, 2.0); PointViewPtr b2(new PointView(table)); set_points(b2, 0, 3.0, 3.0, 3.0); set_points(b2, 1, 1.0, 1.0, 1.0); PointViewSet bs; bs.insert(b1); bs.insert(b2); BOX3D box_b1; b1->calculateBounds(box_b1); check_bounds(box_b1, 0.0, 2.0, 0.0, 2.0, 0.0, 2.0); BOX3D box_b2; b2->calculateBounds(box_b2); check_bounds(box_b2, 1.0, 3.0, 1.0, 3.0, 1.0, 3.0); BOX3D box_bs; PointView::calculateBounds(bs, box_bs); check_bounds(box_bs, 0.0, 3.0, 0.0, 3.0, 0.0, 3.0); }
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(ComputeRangeFilterTest, compute) { using namespace Dimension; PointTable table; PointLayoutPtr layout(table.layout()); layout->registerDim(Id::X); layout->registerDim(Id::Y); layout->registerDim(Id::Z); Id pn = layout->registerOrAssignDim("Pixel Number", Type::Double); Id fn = layout->registerOrAssignDim("Frame Number", Type::Double); PointViewPtr view(new PointView(table)); BufferReader r; r.addView(view); ComputeRangeFilter crop; crop.setInput(r); crop.prepare(table); view->setField(Id::X, 0, 0.0); view->setField(Id::Y, 0, 0.0); view->setField(Id::Z, 0, 0.0); view->setField(pn, 0, 0.0); view->setField(fn, 0, 0.0); view->setField(Id::X, 1, 0.0); view->setField(Id::Y, 1, 3.0); view->setField(Id::Z, 1, 4.0); view->setField(pn, 1, -5.0); view->setField(fn, 1, 0.0); PointViewSet s = crop.execute(table); EXPECT_EQ(1u, s.size()); Id range = layout->findDim("Range"); EXPECT_NE(Id::Unknown, range); PointViewPtr out = *s.begin(); EXPECT_EQ(2u, out->size()); EXPECT_EQ(5.0, out->getFieldAs<double>(range, 0)); EXPECT_EQ(0.0, out->getFieldAs<double>(range, 1)); }
TEST(TextReaderTest, insertHeader) { TextReader reader; Options options; options.add("header", "A,B,C,G"); options.add("filename", Support::datapath("text/crlf_test.txt")); reader.setOptions(options); PointTable table; reader.prepare(table); PointViewSet pointViewSet = reader.execute(table); PointViewPtr pointViewPtr = *pointViewSet.begin(); EXPECT_EQ(pointViewPtr->size(), 11U); PointLayoutPtr layout = table.layout(); EXPECT_TRUE(layout->findDim("A") != Dimension::Id::Unknown); EXPECT_TRUE(layout->findDim("B") != Dimension::Id::Unknown); EXPECT_TRUE(layout->findDim("C") != Dimension::Id::Unknown); EXPECT_TRUE(layout->findDim("G") != Dimension::Id::Unknown); }
TEST(GDALReaderTest, simple) { Options ro; ro.add("filename", Support::datapath("png/autzen-height.png")); GDALReader gr; gr.setOptions(ro); PointTable t; gr.prepare(t); PointViewSet s = gr.execute(t); PointViewPtr v = *s.begin(); PointLayoutPtr l = t.layout(); Dimension::Id::Enum id1 = l->findDim("band-1"); Dimension::Id::Enum id2 = l->findDim("band-2"); Dimension::Id::Enum id3 = l->findDim("band-3"); EXPECT_EQ(v->size(), (size_t)(735 * 973)); auto verify = [v, id1, id2, id3] (PointId idx, double xx, double xy, double xr, double xg, double xb) { double r, g, b, x, y; x = v->getFieldAs<double>(Dimension::Id::X, idx); y = v->getFieldAs<double>(Dimension::Id::Y, idx); r = v->getFieldAs<double>(id1, idx); g = v->getFieldAs<double>(id2, idx); b = v->getFieldAs<double>(id3, idx); EXPECT_DOUBLE_EQ(x, xx); EXPECT_DOUBLE_EQ(y, xy); EXPECT_DOUBLE_EQ(r, xr); EXPECT_DOUBLE_EQ(g, xg); EXPECT_DOUBLE_EQ(b, xb); }; verify(0, .5, .5, 0, 0, 0); verify(120000, 195.5, 163.5, 255, 213, 0); verify(290000, 410.5, 394.5, 0, 255, 206); verify(715154, 734.5, 972.5, 0, 0, 0); }
TEST(PolygonTest, covers) { using namespace pdal::Dimension; pdal::Polygon p(getWKT()); PointTable table; PointLayoutPtr layout(table.layout()); layout->registerDim(Dimension::Id::X); layout->registerDim(Dimension::Id::Y); // Check if the very first point in the polygon is // covered by the polyg. Should be true // PointViewPtr view(new PointView(table)); view->setField(Id::X, 0, 636889.412951239268295 ); view->setField(Id::Y, 0, 851528.512293258565478); pdal::PointRef ref(*view, 0); bool covered = p.covers(ref); EXPECT_EQ(covered, true); }
TEST_F(PgpointcloudWriterTest, writeXYZ) { if (shouldSkipTests()) { return; } Options ops = getDbOptions(); ops.add("output_dims", "X,Y,Z"); optionsWrite(ops); PointTable table; StageFactory factory; Stage* reader(factory.createStage("readers.pgpointcloud")); reader->setOptions(getDbOptions()); reader->prepare(table); Dimension::IdList dims = table.layout()->dims(); EXPECT_EQ(dims.size(), (size_t)3); EXPECT_TRUE(Utils::contains(dims, Dimension::Id::X)); EXPECT_TRUE(Utils::contains(dims, Dimension::Id::Y)); EXPECT_TRUE(Utils::contains(dims, Dimension::Id::Z)); }
TEST(PointViewTest, issue1264) { PointTable t; PointLayoutPtr layout(t.layout()); Dimension::Id foo = layout->assignDim("foo", Dimension::Type::Unsigned8); Dimension::Id bar = layout->assignDim("bar", Dimension::Type::Signed8); layout->finalize(); PointView v(t); double d(250.0); v.setField(foo, 0, d); d = v.getFieldAs<double>(foo, 0); EXPECT_DOUBLE_EQ(d, 250.0); d = 123.0; v.setField(bar, 0, d); d = v.getFieldAs<double>(bar, 0); EXPECT_DOUBLE_EQ(d, 123.0); d = -120.23456; v.setField(bar, 0, d); d = v.getFieldAs<double>(bar, 0); EXPECT_DOUBLE_EQ(d, -120.0); d = 260.0; EXPECT_THROW(v.setField(foo, 0, d), pdal_error); }
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(Compression, simple) { const std::string file(Support::datapath("las/1.2-with-color.las")); const pdal::Option opt_filename("filename", file); pdal::Options opts; opts.add(opt_filename); LasReader reader; reader.setOptions(opts); PointTable table; PointLayoutPtr layout(table.layout()); reader.prepare(table); PointViewSet viewSet = reader.execute(table); PointViewPtr view = *viewSet.begin(); EXPECT_EQ(layout->pointSize(), 52U); std::vector<unsigned char> rawBuf; DimTypeList dimTypes = layout->dimTypes(); auto cb = [&rawBuf](char *buf, size_t bufsize) { unsigned char *ubuf = reinterpret_cast<unsigned char *>(buf); rawBuf.insert(rawBuf.end(), ubuf, ubuf + bufsize); }; LazPerfCompressor compressor(cb, dimTypes); std::vector<char> tmpbuf(layout->pointSize()); for (PointId idx = 0; idx < view->size(); ++idx) { view->getPackedPoint(dimTypes, idx, tmpbuf.data()); compressor.compress(tmpbuf.data(), layout->pointSize()); } compressor.done(); EXPECT_EQ(view->size() * layout->pointSize(), (size_t)55380); EXPECT_EQ(rawBuf.size(), (size_t)30945); PointViewPtr otherView(new PointView(table)); PointId nextId(0); auto cb2 = [&otherView, &dimTypes, &nextId](char *buf, size_t bufsize) { otherView->setPackedPoint(dimTypes, nextId, buf); nextId++; }; LazPerfDecompressor(cb2, dimTypes, view->size()). decompress(reinterpret_cast<const char *>(rawBuf.data()), rawBuf.size()); EXPECT_EQ(otherView->size(), 1065U); EXPECT_EQ(getBytes(otherView).size(), (size_t)(52 * 1065)); uint16_t r = otherView->getFieldAs<uint16_t>(Dimension::Id::Red, 10); EXPECT_EQ(r, 64U); int32_t x = otherView->getFieldAs<int32_t>(Dimension::Id::X, 10); EXPECT_EQ(x, 636038); double xd = otherView->getFieldAs<double>(Dimension::Id::X, 10); EXPECT_FLOAT_EQ(xd, 636037.53); int32_t y = otherView->getFieldAs<int32_t>(Dimension::Id::Y, 10); EXPECT_EQ(y, 849338); }
TEST(Compression, Simple) { const std::string file(Support::datapath("las/1.2-with-color.las")); const pdal::Option opt_filename("filename", file); pdal::Options opts; opts.add(opt_filename); LasReader reader; reader.setOptions(opts); PointTable table; PointLayoutPtr layout(table.layout()); reader.prepare(table); PointViewSet viewSet = reader.execute(table); PointViewPtr view = *viewSet.begin(); EXPECT_EQ(layout->pointSize(), 52U); std::vector<unsigned char> rawBuf; LazPerfBuf b(rawBuf); DimTypeList dimTypes = layout->dimTypes(); LazPerfCompressor<LazPerfBuf> compressor(b, dimTypes); std::vector<char> tmpbuf(compressor.pointSize()); for (PointId idx = 0; idx < view->size(); ++idx) { view->getPackedPoint(dimTypes, idx, tmpbuf.data()); compressor.compress(tmpbuf.data(), compressor.pointSize()); } compressor.done(); EXPECT_EQ(view->size() * compressor.pointSize(), (size_t)55380); EXPECT_EQ(rawBuf.size(), (size_t)30945); LazPerfBuf b2(rawBuf); LazPerfDecompressor<LazPerfBuf> decompressor(b2, dimTypes); size_t outbufSize = decompressor.pointSize() * view->size(); std::vector<char> outbuf(outbufSize); decompressor.decompress(outbuf.data(), outbufSize); PointViewPtr otherView(new PointView(table)); char *pos = outbuf.data(); for (PointId nextId = 0; nextId < 11; nextId++) { otherView->setPackedPoint(dimTypes, nextId, pos); pos += decompressor.pointSize(); } EXPECT_EQ(otherView->size(), 11U); EXPECT_EQ(getBytes(otherView).size(), (size_t)(52 * 11)); uint16_t r = otherView->getFieldAs<uint16_t>(Dimension::Id::Red, 10); EXPECT_EQ(r, 64U); int32_t x = otherView->getFieldAs<int32_t>(Dimension::Id::X, 10); EXPECT_EQ(x, 636038); double xd = otherView->getFieldAs<double>(Dimension::Id::X, 10); EXPECT_FLOAT_EQ(xd, 636037.53); int32_t y = otherView->getFieldAs<int32_t>(Dimension::Id::Y, 10); EXPECT_EQ(y, 849338); }
TEST(LasReaderTest, extraBytes) { PointTable table; PointLayoutPtr layout(table.layout()); Options readOps; readOps.add("filename", Support::datapath("las/extrabytes.las")); LasReader reader; reader.setOptions(readOps); reader.prepare(table); DimTypeList dimTypes = layout->dimTypes(); EXPECT_EQ(dimTypes.size(), (size_t)24); Dimension::Id color0 = layout->findProprietaryDim("Colors0"); EXPECT_EQ(layout->dimType(color0), Dimension::Type::Unsigned16); Dimension::Id color1 = layout->findProprietaryDim("Colors1"); EXPECT_EQ(layout->dimType(color1), Dimension::Type::Unsigned16); Dimension::Id color2 = layout->findProprietaryDim("Colors2"); EXPECT_EQ(layout->dimType(color2), Dimension::Type::Unsigned16); Dimension::Id flag0 = layout->findProprietaryDim("Flags0"); EXPECT_EQ(layout->dimType(flag0), Dimension::Type::Signed8); Dimension::Id flag1 = layout->findProprietaryDim("Flags1"); EXPECT_EQ(layout->dimType(flag1), Dimension::Type::Signed8); Dimension::Id time2 = layout->findDim("Time"); EXPECT_EQ(layout->dimType(time2), Dimension::Type::Unsigned64); PointViewSet viewSet = reader.execute(table); EXPECT_EQ(viewSet.size(), (size_t)1); PointViewPtr view = *viewSet.begin(); Dimension::Id red = layout->findDim("Red"); Dimension::Id green = layout->findDim("Green"); Dimension::Id blue = layout->findDim("Blue"); Dimension::Id returnNum = layout->findDim("ReturnNumber"); Dimension::Id numReturns = layout->findDim("NumberOfReturns"); Dimension::Id intensity = layout->findDim("Intensity"); Dimension::Id time = layout->findDim("GpsTime"); for (PointId idx = 0; idx < view->size(); ++idx) { ASSERT_EQ(view->getFieldAs<uint16_t>(red, idx), view->getFieldAs<uint16_t>(color0, idx)); ASSERT_EQ(view->getFieldAs<uint16_t>(green, idx), view->getFieldAs<uint16_t>(color1, idx)); ASSERT_EQ(view->getFieldAs<uint16_t>(blue, idx), view->getFieldAs<uint16_t>(color2, idx)); ASSERT_EQ(view->getFieldAs<uint16_t>(flag0, idx), view->getFieldAs<uint16_t>(returnNum, idx)); ASSERT_EQ(view->getFieldAs<uint16_t>(flag1, idx), view->getFieldAs<uint16_t>(numReturns, idx)); // Time was written truncated rather than rounded. ASSERT_NEAR(view->getFieldAs<double>(time, idx), view->getFieldAs<double>(time2, idx), 1.0); } }
TEST(CropFilterTest, multibounds) { using namespace Dimension; PointTable table; table.layout()->registerDim(Id::X); table.layout()->registerDim(Id::Y); table.layout()->registerDim(Id::Z); PointViewPtr view(new PointView(table)); view->setField(Id::X, 0, 2); view->setField(Id::Y, 0, 2); view->setField(Id::X, 1, 4); view->setField(Id::Y, 1, 2); view->setField(Id::X, 2, 6); view->setField(Id::Y, 2, 2); view->setField(Id::X, 3, 8); view->setField(Id::Y, 3, 2); view->setField(Id::X, 4, 10); view->setField(Id::Y, 4, 2); view->setField(Id::X, 5, 12); view->setField(Id::Y, 5, 2); BufferReader r; r.addView(view); CropFilter crop; Options o; o.add("bounds", "([1, 3], [1, 3])"); o.add("bounds", "([5, 7], [1, 3])"); o.add("polygon", "POLYGON ((9 1, 11 1, 11 3, 9 3, 9 1))"); crop.setInput(r); crop.setOptions(o); crop.prepare(table); PointViewSet s = crop.execute(table); // Make sure we get three views, one with the point 2, 2, one with the // point 6, 2 and one with 10,2. EXPECT_EQ(s.size(), 3u); static int total_cnt = 0; for (auto v : s) { int cnt = 0; EXPECT_EQ(v->size(), 1u); double x = v->getFieldAs<double>(Dimension::Id::X, 0); double y = v->getFieldAs<double>(Dimension::Id::Y, 0); if (x == 2 && y == 2) cnt = 1; if (x == 6 && y == 2) cnt = 2; if (x == 10 && y == 2) cnt = 4; EXPECT_TRUE(cnt > 0); total_cnt += cnt; } EXPECT_EQ(total_cnt, 7); }
TEST(LasWriterTest, extra_dims) { Options readerOps; readerOps.add("filename", Support::datapath("las/1.2-with-color.las")); LasReader reader; reader.setOptions(readerOps); Options writerOps; writerOps.add("extra_dims", "Red=int32, Blue = int16, Green = int32_t"); writerOps.add("filename", Support::temppath("simple.las")); LasWriter writer; writer.setInput(reader); writer.setOptions(writerOps); PointTable table; writer.prepare(table); PointViewSet viewSet = writer.execute(table); LasTester tester; LasHeader *header = tester.header(writer); EXPECT_EQ(header->pointLen(), header->basePointLen() + 10); PointViewPtr pb = *viewSet.begin(); uint16_t colors[][3] = { { 68, 77, 88 }, { 92, 100, 110 }, { 79, 87, 87 }, { 100, 102, 116 }, { 162, 114, 145 }, { 163, 137, 155 }, { 154, 131, 144 }, { 104, 111, 126 }, { 164, 136, 156 }, { 72, 87, 82 }, { 117, 117, 136 } }; Options reader2Ops; reader2Ops.add("filename", Support::temppath("simple.las")); reader2Ops.add("extra_dims", "R1 =int32, B1= int16 ,G1=int32_t"); LasReader reader2; reader2.setOptions(reader2Ops); PointTable readTable; reader2.prepare(readTable); viewSet = reader2.execute(readTable); pb = *viewSet.begin(); Dimension::Id r1 = readTable.layout()->findDim("R1"); EXPECT_TRUE(r1 != Dimension::Id::Unknown); Dimension::Id b1 = readTable.layout()->findDim("B1"); EXPECT_TRUE(b1 != Dimension::Id::Unknown); Dimension::Id g1 = readTable.layout()->findDim("G1"); EXPECT_TRUE(g1 != Dimension::Id::Unknown); EXPECT_EQ(pb->size(), (size_t)1065); size_t j = 0; for (PointId i = 0; i < pb->size(); i += 100) { EXPECT_EQ(pb->getFieldAs<int16_t>(r1, i), colors[j][0]); EXPECT_EQ(pb->getFieldAs<int16_t>(g1, i), colors[j][1]); EXPECT_EQ(pb->getFieldAs<int16_t>(b1, i), colors[j][2]); j++; } }
// Identical to above, but writes each input view to a separate output file. TEST(LasWriterTest, auto_offset2) { using namespace Dimension; const std::string outname(Support::temppath("offset_test#.las")); const std::string inname1(Support::temppath("offset_test1.las")); const std::string inname2(Support::temppath("offset_test2.las")); PointTable table; table.layout()->registerDims({Id::X, Id::Y, Id::Z}); 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, 1000000.02); view->setField(Id::Y, 0, 0); view->setField(Id::Y, 1, 1); view->setField(Id::Y, 2, 2); view->setField(Id::Z, 0, -123); view->setField(Id::Z, 1, 456.78); view->setField(Id::Z, 2, 945.23); bufferReader.addView(view); view.reset(new PointView(table)); view->setField(Id::X, 0, 25.00); view->setField(Id::X, 1, 74529.00); view->setField(Id::X, 2, 534252.35); view->setField(Id::Y, 0, 3); view->setField(Id::Y, 1, 4); view->setField(Id::Y, 2, 5); view->setField(Id::Z, 0, 1.5); view->setField(Id::Z, 1, 2147483524); view->setField(Id::Z, 2, 745.23); bufferReader.addView(view); Options writerOps; writerOps.add("filename", outname); writerOps.add("offset_x", "auto"); writerOps.add("scale_x", "auto"); writerOps.add("offset_z", "auto"); writerOps.add("scale_z", "auto"); LasWriter writer; writer.setOptions(writerOps); writer.setInput(bufferReader); writer.prepare(table); writer.execute(table); { Options readerOps; readerOps.add("filename", inname1); PointTable readTable; LasReader reader; reader.setOptions(readerOps); reader.prepare(readTable); EXPECT_DOUBLE_EQ(74529.00, reader.header().offsetX()); EXPECT_DOUBLE_EQ(0, reader.header().offsetY()); EXPECT_DOUBLE_EQ(-123, reader.header().offsetZ()); EXPECT_NEAR(4.30956e-4, reader.header().scaleX(), 1e-4); EXPECT_DOUBLE_EQ(.01, reader.header().scaleY()); // (max - min) are chosen to yield std::numeric_limits<int>::max(); EXPECT_NEAR(4.9743e-7, reader.header().scaleZ(), 1e-7); 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), .001); EXPECT_NEAR(74529.00, view->getFieldAs<double>(Id::X, 1), .001); EXPECT_NEAR(1000000.02, view->getFieldAs<double>(Id::X, 2), .0001); } { Options readerOps; readerOps.add("filename", inname2); PointTable readTable; LasReader reader; reader.setOptions(readerOps); reader.prepare(readTable); EXPECT_DOUBLE_EQ(25.0, reader.header().offsetX()); EXPECT_DOUBLE_EQ(0, reader.header().offsetY()); EXPECT_DOUBLE_EQ(1.5, reader.header().offsetZ()); EXPECT_NEAR(2.4876e-4, reader.header().scaleX(), 1e-7); EXPECT_DOUBLE_EQ(.01, reader.header().scaleY()); EXPECT_NEAR(.99999, reader.header().scaleZ(), 1e-5); PointViewSet viewSet = reader.execute(readTable); EXPECT_EQ(viewSet.size(), 1u); view = *viewSet.begin(); EXPECT_EQ(view->size(), 3u); EXPECT_NEAR(25.00, view->getFieldAs<double>(Id::X, 0), .0001); EXPECT_NEAR(74529.00, view->getFieldAs<double>(Id::X, 1), .001); EXPECT_NEAR(534252.35, view->getFieldAs<double>(Id::X, 2), .0001); } FileUtils::deleteFile(inname1); FileUtils::deleteFile(inname2); }
TEST(SegmentationTest, SegmentReturns) { using namespace Segmentation; PointTable table; PointLayoutPtr layout(table.layout()); layout->registerDim(Dimension::Id::X); layout->registerDim(Dimension::Id::Y); layout->registerDim(Dimension::Id::Z); layout->registerDim(Dimension::Id::NumberOfReturns); layout->registerDim(Dimension::Id::ReturnNumber); PointViewPtr src(new PointView(table)); src->setField(Dimension::Id::X, 0, 10.0); src->setField(Dimension::Id::Y, 0, 10.0); src->setField(Dimension::Id::Z, 0, 10.0); src->setField(Dimension::Id::NumberOfReturns, 0, 1); src->setField(Dimension::Id::ReturnNumber, 0, 1); PointViewPtr first, second; StringList returns; first = src->makeNew(); second = src->makeNew(); segmentReturns(src, first, second, returns); EXPECT_EQ(1u, src->size()); EXPECT_EQ(1u, first->size()); EXPECT_EQ(0u, second->size()); returns = {"last", "only"}; first = src->makeNew(); second = src->makeNew(); segmentReturns(src, first, second, returns); EXPECT_EQ(1u, src->size()); EXPECT_EQ(1u, first->size()); EXPECT_EQ(0u, second->size()); src->setField(Dimension::Id::X, 1, 10.0); src->setField(Dimension::Id::Y, 1, 10.0); src->setField(Dimension::Id::Z, 1, 10.0); src->setField(Dimension::Id::NumberOfReturns, 1, 2); src->setField(Dimension::Id::ReturnNumber, 1, 1); returns = {"last", "only"}; first = src->makeNew(); second = src->makeNew(); segmentReturns(src, first, second, returns); EXPECT_EQ(2u, src->size()); EXPECT_EQ(1u, first->size()); EXPECT_EQ(1u, second->size()); src->setField(Dimension::Id::X, 2, 10.0); src->setField(Dimension::Id::Y, 2, 10.0); src->setField(Dimension::Id::Z, 2, 10.0); src->setField(Dimension::Id::NumberOfReturns, 2, 0); src->setField(Dimension::Id::ReturnNumber, 2, 0); returns = {"last", "only"}; first = src->makeNew(); second = src->makeNew(); segmentReturns(src, first, second, returns); EXPECT_EQ(3u, src->size()); EXPECT_EQ(1u, first->size()); EXPECT_EQ(2u, second->size()); src->setField(Dimension::Id::X, 3, 10.0); src->setField(Dimension::Id::Y, 3, 10.0); src->setField(Dimension::Id::Z, 3, 10.0); src->setField(Dimension::Id::NumberOfReturns, 3, 3); src->setField(Dimension::Id::ReturnNumber, 3, 2); returns = {"intermediate", "last", "only"}; first = src->makeNew(); second = src->makeNew(); segmentReturns(src, first, second, returns); EXPECT_EQ(4u, src->size()); EXPECT_EQ(2u, first->size()); EXPECT_EQ(2u, second->size()); returns = {"first", "intermediate", "last", "only"}; first = src->makeNew(); second = src->makeNew(); segmentReturns(src, first, second, returns); EXPECT_EQ(4u, src->size()); EXPECT_EQ(3u, first->size()); EXPECT_EQ(1u, second->size()); }
TEST(PointViewTest, bigfile) { PointTable table; point_count_t NUM_PTS = 1000000; PointLayoutPtr layout(table.layout()); layout->registerDim(Dimension::Id::X); layout->registerDim(Dimension::Id::Y); layout->registerDim(Dimension::Id::Z); PointView view(table); for (PointId id = 0; id < NUM_PTS; ++id) { view.setField(Dimension::Id::X, id, id); view.setField(Dimension::Id::Y, id, 2 * id); view.setField(Dimension::Id::Z, id, -(int)id); } for (PointId id = 0; id < NUM_PTS; ++id) { EXPECT_EQ( view.getFieldAs<PointId>(Dimension::Id::X, id), id); EXPECT_EQ( view.getFieldAs<PointId>(Dimension::Id::Y, id), id * 2); EXPECT_EQ( view.getFieldAs<int>(Dimension::Id::Z, id), -(int)id); } // Test some random access. std::unique_ptr<PointId[]> ids(new PointId[NUM_PTS]); for (PointId idx = 0; idx < NUM_PTS; ++idx) ids[idx] = idx; // Do a bunch of random swaps. std::default_random_engine generator; std::uniform_int_distribution<PointId> distribution(0, NUM_PTS-1); for (PointId idx = 0; idx < NUM_PTS; ++idx) { PointId y = distribution(generator); PointId temp = std::move(ids[idx]); ids[idx] = std::move(ids[y]); ids[y] = std::move(temp); } for (PointId idx = 0; idx < NUM_PTS; ++idx) { PointId id = ids[idx]; view.setField(Dimension::Id::X, id, idx); view.setField(Dimension::Id::Y, id, 2 * idx); view.setField(Dimension::Id::Z, id, -(int)idx); } for (PointId idx = 0; idx < NUM_PTS; ++idx) { PointId id = ids[idx]; EXPECT_EQ( view.getFieldAs<PointId>(Dimension::Id::X, id), idx); EXPECT_EQ( view.getFieldAs<PointId>(Dimension::Id::Y, id), idx * 2); EXPECT_EQ( view.getFieldAs<int>(Dimension::Id::Z, id), -(int)idx); } }
TEST(EptAddonWriterTest, fullLoop) { // Test the writing, and subsequent reading, of EPT addons from both // well-known and proprietary dimensions. const std::string addonDir(Support::datapath("ept/addon/")); FileUtils::deleteDirectory(addonDir); // First write the output. { EptReader reader; { Options o; o.add("filename", "ept://" + Support::datapath("ept/ept-star")); reader.setOptions(o); } // Assign Classification values. AssignFilter assign1; { Options o; o.add("assignment", "Classification[:]=42"); assign1.setOptions(o); assign1.setInput(reader); } // Ferry Classification => Other to create a new dimension that we can // access in the next step. FerryFilter ferry; { Options o; o.add("dimensions", "Classification => Other"); ferry.setOptions(o); ferry.setInput(assign1); } // Assign proprietary dimension values. AssignFilter assign2; { Options o; o.add("assignment", "Other[:]=88"); assign2.setOptions(o); assign2.setInput(ferry); } EptAddonWriter writer; { NL::json addons; addons[addonDir + "class"] = "Classification"; addons[addonDir + "other"] = "Other"; Options o; o.add("addons", addons); writer.setOptions(o); writer.setInput(assign2); } PointTable table; writer.prepare(table); writer.execute(table); } // Then read the output, making sure our dimension values are overridden // with the addon values. EptReader reader; { NL::json addons; addons["Classification"] = addonDir + "class"; addons["Other"] = addonDir + "other"; Options o; o.add("filename", "ept://" + Support::datapath("ept/ept-star")); o.add("addons", addons); reader.setOptions(o); } PointTable table; reader.prepare(table); const auto set(reader.execute(table)); const Dimension::Id classDim(Dimension::Id::Classification); const Dimension::Id otherDim(table.layout()->findDim("Other")); for (const PointViewPtr& view : set) { for (point_count_t i(0); i < view->size(); ++i) { ASSERT_EQ(view->getFieldAs<uint16_t>(classDim, i), 42u); ASSERT_EQ(view->getFieldAs<uint16_t>(otherDim, i), 88u); } } }
int CpdKernel::execute() { PointTable tableX; PointTable tableY; cpd::Matrix X = readFile(m_filex); cpd::Matrix Y = readFile(m_filey); if (X.rows() == 0 || Y.rows() == 0) { throw pdal_error("No points to process."); } cpd::Matrix result; if (m_method == "rigid") { cpd::Rigid rigid; rigid .set_tolerance(m_tolerance) .set_max_iterations(m_max_it) .set_outlier_weight(m_outliers); rigid .no_reflections(m_no_reflections) .allow_scaling(m_allow_scaling); if (m_sigma2 > 0) { result = rigid.compute(X, Y, m_sigma2).points; } else { result = rigid.compute(X, Y).points; } } else if (m_method == "nonrigid") { cpd::Nonrigid nonrigid; nonrigid .set_tolerance(m_tolerance) .set_max_iterations(m_max_it) .set_outlier_weight(m_outliers); nonrigid .set_beta(m_beta) .set_lambda(m_lambda); if (m_sigma2 > 0) { result = nonrigid.compute(X, Y, m_sigma2).points; } else { result = nonrigid.compute(X, Y).points; } } else { std::stringstream ss; ss << "Invalid cpd method: " << m_method << std::endl; throw pdal_error(ss.str()); } PointTable outTable; PointLayoutPtr outLayout(outTable.layout()); outLayout->registerDim(Dimension::Id::X); outLayout->registerDim(Dimension::Id::Y); outLayout->registerDim(Dimension::Id::Z); outLayout->registerDim(Dimension::Id::XVelocity); outLayout->registerDim(Dimension::Id::YVelocity); outLayout->registerDim(Dimension::Id::ZVelocity); PointViewPtr outView(new PointView(outTable)); size_t M = Y.rows(); for (size_t i = 0; i < M; ++i) { outView->setField<double>(Dimension::Id::X, i, result(i, 0)); outView->setField<double>(Dimension::Id::Y, i, result(i, 1)); outView->setField<double>(Dimension::Id::Z, i, result(i, 2)); outView->setField<double>(Dimension::Id::XVelocity, i, Y(i, 0) - result(i, 0)); outView->setField<double>(Dimension::Id::YVelocity, i, Y(i, 1) - result(i, 1)); outView->setField<double>(Dimension::Id::ZVelocity, i, Y(i, 2) - result(i, 2)); } BufferReader reader; reader.addView(outView); Options writerOpts; if (StageFactory::inferReaderDriver(m_output) == "writers.text") { writerOpts.add("order", "X,Y,Z,XVelocity,YVelocity,ZVelocity"); writerOpts.add("keep_unspecified", false); } Stage& writer = makeWriter(m_output, reader, "", writerOpts); writer.prepare(outTable); writer.execute(outTable); return 0; }