예제 #1
0
PipelineManagerPtr InfoKernel::makePipeline(const std::string& filename,
    bool noPoints)
{
    if (!pdal::FileUtils::fileExists(filename))
        throw pdal_error("File not found: " + filename);

    PipelineManagerPtr output(new PipelineManager);

    if (filename == "STDIN")
    {
        output->readPipeline(std::cin);
    }
    else if (FileUtils::extension(filename) == ".xml" ||
        FileUtils::extension(filename) == ".json")
    {
        output->readPipeline(filename);
    }
    else
    {
        StageFactory factory;
        std::string driver = factory.inferReaderDriver(filename);

        if (driver.empty())
            throw pdal_error("Cannot determine input file type of " + filename);
        Stage& reader = output->addReader(driver);
        Options ro;
        ro.add("filename", filename);
        if (noPoints)
            ro.add("count", 0);
        reader.setOptions(ro);
        m_reader = &reader;
    }
    return output;
}
예제 #2
0
bool ossimPdalFileReader::open(const ossimFilename& fname)
{
   // PDAL opens the file here.
   m_inputFilename = fname;
   pdal::Stage* reader = 0;
   try
   {
      if (m_inputFilename.contains("fauxreader"))
      {
         // Debug generated image:
         reader = new FauxReader;
         m_pdalPipe = reader;
         m_pdalOptions.add("mode", "ramp");
         BOX3D bbox(-0.001, -0.001, -100.0, 0.001, 0.001, 100.0);
         m_pdalOptions.add("bounds", bbox);
         m_pdalOptions.add("num_points", "11");
         m_pdalPipe->setOptions(m_pdalOptions);
      }
      else
      {
         StageFactory factory;
         const string driver = factory.inferReaderDriver(m_inputFilename.string());
         if (driver == "")
            throw pdal_error("File type not supported by PDAL");
         reader = factory.createStage(driver);
         if (!reader)
            throw pdal_error("No reader created by PDAL");

         m_pdalOptions.add("filename", m_inputFilename.string());
         reader->setOptions(m_pdalOptions);

         // Stick a stats filter in the pipeline:
         m_pdalPipe = new StatsFilter();
         m_pdalPipe->setInput(*reader);
      }

      m_pointTable = PointTablePtr(new PointTable);
      m_pdalPipe->prepare(*m_pointTable);
      m_pvs = m_pdalPipe->execute(*m_pointTable);
      if (!m_pvs.empty())
      {
         m_currentPV = *(m_pvs.begin());

         // Determine available data fields:
         establishAvailableFields();
      }

      std::string wkt;
      const SpatialReference& srs = reader->getSpatialReference();
      wkt = srs.getWKT(SpatialReference::eCompoundOK, false);
      m_geometry = new ossimPointCloudGeometry(wkt);
   }
   catch (std::exception& e)
   {
      //ossimNotify() << e.what() << endl;
      return false;
   }

   // Establish the bounds (geographic & radiometric). These are stored in two extreme point records
   // maintained by the base class:
   establishMinMax();

   return true;
}
예제 #3
0
int TranslateKernel::execute()
{
    // setting common options for each stage propagates the debug flag and
    // verbosity level
    Options readerOptions, filterOptions, writerOptions;
    setCommonOptions(readerOptions);
    setCommonOptions(filterOptions);
    setCommonOptions(writerOptions);

    m_manager = std::unique_ptr<PipelineManager>(new PipelineManager);

    if (!m_readerType.empty())
    {
        m_manager->addReader(m_readerType);
    }
    else
    {
        StageFactory factory;
        std::string driver = factory.inferReaderDriver(m_inputFile);

        if (driver.empty())
            throw app_runtime_error("Cannot determine input file type of " +
                                    m_inputFile);
        m_manager->addReader(driver);
    }

    if (m_manager == NULL)
        throw pdal_error("Error making pipeline\n");

    Stage* reader = m_manager->getStage();

    if (reader == NULL)
        throw pdal_error("Error getting reader\n");

    readerOptions.add("filename", m_inputFile);
    reader->setOptions(readerOptions);

    Stage* stage = reader;

    // add each filter provided on the command-line, updating the stage pointer
    for (auto const f : m_filterType)
    {
        std::string filter_name(f);

        if (!Utils::startsWith(f, "filters."))
            filter_name.insert(0, "filters.");

        Stage* filter = &(m_manager->addFilter(filter_name));

        if (filter == NULL)
        {
            std::ostringstream oss;
            oss << "Unable to add filter " << filter_name << ".  Filter "
              "is invalid or plugin could not be loaded.  Check "
              "'pdal --drivers'.";
            throw pdal_error("Error getting filter\n");
        }

        filter->setOptions(filterOptions);
        filter->setInput(*stage);
        stage = filter;
    }

    if (!m_writerType.empty())
    {
        m_manager->addWriter(m_writerType);
    }
    else
    {
        StageFactory factory;
        std::string driver = factory.inferWriterDriver(m_outputFile);

        if (driver.empty())
            throw app_runtime_error("Cannot determine output file type of " +
                                    m_outputFile);
        Options options = factory.inferWriterOptionsChanges(m_outputFile);
        writerOptions += options;
        m_manager->addWriter(driver);
    }

    Stage* writer = m_manager->getStage();

    if (writer == NULL)
        throw pdal_error("Error getting writer\n");

    writerOptions.add("filename", m_outputFile);
    writer->setOptions(writerOptions);
    writer->setInput(*stage);

    // be sure to recurse through any extra stage options provided by the user
    applyExtraStageOptionsRecursive(writer);

    m_manager->execute();

    if (m_pipelineOutput.size() > 0)
        PipelineWriter::writePipeline(m_manager->getStage(), m_pipelineOutput);

    return 0;
}
예제 #4
0
int HeightAboveGroundKernel::execute()
{
    // we require separate contexts for the input and ground files
    PointContextRef input_ctx;
    PointContextRef ground_ctx;

    // because we are appending HeightAboveGround to the input buffer, we must
    // register it's Dimension
    input_ctx.registerDim(Dimension::Id::HeightAboveGround);

    // StageFactory will be used to create required stages
    StageFactory f;

    // setup the reader, inferring driver type from the filename
    std::string reader_driver = f.inferReaderDriver(m_input_file);
    std::unique_ptr<Reader> input(f.createReader(reader_driver));
    Options readerOptions;
    readerOptions.add("filename", m_input_file);
    input->setOptions(readerOptions);

    // go ahead and execute to get the PointBuffer
    input->prepare(input_ctx);
    PointBufferSet pbSetInput = input->execute(input_ctx);
    PointBufferPtr input_buf = *pbSetInput.begin();

    PointBufferSet pbSetGround;
    PointBufferPtr ground_buf;

    if (m_use_classification)
    {
        // the user has indicated that the classification dimension exists, so
        // we will find all ground returns
        Option source("source",
                      "import numpy as np\n"
                      "def yow1(ins,outs):\n"
                      "  cls = ins['Classification']\n"
                      "  keep_classes = [2]\n"
                      "  keep = np.equal(cls, keep_classes[0])\n"
                      "  outs['Mask'] = keep\n"
                      "  return True\n"
                     );
        Option module("module", "MyModule");
        Option function("function", "yow1");
        Options opts;
        opts.add(source);
        opts.add(module);
        opts.add(function);

        // and create a PointBuffer of only ground returns
        std::unique_ptr<Filter> pred(f.createFilter("filters.predicate"));
        pred->setOptions(opts);
        pred->setInput(input.get());
        pred->prepare(ground_ctx);
        pbSetGround = pred->execute(ground_ctx);
        ground_buf = *pbSetGround.begin();
    }
    else
    {
        // the user has provided a file containing only ground returns, setup
        // the reader, inferring driver type from the filename
        std::string ground_driver = f.inferReaderDriver(m_ground_file);
        std::unique_ptr<Reader> ground(f.createReader(ground_driver));
        Options ro;
        ro.add("filename", m_ground_file);
        ground->setOptions(ro);

        // go ahead and execute to get the PointBuffer
        ground->prepare(ground_ctx);
        pbSetGround = ground->execute(ground_ctx);
        ground_buf = *pbSetGround.begin();
    }

    typedef pcl::PointXYZ PointT;
    typedef pcl::PointCloud<PointT> Cloud;
    typedef Cloud::Ptr CloudPtr;

    // convert the input PointBuffer to a PointCloud
    CloudPtr cloud(new Cloud);
    BOX3D const& bounds = input_buf->calculateBounds();
    pclsupport::PDALtoPCD(*input_buf, *cloud, bounds);

    // convert the ground PointBuffer to a PointCloud
    CloudPtr cloud_g(new Cloud);
    // here, we offset the ground cloud by the input bounds so that the two are aligned
    pclsupport::PDALtoPCD(*ground_buf, *cloud_g, bounds);

    // create a set of planar coefficients with X=Y=0,Z=1
    pcl::ModelCoefficients::Ptr coefficients(new pcl::ModelCoefficients());
    coefficients->values.resize(4);
    coefficients->values[0] = coefficients->values[1] = 0;
    coefficients->values[2] = 1.0;
    coefficients->values[3] = 0;

    // create the filtering object and project ground returns into xy plane
    pcl::ProjectInliers<PointT> proj;
    proj.setModelType(pcl::SACMODEL_PLANE);
    proj.setInputCloud(cloud_g);
    proj.setModelCoefficients(coefficients);
    CloudPtr cloud_projected(new Cloud);
    proj.filter(*cloud_projected);

    // setup the KdTree
    pcl::KdTreeFLANN<PointT> tree;
    tree.setInputCloud(cloud_projected);

    // loop over all points in the input cloud, finding the nearest neighbor in
    // the ground returns (XY plane only), and calculating the difference in z
    int32_t k = 1;
    for (size_t idx = 0; idx < cloud->points.size(); ++idx)
    {
        // Search for nearesrt neighbor of the query point
        std::vector<int32_t> neighbors(k);
        std::vector<float> distances(k);
        PointT temp_pt = cloud->points[idx];
        temp_pt.z = 0.0f;
        int num_neighbors = tree.nearestKSearch(temp_pt, k, neighbors, distances);

        double hag = cloud->points[idx].z - cloud_g->points[neighbors[0]].z;
        input_buf->setField(Dimension::Id::HeightAboveGround, idx, hag);
    }

    // populate BufferReader with the input PointBuffer, which now has the
    // HeightAboveGround dimension
    BufferReader bufferReader;
    bufferReader.addBuffer(input_buf);

    // we require that the output be BPF for now, to house our non-standard
    // dimension
    Options wo;
    wo.add("filename", m_output_file);
    std::unique_ptr<Writer> writer(f.createWriter("writers.bpf"));
    writer->setOptions(wo);
    writer->setInput(&bufferReader);
    writer->prepare(input_ctx);
    writer->execute(input_ctx);

    return 0;
}
예제 #5
0
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;
}
예제 #6
0
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);
}