#include "onf_stepcomputescandirection.h"
#include "ct_log/ct_logmanager.h"
ONF_StepComputeScanDirection::ONF_StepComputeScanDirection() : SuperClass()
{
}
QString ONF_StepComputeScanDirection::description() const
{
return tr("Calcule les directions de scan (ALS)");
}
QString ONF_StepComputeScanDirection::detailledDescription() const
{
return tr("Utilise la trajectographie du vol Lidar pour recalculer une direction de tir pour chaque point du nuage. ");
}
QString ONF_StepComputeScanDirection::inputDescription() const
{
return SuperClass::inputDescription() + tr("
");
}
QString ONF_StepComputeScanDirection::outputDescription() const
{
return SuperClass::outputDescription() + tr("
");
}
QString ONF_StepComputeScanDirection::detailsDescription() const
{
return tr("");
}
CT_VirtualAbstractStep* ONF_StepComputeScanDirection::createNewInstance() const
{
return new ONF_StepComputeScanDirection();
}
//////////////////// PROTECTED METHODS //////////////////
void ONF_StepComputeScanDirection::declareInputModels(CT_StepInModelStructureManager& manager)
{
manager.addResult(_inResult, tr("Scene(s)"));
manager.setZeroOrMoreRootGroup(_inResult, _inZeroOrMoreRootGroup);
manager.addGroup(_inZeroOrMoreRootGroup, _inGroup);
manager.addItem(_inGroup, _inScene, tr("Scène"));
manager.addItem(_inGroup, _inLAS, tr("Attributs LAS"));
manager.addResult(_inResultTraj, tr("Trajectory"), "", true);
manager.setZeroOrMoreRootGroup(_inResultTraj, _inZeroOrMoreRootGroupTraj);
manager.addGroup(_inZeroOrMoreRootGroupTraj, _inGroupTraj);
manager.addItem(_inGroupTraj, _inTraj, tr("Trajectory"));
}
void ONF_StepComputeScanDirection::declareOutputModels(CT_StepOutModelStructureManager& manager)
{
manager.addResultCopy(_inResult);
manager.addPointAttribute(_inGroup, _outDir, tr("Scan direction"));
}
void ONF_StepComputeScanDirection::compute()
{
QList trajectories;
for (const CT_ScanPath* traj : _inTraj.iterateInputs(_inResultTraj))
{
trajectories.append(const_cast(traj));
}
if (trajectories.isEmpty())
return;
auto iterator = _inScene.iterateOutputs(_inResult);
auto it = iterator.begin();
auto end = iterator.end();
while(it != end)
{
const CT_AbstractItemDrawableWithPointCloud* scene = *it;
CT_StandardItemGroup* grp = it.currentParent();
CT_AbstractPointAttributesScalar* attributeGPS = nullptr;
for(const CT_StdLASPointsAttributesContainer* attributeLAS : grp->singularItems(_inLAS))
{
attributeGPS = dynamic_cast(attributeLAS->pointsAttributesAt(CT_LasDefine::GPS_Time));
if (attributeGPS != nullptr)
break;
}
if (isStopped())
return;
if (attributeGPS != nullptr)
{
CT_PointIterator itP(scene->pointCloudIndexRegistered());
auto setter = _outDir.createAttributesSetter(scene->pointCloudIndexRegistered().dynamicCast());
size_t errorCount = 0;
size_t i = 0;
const size_t n_points = itP.size();
while(itP.hasNext())
{
if (isStopped())
return;
itP.next();
const auto gi = itP.currentGlobalIndex();
const CT_Point point = itP.currentPoint();
if(attributeGPS->hasBeenSet(gi))
{
const double gpsTime = attributeGPS->scalarAsDoubleAt(gi);
bool found = false;
Eigen::Vector3d trajCoord;
for (int tra = 0 ; tra < trajectories.size() && !found ; tra++)
{
CT_ScanPath* sp = trajectories.at(tra);
if (sp->isInScanPath(gpsTime))
{
trajCoord = sp->getPathPointForGPSTime(gpsTime);
found = true;
}
}
double length = -1;
Eigen::Vector3d dir(0,0,0);
if (found)
{
length = sqrt(pow(point(0) - trajCoord(0), 2) + pow(point(1) - trajCoord(1), 2) + pow(point(2) - trajCoord(2), 2));
dir = trajCoord - point;
dir.normalize();
} else {
errorCount++;
if (errorCount < 5)
{
PS_LOG->addMessage(LogInterface::warning, LogInterface::step, QString(tr("Pas d'information de trajectoire pour le point (%1 ; %2 ; %3)")).arg(point(0)).arg(point(1)).arg(point(2)));
}
}
CT_Normal ctNormal;
ctNormal.x() = float(dir(0));
ctNormal.y() = float(dir(1));
ctNormal.z() = float(dir(2));
ctNormal.w() = float(length);
setter.setValueWithGlobalIndex(gi, ctNormal);
setProgress(float(95.0*i++ / n_points));
}
}
if (errorCount > 0) {PS_LOG->addMessage(LogInterface::warning, LogInterface::step, QString(tr("Pas d'information de trajectoire pour au total %1 points sur %2")).arg(errorCount).arg(i));}
if (i > 0)
{
grp->addSingularItem(_outDir, _outDir.createAttributeInstance(scene->pointCloudIndexRegistered()));
}
}
++it;
}
}