vector<uint32_t> getListOfPoints(std::string p) { vector<uint32_t> output; //Remove whitespace from string with awful remove/erase idiom. p.erase(remove_if(p.begin(), p.end(), ::isspace), p.end()); vector<string> ranges = tokenize(p, ','); for (string s : ranges) { vector<string> limits = tokenize(s, '-'); if (limits.size() == 1) addSingle(limits[0], output); else if (limits.size() == 2) addRange(limits[0], limits[1], output); else throw pdal_error(string("Invalid point range: ") + s); } return output; }
Stage& PipelineManager::makeWriter(StageCreationOptions& o) { if (o.m_driver.empty()) { o.m_driver = StageFactory::inferWriterDriver(o.m_filename); if (o.m_driver.empty()) throw pdal_error("Cannot determine writer for output file: " + o.m_filename); } if (!o.m_filename.empty()) o.m_options.replace("filename", o.m_filename); auto& writer = addWriter(o.m_driver); writer.setTag(o.m_tag); setOptions(writer, o.m_options); if (o.m_parent) writer.setInput(*o.m_parent); return writer; }
int PipelineKernel::execute() { if (!Utils::fileExists(m_inputFile)) throw pdal_error("file not found: " + m_inputFile); if (m_progressFile.size()) m_progressFd = Utils::openProgress(m_progressFile); m_manager.readPipeline(m_inputFile); if (m_validate) { // Validate the options of the pipeline we were // given, and once we succeed, we're done m_manager.prepare(); Utils::closeProgress(m_progressFd); return 0; } m_manager.execute(); if (m_pipelineFile.size() > 0) PipelineWriter::writePipeline(m_manager.getStage(), m_pipelineFile); if (m_PointCloudSchemaOutput.size() > 0) { #ifdef PDAL_HAVE_LIBXML2 XMLSchema schema(m_manager.pointTable().layout()); std::ostream *out = Utils::createFile(m_PointCloudSchemaOutput); std::string xml(schema.xml()); out->write(xml.c_str(), xml.size()); Utils::closeFile(out); #else std::cerr << "libxml2 support not available, no schema is produced" << std::endl; #endif } Utils::closeProgress(m_progressFd); return 0; }
std::vector<Polygon::Ring> Polygon::interiorRings() const { std::vector<Ring> rings; OGRwkbGeometryType t = m_geom->getGeometryType(); if (t != wkbPolygon && t != wkbPolygon25D) throw pdal_error("Request for exterior ring on non-polygon."); // OGRPolygon *poly = m_geom->toPolygon(); OGRPolygon *poly = static_cast<OGRPolygon *>(m_geom.get()); for (int i = 0; i < poly->getNumInteriorRings(); ++i) { OGRLinearRing *er = poly->getInteriorRing(i); Ring r; for (int j = 0; j < er->getNumPoints(); ++j) r.push_back({er->getX(j), er->getY(j)}); rings.push_back(r); } return rings; }
void PipelineManager::validateStageOptions() const { // Make sure that the options specified are for relevant stages. for (auto& si : m_stageOptions) { const std::string& stageName = si.first; auto it = std::find_if(m_stages.begin(), m_stages.end(), [stageName](Stage *s) { return (s->getName() == stageName || "stage." + s->tag() == stageName); }); // If the option stage name matches no created stage, then error. if (it == m_stages.end()) { std::ostringstream oss; oss << "Argument references invalid/unused stage: '" << stageName << "'."; throw pdal_error(oss.str()); } } }
void BpfWriter::loadBpfDimensions(PointLayoutPtr layout) { // Verify that we have X, Y and Z and that they're the first three // dimensions. Dimension::IdList dims = layout->dims(); std::sort(dims.begin(), dims.end()); if (dims.size() < 3 || dims[0] != Dimension::Id::X || dims[1] != Dimension::Id::Y || dims[2] != Dimension::Id::Z) { throw pdal_error("Missing one of dimensions X, Y or Z. " "Can't write BPF."); } for (auto id : dims) { BpfDimension dim; dim.m_id = id; dim.m_label = layout->dimName(id); m_dims.push_back(dim); } }
void Reprojection::transform(double& x, double& y, double& z) const { #ifdef PDAL_HAVE_GDAL int ret = 0; ret = OCTTransform(m_transform_ptr.get(), 1, &x, &y, &z); if (!ret) { std::ostringstream msg; msg << "Could not project point for ReprojectionTransform::" << CPLGetLastErrorMsg() << ret; throw pdal_error(msg.str()); } #else boost::ignore_unused_variable_warning(x); boost::ignore_unused_variable_warning(y); boost::ignore_unused_variable_warning(z); #endif return; }
bool PluginManager::loadPlugin(const std::string& driverFileName) { std::vector<std::string> driverPathVec; driverPathVec = Utils::split2(driverFileName, '.'); boost::filesystem::path full_path(driverFileName); if (boost::filesystem::is_directory(full_path)) return false; std::string ext = full_path.extension().string(); if (ext != dynamicLibraryExtension) return false; std::string stem = full_path.stem().string(); std::vector<std::string> driverNameVec; driverNameVec = Utils::split2(driverPathVec[0], '_'); std::string ptype; if (driverNameVec.size() >=3) ptype = driverNameVec[2]; PF_PluginType type; if (Utils::iequals(ptype, "reader")) type = PF_PluginType_Reader; else if (Utils::iequals(ptype,"kernel")) type = PF_PluginType_Kernel; else if (Utils::iequals(ptype, "filter")) type = PF_PluginType_Filter; else if (Utils::iequals(ptype, "writer")) type = PF_PluginType_Writer; else throw pdal_error("Unknown plugin type '" + ptype +"'"); if (loadByPath(full_path.string(), type)) { return true; } return false; }
std::string Writer::LoadSQLData(std::string const& filename) { if (!FileUtils::fileExists(filename)) { std::ostringstream oss; oss << filename << " does not exist"; throw pdal_error(oss.str()); } std::istream::pos_type size; std::istream* input = FileUtils::openFile(filename, true); if (input->good()) { std::string output; std::string line; while (input->good()) { getline(*input, line); if (output.size()) { output = output + "\n" + line; } else { output = line; } } return output; } else { FileUtils::closeFile(input); return std::string(""); } }
Geometry(const std::string& wkt, const SpatialRef& srs) { OGRGeometryH geom; char *p_wkt = const_cast<char *>(wkt.data()); OGRSpatialReferenceH ref = srs.get(); if (srs.empty()) { ref = NULL; } bool isJson = wkt.find("{") != wkt.npos || wkt.find("}") != wkt.npos; if (!isJson) { OGRErr err = OGR_G_CreateFromWkt(&p_wkt, ref, &geom); if (err != OGRERR_NONE) { std::cout << "wkt: " << wkt << std::endl; std::ostringstream oss; oss << "unable to construct OGR Geometry"; oss << " '" << CPLGetLastErrorMsg() << "'"; throw pdal::pdal_error(oss.str()); } } else { // Assume it is GeoJSON and try constructing from that geom = OGR_G_CreateGeometryFromJson(p_wkt); if (!geom) throw pdal_error("Unable to create geometry from " "input GeoJSON"); OGR_G_AssignSpatialReference(geom, ref); } newRef(geom); }
void LasReader::initialize() { if (m_initialized) return; m_istream = createStream(); m_istream->seekg(0); ILeStream in(m_istream); in >> m_lasHeader; if (!m_lasHeader.pointFormatSupported()) { std::ostringstream oss; oss << "Unsupported LAS input point format: " << (int)m_lasHeader.pointFormat() << "."; throw pdal_error(oss.str()); } // We need to read the VLRs in initialize() because they may contain an // extra-bytes VLR that is needed to determine dimensions. m_istream->seekg(m_lasHeader.vlrOffset()); for (size_t i = 0; i < m_lasHeader.vlrCount(); ++i) { VariableLengthRecord r; in >> r; m_vlrs.push_back(std::move(r)); } if (m_lasHeader.versionAtLeast(1, 4)) { m_istream->seekg(m_lasHeader.eVlrOffset()); for (size_t i = 0; i < m_lasHeader.eVlrCount(); ++i) { ExtVariableLengthRecord r; in >> r; m_vlrs.push_back(std::move(r)); } readExtraBytesVlr(); }
void Reader::initialize() { pdal::Reader::initialize(); boost::scoped_ptr<PipelineManager> tmp(new PipelineManager()); m_manager.swap(tmp); PipelineReader xmlreader(*m_manager); bool isWriter = xmlreader.readPipeline(m_filename); if (isWriter) { throw pdal_error("pipeline file is not a Reader"); } m_stage = m_manager->getStage(); m_stage->initialize(); setNumPoints(m_stage->getNumPoints()); setPointCountType(m_stage->getPointCountType()); setBounds(m_stage->getBounds()); return; }
void AttributeFilter::ready(PointTableRef table) { for (auto& dim_par : m_dimensions) { Dimension::Id::Enum t = table.layout()->findDim(dim_par.first); dim_par.second.dim = t; if (dim_par.second.isogr) { OGRDSPtr ds = OGRDSPtr(OGROpen(dim_par.second.datasource.c_str(), 0, 0), OGRDataSourceDeleter()); if (!ds) { std::ostringstream oss; oss << "Unable to open data source '" << dim_par.second.datasource <<"'"; throw pdal_error(oss.str()); } dim_par.second.ds = ds; } } }
// Determines the pixel/line position given an x/y. // No reprojection is done at this time. bool Colorization::getPixelAndLinePosition(double x, double y, boost::array<double, 6> const& inverse, boost::int32_t& pixel, boost::int32_t& line, void* ds) { #ifdef PDAL_HAVE_GDAL pixel = (boost::int32_t) std::floor( inverse[0] + inverse[1] * x + inverse[2] * y); line = (boost::int32_t) std::floor( inverse[3] + inverse[4] * x + inverse[5] * y); int xs = GDALGetRasterXSize(ds); int ys = GDALGetRasterYSize(ds); if (!xs || !ys) { throw pdal_error("Unable to get X or Y size from raster!"); } if (pixel < 0 || line < 0 || pixel >= xs || line >= ys ) { // The x, y is not coincident with this raster return false; } #endif return true; }
void OptechReader::initialize() { ILeStream stream(Utils::openFile(m_filename)); if (!stream) { std::stringstream ss; ss << "Unable to open " << m_filename << " for reading."; throw pdal_error(ss.str()); } stream.get(m_header.signature, 4); if (strcmp(m_header.signature, "CSD") != 0) { std::stringstream ss; ss << "Invalid header signature when reading CSD file: '" << m_header.signature << "'"; throw optech_error(ss.str()); } stream.get(m_header.vendorId, 64); stream.get(m_header.softwareVersion, 32); stream >> m_header.formatVersion >> m_header.headerSize >> m_header.gpsWeek >> m_header.minTime >> m_header.maxTime >> m_header.numRecords >> m_header.numStrips; for (size_t i = 0; i < 256; ++i) { stream >> m_header.stripPointers[i]; } stream >> m_header.misalignmentAngles[0] >> m_header.misalignmentAngles[1] >> m_header.misalignmentAngles[2] >> m_header.imuOffsets[0] >> m_header.imuOffsets[1] >> m_header.imuOffsets[2] >> m_header.temperature >> m_header.pressure; stream.get(m_header.freeSpace, 830); m_boresightMatrix = createOptechRotationMatrix( m_header.misalignmentAngles[0] + m_header.imuOffsets[0], m_header.misalignmentAngles[1] + m_header.imuOffsets[1], m_header.misalignmentAngles[2] + m_header.imuOffsets[2]); }
void GeoPackageWriter::createTableGpkgPctile(const std::string& table_name) { if (m_sqlite->doesTableExist(table_name)) { throw pdal_error("RialtoDB: invalid state (table '" + table_name + "' already exists)"); } const std::string sql = "CREATE TABLE " + table_name + "(" "id INTEGER PRIMARY KEY AUTOINCREMENT," "zoom_level INTEGER NOT NULL," "tile_column INTEGER NOT NULL," "tile_row INTEGER NOT NULL," "tile_data BLOB NOT NULL," "num_points INTEGER NOT NULL," "child_mask INTEGER NOT NULL," "UNIQUE(zoom_level, tile_column, tile_row)" ")"; m_sqlite->execute(sql); const std::string data = "INSERT INTO gpkg_extensions " "(table_name, column_name, extension_name, definition, scope) " "VALUES (?, ?, ?, ?, ?)"; records rs; row r; r.push_back(column(table_name)); r.push_back(column("NULL")); r.push_back(column("radiantblue_pctiles")); r.push_back(column("mailto:[email protected]")); r.push_back(column("read-write")); rs.push_back(r); m_sqlite->insert(data, rs); }
void GeoPackageWriter::writeTile(const std::string& tileTableName, const GpkgTile& data) { if (!m_sqlite) { throw pdal_error("RialtoDB: invalid state (session does exist)"); } e_tilesWritten.start(); const uint32_t buflen = data.getBlob().size(); const char* buf = data.getBlob().data(); assert(buf); assert(buflen); { const std::string sql = "INSERT INTO " + tileTableName + " (zoom_level, tile_column, tile_row, tile_data, num_points, child_mask)" " VALUES (?, ?, ?, ?, ?, ?)"; records rs; row r; r.push_back(column(data.getLevel())); r.push_back(column(data.getColumn())); r.push_back(column(data.getRow())); r.push_back(blob(buf, (size_t)buflen)); r.push_back(column(data.getNumPoints())); r.push_back(column(data.getMask())); rs.push_back(r); m_sqlite->insert(sql, rs); } e_tilesWritten.stop(); m_numPointsWritten += data.getNumPoints(); }
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(); }
Polygon::Ring Polygon::exteriorRing() const { Ring r; OGRwkbGeometryType t = m_geom->getGeometryType(); if (t != wkbPolygon && t != wkbPolygon25D) throw pdal_error("Request for exterior ring on non-polygon."); // Not until GDAL 2.3 /** OGRLinearRing *er = m_geom->toPolygon()->getExteriorRing(); // For some reason there's no operator -> on an iterator. for (auto it = er->begin(); it != er->end(); ++it) r.push_back({(*it).getX(), (*it).getY()}); **/ OGRLinearRing *er = static_cast<OGRPolygon *>(m_geom.get())->getExteriorRing(); for (int i = 0; i < er->getNumPoints(); ++i) r.push_back({er->getX(i), er->getY(i)}); return r; }
int RandomKernel::execute() { Options readerOptions; if (!m_bounds.empty()) readerOptions.add("bounds", m_bounds); std::string distribution(Utils::tolower(m_distribution)); if (distribution == "uniform") readerOptions.add("mode", "uniform"); else if (distribution == "normal") readerOptions.add("mode", "normal"); else if (distribution == "random") readerOptions.add("mode", "random"); else throw pdal_error("invalid distribution: " + m_distribution); readerOptions.add("count", m_numPointsToWrite); Options writerOptions; if (m_bCompress) writerOptions.add("compression", true); Stage& reader = makeReader("", "readers.faux"); reader.addOptions(readerOptions); Stage& writer = makeWriter(m_outputFile, reader, ""); writer.addOptions(writerOptions); PointTable table; writer.prepare(table); PointViewSet viewSet = writer.execute(table); if (isVisualize()) visualize(*viewSet.begin()); return 0; }
void GreyhoundReader::initialize(PointTableRef table) { // Parse the URL and query parameters (although we won't handle the schema // until addDimensions) and fetch the dataset `info`. Json::Value config; if (log()->getLevel() > LogLevel::Debug4) config["arbiter"]["verbose"] = true; m_arbiter.reset(new arbiter::Arbiter(config)); // If this stage was parsed from a string parameter rather than JSON object // specification, normalize it to our URL. if (m_filename.size() && m_args.url.empty()) { m_args.url = m_filename; const std::string pre("greyhound://"); if (m_args.url.find(pre) == 0) m_args.url = m_args.url.substr(pre.size()); } m_params = GreyhoundParams(m_args); log()->get(LogLevel::Debug) << "Fetching info from " << m_params.root() << std::endl; try { m_info = parse(m_arbiter->get(m_params.root() + "info")); } catch (std::exception& e) { throw pdal_error(std::string("Failed to fetch info: ") + e.what()); } if (m_info.isMember("srs") && getSpatialReference().empty()) setSpatialReference(m_info["srs"].asString()); }
void PipelineReaderJSON::readPipeline(const std::string& filename) { m_inputJSONFile = filename; std::istream* input = Utils::openFile(filename); if (!input) { throw pdal_error("JSON pipeline: Unable to open stream for " "file \"" + filename + "\""); } try { readPipeline(*input); } catch (...) { Utils::closeFile(input); throw; } Utils::closeFile(input); m_inputJSONFile = ""; }
void AttributeFilter::processOptions(const Options& options) { std::vector<Option> dimensions = options.getOptions("dimension"); for (auto i = dimensions.begin(); i != dimensions.end(); ++i) { std::string name = i->getValue<std::string>(); boost::optional<Options const&> dimensionOptions = i->getOptions(); if (!dimensionOptions) { std::ostringstream oss; oss << "No options dimension given for dimension '" << name << "'"; throw pdal_error(oss.str()); } AttributeInfo info; info.datasource = dimensionOptions->getValueOrDefault<std::string>("datasource", ""); // If we have no datasource, then we're simply setting a value. // If we have no value, throw an exception. if (!info.datasource.size()) { info.value = dimensionOptions->getValueOrThrow<std::string>("value"); info.isogr = false; } else { info.column = dimensionOptions->getValueOrDefault<std::string>("column",""); // take first column info.query = dimensionOptions->getValueOrDefault<std::string>("query",""); info.layer = dimensionOptions->getValueOrDefault<std::string>("layer",""); // take first layer } m_dimensions.insert(std::make_pair(name, info)); } }
void InPlaceReprojection::reprojectOffsets( double& offset_x, double& offset_y, double& offset_z) { #ifdef PDAL_HAVE_GDAL int ret = 0; double dummy_x(0.0); bool doOffsetZ = getOptions().getValueOrDefault<bool>("do_offset_z", false); double* x = doOffsetZ ? &offset_x : &dummy_x; ret = OCTTransform(m_transform_ptr.get(), 1, &offset_x, &offset_y, x); if (!ret) { std::ostringstream msg; msg << "Could not project offset for InPlaceReprojection::" << CPLGetLastErrorMsg() << ret; throw pdal_error(msg.str()); } #else #endif }
void ColorizationFilter::processOptions(const Options& options) { m_rasterFilename = options.getValueOrThrow<std::string>("raster"); if (options.hasOption("dimension") && !options.hasOption("dimensions")) throw pdal_error("Option 'dimension' no longer supported. Use " "'dimensions' instead."); StringList defaultDims; defaultDims.push_back("Red"); defaultDims.push_back("Green"); defaultDims.push_back("Blue"); StringList dims = options.getValueOrDefault<StringList>("dimensions", defaultDims); uint32_t defaultBand = 1; for (std::string& dim : dims) { BandInfo bi = parseDim(dim, defaultBand); defaultBand = bi.m_band + 1; m_bands.push_back(bi); } }
pdal::drivers::oci::Connection connect() { std::string connection = m_options.getValueOrThrow<std::string>("connection"); if (connection.empty()) throw pdal_error("Oracle connection string empty! Unable to connect"); std::string::size_type slash_pos = connection.find("/",0); std::string username = connection.substr(0,slash_pos); std::string::size_type at_pos = connection.find("@",slash_pos); std::string password = connection.substr(slash_pos+1, at_pos-slash_pos-1); std::string instance = connection.substr(at_pos+1); Connection con = boost::make_shared<OWConnection>(username.c_str(),password.c_str(),instance.c_str()); if (!con->Succeeded()) { throw connection_failed("Oracle connection failed"); } return con; }
void NitfWriter::doneFile() { finishOutput(); try { ::nitf::Record record(NITF_VER_21); ::nitf::FileHeader header = record.getHeader(); header.getFileHeader().set("NITF"); header.getComplianceLevel().set(m_cLevel); header.getSystemType().set(m_sType); header.getOriginStationID().set(m_oStationId); if (m_fileTitle.empty()) m_fileTitle = FileUtils::getFilename(m_nitfFilename); header.getFileTitle().set(m_fileTitle); header.getClassification().set(m_fileClass); header.getMessageCopyNum().set("00000"); header.getMessageNumCopies().set("00000"); header.getEncrypted().set("0"); header.getBackgroundColor().setRawData(const_cast<char*>("000"), 3); header.getOriginatorName().set(m_origName); header.getOriginatorPhone().set(m_origPhone); header.getSecurityGroup().getClassificationSystem().set( m_securityClassificationSystem); header.getSecurityGroup().getControlAndHandling().set( m_securityControlAndHandling); header.getSecurityGroup().getClassificationText().set(m_sic); ::nitf::DESegment des = record.newDataExtensionSegment(); des.getSubheader().getFilePartType().set("DE"); des.getSubheader().getTypeID().set("LIDARA DES"); des.getSubheader().getVersion().set("01"); des.getSubheader().getSecurityClass().set(m_securityClass); ::nitf::FileSecurity security = record.getHeader().getSecurityGroup(); des.getSubheader().setSecurityGroup(security.clone()); ::nitf::TRE usrHdr("LIDARA DES", "raw_data"); usrHdr.setField("raw_data", "not"); ::nitf::Field fld = usrHdr.getField("raw_data"); fld.setType(::nitf::Field::BINARY); std::streambuf *buf = m_oss.rdbuf(); long size = buf->pubseekoff(0, m_oss.end); buf->pubseekoff(0, m_oss.beg); std::vector<char> bytes(size); buf->sgetn(bytes.data(), size); m_oss.clear(); des.getSubheader().setSubheaderFields(usrHdr); ::nitf::ImageSegment image = record.newImageSegment(); ::nitf::ImageSubheader subheader = image.getSubheader(); BOX3D bounds = reprojectBoxToDD(m_srs, m_bounds); //NITF decimal degree values for corner coordinates only has a // precision of 3 after the decimal. This may cause an invalid // polygon due to rounding errors with a small tile. Therefore // instead of rounding min values will use the floor value and // max values will use the ceiling values. bounds.minx = (floor(bounds.minx * 1000)) / 1000.0; bounds.miny = (floor(bounds.miny * 1000)) / 1000.0; bounds.maxx = (ceil(bounds.maxx * 1000)) / 1000.0; bounds.maxy = (ceil(bounds.maxy * 1000)) / 1000.0; double corners[4][2]; corners[0][0] = bounds.maxy; corners[0][1] = bounds.minx; corners[1][0] = bounds.maxy; corners[1][1] = bounds.maxx; corners[2][0] = bounds.miny; corners[2][1] = bounds.maxx; corners[3][0] = bounds.miny; corners[3][1] = bounds.minx; subheader.setCornersFromLatLons(NRT_CORNERS_DECIMAL, corners); subheader.getImageSecurityClass().set(m_imgSecurityClass); subheader.setSecurityGroup(security.clone()); if (m_imgDate.size()) subheader.getImageDateAndTime().set(m_imgDate); ::nitf::BandInfo info; ::nitf::LookupTable lt(0,0); info.init(" ", /* The band representation, Nth band */ " ", /* The band subcategory */ "N", /* The band filter condition */ " ", /* The band standard image filter code */ 0, /* The number of look-up tables */ 0, /* The number of entries/LUT */ lt); /* The look-up tables */ std::vector< ::nitf::BandInfo> bands; bands.push_back(info); subheader.setPixelInformation( "INT", /* Pixel value type */ 8, /* Number of bits/pixel */ 8, /* Actual number of bits/pixel */ "R", /* Pixel justification */ "NODISPLY", /* Image representation */ "VIS", /* Image category */ 1, /* Number of bands */ bands); subheader.setBlocking( 8, /*!< The number of rows */ 8, /*!< The number of columns */ 8, /*!< The number of rows/block */ 8, /*!< The number of columns/block */ "B"); /*!< Image mode */ //Image Header fields to set subheader.getImageId().set("None"); subheader.getImageTitle().set(m_imgIdentifier2); // 64 char string std::string zeros(64, '0'); std::unique_ptr< ::nitf::BandSource> band(new ::nitf::MemorySource( const_cast<char*>(zeros.c_str()), zeros.size() /* memory size */, 0 /* starting offset */, 1 /* bytes per pixel */, 0 /*skip*/)); ::nitf::ImageSource iSource; iSource.addBand(*band); //AIMIDB ::nitf::TRE aimidbTre("AIMIDB"); //LIDAR defaults if (m_imgDate.size()) aimidbTre.setField("ACQUISITION_DATE", m_imgDate); aimidbTre.setField("MISSION_NO", "UNKN"); aimidbTre.setField("MISSION_IDENTIFICATION", "NOT AVAIL."); aimidbTre.setField("FLIGHT_NO", "00"); aimidbTre.setField("CURRENT_SEGMENT", "AA"); aimidbTre.setField("START_TILE_COLUMN", "001"); aimidbTre.setField("START_TILE_ROW", "00001"); aimidbTre.setField("END_SEGMENT", "00"); aimidbTre.setField("END_TILE_COLUMN", "001"); aimidbTre.setField("END_TILE_ROW", "00001"); for (auto& s : m_aimidb) { StringList v = Utils::split2(s, ':'); if (v.size() != 2) { std::ostringstream oss; oss << "Invalid name/value for AIMIDB '" << s << "'. Format: <name>:<value>."; throw oss.str(); } Utils::trim(v[0]); Utils::trim(v[1]); aimidbTre.setField(v[0], v[1]); } subheader.getExtendedSection().appendTRE(aimidbTre); //if IDATIM is empty set it equal to AIMIDB.ACQUISITION_DATE if(!m_imgDate.size()) { m_imgDate=aimidbTre.getField("ACQUISITION_DATE").toString(); if (m_imgDate.size()) subheader.getImageDateAndTime().set(m_imgDate); } //ACFTB ::nitf::TRE acftbTre("ACFTB"); //LIDAR defaults acftbTre.setField("AC_MSN_ID", "NOT AVAILABLE"); acftbTre.setField("SCENE_SOURCE", " "); if (m_imgDate.size()>7) acftbTre.setField("PDATE", m_imgDate.substr(0,8)); acftbTre.setField("MPLAN", "999"); acftbTre.setField("LOC_ACCY", "000.00"); acftbTre.setField("ROW_SPACING", "0000000"); acftbTre.setField("ROW_SPACING_UNITS", "u"); acftbTre.setField("COL_SPACING", "0000000"); acftbTre.setField("COL_SPACING_UNITS", "u"); acftbTre.setField("FOCAL_LENGTH", "999.99"); for (auto& s : m_acftb) { StringList v = Utils::split2(s, ':'); if (v.size() != 2) { std::ostringstream oss; oss << "Invalid name/value for ACFTB '" << s << "'. Format: <name>:<value>."; throw oss.str(); } Utils::trim(v[0]); Utils::trim(v[1]); acftbTre.setField(v[0], v[1]); } subheader.getExtendedSection().appendTRE(acftbTre); ::nitf::Writer writer; ::nitf::IOHandle output_io(m_nitfFilename.c_str(), NITF_ACCESS_WRITEONLY, NITF_CREATE); writer.prepare(output_io, record); ::nitf::SegmentWriter sWriter = writer.newDEWriter(0); ::nitf::SegmentMemorySource sSource(bytes.data(), size, 0, 0, false); sWriter.attachSource(sSource); ::nitf::ImageWriter iWriter = writer.newImageWriter(0); iWriter.attachSource(iSource); writer.write(); output_io.close(); } catch (except::Throwable & t) { std::ostringstream oss; // std::cout << t.getTrace(); throw pdal_error(t.getMessage()); } }
void AttributeFilter::UpdateGEOSBuffer(PointBuffer& buffer, AttributeInfo& info) { QuadIndex idx(buffer); idx.build(); if (!info.lyr) // wake up the layer { if (info.layer.size()) info.lyr = OGR_DS_GetLayerByName(info.ds.get(), info.layer.c_str()); else if (info.query.size()) { info.lyr = OGR_DS_ExecuteSQL(info.ds.get(), info.query.c_str(), 0, 0); } else info.lyr = OGR_DS_GetLayer(info.ds.get(), 0); if (!info.lyr) { std::ostringstream oss; oss << "Unable to select layer '" << info.layer << "'"; throw pdal_error(oss.str()); } } OGRFeaturePtr feature = OGRFeaturePtr(OGR_L_GetNextFeature(info.lyr), OGRFeatureDeleter()); int field_index(1); // default to first column if nothing was set if (info.column.size()) { field_index = OGR_F_GetFieldIndex(feature.get(), info.column.c_str()); if (field_index == -1) { std::ostringstream oss; oss << "No column name '" << info.column << "' was found."; throw pdal_error(oss.str()); } } while(feature) { OGRGeometryH geom = OGR_F_GetGeometryRef(feature.get()); OGRwkbGeometryType t = OGR_G_GetGeometryType(geom); int f_count = OGR_F_GetFieldCount (feature.get()); if (!(t == wkbPolygon || t == wkbMultiPolygon || t == wkbPolygon25D || t == wkbMultiPolygon25D)) { std::ostringstream oss; oss << "Geometry is not Polygon or MultiPolygon!"; throw pdal::pdal_error(oss.str()); } OGRGeometry* ogr_g = (OGRGeometry*) geom; GEOSGeometry* geos_g (0); if (!m_geosEnvironment) { #if (GDAL_VERSION_MINOR < 11) && (GDAL_VERSION_MAJOR == 1) geos_g = ogr_g->exportToGEOS(); #else m_geosEnvironment = ogr_g->createGEOSContext(); geos_g = ogr_g->exportToGEOS(m_geosEnvironment); #endif } GEOSPreparedGeometry const* geos_pg = GEOSPrepare_r(m_geosEnvironment, geos_g); if (!geos_pg) throw pdal_error("unable to prepare geometry for index-accelerated intersection"); // Compute a total bounds for the geometry. Query the QuadTree to // find out the points that are inside the bbox. Then test each // point in the bbox against the prepared geometry. BOX3D box = computeBounds(m_geosEnvironment, geos_g); std::vector<std::size_t> ids = idx.getPoints(box); for (const auto& i : ids) { double x = buffer.getFieldAs<double>(Dimension::Id::X, i); double y = buffer.getFieldAs<double>(Dimension::Id::Y, i); double z = buffer.getFieldAs<double>(Dimension::Id::Z, i); GEOSGeometry* p = createGEOSPoint(m_geosEnvironment, x, y ,z); if (static_cast<bool>(GEOSPreparedContains_r(m_geosEnvironment, geos_pg, p))) { // We're in the poly, write the attribute value int32_t v = OGR_F_GetFieldAsInteger(feature.get(), field_index); buffer.setField(info.dim, i, v); // log()->get(LogLevel::Debug) << "Setting value: " << v << std::endl; } GEOSGeom_destroy_r(m_geosEnvironment, p); } feature = OGRFeaturePtr(OGR_L_GetNextFeature(info.lyr), OGRFeatureDeleter()); } }
boost::uint64_t Writer::write( boost::uint64_t targetNumPointsToWrite, boost::uint64_t startingPosition) { if (!isInitialized()) { throw pdal_error("stage not initialized"); } boost::uint64_t actualNumPointsWritten = 0; UserCallback* callback = getUserCallback(); do_callback(0.0, callback); const Schema& schema = getPrevStage().getSchema(); if (m_writer_buffer == 0) { boost::uint64_t capacity(targetNumPointsToWrite); if (capacity == 0) { capacity = m_chunkSize; } else { capacity = (std::min)(static_cast<boost::uint64_t>(m_chunkSize), targetNumPointsToWrite) ; } m_writer_buffer = new PointBuffer (schema, capacity); } boost::scoped_ptr<StageSequentialIterator> iter(getPrevStage().createSequentialIterator(*m_writer_buffer)); if (startingPosition) iter->skip(startingPosition); if (!iter) throw pdal_error("Unable to obtain iterator from previous stage!"); // if we don't have an SRS, try to forward the one from the prev stage if (m_spatialReference.empty()) m_spatialReference = getPrevStage().getSpatialReference(); writeBegin(targetNumPointsToWrite); iter->readBegin(); // // The user has requested a specific number of points: proceed a // chunk at a time until we reach that number. (If that number // is 0, we proceed until no more points can be read.) // // If the user requests an interrupt while we're running, we'll throw. // while (true) { // have we hit the end already? if (iter->atEnd()) break; // rebuild our PointBuffer, if it needs to hold less than the default max chunk size if (targetNumPointsToWrite != 0) { const boost::uint64_t numRemainingPointsToRead = targetNumPointsToWrite - actualNumPointsWritten; const boost::uint64_t numPointsToReadThisChunk64 = std::min<boost::uint64_t>(numRemainingPointsToRead, m_chunkSize); // this case is safe because m_chunkSize is a uint32 const boost::uint32_t numPointsToReadThisChunk = static_cast<boost::uint32_t>(numPointsToReadThisChunk64); // we are reusing the buffer, so we may need to adjust the capacity for the last (and likely undersized) chunk if (m_writer_buffer->getCapacity() < numPointsToReadThisChunk) { m_writer_buffer->resize(numPointsToReadThisChunk); } } // read... iter->readBufferBegin(*m_writer_buffer); const boost::uint32_t numPointsReadThisChunk = iter->readBuffer(*m_writer_buffer); iter->readBufferEnd(*m_writer_buffer); assert(numPointsReadThisChunk == m_writer_buffer->getNumPoints()); assert(numPointsReadThisChunk <= m_writer_buffer->getCapacity()); // have we reached the end yet? if (numPointsReadThisChunk == 0) break; // write... writeBufferBegin(*m_writer_buffer); const boost::uint32_t numPointsWrittenThisChunk = writeBuffer(*m_writer_buffer); assert(numPointsWrittenThisChunk == numPointsReadThisChunk); writeBufferEnd(*m_writer_buffer); // update count actualNumPointsWritten += numPointsWrittenThisChunk; do_callback(actualNumPointsWritten, targetNumPointsToWrite, callback); if (targetNumPointsToWrite != 0) { // have we done enough yet? if (actualNumPointsWritten >= targetNumPointsToWrite) break; } // reset the buffer, so we can use it again m_writer_buffer->setNumPoints(0); } iter->readEnd(); writeEnd(actualNumPointsWritten); assert((targetNumPointsToWrite == 0) || (actualNumPointsWritten <= targetNumPointsToWrite)); do_callback(100.0, callback); return actualNumPointsWritten; }
void FauxReader::processOptions(const Options& options) { BOX3D bounds; try { bounds = options.getValueOrDefault<BOX3D>("bounds", BOX3D(0, 0, 0, 1, 1, 1)); } catch (Option::cant_convert) { std::string s = options.getValueOrDefault<std::string>("bounds"); std::ostringstream oss; oss << getName() << ": Invalid 'bounds' specification: '" << s << "'. Format: '([xmin,xmax],[ymin,ymax],[zmin,zmax])'."; throw pdal_error(oss.str()); } m_minX = bounds.minx; m_maxX = bounds.maxx; m_minY = bounds.miny; m_maxY = bounds.maxy; m_minZ = bounds.minz; m_maxZ = bounds.maxz; // For backward compatibility. if (m_count == 0) m_count = options.getValueOrThrow<point_count_t>("num_points"); if (m_count == 0) { std::ostringstream oss; oss << getName() << ": Option 'count' must be non-zero."; throw pdal_error(oss.str()); } m_mean_x = options.getValueOrDefault<double>("mean_x",0.0); m_mean_y = options.getValueOrDefault<double>("mean_y",0.0); m_mean_z = options.getValueOrDefault<double>("mean_z",0.0); m_stdev_x = options.getValueOrDefault<double>("stdev_x",1.0); m_stdev_y = options.getValueOrDefault<double>("stdev_y",1.0); m_stdev_z = options.getValueOrDefault<double>("stdev_z",1.0); m_mode = string2mode(options.getValueOrThrow<std::string>("mode")); m_numReturns = options.getValueOrDefault("number_of_returns", 0); if (m_numReturns > 10) { std::ostringstream oss; oss << getName() << ": Option 'number_of_returns' must be in the range " "[0,10]."; throw pdal_error(oss.str()); } if (m_count > 1) { m_delX = (m_maxX - m_minX) / (m_count - 1); m_delY = (m_maxY - m_minY) / (m_count - 1); m_delZ = (m_maxZ - m_minZ) / (m_count - 1); } else { m_delX = 0; m_delY = 0; m_delZ = 0; } }