/**************************************************************************** Copyright (C) 2010-2012 the Office National des Forêts (ONF), France All rights reserved. Contact : alexandre.piboule@onf.fr Developers : Alexandre PIBOULE (ONF) This file is part of PluginONF library. PluginONF is free library: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. PluginONF is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with PluginONF. If not, see . *****************************************************************************/ #include "onf_steploadbufferedrasters.h" #include "tools/ct_readerstools.h" #include "onf_steppluginmanager.h" #include "ct_log/ct_logmanager.h" #include ONF_StepLoadBufferedRasters::ONF_StepLoadBufferedRasters() : SuperClass() { _bufferSize = 20.0; _rasterName = tr("Raster"); } QString ONF_StepLoadBufferedRasters::description() const { return tr("Charge un raster avec une zone tampon"); } QString ONF_StepLoadBufferedRasters::detailledDescription() const { return tr("A partir d'une liste de rasters en entrée, charge l'un d'entre eux (à chaque tour de boucle), en intégrant une zone tampon tout autour issue des rasters voisins. "); } QString ONF_StepLoadBufferedRasters::inputDescription() const { return SuperClass::inputDescription() + tr("

"); } QString ONF_StepLoadBufferedRasters::outputDescription() const { return SuperClass::outputDescription() + tr("

