/**************************************************************************** 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_stepmergeneighbourclustersingrid.h" #include "ct_pointcloudindex/ct_pointcloudindexvector.h" #include "ct_itemdrawable/tools/iterator/ct_groupiterator.h" #include "ct_result/ct_resultgroup.h" #include "ct_result/model/inModel/ct_inresultmodelgroup.h" #include "ct_result/model/inModel/ct_inresultmodelgrouptocopy.h" #include "ct_result/model/outModel/ct_outresultmodelgroupcopy.h" #include "ct_result/model/outModel/tools/ct_outresultmodelgrouptocopypossibilities.h" #include "ct_model/inModel/tools/ct_instdmodelpossibility.h" #include "ct_view/ct_stepconfigurabledialog.h" #include "ct_math/ct_mathpoint.h" #include "ct_iterator/ct_pointiterator.h" #include "ct_global/ct_context.h" #if QT_VERSION < QT_VERSION_CHECK(5,0,0) #include #else #include #endif #include #include // Alias for indexing models #define DEF_SearchInResult "r" #define DEF_SearchInGroup "gr" #define DEF_SearchInGridSeeds "gridSeeds" // Constructor : initialization of parameters ONF_StepMergeNeighbourClustersInGrid::ONF_StepMergeNeighbourClustersInGrid(CT_StepInitializeData &dataInit) : CT_AbstractStep(dataInit) { _ncellsXY = 1; _ncellsZ = 3; } // Step description (tooltip of contextual menu) QString ONF_StepMergeNeighbourClustersInGrid::getStepDescription() const { return tr("Fusionner les clusters jointifs d'une grille"); } // Step detailled description QString ONF_StepMergeNeighbourClustersInGrid::getStepDetailledDescription() const { return tr(""); } // Step URL QString ONF_StepMergeNeighbourClustersInGrid::getStepURL() const { //return tr("STEP URL HERE"); return CT_AbstractStep::getStepURL(); //by default URL of the plugin } // Step copy method CT_VirtualAbstractStep* ONF_StepMergeNeighbourClustersInGrid::createNewInstance(CT_StepInitializeData &dataInit) { return new ONF_StepMergeNeighbourClustersInGrid(dataInit); } //////////////////// PROTECTED METHODS ////////////////// // Creation and affiliation of IN models void ONF_StepMergeNeighbourClustersInGrid::createInResultModelListProtected() { CT_InResultModelGroupToCopy *resultModel = createNewInResultModelForCopy(DEF_SearchInResult, tr("Grilles")); resultModel->setZeroOrMoreRootGroup(); resultModel->addGroupModel("", DEF_SearchInGroup); resultModel->addItemModel(DEF_SearchInGroup, DEF_SearchInGridSeeds, CT_Grid3D_Sparse::staticGetType(), tr("Grille segmentée")); } // Creation and affiliation of OUT models void ONF_StepMergeNeighbourClustersInGrid::createOutResultModelListProtected() { CT_OutResultModelGroupToCopyPossibilities *res = createNewOutResultModelToCopy(DEF_SearchInResult); if(res != NULL) { res->addItemModel(DEF_SearchInGroup, _outMergedGridModelName, new CT_Grid3D_Sparse(), tr("Grille fusionnée")); } } // Semi-automatic creation of step parameters DialogBox void ONF_StepMergeNeighbourClustersInGrid::createPostConfigurationDialog() { CT_StepConfigurableDialog *configDialog = newStandardPostConfigurationDialog(); configDialog->addInt(tr("Voisinnage de fusion en XY"), tr("cases"), 1, 9999, _ncellsXY); configDialog->addInt(tr("Voisinnage de fusion en Z"), tr("cases"), 1, 9999, _ncellsZ); } void ONF_StepMergeNeighbourClustersInGrid::compute() { CT_ResultGroup* res_out = getOutResultList().first(); CT_StandardItemGroup* grp = NULL; CT_ResultGroupIterator grpPosIt(res_out, this, DEF_SearchInGroup); while (grpPosIt.hasNext()) { grp = (CT_StandardItemGroup*) grpPosIt.next(); CT_Grid3D_Sparse* gridIn = (CT_Grid3D_Sparse*)grp->firstItemByINModelName(this, DEF_SearchInGridSeeds); if (gridIn != NULL) { CT_Grid3D_Sparse* outGrid = new CT_Grid3D_Sparse(_outMergedGridModelName.completeName(), res_out, gridIn->minX(), gridIn->minY(), gridIn->minZ(), gridIn->xdim(), gridIn->ydim(), gridIn->zdim(), gridIn->resolution(), -1, -1); QMultiMap corresp; // recherche les clusters voisins for (size_t zz = 0 ; zz < gridIn->zdim() ; zz++) { for (size_t xx = 0 ; xx < gridIn->xdim() ; xx++) { for (size_t yy = 0 ; yy < gridIn->ydim() ; yy++) { size_t currentIndex; if (gridIn->index(xx, yy, zz, currentIndex)) { int currentCluster = gridIn->valueAtIndex(currentIndex); if (currentCluster >= 0) { size_t minz, minx, miny, maxz, maxx, maxy; if (zz >= _ncellsZ) {minz = zz - _ncellsZ;} else {minz = 0;} if (xx >= _ncellsXY) {minx = xx - _ncellsXY;} else {minx = 0;} if (yy >= _ncellsXY) {miny = yy - _ncellsXY;} else {miny = 0;} if (zz < gridIn->zdim() - _ncellsZ) {maxz = zz + _ncellsZ;} else {maxz = gridIn->zdim() - 1;} if (xx < gridIn->xdim() - _ncellsXY) {maxx = xx + _ncellsXY;} else {maxx = gridIn->xdim() - 1;} if (yy < gridIn->ydim() - _ncellsXY) {maxy = yy + _ncellsXY;} else {maxy = gridIn->ydim() - 1;} for (size_t zzz = minz ; zzz <= maxz ; zzz++) { for (size_t xxx = minx ; xxx <= maxx ; xxx++) { for (size_t yyy = miny ; yyy <= maxy ; yyy++) { size_t neighbourIndex; if (gridIn->index(xxx, yyy, zzz, neighbourIndex)) { int neighbourCluster = gridIn->valueAtIndex(neighbourIndex); if (neighbourCluster != -1 && neighbourCluster != currentCluster) { if (!corresp.contains(currentCluster, neighbourCluster)) {corresp.insert(currentCluster, neighbourCluster);} if (!corresp.contains(neighbourCluster, currentCluster)) {corresp.insert(neighbourCluster, currentCluster);} } } } } } } } } } } // Créer le vecteur de correspondances QVector newClusters(gridIn->dataMax() + 1); QVector removed(gridIn->dataMax() + 1); removed.fill(false); for (int i = 0 ; i < newClusters.size() ; i++) { newClusters[i] = i; } QList keys = corresp.uniqueKeys(); for (int i = 0 ; i < keys.size() ; i++) { int key = keys.at(i); if (!removed[key]) { QList neighbours; neighbours.append(key); removed[key] = true; int cpt = 0; while (cpt < neighbours.size()) { int k = neighbours.at(cpt); QList values = corresp.values(k); for (int j = 0 ; j < values.size() ; j++) { int value = values.at(j); if (!removed[value]) { neighbours.append(value); removed[value] = true; } } cpt++; } for (int j = 0 ; j < neighbours.size() ; j++) { int value = neighbours.at(j); newClusters[value] = key; } } } // répercuter sur la grille de sortie for (size_t zz = 0 ; zz < gridIn->zdim() ; zz++) { for (size_t xx = 0 ; xx < gridIn->xdim() ; xx++) { for (size_t yy = 0 ; yy < gridIn->ydim() ; yy++) { size_t currentIndex; if (gridIn->index(xx, yy, zz, currentIndex)) { int currentCluster = gridIn->valueAtIndex(currentIndex); if (currentCluster >= 0) { outGrid->setValue(xx, yy, zz, newClusters[currentCluster]); } } } } } outGrid->computeMinMax(); grp->addItemDrawable(outGrid); } } }