inline ptree toPTree(MetadataNode const& node) { typedef ptree::path_type path; ptree tree; tree.put("name", node.name()); tree.put("description", node.description()); tree.put("type", node.type()); tree.put("value", node.value()); MetadataNodeList children = node.children(); for (auto n = children.begin(); n != children.end(); ++n) { ptree pnode = toPTree(*n); if (node.kind() == MetadataType::Array) { boost::optional<ptree&> opt = tree.get_child_optional(path(node.name(), '/')); if (opt) opt->push_back(std::make_pair("", pnode)); else { tree.push_back(ptree::value_type(node.name(), ptree())); auto& p = tree.get_child(path(node.name(), '/')); p.push_back(std::make_pair("", pnode)); } } else if (node.name().size()) tree.push_back(std::make_pair(node.name(), pnode)); } return tree; }
TEST(XMLSchemaTest, utf8) { using namespace pdal; std::string inFilename(TestConfig::dataPath() + "../../schemas/utf8-schema.xml"); std::string inXsdFilename(TestConfig::dataPath() + "../../schemas/LAS.xsd"); std::string xml = ReadXML(inFilename); std::string xsd = ReadXML(inXsdFilename); XMLSchema s1(xml, xsd); std::string descripValue("Ég get etið gler án þess að meiða mig."); std::string metaName("אני יכול לאכול זכוכית וזה לא מזיק לי."); std::string metaValue("أنا قادر على أكل الزجاج و هذا لا يؤلمني"); XMLDimList dims = s1.xmlDims(); EXPECT_EQ(dims.size(), 1U); if (dims.size()) { XMLDim& dim = *dims.begin(); EXPECT_EQ(descripValue, dim.m_description); MetadataNodeList mlist = s1.getMetadata().children(); EXPECT_EQ(mlist.size(), 1U); MetadataNode& m = *mlist.begin(); EXPECT_EQ(m.name(), metaName); EXPECT_EQ(m.value(), metaValue); } }
// Make sure that we can forward the LAS_Spec/3 VLR TEST(LasWriterTest, forward_spec_3) { PointTable table; std::string infile(Support::datapath("las/spec_3.las")); std::string outfile(Support::temppath("out.las")); // remove file from earlier run, if needed FileUtils::deleteFile(outfile); Options readerOpts; readerOpts.add("filename", infile); Options writerOpts; writerOpts.add("forward", "all,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); auto pred = [](MetadataNode temp) { auto recPred = [](MetadataNode n) { return n.name() == "record_id" && n.value() == "3"; }; auto userPred = [](MetadataNode n) { return n.name() == "user_id" && n.value() == "LASF_Spec"; }; return Utils::startsWith(temp.name(), "vlr_") && !temp.findChild(recPred).empty() && !temp.findChild(userPred).empty(); }; MetadataNode root = reader2.getMetadata(); MetadataNodeList nodes = root.findChildren(pred); EXPECT_EQ(nodes.size(), 1u); }
MetadataNodeList findChildren(PREDICATE p) { MetadataNodeList matches; auto nodes = children(); for (auto ai = nodes.begin(); ai != nodes.end(); ++ai) { MetadataNode& n = *ai; if (p(n)) matches.push_back(n); } return matches; }
MetadataNodeList children(const std::string& name) const { MetadataNodeList outnodes; auto si = m_impl->m_subnodes.find(name); if (si != m_impl->m_subnodes.end()) { const MetadataImplList& l = si->second; for (auto li = l.begin(); li != l.end(); ++li) outnodes.push_back(MetadataNode(*li)); } return outnodes; }
MetadataNodeList children() const { MetadataNodeList outnodes; const MetadataSubnodes& nodes = m_impl->m_subnodes; for (auto si = nodes.begin(); si != nodes.end(); ++si) { const MetadataImplList& l = si->second; for (auto li = l.begin(); li != l.end(); ++li) outnodes.push_back(MetadataNode(*li)); } return outnodes; }
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(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(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); }
PyObject *fromMetadata(MetadataNode m) { std::string name = m.name(); std::string value = m.value(); std::string type = m.type(); std::string description = m.description(); MetadataNodeList children = m.children(); PyObject *submeta = PyList_New(0); if (children.size()) { for (MetadataNode& child : children) PyList_Append(submeta, fromMetadata(child)); } PyObject *data = PyDict_New(); PyDict_SetItemString(data, "name", PyUnicode_FromString(name.data())); PyDict_SetItemString(data, "value", PyUnicode_FromString(value.data())); PyDict_SetItemString(data, "type", PyUnicode_FromString(type.data())); PyDict_SetItemString(data, "description", PyUnicode_FromString(description.data())); PyDict_SetItemString(data, "children", submeta); return data; }
PyObject *fromMetadata(MetadataNode m) { std::string name = m.name(); std::string value = m.value(); std::string type = m.type(); std::string description = m.description(); MetadataNodeList children = m.children(); PyObject *submeta = NULL; if (children.size()) { submeta = PyList_New(0); for (MetadataNode& child : children) PyList_Append(submeta, fromMetadata(child)); } PyObject *data = PyTuple_New(5); PyTuple_SetItem(data, 0, PyUnicode_FromString(name.data())); PyTuple_SetItem(data, 1, PyUnicode_FromString(value.data())); PyTuple_SetItem(data, 2, PyUnicode_FromString(type.data())); PyTuple_SetItem(data, 3, PyUnicode_FromString(description.data())); PyTuple_SetItem(data, 4, submeta); return data; }