PointViewSet Stage::execute(PointTableRef table) { table.finalize(); PointViewSet views; // If the inputs are empty, we're a reader. if (m_inputs.empty()) { views.insert(PointViewPtr(new PointView(table))); } else { for (size_t i = 0; i < m_inputs.size(); ++i) { Stage *prev = m_inputs[i]; PointViewSet temp = prev->execute(table); views.insert(temp.begin(), temp.end()); } } PointViewSet outViews; std::vector<StageRunnerPtr> runners; // Put the spatial references from the views onto the table. // The table's spatial references are only valid as long as the stage // is running. // ABELL - Should we clear the references once the stage run has // completed? Wondering if that would break something where a // writer wants to check a table's SRS. SpatialReference srs; table.clearSpatialReferences(); for (auto const& it : views) table.addSpatialReference(it->spatialReference()); // Do the ready operation and then start running all the views // through the stage. ready(table); for (auto const& it : views) { StageRunnerPtr runner(new StageRunner(this, it)); runners.push_back(runner); runner->run(); } // As the stages complete (synchronously at this time), propagate the // spatial reference and merge the output views. srs = getSpatialReference(); for (auto const& it : runners) { StageRunnerPtr runner(it); PointViewSet temp = runner->wait(); // If our stage has a spatial reference, the view takes it on once // the stage has been run. if (!srs.empty()) for (PointViewPtr v : temp) v->setSpatialReference(srs); outViews.insert(temp.begin(), temp.end()); } done(table); return outViews; }
void TIndexKernel::mergeFile() { using namespace gdal; std::ostringstream out; if (!openDataset(m_idxFilename)) { std::ostringstream out; out << "Couldn't open index dataset file '" << m_idxFilename << "'."; throw pdal_error(out.str()); } if (!openLayer(m_layerName)) { std::ostringstream out; out << "Couldn't open layer '" << m_layerName << "' in output file '" << m_idxFilename << "'."; throw pdal_error(out.str()); } FieldIndexes indexes = getFields(); SpatialRef outSrs(m_tgtSrsString); if (!outSrs) throw pdal_error("Couldn't interpret target SRS string."); if (!m_wkt.empty()) { Geometry g(m_wkt, outSrs); if (!g) throw pdal_error("Couldn't interpret geometry filter string."); OGR_L_SetSpatialFilter(m_layer, g.get()); } std::vector<FileInfo> files; // Docs are bad here. You need this call even if you haven't read anything // or nothing happens. OGR_L_ResetReading(m_layer); while (true) { OGRFeatureH feature = OGR_L_GetNextFeature(m_layer); if (!feature) break; FileInfo fileInfo; fileInfo.m_filename = OGR_F_GetFieldAsString(feature, indexes.m_filename); fileInfo.m_srs = OGR_F_GetFieldAsString(feature, indexes.m_srs); files.push_back(fileInfo); OGR_F_Destroy(feature); } StageFactory factory; MergeFilter merge; Options cropOptions; if (!m_bounds.empty()) cropOptions.add("bounds", m_bounds); else cropOptions.add("polygon", m_wkt); for (auto f : files) { Stage *premerge = NULL; std::string driver = factory.inferReaderDriver(f.m_filename); Stage *reader = factory.createStage(driver); if (!reader) { out << "Unable to create reader for file '" << f.m_filename << "'."; throw pdal_error(out.str()); } Options readerOptions; readerOptions.add("filename", f.m_filename); reader->setOptions(readerOptions); premerge = reader; if (m_tgtSrsString != f.m_srs) { Stage *repro = factory.createStage("filters.reprojection"); repro->setInput(*reader); Options reproOptions; reproOptions.add("out_srs", m_tgtSrsString); reproOptions.add("in_srs", f.m_srs); repro->setOptions(reproOptions); premerge = repro; } // WKT is set, even if we're using a bounding box for fitering, so // can be used as a test here. if (!m_wkt.empty()) { Stage *crop = factory.createStage("filters.crop"); crop->setOptions(cropOptions); crop->setInput(*premerge); premerge = crop; } merge.setInput(*premerge); } std::string driver = factory.inferWriterDriver(m_filespec); Options factoryOptions = factory.inferWriterOptionsChanges(m_filespec); Stage *writer = factory.createStage(driver); if (!writer) { out << "Unable to create reader for file '" << m_filespec << "'."; throw pdal_error(out.str()); } writer->setInput(merge); applyExtraStageOptionsRecursive(writer); Options writerOptions(factoryOptions); setCommonOptions(writerOptions); writerOptions.add("filename", m_filespec); writerOptions.add("offset_x", "auto"); writerOptions.add("offset_y", "auto"); writerOptions.add("offset_z", "auto"); writer->addConditionalOptions(writerOptions); PointTable table; writer->prepare(table); writer->execute(table); }
TIndexKernel::FileInfo TIndexKernel::getFileInfo(KernelFactory& factory, const std::string& filename) { FileInfo fileInfo; StageFactory f; std::string driverName = f.inferReaderDriver(filename); Stage *s = f.createStage(driverName); Options ops; ops.add("filename", filename); setCommonOptions(ops); s->setOptions(ops); applyExtraStageOptionsRecursive(s); if (m_fastBoundary) { QuickInfo qi = s->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 { PointTable table; Stage *hexer = f.createStage("filters.hexbin"); if (! hexer) { std::ostringstream oss; oss << "Unable to create hexer stage to create boundaries. " << "Is PDAL_DRIVER_PATH environment variable set?"; throw pdal_error(oss.str()); } hexer->setInput(*s); 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; }