"); } QString ONF_StepLoadBufferedRasters::detailsDescription() const { return tr(""); } CT_VirtualAbstractStep* ONF_StepLoadBufferedRasters::createNewInstance() const { // cree une copie de cette etape return new ONF_StepLoadBufferedRasters(); } //////////////////// PROTECTED ////////////////// void ONF_StepLoadBufferedRasters::declareInputModels(CT_StepInModelStructureManager& manager) { manager.addResult(_InResultCounter, tr("Résultat compteur"), QString(), true); manager.setRootGroup(_InResultCounter, _InGroupCounter); manager.addItem(_InGroupCounter, _InLoopCounter, tr("Compteur")); manager.addResult(_inResult, tr("Item")); manager.setZeroOrMoreRootGroup(_inResult, _inZeroOrMoreRootGroup); manager.addGroup(_inZeroOrMoreRootGroup, _inGroup); manager.addItem(_inGroup, _inItem, tr("Item")); manager.addItemAttribute(_inItem, _inAttName, CT_AbstractCategory::DATA_VALUE, tr("Name")); manager.addResult(_inResultRasters, tr("Dalles"), "", true); manager.setZeroOrMoreRootGroup(_inResultRasters, _inZeroOrMoreRootGroupRasters); manager.addGroup(_inZeroOrMoreRootGroupRasters, _inGroupRasters); manager.addItem(_inGroupRasters, _inReaderItem, tr("Entête (raster)")); manager.addItemAttribute(_inReaderItem, _inAttFileName, CT_AbstractCategory::DATA_VALUE, tr("FileName")); manager.addItem(_inGroupRasters, _inArea, tr("Emprise")); } void ONF_StepLoadBufferedRasters::fillPostInputConfigurationDialog(CT_StepConfigurableDialog* postInputConfigDialog) { postInputConfigDialog->addDouble(tr("Taille de la zone tampon"), "m", -std::numeric_limits::max(), std::numeric_limits::max(), 4, _bufferSize); postInputConfigDialog->addString(tr("Nom du raster"), "", _rasterName); } void ONF_StepLoadBufferedRasters::declareOutputModels(CT_StepOutModelStructureManager& manager) { manager.addResultCopy(_inResult); manager.addItem(_inGroup, _outRaster, _rasterName); manager.addItem(_inGroup, _outArea, tr("Emprise %1").arg(_rasterName)); manager.addItem(_inGroup, _outAreaBuffer, tr("Emprise %1 (buffer)").arg(_rasterName)); } void ONF_StepLoadBufferedRasters::compute() { const CT_LoopCounter* counter = _InLoopCounter.firstInput(_InResultCounter); if (counter == nullptr) { PS_LOG->addMessage(LogInterface::error, LogInterface::step, tr("Pas de tour de boucle identifié. Arrêt du traitement.")); return; } // first turn get all readers and areas if (counter->currentTurn() == 1) { _rasterList.clear(); for (const CT_StandardItemGroup* group : _inGroupRasters.iterateInputs(_inResultRasters)) { for (const CT_FileHeader *readerItem : group->singularItems(_inReaderItem)) { if (isStopped()) {return;} const CT_AbstractItemAttribute* att = readerItem->itemAttribute(_inAttFileName); const CT_Box2D* area = group->singularItem(_inArea); QString fileName = readerItem->displayableName(); if (att != nullptr) { fileName = att->toString(readerItem, nullptr); } fileName = QFileInfo(fileName).baseName(); const CT_AbstractReader* abstractReader = const_cast(readerItem)->reader(); const CT_Reader_GDAL* readerGdal = static_cast(abstractReader); if (area != nullptr && readerGdal != nullptr && readerGdal->getTypeOfDriver() == "Raster") { _rasterList.insert(fileName, RasterData(readerGdal, fileName, area)); } else { PS_LOG->addErrorMessage(LogInterface::step, tr("Le reader n'est pas de type raster GDAL")); } } } } for (CT_StandardItemGroup* group : _inGroup.iterateOutputs(_inResult)) { for (const CT_AbstractSingularItemDrawable *item : group->singularItems(_inItem)) { if (isStopped()) {return;} const CT_AbstractItemAttribute* att = item->itemAttribute(_inAttName); QString baseName = ""; if (att != nullptr) { baseName = att->toString(item, nullptr); } baseName = QFileInfo(baseName).baseName(); if (_rasterList.contains(baseName)) { RasterData baseRasterData = _rasterList.value(baseName); CT_Image2D* baseRaster = baseRasterData._reader->firstFloatRaster(); double res = baseRaster->resolution(); int bufferDim = int(_bufferSize / res); if (_bufferSize > bufferDim * res) {bufferDim++;} CT_Image2D* outRaster = new CT_Image2D(baseRaster->minX() - double(bufferDim) * res, baseRaster->minY() - double(bufferDim) * res, baseRaster->xdim() + 2 * bufferDim, baseRaster->ydim() + 2 * bufferDim, res, baseRaster->level(), baseRaster->NA(), baseRaster->NA()); Eigen::Vector3d outRasterMin, outRasterMax; outRasterMin(0) = outRaster->minX(); outRasterMin(1) = outRaster->minY(); outRasterMax(0) = outRaster->maxX(); outRasterMax(1) = outRaster->maxY(); for (int row = 0 ; row < baseRaster->ydim() ; row++) { for (int col = 0 ; col < baseRaster->xdim() ; col++) { outRaster->setValue(col + bufferDim, row + bufferDim, baseRaster->value(col, row)); } } QMapIterator it(_rasterList); while (it.hasNext()) { it.next(); QString name = it.key(); const RasterData& rasterData = it.value(); Eigen::Vector3d minOut, maxOut; if (name != baseName && intersection2D(outRasterMin, outRasterMax, rasterData._minArea, rasterData._maxArea, minOut, maxOut)) { CT_Image2D* raster = rasterData._reader->firstFloatRaster(); if (raster != nullptr) { int firstCol, lastCol, firstRow, lastRow; if (!raster->xcol(minOut(0) + 0.01, firstCol)) {firstCol = 0;} if (!raster->xcol(maxOut(0) - 0.01, lastCol)) {lastCol = raster->xdim() - 1;} // warning : ct_image2d are reversed in y dim if (!raster->lin(minOut(1) + 0.01, lastRow)) {lastRow = 0;} if (!raster->lin(maxOut(1) - 0.01, firstRow)) {firstRow = raster->ydim() - 1;} for (int col = firstCol ; col <= lastCol ; col++) { for (int row = firstRow ; row <= lastRow ; row++) { Eigen::Vector3d center; if (raster->getCellCenterCoordinates(col, row, center) && outRaster->valueAtCoords(center(0), center(1)) == raster->NA()) { outRaster->setValueAtCoords(center(0), center(1), raster->value(col, row)); } } } } delete raster; } } outRaster->computeMinMax(); group->addSingularItem(_outRaster, outRaster); group->addSingularItem(_outArea, new CT_Box2D(new CT_Box2DData(Eigen::Vector2d(baseRaster->minX(), baseRaster->minY()), Eigen::Vector2d(baseRaster->maxX(), baseRaster->maxY())))); group->addSingularItem(_outAreaBuffer, new CT_Box2D(new CT_Box2DData(Eigen::Vector2d(outRaster->minX(), outRaster->minY()), Eigen::Vector2d(outRaster->maxX(), outRaster->maxY())))); delete baseRaster; } } } } bool ONF_StepLoadBufferedRasters::intersection2D(const Eigen::Vector3d &minBase, const Eigen::Vector3d &maxBase, const Eigen::Vector3d &min, const Eigen::Vector3d &max, Eigen::Vector3d &minOut, Eigen::Vector3d &maxOut) { if (max(0) < minBase(0)) {return false;} if (max(1) < minBase(1)) {return false;} if (min(0) > maxBase(0)) {return false;} if (min(1) > maxBase(1)) {return false;} if (min(0) < minBase(0)) {minOut(0) = minBase(0);} else {minOut(0) = min(0);} if (min(1) < minBase(1)) {minOut(1) = minBase(1);} else {minOut(1) = min(1);} if (max(0) > maxBase(0)) {maxOut(0) = maxBase(0);} else {maxOut(0) = max(0);} if (max(1) > maxBase(1)) {maxOut(1) = maxBase(1);} else {maxOut(1) = max(1);} minOut(2) = 0; maxOut(2) = 0; return true; }