void PluginRegistry::discoverPlugins() { clearUnloadedPluginsFromInfoList(); WIN32_FIND_DATA FindFileData; HANDLE hFind; hFind = FindFirstFile(TEXT("*.dll"), &FindFileData); do { if (hFind == INVALID_HANDLE_VALUE) { break; } else { HINSTANCE hinst= LoadLibrary(FindFileData.cFileName); if(!hinst) { wprintf(TEXT("Failure in LoadLibrary(%s: error code %i): check for missing dependencies\n"), FindFileData.cFileName,GetLastError()); continue; } else { PLUGIN_DLL_FUNC registerPlugin = (PLUGIN_DLL_FUNC)GetProcAddress(hinst, LPCSTR("RegisterNervePlugin")); if(registerPlugin) { QString tempstr = QString::fromWCharArray(FindFileData.cFileName); std::list<PluginInfo>::iterator iter = pluginInfoList.begin(); bool shouldskip = false; while(iter != pluginInfoList.end()) { if(iter->dll_filename == tempstr.toStdString() ) { //printf("Plugin %s already loaded; skipping\n",tempstr.toAscii().constData()); FreeLibrary(hinst); shouldskip=true; break; } ++iter; } if(shouldskip)continue; pluginInfoList.push_back(PluginInfo(tempstr.toStdString())); activePluginInfoIter = pluginInfoList.end(); --activePluginInfoIter; registerPlugin(this); pluginInfoList.back().hinst = hinst; pluginInfoList.back().loaded = true; pluginInfoList.back().freeLibrary(); } else { FreeLibrary(hinst); } } } } while(FindNextFile(hFind, &FindFileData) != 0); discoverTasks(); setPluginTypes(); }
const PluginFactory::PluginInfo PluginFactory::pluginInfo(const char* name) const { for (const PluginInfo& info : m_pluginInfos) { if (qstrcmp(info.descriptor->name, name) == 0) return info; } return PluginInfo(); }
void PluginRegistry::discoverTasks() { WIN32_FIND_DATA FindFileData; HANDLE hFind; hFind = FindFirstFile(TEXT("*.dll"), &FindFileData); do { if (hFind == INVALID_HANDLE_VALUE) { break; } else { HINSTANCE hinst= LoadLibrary(FindFileData.cFileName); if(!hinst) { wprintf(TEXT("Failure in LoadLibrary(%s: error code %i): check for missing dependencies\n"), FindFileData.cFileName,GetLastError()); continue; } else { TASK_DLL_FUNC registerTask = (TASK_DLL_FUNC)GetProcAddress(hinst, LPCSTR("RegisterNerveTask")); if(registerTask) { QString tempstr = QString::fromWCharArray(FindFileData.cFileName); std::list<PluginInfo>::iterator iter = pluginInfoList.begin(); bool shouldskip = false; while(iter != pluginInfoList.end()) { if(iter->dll_filename == tempstr.toStdString() ) { FreeLibrary(hinst); shouldskip=true; break; } ++iter; } if(shouldskip)continue; pluginInfoList.push_back(PluginInfo(tempstr.toStdString())); activePluginInfoIter = pluginInfoList.end(); --activePluginInfoIter; activePluginInfoIter->hinst = hinst; activePluginInfoIter->loaded = true; activePluginInfoIter->allow_runtime_unloading = false; registerTask(&taskRegistry); } else { FreeLibrary(hinst); } } } } while(FindNextFile(hFind, &FindFileData) != 0); }
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY * OF SUCH DAMAGE. ****************************************************************************/ #include <rialto/RialtoReader.hpp> #include <rialto/GeoPackageReader.hpp> #include <rialto/GeoPackageCommon.hpp> #include "WritableTileCommon.hpp" #include "TileMath.hpp" #include <boost/filesystem.hpp> static PluginInfo const s_info = PluginInfo( "readers.rialto", "Read data from a Rialto DB", "" ); //CREATE_SHARED_PLUGIN(1, 0, rialto::RialtoReader, Reader, s_info) namespace rialto { std::string RialtoReader::getName() const { return s_info.name; } RialtoReader::RialtoReader() : Reader(), m_gpkg(NULL) {}
namespace pdal { static PluginInfo const s_info = PluginInfo( "writers.mywriter", "My Awesome Writer", "http://path/to/documentation" ); CREATE_SHARED_PLUGIN(1, 0, MyWriter, Writer, s_info); std::string MyWriter::getName() const { return s_info.name; } struct FileStreamDeleter { template <typename T> void operator()(T* ptr) { if (ptr) { ptr->flush(); FileUtils::closeFile(ptr); } } }; void MyWriter::addArgs(ProgramArgs& args) { // setPositional() Makes the argument required. args.add("filename", "Output filename", m_filename).setPositional(); args.add("newline", "Line terminator", m_newline, "\n"); args.add("datafield", "Data field", m_datafield, "UserData"); args.add("precision", "Precision", m_precision, 3); } void MyWriter::initialize() { m_stream = FileStreamPtr(FileUtils::createFile(m_filename, true), FileStreamDeleter()); if (!m_stream) { std::stringstream out; out << "writers.mywriter couldn't open '" << m_filename << "' for output."; throw pdal_error(out.str()); } } void MyWriter::ready(PointTableRef table) { m_stream->precision(m_precision); *m_stream << std::fixed; Dimension::Id d = table.layout()->findDim(m_datafield); if (d == Dimension::Id::Unknown) { std::ostringstream oss; oss << "Dimension not found with name '" << m_datafield << "'"; throw pdal_error(oss.str()); } m_dataDim = d; *m_stream << "#X:Y:Z:MyData" << m_newline; } void MyWriter::write(PointViewPtr view) { for (PointId idx = 0; idx < view->size(); ++idx) { double x = view->getFieldAs<double>(Dimension::Id::X, idx); double y = view->getFieldAs<double>(Dimension::Id::Y, idx); double z = view->getFieldAs<double>(Dimension::Id::Z, idx); unsigned int myData = 0; if (!m_datafield.empty()) { myData = (int)(view->getFieldAs<double>(m_dataDim, idx) + 0.5); } *m_stream << x << ":" << y << ":" << z << ":" << myData << m_newline; } } void MyWriter::done(PointTableRef) { m_stream.reset(); } }
namespace pdal { static PluginInfo const s_info = PluginInfo( "readers.gdal", "Read GDAL rasters as point clouds.", "http://pdal.io/stages/reader.gdal.html"); CREATE_STATIC_PLUGIN(1, 0, GDALReader, Reader, s_info); std::string GDALReader::getName() const { return s_info.name; } GDALReader::GDALReader() : m_index(0) {} void GDALReader::initialize() { gdal::registerDrivers(); m_raster.reset(new gdal::Raster(m_filename)); m_raster->open(); setSpatialReference(m_raster->getSpatialRef()); m_count = m_raster->m_raster_x_size * m_raster->m_raster_y_size; m_raster->close(); } QuickInfo GDALReader::inspect() { QuickInfo qi; std::unique_ptr<PointLayout> layout(new PointLayout()); addDimensions(layout.get()); initialize(); m_raster = std::unique_ptr<gdal::Raster>(new gdal::Raster(m_filename)); m_raster->open(); qi.m_pointCount = m_raster->m_raster_x_size * m_raster->m_raster_y_size; // qi.m_bounds = ???; qi.m_srs = m_raster->getSpatialRef(); qi.m_valid = true; return qi; } void GDALReader::addDimensions(PointLayoutPtr layout) { layout->registerDim(pdal::Dimension::Id::X); layout->registerDim(pdal::Dimension::Id::Y); for (int i = 0; i < m_raster->m_band_count; ++i) { std::ostringstream oss; oss << "band-" << (i + 1); layout->registerOrAssignDim(oss.str(), Dimension::Type::Double); } } void GDALReader::ready(PointTableRef table) { m_index = 0; m_raster->open(); } point_count_t GDALReader::read(PointViewPtr view, point_count_t num) { point_count_t count = std::min(num, m_count - m_index); PointId nextId = view->size(); std::array<double, 2> coords; for (int row = 0; row < m_raster->m_raster_y_size; ++row) { for (int col = 0; col < m_raster->m_raster_x_size; ++col) { m_raster->pixelToCoord(col, row, coords); view->setField(Dimension::Id::X, nextId, coords[0]); view->setField(Dimension::Id::Y, nextId, coords[1]); nextId++; } } std::vector<uint8_t> band; std::vector<Dimension::Type> band_types = m_raster->getPDALDimensionTypes(); for (int b = 0; b < m_raster->m_band_count; ++b) { // Bands count from 1 m_raster->readBand(band, b + 1); std::stringstream oss; oss << "band-" << (b + 1); log()->get(LogLevel::Info) << "Read band '" << oss.str() << "'" << std::endl; Dimension::Id d = view->layout()->findDim(oss.str()); size_t dimSize = Dimension::size(band_types[b]); uint8_t* p = band.data(); for (point_count_t i = 0; i < count; ++i) { view->setField(d, band_types[b], i, p); p = p + dimSize; } } return view->size(); } } // namespace pdal
return PLY_FLOAT32; case Double: return PLY_FLOAT64; default: // I went back and forth about throwing here, but since it's not // wrong to fall back onto a double (just bad, b/c it can take up // extra space), I chose to default rather than throw. return PLY_FLOAT64; } } } static PluginInfo const s_info = PluginInfo( "writers.ply", "ply writer", "http://pdal.io/stages/writers.ply.html" ); CREATE_STATIC_PLUGIN(1, 0, PlyWriter, Writer, s_info) std::string PlyWriter::getName() const { return s_info.name; } PlyWriter::PlyWriter() : m_ply(nullptr) , m_pointCollector(nullptr) , m_storageMode(PLY_DEFAULT) {}
namespace pdal { namespace { struct CallbackContext { PointViewPtr view; DimensionMap dimensionMap; }; void plyErrorCallback(p_ply ply, const char * message) { std::stringstream ss; ss << "Error opening ply file: " << message; throw pdal_error(ss.str()); } p_ply openPly(std::string filename) { p_ply ply = ply_open(filename.c_str(), &plyErrorCallback, 0, nullptr); if (!ply) { std::stringstream ss; ss << "Unable to open file " << filename << " for reading."; throw pdal_error(ss.str()); } if (!ply_read_header(ply)) { std::stringstream ss; ss << "Unable to read header of " << filename << "."; throw pdal_error(ss.str()); } return ply; } int readPlyCallback(p_ply_argument argument) { p_ply_element element; long index; void * contextAsVoid; long numToRead; p_ply_property property; const char * propertyName; if (!ply_get_argument_element(argument, &element, &index)) { std::stringstream ss; ss << "Error getting argument element."; throw pdal_error(ss.str()); } if (!ply_get_argument_user_data(argument, &contextAsVoid, &numToRead)) { std::stringstream ss; ss << "Error getting argument user data."; throw pdal_error(ss.str()); } // We've read enough, abort the callback cycle if (numToRead <= index) { return 0; } if (!ply_get_argument_property(argument, &property, nullptr, nullptr)) { std::stringstream ss; ss << "Error getting argument property."; throw pdal_error(ss.str()); } if (!ply_get_property_info(property, &propertyName, nullptr, nullptr, nullptr)) { std::stringstream ss; ss << "Error getting property info."; throw pdal_error(ss.str()); } CallbackContext * context = static_cast<CallbackContext *>(contextAsVoid); double value = ply_get_argument_value(argument); Dimension::Id::Enum dimension = context->dimensionMap.at(propertyName); context->view->setField(dimension, index, value); return 1; } } static PluginInfo const s_info = PluginInfo( "readers.ply", "Read ply files.", "http://pdal.io/stages/reader.ply.html"); CREATE_STATIC_PLUGIN(1, 0, PlyReader, Reader, s_info); std::string PlyReader::getName() const { return s_info.name; } PlyReader::PlyReader() : m_ply(nullptr) , m_vertexDimensions() {} void PlyReader::initialize() { p_ply ply = openPly(m_filename); p_ply_element vertex_element = nullptr; bool found_vertex_element = false; const char* element_name; long element_count; while ((vertex_element = ply_get_next_element(ply, vertex_element))) { if (!ply_get_element_info(vertex_element, &element_name, &element_count)) { std::stringstream ss; ss << "Error reading element info in " << m_filename << "."; throw pdal_error(ss.str()); } if (strcmp(element_name, "vertex") == 0) { found_vertex_element = true; break; } } if (!found_vertex_element) { std::stringstream ss; ss << "File " << m_filename << " does not contain a vertex element."; throw pdal_error(ss.str()); } p_ply_property property = nullptr; while ((property = ply_get_next_property(vertex_element, property))) { const char* name; e_ply_type type; e_ply_type length_type; e_ply_type value_type; if (!ply_get_property_info(property, &name, &type, &length_type, &value_type)) { std::stringstream ss; ss << "Error reading property info in " << m_filename << "."; throw pdal_error(ss.str()); } // For now, we'll just use PDAL's built in dimension matching. // We could be smarter about this, e.g. by using the length // and value type attributes. Dimension::Id::Enum dim = Dimension::id(name); if (dim != Dimension::Id::Unknown) { m_vertexDimensions[name] = dim; } } ply_close(ply); } void PlyReader::addDimensions(PointLayoutPtr layout) { for (auto it : m_vertexDimensions) { layout->registerDim(it.second); } } void PlyReader::ready(PointTableRef table) { m_ply = openPly(m_filename); } point_count_t PlyReader::read(PointViewPtr view, point_count_t num) { CallbackContext context; context.view = view; context.dimensionMap = m_vertexDimensions; // It's possible that point_count_t holds a value that's larger than the // long that is the maximum rply (don't know about ply) point count. long cnt; cnt = Utils::inRange<long>(num) ? num : (std::numeric_limits<long>::max)(); for (auto it : m_vertexDimensions) { ply_set_read_cb(m_ply, "vertex", it.first.c_str(), readPlyCallback, &context, cnt); } if (!ply_read(m_ply)) { std::stringstream ss; ss << "Error reading " << m_filename << "."; throw pdal_error(ss.str()); } return view->size(); } void PlyReader::done(PointTableRef table) { if (!ply_close(m_ply)) { std::stringstream ss; ss << "Error closing " << m_filename << "."; throw pdal_error(ss.str()); } } }
{} }; } // unnamed namespace void LasReader::processOptions(const Options& options) { StringList extraDims = options.getValueOrDefault<StringList>("extra_dims"); m_extraDims = LasUtils::parse(extraDims); m_error.setFilename(m_filename); } static PluginInfo const s_info = PluginInfo( "readers.las", "ASPRS LAS 1.0 - 1.4 read support. LASzip support is also \n" \ "enabled through this driver if LASzip was found during \n" \ "compilation.", "http://pdal.io/stages/readers.las.html" ); CREATE_STATIC_PLUGIN(1, 0, LasReader, Reader, s_info) std::string LasReader::getName() const { return s_info.name; } QuickInfo LasReader::inspect() { QuickInfo qi; std::unique_ptr<PointLayout> layout(new PointLayout()); addDimensions(layout.get()); initialize();
const PluginFactory::PluginInfo PluginFactory::pluginSupportingExtension(const QString& ext) { return m_pluginByExt.value(ext, PluginInfo()); }
namespace pdal { static PluginInfo const s_info = PluginInfo( "writers.mywriter", "My Awesome Writer", "http://path/to/documentation" ); CREATE_SHARED_PLUGIN(1, 0, MyWriter, Writer, s_info); std::string MyWriter::getName() const { return s_info.name; } struct FileStreamDeleter { template <typename T> void operator()(T* ptr) { if (ptr) { ptr->flush(); FileUtils::closeFile(ptr); } } }; Options MyWriter::getDefaultOptions() { Options options; options.add("newline", "\n", "Newline character to use for additional lines"); options.add("filename", "", "filename to write output to"); options.add("datafield", "", "field to use as the User Data field"); options.add("precision", 3, "Precision to use for data fields"); return options; } void MyWriter::processOptions(const Options& options) { m_filename = options.getValueOrThrow<std::string>("filename"); m_stream = FileStreamPtr(FileUtils::createFile(m_filename, true), FileStreamDeleter()); if (!m_stream) { std::stringstream out; out << "writers.mywriter couldn't open '" << m_filename << "' for output."; throw pdal_error(out.str()); } m_newline = options.getValueOrDefault<std::string>("newline", "\n"); m_datafield = options.getValueOrDefault<std::string>("datafield", "UserData"); m_precision = options.getValueOrDefault<int>("precision", 3); } void MyWriter::ready(PointTableRef table) { m_stream->precision(m_precision); *m_stream << std::fixed; Dimension::Id::Enum d = table.layout()->findDim(m_datafield); if (d == Dimension::Id::Unknown) { std::ostringstream oss; oss << "Dimension not found with name '" << m_datafield << "'"; throw pdal_error(oss.str()); } m_dataDim = d; *m_stream << "#X:Y:Z:MyData" << m_newline; } void MyWriter::write(PointViewPtr view) { for (PointId idx = 0; idx < view->size(); ++idx) { double x = view->getFieldAs<double>(Dimension::Id::X, idx); double y = view->getFieldAs<double>(Dimension::Id::Y, idx); double z = view->getFieldAs<double>(Dimension::Id::Z, idx); unsigned int myData = 0; if (!m_datafield.empty()) { myData = (int)(view->getFieldAs<double>(m_dataDim, idx) + 0.5); } *m_stream << x << ":" << y << ":" << z << ":" << myData << m_newline; } } void MyWriter::done(PointTableRef) { m_stream.reset(); } }