/**************************************************************************** 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_stepextractpositionsfromdensity.h" ONF_StepExtractPositionsFromDensity::ONF_StepExtractPositionsFromDensity() : SuperClass() { _resolution = 0.05; _threshold = 0.2; _thresholdN = 2; _relativeMode = 0; } QString ONF_StepExtractPositionsFromDensity::description() const { return tr("Créer des positions 2D à partir des densités des points"); } QString ONF_StepExtractPositionsFromDensity::detailledDescription() const { return tr(""); } QString ONF_StepExtractPositionsFromDensity::inputDescription() const { return SuperClass::inputDescription() + tr("

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

"); } QString ONF_StepExtractPositionsFromDensity::detailsDescription() const { return tr(""); } QString ONF_StepExtractPositionsFromDensity::URL() const { //return tr("STEP URL HERE"); return SuperClass::URL(); //by default URL of the plugin } CT_VirtualAbstractStep* ONF_StepExtractPositionsFromDensity::createNewInstance() const { return new ONF_StepExtractPositionsFromDensity(); } //////////////////// PROTECTED METHODS ////////////////// void ONF_StepExtractPositionsFromDensity::declareInputModels(CT_StepInModelStructureManager& manager) { manager.addResult(_inResult, tr("Scene(s)")); manager.setZeroOrMoreRootGroup(_inResult, _inZeroOrMoreRootGroup); manager.addGroup(_inZeroOrMoreRootGroup, _inGroup); manager.addItem(_inGroup, _inPoints, tr("Points")); } void ONF_StepExtractPositionsFromDensity::declareOutputModels(CT_StepOutModelStructureManager& manager) { manager.addResultCopy(_inResult); manager.addGroup(_inGroup, _grpPosition2D, tr("Positions 2D (grp)")); manager.addItem(_grpPosition2D, _position2D, tr("Positions 2D")); manager.addItemAttribute(_position2D, _position2DAtt, PS_CATEGORY_MANAGER->findByUniqueName(CT_AbstractCategory::DATA_NUMBER), tr("Densité")); manager.addItemAttribute(_position2D, _position2DAttMax, PS_CATEGORY_MANAGER->findByUniqueName(CT_AbstractCategory::DATA_NUMBER), tr("DensitéMax")); manager.addItem(_inGroup, _grid2D, tr("Grille de densité")); } void ONF_StepExtractPositionsFromDensity::fillPostInputConfigurationDialog(CT_StepConfigurableDialog* postInputConfigDialog) { postInputConfigDialog->addDouble(tr("Résolution du raster densité"), "cm", 0.1, 1e+09, 1, _resolution, 100); CT_ButtonGroup &bg_relativeMode = postInputConfigDialog->addButtonGroup(_relativeMode); postInputConfigDialog->addExcludeValue(tr("Seuil en valeur relative"), "", "", bg_relativeMode, 0); postInputConfigDialog->addDouble(tr("Seuil de densité (inclus)"), "% du max", 0, 100, 2, _threshold, 100); postInputConfigDialog->addExcludeValue(tr("Seuil en valeur absolue"), "", "", bg_relativeMode, 1); postInputConfigDialog->addInt(tr("Seuil de densité (inclus)"), "pts", 0, 10000, _thresholdN); } void ONF_StepExtractPositionsFromDensity::compute() { for (CT_StandardItemGroup* grp : _inGroup.iterateOutputs(_inResult)) { if (isStopped()) {return;} const CT_AbstractItemDrawableWithPointCloud* scene = grp->singularItem(_inPoints); if (scene != nullptr) { double xmin = scene->minX(); double ymin = scene->minY(); double xmax = scene->maxX(); double ymax = scene->maxY(); // Création de la grille de densité CT_Image2D* grid = CT_Image2D::createImage2DFromXYCoords(xmin, ymin, xmax, ymax, _resolution, 0, -1, 0); grp->addSingularItem(_grid2D, grid); CT_PointIterator itP(scene->pointCloudIndex()); while (itP.hasNext() && !isStopped()) { itP.next(); const CT_Point &point = itP.currentPoint(); grid->addValueAtCoords(point(0), point(1), 1); } grid->computeMinMax(); //Seuillage double threshold = _threshold * grid->dataMax(); if (_relativeMode == 1) { threshold = _thresholdN; } for (size_t indice = 0 ; indice < grid->nCells() ; indice++) { if (grid->valueAtIndex(indice) < threshold) { grid->setValueAtIndex(indice, 0); } } CT_Image2D* clusters = new CT_Image2D(xmin, ymin, grid->xdim(), grid->ydim(), _resolution, 0, -1, -1); int colDim = grid->xdim(); int linDim = grid->ydim(); int lastCluster = 0; for (int cx = 0 ; cx < colDim ; cx++) { for (int ly = 0 ; ly < linDim ; ly++) { int cluster = clusters->value(cx, ly); if (cluster < 0) { QList liste = computeColonize(cx, ly, grid); int size = liste.size(); if (size > 0) { int density = 0; int densityMax = 0; fillCellsInList(liste, lastCluster++, clusters, grid, density, densityMax); double x = 0; double y = 0; for (int i = 0 ; i < size ; i++) { Eigen::Vector3d cell; if (grid->getCellCenterCoordinates(liste.at(i), cell)) { x += cell(0); y += cell(1); } } x /= size; y /= size; CT_StandardItemGroup* grpPos = new CT_StandardItemGroup(); grp->addGroup(_grpPosition2D, grpPos); CT_Point2DData* point2dData = new CT_Point2DData(x, y); CT_Point2D* point2d = new CT_Point2D(point2dData); grpPos->addSingularItem(_position2D, point2d); point2d->addItemAttribute(_position2DAtt, new CT_StdItemAttributeT(CT_AbstractCategory::DATA_NUMBER, density)); point2d->addItemAttribute(_position2DAttMax, new CT_StdItemAttributeT(CT_AbstractCategory::DATA_NUMBER,densityMax)); } } } } delete clusters; } } } void ONF_StepExtractPositionsFromDensity::fillCellsInList(QList &liste, const int cluster, CT_Image2D *clustersGrid, CT_Image2D *densityGrid, int &density, int &densityMax) { if (liste.isEmpty()) {return;} density = 0; densityMax = 0; for (int i = 0 ; i < liste.size() ; i++) { size_t index = liste.at(i); clustersGrid->setValueAtIndex(index, cluster); int value = densityGrid->valueAtIndex(index); density += value; if (value > densityMax) {densityMax = value;} } } QList ONF_StepExtractPositionsFromDensity::computeColonize(int originColumn, int originRow, const CT_Image2D *densityGrid) { QList result; size_t index; if (!densityGrid->index(originColumn, originRow, index)) { return result; } if (densityGrid->valueAtIndex(index) > 0) {result.append(index);} int i = 0; while (i < result.size()) { int current_col = 0, current_row =0 ; densityGrid->indexToGrid(result.at(i), current_col, current_row); appendIfNotNulValue(result, current_col - 1, current_row, densityGrid); appendIfNotNulValue(result, current_col, current_row - 1, densityGrid); appendIfNotNulValue(result, current_col + 1, current_row, densityGrid); appendIfNotNulValue(result, current_col, current_row + 1, densityGrid); appendIfNotNulValue(result, current_col - 1, current_row - 1, densityGrid); appendIfNotNulValue(result, current_col - 1, current_row + 1, densityGrid); appendIfNotNulValue(result, current_col + 1, current_row - 1, densityGrid); appendIfNotNulValue(result, current_col + 1, current_row + 1, densityGrid); ++i; } return result; } void ONF_StepExtractPositionsFromDensity::appendIfNotNulValue(QList &result, int col, int lin, const CT_Image2D *densityGrid) { size_t index; if (densityGrid->index(col, lin, index)) { if (densityGrid->valueAtIndex(index) > 0 && !result.contains(index)) { result.append(index); } } }