#include "onf_stepcomputeroadprobabilityrasters.h"
#include "ct_itemdrawable/ct_image2d_points.h"
#include "ct_math/ct_mathpoint.h"
#include "ct_accessor/ct_pointaccessor.h"
#define EPSILON 0.000001
ONF_StepComputeRoadProbabilityRasters::ONF_StepComputeRoadProbabilityRasters() : SuperClass()
{
_gndClass = 2;
_slopeMin = 5.0;
_slopeMax = 20.0;
_roughMin = 0.05;
_roughMax = 0.10;
_roughPtsMaxHeight = 0.2;
_roughPtsRadius = 2.0;
_roughMinPoints = 0.10;
_roughMaxPoints = 0.10;
_sobelThMin = 30.0;
_sobelThMax = 50.0;
_chmMin = 0.1;
_chmMax = 0.2;
_lowVegDensTh = 1.0;
_lowVegHmin = 0.5;
_lowVegHmax = 3.0;
_gndDensityMinPoints = 0.0;
_gndDensityMaxPoints = 0.4;
_slopeAdd = -1;
_roughnessAdd = 1;
_sobelAdd = -1;
_chmAdd = 1;
_intensityAdd = 1;
_gndDensAdd = 2;
_lowVegAdd = -1;
}
QString ONF_StepComputeRoadProbabilityRasters::description() const
{
return tr("Créer des rasters de probabilité de route");
}
QString ONF_StepComputeRoadProbabilityRasters::detailledDescription() const
{
return tr("Calcul d'un raster de pente (en degrés)"
"Formula from https://pro.arcgis.com/fr/pro-app/tool-reference/3d-analyst/how-slope-works.htm");
}
QString ONF_StepComputeRoadProbabilityRasters::inputDescription() const
{
return SuperClass::inputDescription() + tr("
");
}
QString ONF_StepComputeRoadProbabilityRasters::outputDescription() const
{
return SuperClass::outputDescription() + tr("
");
}
QString ONF_StepComputeRoadProbabilityRasters::detailsDescription() const
{
return tr("");
}
QString ONF_StepComputeRoadProbabilityRasters::URL() const
{
//return tr("STEP URL HERE");
return SuperClass::URL(); //by default URL of the plugin
}
CT_VirtualAbstractStep* ONF_StepComputeRoadProbabilityRasters::createNewInstance() const
{
return new ONF_StepComputeRoadProbabilityRasters();
}
//////////////////// PROTECTED METHODS //////////////////
void ONF_StepComputeRoadProbabilityRasters::declareInputModels(CT_StepInModelStructureManager& manager)
{
manager.addResult(_inResult, tr("MNT"));
manager.setZeroOrMoreRootGroup(_inResult, _inZeroOrMoreRootGroup);
manager.addGroup(_inZeroOrMoreRootGroup, _inGroup);
manager.addItem(_inGroup, _inDTM, tr("MNT"));
manager.addItem(_inGroup, _inScene, tr("Scène"));
manager.addItem(_inGroup, _inLASAttributes, tr("Attributs LAS"));
manager.addItem(_inGroup, _inArea, tr("Emprise"));
}
void ONF_StepComputeRoadProbabilityRasters::fillPostInputConfigurationDialog(CT_StepConfigurableDialog* postInputConfigDialog)
{
postInputConfigDialog->addInt(tr("Classe pour les points sol"), "", 0, 255, _gndClass);
postInputConfigDialog->addDouble(tr("Pente, seuil minimum"), "°", 0, 90, 2, _slopeMin);
postInputConfigDialog->addDouble(tr("Pente, seuil maximum"), "°", 0, 90, 2, _slopeMax);
postInputConfigDialog->addDouble(tr("Rugosité Points, hauteur max"), "m", 0, 99, 2, _roughPtsMaxHeight);
postInputConfigDialog->addDouble(tr("Rugosité Points, rayon"), "m", 0, 99, 2, _roughPtsRadius);
postInputConfigDialog->addDouble(tr("Rugosité Points, seuil minimum"), "", 0, 99, 2, _roughMinPoints);
postInputConfigDialog->addDouble(tr("Rugosité Points, seuil maximum"), "", 0, 99, 2, _roughMaxPoints);
postInputConfigDialog->addDouble(tr("Vivacité arête, seuil minimum"), "", 0, 500, 2, _sobelThMin);
postInputConfigDialog->addDouble(tr("Vivacité arête, seuil maximum"), "", 0, 500, 2, _sobelThMax);
postInputConfigDialog->addDouble(tr("Hauteur CHM, seuil minimum"), "", 0, 99, 2, _chmMin);
postInputConfigDialog->addDouble(tr("Hauteur CHM, seuil maximum"), "", 0, 99, 2, _chmMax);
postInputConfigDialog->addDouble(tr("Densité pts sol, seuil minimum"), "", 0, 99, 2, _gndDensityMinPoints);
postInputConfigDialog->addDouble(tr("Densité pts sol, seuil maximum"), "", 0, 99, 2, _gndDensityMaxPoints);
postInputConfigDialog->addDouble(tr("Densité végétation, seuil"), "pts", 0, 999, 2, _lowVegDensTh);
postInputConfigDialog->addDouble(tr("Densité végétation, Hmin"), "m", 0, 999, 2, _lowVegHmin);
postInputConfigDialog->addDouble(tr("Densité végétation, Hmax"), "m", 0, 999, 2, _lowVegHmax);
postInputConfigDialog->addEmpty();
postInputConfigDialog->addTitle(tr("Poids des composants additifs (-1 pour un composant multiplicatif) :"));
postInputConfigDialog->addDouble(tr("Pente"), "", -1, 10, 2, _slopeAdd);
postInputConfigDialog->addDouble(tr("Rugosité Points"), "", -1, 10, 2, _roughnessAdd);
postInputConfigDialog->addDouble(tr("Arêtes vives"), "", -1, 10, 2, _sobelAdd);
postInputConfigDialog->addDouble(tr("MNH"), "", -1, 10, 2, _chmAdd);
postInputConfigDialog->addDouble(tr("Amplitude d'intensité"), "", -1, 10, 2, _intensityAdd);
postInputConfigDialog->addDouble(tr("Densité de points sol"), "", -1, 10, 2, _gndDensAdd);
postInputConfigDialog->addDouble(tr("Densité de végétation basse"), "", -1, 10, 2, _lowVegAdd);
}
void ONF_StepComputeRoadProbabilityRasters::declareOutputModels(CT_StepOutModelStructureManager& manager)
{
manager.addResultCopy(_inResult);
manager.addItem(_inGroup, _outSlopePourc, tr("Pente (Degrés)"));
manager.addItem(_inGroup, _outRoughnessPoints, tr("Rugosité Points"));
manager.addItem(_inGroup, _outSobel, tr("Arêtes vives"));
manager.addItem(_inGroup, _outCHM, tr("MNH"));
manager.addItem(_inGroup, _outIntensityRange, tr("Amplitude d'intensité"));
manager.addItem(_inGroup, _outGndPtsDensity, tr("Densité de points sol"));
manager.addItem(_inGroup, _outLowVegDensity, tr("Densité de végétation basse"));
manager.addItem(_inGroup, _outSlopePourcConductivity, tr("Conductivité Pente (Degrés)"));
manager.addItem(_inGroup, _outRoughnessPointsConductivity, tr("Conductivité Rugosité Points"));
manager.addItem(_inGroup, _outSobelConductivity, tr("Conductivité Arêtes vives"));
manager.addItem(_inGroup, _outCHMConductivity, tr("Conductivité MNH"));
manager.addItem(_inGroup, _outIntensityRangeConductivity, tr("Conductivité Amplitude d'intensité"));
manager.addItem(_inGroup, _outGndPtsDensityConductivity, tr("Conductivité Densité de points sol"));
manager.addItem(_inGroup, _outLowVegDensityConductivity, tr("Conductivité Densité de végétation basse"));
manager.addItem(_inGroup, _outConductivity, tr("Conductivité"));
}
void ONF_StepComputeRoadProbabilityRasters::compute()
{
for (CT_StandardItemGroup* grp : _inGroup.iterateOutputs(_inResult))
{
const CT_Image2D* dtm = grp->singularItem(_inDTM);
const CT_AbstractItemDrawableWithPointCloud* scene = grp->singularItem(_inScene);
const CT_StdLASPointsAttributesContainer* attributeLAS = grp->singularItem(_inLASAttributes);
const CT_AbstractGeometricalItem *emprise = grp->singularItem(_inArea);
if (isStopped()) {return;}
if (dtm != nullptr && scene != nullptr && attributeLAS != nullptr && scene->pointCloudIndex() != nullptr && emprise != nullptr && scene->pointCloudIndexSize() != 0)
{
Eigen::Vector3d min, max;
emprise->boundingBox(min, max);
double minX = min(0);
double minY = min(1);
double maxX = max(0) - EPSILON;
double maxY = max(1) - EPSILON;
CT_AbstractPointAttributesScalar* attributeIntensity = dynamic_cast(attributeLAS->pointsAttributesAt(CT_LasDefine::Intensity));
CT_AbstractPointAttributesScalar* attributeLineOfFlight = dynamic_cast(attributeLAS->pointsAttributesAt(CT_LasDefine::Point_Source_ID));
CT_AbstractPointAttributesScalar* attributeClassification = dynamic_cast(attributeLAS->pointsAttributesAt(CT_LasDefine::Classification));
CT_Image2D* slopeDeg = new CT_Image2D(dtm->minX(), dtm->minY(), dtm->xdim(), dtm->ydim(), dtm->resolution(), dtm->level(), dtm->NA(), dtm->NA());
CT_Image2D* roughness = new CT_Image2D(dtm->minX(), dtm->minY(), dtm->xdim(), dtm->ydim(), dtm->resolution(), dtm->level(), dtm->NA(), dtm->NA());
CT_Image2D* roughnessPoints = new CT_Image2D(dtm->minX(), dtm->minY(), dtm->xdim(), dtm->ydim(), dtm->resolution(), dtm->level(), dtm->NA(), dtm->NA());
CT_Image2D* sobel = new CT_Image2D(dtm->minX(), dtm->minY(), dtm->xdim(), dtm->ydim(), dtm->resolution(), dtm->level(), dtm->NA(), dtm->NA());
CT_Image2D* chm = new CT_Image2D(dtm->minX(), dtm->minY(), dtm->xdim(), dtm->ydim(), dtm->resolution(), dtm->level(), dtm->NA(), dtm->NA());
CT_Image2D* intensityMin = new CT_Image2D(dtm->minX(), dtm->minY(), dtm->xdim(), dtm->ydim(), dtm->resolution(), dtm->level(), dtm->NA(), dtm->NA());
CT_Image2D* intensityMax = new CT_Image2D(dtm->minX(), dtm->minY(), dtm->xdim(), dtm->ydim(), dtm->resolution(), dtm->level(), dtm->NA(), dtm->NA());
CT_Image2D* intensityRange = new CT_Image2D(dtm->minX(), dtm->minY(), dtm->xdim(), dtm->ydim(), dtm->resolution(), dtm->level(), dtm->NA(), dtm->NA());
CT_Image2D* gndPtsDensity = new CT_Image2D(dtm->minX(), dtm->minY(), dtm->xdim(), dtm->ydim(), dtm->resolution(), dtm->level(), dtm->NA(), dtm->NA());
CT_Image2D* gndPtsDensityTot = new CT_Image2D(dtm->minX(), dtm->minY(), dtm->xdim(), dtm->ydim(), dtm->resolution(), dtm->level(), dtm->NA(), dtm->NA());
CT_Image2D* gndPtsDensityStd = new CT_Image2D(dtm->minX(), dtm->minY(), dtm->xdim(), dtm->ydim(), dtm->resolution(), dtm->level(), dtm->NA(), dtm->NA());
CT_Image2D* gndPtsDensity2 = new CT_Image2D(dtm->minX(), dtm->minY(), dtm->xdim(), dtm->ydim(), dtm->resolution(), dtm->level(), dtm->NA(), dtm->NA());
CT_Image2D* gndPtsDensityStd2 = new CT_Image2D(dtm->minX(), dtm->minY(), dtm->xdim(), dtm->ydim(), dtm->resolution(), dtm->level(), dtm->NA(), dtm->NA());
CT_Image2D* lowVegDensity = new CT_Image2D(dtm->minX(), dtm->minY(), dtm->xdim(), dtm->ydim(), dtm->resolution(), dtm->level(), dtm->NA(), 0);
CT_Image2D* deltaDTM = new CT_Image2D(dtm->minX(), dtm->minY(), dtm->xdim(), dtm->ydim(), dtm->resolution(), dtm->level(), dtm->NA(), dtm->NA());
CT_Image2D* slopeDegClipped = CT_Image2D::createImage2DFromXYCoords(minX, minY, maxX, maxY, dtm->resolution(), dtm->level(), dtm->NA(), dtm->NA());
CT_Image2D* roughnessClippedPoints = new CT_Image2D(slopeDegClipped->minX(), slopeDegClipped->minY(), slopeDegClipped->xdim(), slopeDegClipped->ydim(), slopeDegClipped->resolution(), slopeDegClipped->level(), slopeDegClipped->NA(), slopeDegClipped->NA());
CT_Image2D* sobelClipped = new CT_Image2D(slopeDegClipped->minX(), slopeDegClipped->minY(), slopeDegClipped->xdim(), slopeDegClipped->ydim(), slopeDegClipped->resolution(), slopeDegClipped->level(), slopeDegClipped->NA(), slopeDegClipped->NA());
CT_Image2D* chmClipped = new CT_Image2D(slopeDegClipped->minX(), slopeDegClipped->minY(), slopeDegClipped->xdim(), slopeDegClipped->ydim(), slopeDegClipped->resolution(), slopeDegClipped->level(), slopeDegClipped->NA(), slopeDegClipped->NA());
CT_Image2D* intensityRangeClipped = new CT_Image2D(slopeDegClipped->minX(), slopeDegClipped->minY(), slopeDegClipped->xdim(), slopeDegClipped->ydim(), slopeDegClipped->resolution(), slopeDegClipped->level(), slopeDegClipped->NA(), slopeDegClipped->NA());
CT_Image2D* gndPtsDensityClipped = new CT_Image2D(slopeDegClipped->minX(), slopeDegClipped->minY(), slopeDegClipped->xdim(), slopeDegClipped->ydim(), slopeDegClipped->resolution(), slopeDegClipped->level(), slopeDegClipped->NA(), slopeDegClipped->NA());
CT_Image2D* lowVegDensityClipped = new CT_Image2D(slopeDegClipped->minX(), slopeDegClipped->minY(), slopeDegClipped->xdim(), slopeDegClipped->ydim(), slopeDegClipped->resolution(), slopeDegClipped->level(), slopeDegClipped->NA(), 0);
CT_Image2D* slopeDegCond = new CT_Image2D(slopeDegClipped->minX(), slopeDegClipped->minY(), slopeDegClipped->xdim(), slopeDegClipped->ydim(), slopeDegClipped->resolution(), slopeDegClipped->level(), slopeDegClipped->NA(), slopeDegClipped->NA());
CT_Image2D* roughnessPointsCond = new CT_Image2D(slopeDegClipped->minX(), slopeDegClipped->minY(), slopeDegClipped->xdim(), slopeDegClipped->ydim(), slopeDegClipped->resolution(), slopeDegClipped->level(), slopeDegClipped->NA(), slopeDegClipped->NA());
CT_Image2D* sobelCond = new CT_Image2D(slopeDegClipped->minX(), slopeDegClipped->minY(), slopeDegClipped->xdim(), slopeDegClipped->ydim(), slopeDegClipped->resolution(), slopeDegClipped->level(), slopeDegClipped->NA(), slopeDegClipped->NA());
CT_Image2D* chmCond = new CT_Image2D(slopeDegClipped->minX(), slopeDegClipped->minY(), slopeDegClipped->xdim(), slopeDegClipped->ydim(), slopeDegClipped->resolution(), slopeDegClipped->level(), slopeDegClipped->NA(), slopeDegClipped->NA());
CT_Image2D* intensityRangeCond = new CT_Image2D(slopeDegClipped->minX(), slopeDegClipped->minY(), slopeDegClipped->xdim(), slopeDegClipped->ydim(), slopeDegClipped->resolution(), slopeDegClipped->level(), slopeDegClipped->NA(), slopeDegClipped->NA());
CT_Image2D* gndPtsDensityCond = new CT_Image2D(slopeDegClipped->minX(), slopeDegClipped->minY(), slopeDegClipped->xdim(), slopeDegClipped->ydim(), slopeDegClipped->resolution(), slopeDegClipped->level(), slopeDegClipped->NA(), slopeDegClipped->NA());
CT_Image2D* lowVegDensityCond = new CT_Image2D(slopeDegClipped->minX(), slopeDegClipped->minY(), slopeDegClipped->xdim(), slopeDegClipped->ydim(), slopeDegClipped->resolution(), slopeDegClipped->level(), slopeDegClipped->NA(), slopeDegClipped->NA());
CT_Image2D* conductivity = new CT_Image2D(slopeDegClipped->minX(), slopeDegClipped->minY(), slopeDegClipped->xdim(), slopeDegClipped->ydim(), slopeDegClipped->resolution(), slopeDegClipped->level(), slopeDegClipped->NA(), slopeDegClipped->NA());
grp->addSingularItem(_outSlopePourc, slopeDegClipped);
grp->addSingularItem(_outRoughnessPoints, roughnessClippedPoints);
grp->addSingularItem(_outSobel, sobelClipped);
grp->addSingularItem(_outCHM, chmClipped);
grp->addSingularItem(_outIntensityRange, intensityRangeClipped);
grp->addSingularItem(_outGndPtsDensity, gndPtsDensityClipped);
grp->addSingularItem(_outLowVegDensity, lowVegDensityClipped);
grp->addSingularItem(_outSlopePourcConductivity, slopeDegCond);
grp->addSingularItem(_outRoughnessPointsConductivity, roughnessPointsCond);
grp->addSingularItem(_outSobelConductivity, sobelCond);
grp->addSingularItem(_outCHMConductivity, chmCond);
grp->addSingularItem(_outIntensityRangeConductivity, intensityRangeCond);
grp->addSingularItem(_outGndPtsDensityConductivity, gndPtsDensityCond);
grp->addSingularItem(_outLowVegDensityConductivity, lowVegDensityCond);
grp->addSingularItem(_outConductivity, conductivity);
std::vector > linesOfFlight(dtm->nCells());
float surfacePixel = dtm->resolution() * dtm->resolution();
const CT_AbstractPointCloudIndex* pointCloudIndex = scene->pointCloudIndex();
QMap* > intensityByLine;
QMap nByLine;
QList intensities;
CT_PointIterator itP0(pointCloudIndex);
while(itP0.hasNext())
{
size_t index = itP0.next().currentGlobalIndex();
bool hasBeenSet, hasBeenSet2;
double intensity = attributeIntensity->scalarAsDoubleAt(index, &hasBeenSet);
quint16 lineOfFlight = quint16(attributeLineOfFlight->scalarAsDoubleAt(index, &hasBeenSet2));
if (hasBeenSet && hasBeenSet2)
{
if (!intensityByLine.contains(lineOfFlight))
{
intensityByLine.insert(lineOfFlight, new QList());
}
QList *list = intensityByLine.value(lineOfFlight);
list->append(intensity);
nByLine.insert(lineOfFlight, nByLine.value(lineOfFlight, 0) + 1);
intensities.append(intensity);
}
}
setProgress(10.0);
double intensityThreshold = computePercentile(intensities, 0.98);
QMap intensityByLineMedian;
QMapIterator* > it(intensityByLine);
int maxN = 0;
double maxI = 0;
while (it.hasNext())
{
it.next();
QList* list = it.value();
double median = computePercentile(*list, 0.5);
intensityByLineMedian.insert(it.key(), median);
int n = nByLine.value(it.key());
if (n > maxN)
{
maxN = n;
maxI = median;
}
delete list;
}
if (maxI == 0) {maxI = 1;}
setProgress(20.0);
CT_Image2D_Points* optiGrid2D = new CT_Image2D_Points(dtm->minX(), dtm->minY(), dtm->xdim(), dtm->ydim(), dtm->resolution());
CT_PointIterator itP(pointCloudIndex);
while(itP.hasNext())
{
size_t index = itP.next().currentGlobalIndex();
const CT_Point& point = itP.currentPoint();
float dtmVal = dtm->valueAtCoords(point(0), point(1));
if (!qFuzzyCompare(dtmVal, dtm->NA()))
{
float h = point(2) - dtmVal;
chm->setMaxValueAtCoords(point(0), point(1), h);
if (h < _roughPtsMaxHeight) {optiGrid2D->addPoint(index);}
bool hasBeenSet = false;
bool hasBeenSet2 = false;
double intensity = attributeIntensity->scalarAsDoubleAt(index, &hasBeenSet);
if (intensity > intensityThreshold) {intensity = intensityThreshold;}
quint16 lineOfFlight = quint16(attributeLineOfFlight->scalarAsDoubleAt(index, &hasBeenSet2));
if (hasBeenSet && hasBeenSet2)
{
intensity = intensity / (intensityByLineMedian.value(lineOfFlight, 1) / maxI);
if (h < 1.0)
{
intensityMin->setMinValueAtCoords(point(0), point(1), intensity);
intensityMax->setMaxValueAtCoords(point(0), point(1), intensity);
}
}
quint8 classification = quint8(attributeClassification->scalarAsDoubleAt(index, &hasBeenSet));
if (hasBeenSet)
{
if (classification == _gndClass)
{
gndPtsDensity->addValueAtCoords(point(0), point(1), 1);
quint16 lineOfFlight = quint16(attributeLineOfFlight->scalarAsDoubleAt(index, &hasBeenSet));
if (hasBeenSet)
{
size_t cellIndex;
gndPtsDensity->indexAtCoords(point(0), point(1), cellIndex);
linesOfFlight[cellIndex].append(lineOfFlight);
}
}
}
gndPtsDensityTot->addValueAtCoords(point(0), point(1), 1);
if (h > _lowVegHmin && h < _lowVegHmax)
{
lowVegDensity->addValueAtCoords(point(0), point(1), 1);
}
}
}
setProgress(40.0);
for (int xx = 0 ; xx < dtm->xdim() ; xx++)
{
for (int yy = 0 ; yy < dtm->ydim() ; yy++)
{
computeNeighbourhood(dtm, xx, yy);
if (!qFuzzyCompare(_e, dtm->NA()))
{
slopeDeg->setValue(xx, yy, computeSlope(dtm));
//sobel->setValue(xx, yy, computeSobel(dtm));
deltaDTM->setValue(xx, yy, _e - smooth5x5(dtm, xx, yy));
if (qFuzzyCompare(chm->value(xx, yy), chm->NA()))
{
chm->setValue(xx, yy, 0);
}
double imin = intensityMin->value(xx, yy);
double imax = intensityMax->value(xx, yy);
if (!qFuzzyCompare(imin, intensityMin->NA()) && !qFuzzyCompare(imax, intensityMax->NA()))
{
//intensityRange->setValue(xx, yy, imax);
intensityRange->setValue(xx, yy, imax - imin);
}
if (qFuzzyCompare(intensityRange->value(xx, yy), intensityRange->NA()))
{
intensityRange->setValue(xx, yy, 0);
}
if (qFuzzyCompare(gndPtsDensity->value(xx, yy), gndPtsDensity->NA()))
{
gndPtsDensity->setValue(xx, yy, 0);
gndPtsDensityStd->setValue(xx, yy, 0);
} else {
float val = gndPtsDensity->value(xx, yy) / surfacePixel;
float valTot = gndPtsDensityTot->value(xx, yy);
if (valTot > 0)
{
gndPtsDensityStd->setValue(xx, yy, gndPtsDensity->value(xx, yy) / valTot);
} else {
gndPtsDensityStd->setValue(xx, yy, 0);
}
gndPtsDensity->setValue(xx, yy, val);
// gndPtsDensityStd->setValue(xx, yy, val);
size_t cellIndex;
gndPtsDensity->index(xx, yy, cellIndex);
QList &list = linesOfFlight[cellIndex];
std::sort(list.begin(), list.end());
int nLineOfFlight = std::unique(list.begin(), list.end()) - list.begin();
// if (nLineOfFlight > 1)
// {
// gndPtsDensityStd->setValue(xx, yy, gndPtsDensityStd->value(xx, yy) / nLineOfFlight);
// }
}
if (qFuzzyCompare(lowVegDensity->value(xx, yy), lowVegDensity->NA()))
{
lowVegDensity->setValue(xx, yy, 0);
}
Eigen::Vector3d center;
dtm->getCellCenterCoordinates(xx, yy, center);
QList neighboursIndices;
if (optiGrid2D->getPointsInCircle(center, _roughPtsRadius, neighboursIndices) < 3)
{
roughnessPoints->setValue(xx, yy, 0);
} else {
CT_PointAccessor pointAccessor;
QList neighboursIndicesCoords;
for (int neigh = 0 ; neigh < neighboursIndices.size() ; neigh++)
{
neighboursIndicesCoords.append(pointAccessor.constPointAt(neighboursIndices.at(neigh)));
}
size_t cellIndex;
optiGrid2D->index(xx, yy, cellIndex);
const QList* neighboursIndices2 = optiGrid2D->getConstPointIndexList(cellIndex);
QList neighboursIndices2Coords;
for (int neigh = 0 ; neigh < neighboursIndices2->size() ; neigh++)
{
neighboursIndices2Coords.append(pointAccessor.constPointAt(neighboursIndices2->at(neigh)));
}
Eigen::Vector3d direction;
Eigen::Vector3d centroid;
if (CT_MathPoint::fitPlaneFromPoints(neighboursIndicesCoords, direction, centroid))
{
double sumDist2 = 0;
int npts = neighboursIndices2Coords.size();
for (int neigh = 0 ; neigh < neighboursIndices2Coords.size() ; neigh++)
{
const Eigen::Vector3d& pt = neighboursIndices2Coords.at(neigh);
double dist = CT_MathPoint::distancePointPlane(pt, direction, centroid);
sumDist2 += dist*dist / npts;
}
roughnessPoints->setValue(xx, yy, sqrt(sumDist2));
} else {
roughnessPoints->setValue(xx, yy, 0);
}
}
}
}
}
setProgress(60.0);
for (int xx = 0 ; xx < slopeDeg->xdim() ; xx++)
{
for (int yy = 0 ; yy < slopeDeg->ydim() ; yy++)
{
computeNeighbourhood(slopeDeg, xx, yy);
if (!qFuzzyCompare(_e, slopeDeg->NA()))
{
sobel->setValue(xx, yy, computeSobel(slopeDeg));
}
}
}
setProgress(65.0);
for (int xx = 0 ; xx < gndPtsDensity->xdim() ; xx++)
{
for (int yy = 0 ; yy < gndPtsDensity->ydim() ; yy++)
{
computeNeighbourhood(gndPtsDensity, xx, yy);
if (!qFuzzyCompare(_e, gndPtsDensity->NA()))
{
gndPtsDensity2->setValue(xx, yy, smooth(gndPtsDensity));
}
}
}
setProgress(70.0);
for (int xx = 0 ; xx < gndPtsDensityStd->xdim() ; xx++)
{
for (int yy = 0 ; yy < gndPtsDensityStd->ydim() ; yy++)
{
computeNeighbourhood(gndPtsDensityStd, xx, yy);
if (!qFuzzyCompare(_e, gndPtsDensityStd->NA()))
{
gndPtsDensityStd2->setValue(xx, yy, smooth(gndPtsDensityStd));
}
}
}
setProgress(75.0);
for (int xx = 0 ; xx < deltaDTM->xdim() ; xx++)
{
for (int yy = 0 ; yy < deltaDTM->ydim() ; yy++)
{
computeNeighbourhood(deltaDTM, xx, yy);
if (!qFuzzyCompare(_e, deltaDTM->NA()))
{
roughness->setValue(xx, yy, computeRoughness(deltaDTM));
}
}
}
setProgress(80.0);
// clip rasters
for (int xx = 0 ; xx < slopeDegClipped->xdim() ; xx++)
{
for (int yy = 0 ; yy < slopeDegClipped->ydim() ; yy++)
{
Eigen::Vector3d center;
slopeDegClipped->getCellCenterCoordinates(xx, yy, center);
slopeDegClipped->setValue(xx, yy, slopeDeg->valueAtCoords(center(0), center(1)));
roughnessClippedPoints->setValue(xx, yy, roughnessPoints->valueAtCoords(center(0), center(1)));
sobelClipped->setValue(xx, yy, sobel->valueAtCoords(center(0), center(1)));
chmClipped->setValue(xx, yy, chm->valueAtCoords(center(0), center(1)));
intensityRangeClipped->setValue(xx, yy, intensityRange->valueAtCoords(center(0), center(1)));
gndPtsDensityClipped->setValue(xx, yy, gndPtsDensityStd->valueAtCoords(center(0), center(1)));
lowVegDensityClipped->setValue(xx, yy, lowVegDensity->valueAtCoords(center(0), center(1)));
}
}
slopeDegClipped->computeMinMax();
roughnessClippedPoints->computeMinMax();
sobelClipped->computeMinMax();
chmClipped->computeMinMax();
intensityRangeClipped->computeMinMax();
gndPtsDensityClipped->computeMinMax();
lowVegDensityClipped->computeMinMax();
// remove useless rasters
delete slopeDeg;
delete roughness;
delete roughnessPoints;
delete sobel;
delete chm;
delete intensityMin;
delete intensityMax;
delete intensityRange;
delete gndPtsDensity;
delete gndPtsDensityTot;
delete gndPtsDensityStd;
delete gndPtsDensity2;
delete gndPtsDensityStd2;
delete lowVegDensity;
delete deltaDTM;
delete optiGrid2D;
setProgress(90.0);
// Conductivités
QList intensityQuant;
QList densityQuant;
for (int xx = 0 ; xx < slopeDegClipped->xdim() ; xx++)
{
for (int yy = 0 ; yy < slopeDegClipped->ydim() ; yy++)
{
if (!qFuzzyCompare(slopeDegClipped->value(xx, yy), slopeDegClipped->NA()))
{
float intensityVal = intensityRangeClipped->value(xx, yy);
if (intensityVal > 0)
{
intensityQuant.append(intensityVal);
}
float dens = gndPtsDensityClipped->value(xx, yy);
if (dens > 0)
{
densityQuant.append(dens);
}
}
}
}
float percI1 = computePercentile(intensityQuant, 0.10);
float percI2 = computePercentile(intensityQuant, 0.50);
// float percD1 = computePercentile(densityQuant, 0.25);
// float percD2 = computePercentile(densityQuant, 0.90);
for (int xx = 0 ; xx < slopeDegClipped->xdim() ; xx++)
{
for (int yy = 0 ; yy < slopeDegClipped->ydim() ; yy++)
{
if (qFuzzyCompare(slopeDegClipped->value(xx, yy), slopeDegClipped->NA()))
{
slopeDegCond->setValue(xx, yy, 0.0);
roughnessPointsCond->setValue(xx, yy, 0.0);
sobelCond->setValue(xx, yy, 0.0);
chmCond->setValue(xx, yy, 0.0);
intensityRangeCond->setValue(xx, yy, 0.0);
gndPtsDensityCond->setValue(xx, yy, 0.0);
lowVegDensityCond->setValue(xx, yy, 0.0);
} else {
slopeDegCond->setValue(xx, yy, activationPiecewiseLinear(slopeDegClipped->value(xx, yy), _slopeMin, _slopeMax, 0, 1, false));
roughnessPointsCond->setValue(xx, yy, activationPiecewiseLinear(roughnessClippedPoints->value(xx, yy), _roughMinPoints, _roughMaxPoints, 0, 1, false));
sobelCond->setValue(xx, yy, activationPiecewiseLinear(sobelClipped->value(xx, yy), _sobelThMin, _sobelThMax, 0, 1, false));
chmCond->setValue(xx, yy, activationPiecewiseLinear(chmClipped->value(xx, yy), _chmMin, _chmMax, 0, 1, false));
intensityRangeCond->setValue(xx, yy, activationPiecewiseLinear(intensityRangeClipped->value(xx, yy), percI1, percI2, 0, 1, false));
gndPtsDensityCond->setValue(xx, yy, activationPiecewiseLinear(gndPtsDensityClipped->value(xx, yy), _gndDensityMinPoints, _gndDensityMaxPoints, 0.5, 1, true));
lowVegDensityCond->setValue(xx, yy, activationThresholds(lowVegDensityClipped->value(xx, yy), _lowVegDensTh));
}
}
}
for (int xx = 0 ; xx < slopeDegClipped->xdim() ; xx++)
{
for (int yy = 0 ; yy < slopeDegClipped->ydim() ; yy++)
{
computeNeighbourhood(slopeDegClipped, xx, yy);
if (!qFuzzyCompare(_e, slopeDegClipped->NA()))
{
float condSlope = slopeDegCond->value(xx, yy);
float condRoughness = roughnessPointsCond->value(xx, yy);
float condSobel = sobelCond->value(xx, yy);
float condCHM = chmCond->value(xx, yy);
float condIntensity = intensityRangeCond->value(xx, yy);
float condGNDDensity = gndPtsDensityCond->value(xx, yy);
float condLowVeg = lowVegDensityCond->value(xx, yy);
float cond = 1.0;
float sum = 0.0;
float weight = 0.0;
if (qFuzzyCompare(_slopeAdd, -1.0)) {cond *= condSlope;} else {sum += _slopeAdd*condSlope; weight += _slopeAdd;}
if (qFuzzyCompare(_roughnessAdd, -1.0)) {cond *= condRoughness;} else {sum += _roughnessAdd*condRoughness; weight += _roughnessAdd;}
if (qFuzzyCompare(_sobelAdd, -1.0)) {cond *= condSobel;} else {sum += _sobelAdd*condSobel; weight += _sobelAdd;}
if (qFuzzyCompare(_chmAdd, -1.0)) {cond *= condCHM;} else {sum += _chmAdd*condCHM; weight += _chmAdd;}
if (qFuzzyCompare(_intensityAdd, -1.0)) {cond *= condIntensity;} else {sum += _intensityAdd*condIntensity; weight += _intensityAdd;}
if (qFuzzyCompare(_gndDensAdd, -1.0)) {cond *= condGNDDensity;} else {sum += _gndDensAdd*condGNDDensity; weight += _gndDensAdd;}
if (qFuzzyCompare(_lowVegAdd, -1.0)) {cond *= condLowVeg;} else {sum += _lowVegAdd*condLowVeg; weight += _lowVegAdd;}
if (weight > 0)
{
cond *= sum / weight;
}
if (cond < 0.1f) {cond = 0.1f;}
conductivity->setValue(xx, yy, cond);
}
}
}
slopeDegCond->computeMinMax();
roughnessPointsCond->computeMinMax();
sobelCond->computeMinMax();
chmCond->computeMinMax();
intensityRangeCond->computeMinMax();
gndPtsDensityCond->computeMinMax();
lowVegDensityCond->computeMinMax();
conductivity->computeMinMax();
}
}
}
void ONF_StepComputeRoadProbabilityRasters::computeNeighbourhood(const CT_Image2D* dtm, int xx, int yy)
{
_a = dtm->value(xx - 1, yy - 1);
_b = dtm->value(xx , yy - 1);
_c = dtm->value(xx + 1, yy - 1);
_d = dtm->value(xx - 1, yy );
_e = dtm->value(xx , yy );
_f = dtm->value(xx + 1, yy );
_g = dtm->value(xx - 1, yy + 1);
_h = dtm->value(xx , yy + 1);
_i = dtm->value(xx + 1, yy + 1);
}
float ONF_StepComputeRoadProbabilityRasters::computeSlope(const CT_Image2D* dtm) const
{
float aa = _a;
float bb = _b;
float cc = _c;
float dd = _d;
float ff = _f;
float gg = _g;
float hh = _h;
float ii = _i;
if (qFuzzyCompare(aa, dtm->NA())) {aa = _e;}
if (qFuzzyCompare(bb, dtm->NA())) {bb = _e;}
if (qFuzzyCompare(cc, dtm->NA())) {cc = _e;}
if (qFuzzyCompare(dd, dtm->NA())) {dd = _e;}
if (qFuzzyCompare(ff, dtm->NA())) {ff = _e;}
if (qFuzzyCompare(gg, dtm->NA())) {gg = _e;}
if (qFuzzyCompare(hh, dtm->NA())) {hh = _e;}
if (qFuzzyCompare(ii, dtm->NA())) {ii = _e;}
float dzdx = ((cc + 2.0f*ff + ii) - (aa + 2.0f*dd + gg)) / (8.0f * float(dtm->resolution()));
float dzdy = ((gg + 2.0f*hh + ii) - (aa + 2.0f*bb + cc)) / (8.0f * float(dtm->resolution()));
double slope_radians = std::atan(std::sqrt(double(dzdx)*double(dzdx) + double(dzdy)*double(dzdy)));
return slope_radians * 180.0 / M_PI;
}
float ONF_StepComputeRoadProbabilityRasters::computeRoughness(const CT_Image2D* dtm) const
{
float min = _e;
float max = _e;
if (!qFuzzyCompare(_a, dtm->NA()))
{
if (_a < min) {min = _a;}
if (_a > max) {max = _a;}
}
if (!qFuzzyCompare(_b, dtm->NA()))
{
if (_b < min) {min = _b;}
if (_b > max) {max = _b;}
}
if (!qFuzzyCompare(_c, dtm->NA()))
{
if (_c < min) {min = _c;}
if (_c > max) {max = _c;}
}
if (!qFuzzyCompare(_d, dtm->NA()))
{
if (_d < min) {min = _d;}
if (_d > max) {max = _d;}
}
if (!qFuzzyCompare(_f, dtm->NA()))
{
if (_f < min) {min = _f;}
if (_f > max) {max = _f;}
}
if (!qFuzzyCompare(_g, dtm->NA()))
{
if (_g < min) {min = _g;}
if (_g > max) {max = _g;}
}
if (!qFuzzyCompare(_h, dtm->NA()))
{
if (_h < min) {min = _h;}
if (_h > max) {max = _h;}
}
if (!qFuzzyCompare(_i, dtm->NA()))
{
if (_i < min) {min = _i;}
if (_i > max) {max = _i;}
}
return max - min;
}
float ONF_StepComputeRoadProbabilityRasters::computeSobel(const CT_Image2D* raster) const
{
float fx = 0;
float fy = 0;
if (!qFuzzyCompare(_a, raster->NA())) {fx += 1*_a; fy += -1*_a;}
if (!qFuzzyCompare(_b, raster->NA())) {fx += 2*_b; }
if (!qFuzzyCompare(_c, raster->NA())) {fx += 1*_c; fy += 1*_c;}
if (!qFuzzyCompare(_d, raster->NA())) { fy += -2*_d;}
if (!qFuzzyCompare(_f, raster->NA())) { fy += 2*_f;}
if (!qFuzzyCompare(_g, raster->NA())) {fx += -1*_g; fy += -1*_g;}
if (!qFuzzyCompare(_h, raster->NA())) {fx += -2*_h; }
if (!qFuzzyCompare(_i, raster->NA())) {fx += -1*_i; fy += 1*_i;}
return sqrt(fx*fx + fy*fy);
}
float ONF_StepComputeRoadProbabilityRasters::smooth(const CT_Image2D* raster) const
{
float mean = 0;
float nb = 0;
if (!qFuzzyCompare(_a, raster->NA())) {mean += _a; nb++;}
if (!qFuzzyCompare(_b, raster->NA())) {mean += _b; nb++;}
if (!qFuzzyCompare(_c, raster->NA())) {mean += _c; nb++;}
if (!qFuzzyCompare(_d, raster->NA())) {mean += _d; nb++;}
if (!qFuzzyCompare(_e, raster->NA())) {mean += 2*_e; nb += 2;}
if (!qFuzzyCompare(_f, raster->NA())) {mean += _f; nb++;}
if (!qFuzzyCompare(_g, raster->NA())) {mean += _g; nb++;}
if (!qFuzzyCompare(_h, raster->NA())) {mean += _h; nb++;}
if (!qFuzzyCompare(_i, raster->NA())) {mean += _i; nb++;}
if (nb > 0)
{
mean /= nb;
}
return mean;
}
float ONF_StepComputeRoadProbabilityRasters::smooth5x5(const CT_Image2D* raster, int xx, int yy) const
{
float mean = 0;
float nb = 0;
float val = raster->value(xx - 2, yy - 2);
if (!qFuzzyCompare(val, raster->NA())) {mean += val; nb++;}
val = raster->value(xx - 1, yy - 2);
if (!qFuzzyCompare(val, raster->NA())) {mean += val; nb++;}
val = raster->value(xx, yy - 2);
if (!qFuzzyCompare(val, raster->NA())) {mean += val; nb++;}
val = raster->value(xx + 1, yy - 2);
if (!qFuzzyCompare(val, raster->NA())) {mean += val; nb++;}
val = raster->value(xx + 2, yy - 2);
if (!qFuzzyCompare(val, raster->NA())) {mean += val; nb++;}
val = raster->value(xx - 2, yy - 1);
if (!qFuzzyCompare(val, raster->NA())) {mean += val; nb++;}
val = raster->value(xx - 1, yy - 1);
if (!qFuzzyCompare(val, raster->NA())) {mean += val; nb++;}
val = raster->value(xx, yy - 1);
if (!qFuzzyCompare(val, raster->NA())) {mean += val; nb++;}
val = raster->value(xx + 1, yy - 1);
if (!qFuzzyCompare(val, raster->NA())) {mean += val; nb++;}
val = raster->value(xx + 2, yy - 1);
if (!qFuzzyCompare(val, raster->NA())) {mean += val; nb++;}
val = raster->value(xx - 2, yy);
if (!qFuzzyCompare(val, raster->NA())) {mean += val; nb++;}
val = raster->value(xx - 1, yy);
if (!qFuzzyCompare(val, raster->NA())) {mean += val; nb++;}
val = raster->value(xx, yy);
if (!qFuzzyCompare(val, raster->NA())) {mean += val; nb++;}
val = raster->value(xx + 1, yy);
if (!qFuzzyCompare(val, raster->NA())) {mean += val; nb++;}
val = raster->value(xx + 2, yy);
if (!qFuzzyCompare(val, raster->NA())) {mean += val; nb++;}
val = raster->value(xx - 2, yy + 1);
if (!qFuzzyCompare(val, raster->NA())) {mean += val; nb++;}
val = raster->value(xx - 1, yy + 1);
if (!qFuzzyCompare(val, raster->NA())) {mean += val; nb++;}
val = raster->value(xx, yy + 1);
if (!qFuzzyCompare(val, raster->NA())) {mean += val; nb++;}
val = raster->value(xx + 1, yy + 1);
if (!qFuzzyCompare(val, raster->NA())) {mean += val; nb++;}
val = raster->value(xx + 2, yy + 1);
if (!qFuzzyCompare(val, raster->NA())) {mean += val; nb++;}
val = raster->value(xx - 2, yy + 2);
if (!qFuzzyCompare(val, raster->NA())) {mean += val; nb++;}
val = raster->value(xx - 1, yy + 2);
if (!qFuzzyCompare(val, raster->NA())) {mean += val; nb++;}
val = raster->value(xx, yy + 2);
if (!qFuzzyCompare(val, raster->NA())) {mean += val; nb++;}
val = raster->value(xx + 1, yy + 2);
if (!qFuzzyCompare(val, raster->NA())) {mean += val; nb++;}
val = raster->value(xx + 2, yy + 2);
if (!qFuzzyCompare(val, raster->NA())) {mean += val; nb++;}
if (nb > 0)
{
mean /= nb;
}
return mean;
}
double ONF_StepComputeRoadProbabilityRasters::computePercentile(QList &array, const double &p)
{
std::sort(array.begin(), array.end());
int arraySize = array.size();
// Second Variant, show wikipedia "Percentile"
double v = ((double)(arraySize-1)) * p;
int ip1 = (int)v;
double f = (v-ip1); // (arraySize-1)*p = ip1+f
int ip2 = ip1 + 1;
if(ip2 == arraySize)
return array[ip1];
if(f == 0)
return array[ip1];
return array[ip1] + (f * (array[ip2] - array[ip1]));
}
float ONF_StepComputeRoadProbabilityRasters::activationPiecewiseLinear(float x, float th1, float th2, float minValue, float maxValue, bool ascending)
{
float y = 0;
if (x <= th1)
{
if (ascending)
{
y = minValue;
} else {
y = maxValue;
}
} else if (x >= th2)
{
if (ascending)
{
y = maxValue;
} else {
y = minValue;
}
} else {
float a = (maxValue - minValue) / (th2 - th1);
if (ascending)
{
y = a*(x - th1) + minValue;
} else {
y = a*(th2 - x) + minValue;
}
}
return std::round(y * 1000.0) / 1000.0;
}
float ONF_StepComputeRoadProbabilityRasters::activationThresholds(float x, float th)
{
if (x >= th) {return 0;}
return 1;
}