#include "onf_stepcomputepointheightfromtin.h"
ONF_StepComputePointHeightFromTIN::ONF_StepComputePointHeightFromTIN() : SuperClass()
{
_ptsAttribute = false;
_ptsCloud = true;
_addLAS = false;
}
QString ONF_StepComputePointHeightFromTIN::description() const
{
return tr("Calculer la hauteur des points à l'aide d'un TIN");
}
QString ONF_StepComputePointHeightFromTIN::detailledDescription() const
{
return tr("Cette étape soustrait à l'altitude des points la coordonnée du TIN."
"En sortie, elle peut (options) générer :
"
"- Un attribut de hauteur sur le nuage d'altitudes
"
"- Un nuage de point
"
"- Recopier les attributs LAS (dans le cas de la création d'un nouveau nuage)");
}
QString ONF_StepComputePointHeightFromTIN::inputDescription() const
{
return SuperClass::inputDescription() + tr("
");
}
QString ONF_StepComputePointHeightFromTIN::outputDescription() const
{
return SuperClass::outputDescription() + tr("
");
}
QString ONF_StepComputePointHeightFromTIN::detailsDescription() const
{
return tr("");
}
CT_VirtualAbstractStep* ONF_StepComputePointHeightFromTIN::createNewInstance() const
{
return new ONF_StepComputePointHeightFromTIN();
}
//////////////////// PROTECTED METHODS //////////////////
void ONF_StepComputePointHeightFromTIN::declareInputModels(CT_StepInModelStructureManager& manager)
{
manager.addResult(_inResult, tr("Scene(s)"));
manager.setZeroOrMoreRootGroup(_inResult, _inZeroOrMoreRootGroup);
manager.addGroup(_inZeroOrMoreRootGroup, _inGroup);
manager.addItem(_inGroup, _inScene, tr("Scene(s)"));
if (_addLAS)
manager.addItem(_inGroup, _inLAS, tr("Attributs LAS"));
manager.addResult(_inResultTIN, tr("TIN"), "", true);
manager.setZeroOrMoreRootGroup(_inResultTIN, _inZeroOrMoreRootGroupTIN);
manager.addGroup(_inZeroOrMoreRootGroupTIN, _inGroupTIN);
manager.addItem(_inGroupTIN, _inTIN, tr("TIN"));
}
void ONF_StepComputePointHeightFromTIN::declareOutputModels(CT_StepOutModelStructureManager& manager)
{
manager.addResultCopy(_inResult);
if (_ptsAttribute)
manager.addPointAttribute(_inGroup, _outHeightAtt, tr("Attribut Hauteur"));
if (_ptsCloud)
manager.addItem(_inGroup, _outScene, tr("Scene H"));
}
void ONF_StepComputePointHeightFromTIN::fillPreInputConfigurationDialog(CT_StepConfigurableDialog* preInputConfigDialog)
{
preInputConfigDialog->addBool(tr("Créer des attributs de points hauteur"), "", "", _ptsAttribute);
preInputConfigDialog->addEmpty();
preInputConfigDialog->addBool(tr("Créer un nuage de points hauteur"), "", "", _ptsCloud);
preInputConfigDialog->addBool(tr("Transférer les attributs las au nuage de points hauteur"), "", "", _addLAS);
}
void ONF_StepComputePointHeightFromTIN::compute()
{
const CT_Triangulation2D* tin = _inTIN.firstInput(_inResultTIN);
if ((tin == nullptr) || (!_ptsAttribute && !_ptsCloud))
return;
auto iterator = _inScene.iterateOutputs(_inResult);
auto it = iterator.begin();
auto end = iterator.end();
while(it != end)
{
const CT_AbstractItemDrawableWithPointCloud* inputScene = *it;
CT_StandardItemGroup* grp = it.currentParent();
if (isStopped())
return;
const CT_AbstractPointCloudIndex *inputPointCloudIndex = inputScene->pointCloudIndex();
const size_t n_points = inputPointCloudIndex->size();
CT_PointIterator itP(inputPointCloudIndex);
CT_NMPCIR outputHeightCloud;
if (_ptsCloud) {outputHeightCloud = PS_REPOSITORY->createNewPointCloud(n_points);}
CT_MutablePointIterator itPM(outputHeightCloud);
// On declare un tableau d'attributs double que l'on va remplir avec les coordonnées correspondant a l'axe demandé
HeightAttManager::SetterPtr attributeSetter = nullptr;
if (_ptsAttribute) {attributeSetter = _outHeightAtt.createAttributesSetterPtr(outputHeightCloud);}
float minAttribute = std::numeric_limits::max();
float maxAttribute = -std::numeric_limits::max();
size_t i = 0;
CT_DelaunayTriangulation *triangulation = tin->getDelaunayT();
double zTin = 0;
CT_DelaunayTriangle* refTri = nullptr;
// On applique la translation a tous les points du nuage
while (itP.hasNext() && !isStopped())
{
CT_Point point = itP.next().currentPoint();
refTri = const_cast(triangulation->getZCoordForXY(point(0), point(1), zTin, refTri));
float h = float(point(2));
if (!std::isnan(zTin))
{
h -= float(zTin);
} else {
h = 0;
}
if (_ptsAttribute)
{
attributeSetter->setValueWithGlobalIndex(itP.currentGlobalIndex(), h);
if (h < minAttribute) {minAttribute = h;}
if (h > maxAttribute) {maxAttribute = h;}
}
if (_ptsCloud)
{
point.setZ(double(h));
itPM.next().replaceCurrentPoint(point);
}
setProgress(float(100.0*i++ / n_points));
}
if (i > 0)
{
if (_ptsAttribute)
{
CT_PointsAttributesScalarTemplated* outAttribute = _outHeightAtt.createAttributeInstance(inputScene->pointCloudIndexRegistered(), minAttribute, maxAttribute);
grp->addSingularItem(_outHeightAtt, outAttribute);
}
if (_ptsCloud)
{
CT_Scene* outputHeightScene = new CT_Scene(outputHeightCloud);
outputHeightScene->updateBoundingBox();
grp->addSingularItem(_outScene, outputHeightScene);
// Copie des attributs LAS pour les lier au nuage de point d'hauteur
if (_addLAS)
{
const CT_StdLASPointsAttributesContainer* attributeLAS = grp->singularItem(_inLAS);
if (attributeLAS != nullptr)
{
// Retrieve attributes
QHashIterator itLAS(attributeLAS->lasPointsAttributes());
while(itLAS.hasNext())
{
CT_AbstractPointAttributesScalar* v = itLAS.next().value();
if(v != nullptr)
v->copyAttributesOfSForD(inputScene->pointCloudIndexRegistered(), outputHeightScene->pointCloudIndexRegistered());
}
}
}
}
}
++it;
}
}