#include "onf_stepcomputedominanceindicators.h"
#include "ct_math/delaunay2d/ct_delaunaytriangulation.h"
#include "opencv2/imgproc/imgproc.hpp"
#include "opencv2/core/core.hpp"
ONF_StepComputeDominanceIndicators::ONF_StepComputeDominanceIndicators() : SuperClass()
{
}
QString ONF_StepComputeDominanceIndicators::description() const
{
return tr("Calcul de l'indice de compétition de Schutz 1989");
}
QString ONF_StepComputeDominanceIndicators::detailledDescription() const
{
return tr("Nécessite en entrée des items représentant des apex, avec les attributs (X, Y, Z, DiamètreHouppier).");
}
QString ONF_StepComputeDominanceIndicators::inputDescription() const
{
return SuperClass::inputDescription() + tr("
");
}
QString ONF_StepComputeDominanceIndicators::outputDescription() const
{
return SuperClass::outputDescription() + tr("
");
}
QString ONF_StepComputeDominanceIndicators::detailsDescription() const
{
return tr("");
}
QString ONF_StepComputeDominanceIndicators::URL() const
{
//return tr("STEP URL HERE");
return SuperClass::URL(); //by default URL of the plugin
}
CT_VirtualAbstractStep* ONF_StepComputeDominanceIndicators::createNewInstance() const
{
return new ONF_StepComputeDominanceIndicators();
}
//////////////////// PROTECTED METHODS //////////////////
void ONF_StepComputeDominanceIndicators::declareInputModels(CT_StepInModelStructureManager& manager)
{
manager.addResult(_inResult, tr("Items (apex)"));
manager.setZeroOrMoreRootGroup(_inResult, _inZeroOrMoreRootGroup);
manager.addGroup(_inZeroOrMoreRootGroup, _inGroup);
manager.addItem(_inGroup, _inApexItem, tr("Item (apex)"));
manager.addItemAttribute(_inApexItem, _inAttXApex, CT_AbstractCategory::DATA_VALUE, tr("X_Apex"));
manager.addItemAttribute(_inApexItem, _inAttYApex, CT_AbstractCategory::DATA_VALUE, tr("Y_Apex"));
manager.addItemAttribute(_inApexItem, _inAttZApex, CT_AbstractCategory::DATA_VALUE, tr("Z_Apex"));
manager.addItemAttribute(_inApexItem, _inAttDiameter, CT_AbstractCategory::DATA_VALUE, tr("Diametre_Houppier"));
manager.addResult(_inResultDTM, tr("MNT"), "", true);
manager.setZeroOrMoreRootGroup(_inResultDTM, _inZeroOrMoreRootGroupDTM);
manager.addGroup(_inZeroOrMoreRootGroupDTM, _inGroupDTM);
manager.addItem(_inGroupDTM, _inDTM, tr("MNT"));
}
void ONF_StepComputeDominanceIndicators::declareOutputModels(CT_StepOutModelStructureManager& manager)
{
manager.addResultCopy(_inResult);
manager.addItem(_inGroup, _outitemAtt, tr("indiceSchutz"));
manager.addItemAttribute(_outitemAtt, _outIndiceSchutzTotal, PS_CATEGORY_MANAGER->findByUniqueName(CT_AbstractCategory::DATA_VALUE), tr("indiceSchutzTotal"));
manager.addItemAttribute(_outitemAtt, _outIndiceSchutzHorTotal, PS_CATEGORY_MANAGER->findByUniqueName(CT_AbstractCategory::DATA_VALUE), tr("indiceSchutzHorTotal"));
manager.addItemAttribute(_outitemAtt, _outIndiceSchutzVerTotal, PS_CATEGORY_MANAGER->findByUniqueName(CT_AbstractCategory::DATA_VALUE), tr("indiceSchutzVerTotal"));
manager.addItemAttribute(_outitemAtt, _outIndiceSchutzMax, PS_CATEGORY_MANAGER->findByUniqueName(CT_AbstractCategory::DATA_VALUE), tr("indiceSchutzMax"));
manager.addItemAttribute(_outitemAtt, _outIndiceSchutzHorMax, PS_CATEGORY_MANAGER->findByUniqueName(CT_AbstractCategory::DATA_VALUE), tr("indiceSchutzHorMax"));
manager.addItemAttribute(_outitemAtt, _outIndiceSchutzVerMax, PS_CATEGORY_MANAGER->findByUniqueName(CT_AbstractCategory::DATA_VALUE), tr("indiceSchutzVerMax"));
manager.addItemAttribute(_outitemAtt, _outAngleNeighbMax, PS_CATEGORY_MANAGER->findByUniqueName(CT_AbstractCategory::DATA_VALUE), tr("angleNeighbMax"));
}
void ONF_StepComputeDominanceIndicators::compute()
{
const CT_Image2D* mnt = nullptr;
for (const CT_Image2D* imageIn : _inDTM.iterateInputs(_inResultDTM))
{
mnt = imageIn;
}
double minx = std::numeric_limits::max();
double miny = std::numeric_limits::max();
double maxx = -std::numeric_limits::max();
double maxy = -std::numeric_limits::max();
QList apexList;
for (CT_StandardItemGroup* group : _inGroup.iterateOutputs(_inResult))
{
for (const CT_AbstractSingularItemDrawable* apexItem : group->singularItems(_inApexItem))
{
if (isStopped()) {return;}
const CT_AbstractItemAttribute *attXApex = apexItem->itemAttribute(_inAttXApex);
const CT_AbstractItemAttribute *attYApex = apexItem->itemAttribute(_inAttYApex);
const CT_AbstractItemAttribute *attZApex = apexItem->itemAttribute(_inAttZApex);
const CT_AbstractItemAttribute *attDiameter = apexItem->itemAttribute(_inAttDiameter);
if (attXApex != nullptr && attYApex != nullptr && attZApex != nullptr && attDiameter != nullptr)
{
bool okX, okY, okZ, okDiameter;
double valX = attXApex->toDouble(apexItem, &okX);
double valY = attYApex->toDouble(apexItem, &okY);
double valZ = attZApex->toDouble(apexItem, &okZ);
double valDiameter = attDiameter->toDouble(apexItem, &okDiameter);
if (okX && okY && okZ && okDiameter)
{
if (valX < minx) {minx = valX;}
if (valY < miny) {miny = valY;}
if (valX > maxx) {maxx = valX;}
if (valY > maxy) {maxy = valY;}
size_t index;
double valH = valZ;
if (mnt != nullptr && mnt->indexAtCoords(valX, valY, index))
{
float zval = mnt->valueAtIndex(index);
if (!qFuzzyCompare(zval, mnt->NA()))
{
valH -= double(zval);
}
}
apexList.append(new Apex(valX, valY, valZ, valH, valDiameter, group));
}
}
}
}
setProgress(50);
QMap apexMap;
// Compute triangulation
CT_DelaunayTriangulation *delaunay = new CT_DelaunayTriangulation();
delaunay->init(minx - 1.0, miny - 1.0, maxx + 1.0, maxy + 1.0);
for (int i = 0 ; i < apexList.size() ; i++)
{
Apex* apex = apexList.at(i);
Eigen::Vector3d *coord = new Eigen::Vector3d(apex->_x, apex->_y, apex->_h);
CT_DelaunayVertex* delaunayVertex = delaunay->addVertex(coord, true);
apexMap.insert(delaunayVertex, apex);
}
delaunay->doInsertion();
delaunay->computeVerticesNeighbors();
QMapIterator itM(apexMap);
while (itM.hasNext())
{
double indiceSchutzTotal = 0;
double indiceSchutzHorTotal = 0;
double indiceSchutzVerTotal = 0;
double indiceSchutzMax = 0;
double indiceSchutzHorMax = 0;
double indiceSchutzVerMax = 0;
double angleNeighbMax = 0;
itM.next();
CT_DelaunayVertex* baseVertex = itM.key();
Apex* baseApex = itM.value();
QList &neighbours = baseVertex->getNeighbors();
for (int j = 0 ; j < neighbours.size() ; j++)
{
CT_DelaunayVertex* neighbour = neighbours.at(j);
Apex* neighbApex = apexMap.value(neighbour);
if (neighbApex != nullptr)
{
double dist2D = std::sqrt(pow(baseApex->_x - neighbApex->_x, 2) + pow(baseApex->_y - neighbApex->_y, 2));
double deltaH = neighbApex->_h - baseApex->_h;
double sommeRadius = baseApex->_diameter / 2.0 + neighbApex->_diameter / 2.0;
double indiceSchutzHor = 0.5 - (dist2D - sommeRadius) / sommeRadius;
if (dist2D < sommeRadius) {indiceSchutzHor = 0.5;}
double indiceSchutzVer = 0.65 * deltaH / dist2D;
double indiceSchutz = indiceSchutzHor + indiceSchutzVer;
if (indiceSchutz < 0) {indiceSchutz = 0;}
if (indiceSchutzHor < 0) {indiceSchutzHor = 0;}
if (indiceSchutzVer < 0) {indiceSchutzVer = 0;}
indiceSchutzTotal += indiceSchutz;
indiceSchutzHorTotal += indiceSchutzHor;
indiceSchutzVerTotal += indiceSchutzVer;
if (indiceSchutz > indiceSchutzMax) {indiceSchutzMax = indiceSchutz;}
if (indiceSchutzHor > indiceSchutzHorMax) {indiceSchutzHorMax = indiceSchutzHor;}
if (indiceSchutzVer > indiceSchutzVerMax) {indiceSchutzVerMax = indiceSchutzVer;}
double angleNeighb = 0;
if (neighbApex->_h > baseApex->_diameter) {angleNeighb = (180.0 / M_PI) * std::atan(deltaH / dist2D);}
if (angleNeighb > angleNeighbMax && dist2D < 1.2*sommeRadius) {angleNeighbMax = angleNeighb;}
}
}
CT_ItemAttributeList* attList = new CT_ItemAttributeList();
baseApex->_group->addSingularItem(_outitemAtt, attList);
attList->addItemAttribute(_outIndiceSchutzTotal, new CT_StdItemAttributeT(PS_CATEGORY_MANAGER->findByUniqueName(CT_AbstractCategory::DATA_VALUE), indiceSchutzTotal));
attList->addItemAttribute(_outIndiceSchutzHorTotal, new CT_StdItemAttributeT(PS_CATEGORY_MANAGER->findByUniqueName(CT_AbstractCategory::DATA_VALUE), indiceSchutzHorTotal));
attList->addItemAttribute(_outIndiceSchutzVerTotal, new CT_StdItemAttributeT(PS_CATEGORY_MANAGER->findByUniqueName(CT_AbstractCategory::DATA_VALUE), indiceSchutzVerTotal));
attList->addItemAttribute(_outIndiceSchutzMax, new CT_StdItemAttributeT(PS_CATEGORY_MANAGER->findByUniqueName(CT_AbstractCategory::DATA_VALUE), indiceSchutzMax));
attList->addItemAttribute(_outIndiceSchutzHorMax, new CT_StdItemAttributeT(PS_CATEGORY_MANAGER->findByUniqueName(CT_AbstractCategory::DATA_VALUE), indiceSchutzHorMax));
attList->addItemAttribute(_outIndiceSchutzVerMax, new CT_StdItemAttributeT(PS_CATEGORY_MANAGER->findByUniqueName(CT_AbstractCategory::DATA_VALUE), indiceSchutzVerMax));
attList->addItemAttribute(_outAngleNeighbMax, new CT_StdItemAttributeT(PS_CATEGORY_MANAGER->findByUniqueName(CT_AbstractCategory::DATA_VALUE), angleNeighbMax));
}
delete delaunay;
setProgress(100.0f);
}