Initial commit

This commit is contained in:
torsten committed 2026-08-13 18:33:10 +02:00
commit b7d90b9afe
16245 files changed
+3396666

No files matched your search

@@ -0,0 +1,365 @@
/**
* @RDE_HEADER@
* TerrainProfileProcessor
* $Id$
* $HeadURL$
* $Author$
*/
// Own
#include "terrain_profile_processor.h"
#include "map_impl.h"
#include <GraphicalObjects/graphical_object_path.h>
#include <Map/object_factory.h>
#include <Map/situation_map_utils.h>
#include <Map/coord_translation_functor.h>
#include <MapImpl/layer_factory_impl.h>
// ESRI
#include <arcgis/GeometryEngine.h>
#include <arcgis/PolylineBuilder.h>
// Qt
namespace SituationMap
{
//-----------------------------------------------------------------------------
// class ViewshedBase
//-----------------------------------------------------------------------------
TerrainProfileProcessor::TerrainProfileProcessor(QObject *parent)
: QObject(parent)
, m_logger(getLogger("TerrainProfileProcessor"))
{
TRACE_LOG(m_logger) << LOGFUNCTION << " START";
TRACE_LOG(m_logger) << LOGFUNCTION << " END";
}
TerrainProfileProcessor::~TerrainProfileProcessor()
{
TRACE_LOG(m_logger) << LOGFUNCTION << " START, id=" << m_id;
removeUserInput();
// maybe clear the view of m_terrainProfileDialog here?
TRACE_LOG(m_logger) << LOGFUNCTION << " END, id=" << m_id;
}
bool TerrainProfileProcessor::init(SituationMap::MapImpl *mapImpl, long id)
{
TRACE_LOG(m_logger) << LOGFUNCTION << " START";
m_id = id;
m_initialized = false;
m_mapImpl = mapImpl;
m_srMap = m_mapImpl->getEsriSpatialReference();
LayerFactoryImpl &layerFactoryImpl = m_mapImpl->layerFactoryImpl();
m_toolsLayername = layerFactoryImpl.toolLayer();
if (!m_surface)
m_surface = layerFactoryImpl.baseSurface();
if (m_surface && m_surface->loadStatus() == Esri::ArcGISRuntime::LoadStatus::Loaded)
m_initialized = true;
else
{
Esri::ArcGISRuntime::LoadStatus ls = Esri::ArcGISRuntime::LoadStatus::Unknown;
if (m_surface)
ls = m_surface->loadStatus();
ERROR_LOG(m_logger) << LOGFUNCTION
<< " d->m_surface = " << m_surface
<< " d->m_surface->loadStatus = " << ls;
}
if (!m_locationToElevationBulk.init(m_mapImpl, m_surface))
{
ERROR_LOG(m_logger) << LOGFUNCTION << " locationToElevationBulk.init() failed";
return false;
}
connect(&m_locationToElevationBulk, &LocationToElevationBulk::locationsToElevationsCompleted,
this, &TerrainProfileProcessor::onLocationsToElevationsCompleted, Qt::UniqueConnection);
TRACE_LOG(m_logger) << LOGFUNCTION << " END" << " m_initialized=" << m_initialized;
return m_initialized;
}
bool TerrainProfileProcessor::start(const TerrainProfileParameter &terrainProfileParameter)
{
TRACE_LOG(m_logger) << LOGFUNCTION << " START"
<< " terrainProfileParameter=" << terrainProfileParameter
<< " m_srMap.wkid=" << m_srMap.wkid();
// don´t allow more than one at once:
if (m_inProgress)
return false;
m_inProgress = true;
m_terrainProfileParameter = terrainProfileParameter;
removeUserInput();
displayUserInput();
// densify
const Esri::ArcGISRuntime::Polyline &polylineOut_Map = densifiy(m_terrainProfileParameter);
// calculate distance
// bulk location to elevation
const Esri::ArcGISRuntime::ImmutablePart &immutablePart = polylineOut_Map.parts().part(0);
const int size = immutablePart.pointCount();
for (int i = 0; i < size; ++i)
{
const Esri::ArcGISRuntime::Point &esriMapLocation = immutablePart.point(i);
// DEBUG_LOG(m_logger) << LOGFUNCTION << " esriMapLocation: " << QPointF(esriMapLocation.x(), esriMapLocation.y());
m_locationToElevationBulk.addLocation(esriMapLocation);
}
m_locationToElevationBulk.start();
TRACE_LOG(m_logger) << LOGFUNCTION << " END" << " m_viewshedInProgress=" << m_inProgress;
return true;
}
QVector<QPair<QPointF, double> > TerrainProfileProcessor::results() const
{
return m_locationToElevationBulk.results();
}
void TerrainProfileProcessor::setTerrainProfileDialog(QPointer<TerrainProfileDialog> &terrainProfileDialog)
{
TRACE_LOG(m_logger) << LOGFUNCTION << " START";
m_terrainProfileDialog = terrainProfileDialog;
if (m_terrainProfileDialog)
{
m_terrainProfileDialog->setMap(m_mapImpl);
// mousePositionChanged
connect(m_terrainProfileDialog.data(), &TerrainProfileDialog::mousePositionChanged,
this, &TerrainProfileProcessor::onDialogMousePositionChanged, Qt::UniqueConnection);
// handle destruction of according dialog:
connect(terrainProfileDialog.data(), &TerrainProfileDialog::destroyed,
this, &TerrainProfileProcessor::deleteLater);
}
TRACE_LOG(m_logger) << LOGFUNCTION << " END";
}
Esri::ArcGISRuntime::Polyline TerrainProfileProcessor::densifiy(TerrainProfileParameter &terrainProfileParameter)
{
TRACE_LOG(m_logger) << LOGFUNCTION << " START"
<< " terrainProfileParameter=" << terrainProfileParameter;
//
// PosCont to EsriPolyline:
//
Esri::ArcGISRuntime::PolylineBuilder polylineBuilder(m_srMap, this);
for (const Point3D &coord : qAsConst(terrainProfileParameter.m_coordinates))
{
// geo to map (polylineBuilder uses map also)
const Point3D &p3D = m_mapImpl->coordTranslationFunctor()->geographicToMap(coord);
polylineBuilder.addPoint(Esri::ArcGISRuntime::Point(p3D.x(), p3D.y(), p3D.z()));
}
const Esri::ArcGISRuntime::Polyline &polylineIn = polylineBuilder.toPolyline();
terrainProfileParameter.m_length =
Esri::ArcGISRuntime::GeometryEngine::lengthGeodetic(polylineIn,
Esri::ArcGISRuntime::LinearUnit::meters(),
Esri::ArcGISRuntime::GeodeticCurveType::Geodesic);
const int numberCoords = 50;
double maxSegmenthLength = terrainProfileParameter.m_length / numberCoords;
INFO_LOG(m_logger) << LOGFUNCTION << " START"
<< " lengthMeter=" << terrainProfileParameter.m_length
<< " numberCoords=" << numberCoords
<< " maxSegmenthLength=" << maxSegmenthLength;
const Esri::ArcGISRuntime::Geometry &geometryOut = Esri::ArcGISRuntime::GeometryEngine::densifyGeodetic(polylineIn,
maxSegmenthLength,
Esri::ArcGISRuntime::LinearUnit::meters(),
Esri::ArcGISRuntime::GeodeticCurveType::Geodesic);
const Esri::ArcGISRuntime::Polyline polylineOut(geometryOut);
TRACE_LOG(m_logger) << LOGFUNCTION << " START"
<< " lengthMeter=" << terrainProfileParameter.m_length
<< " numberCoords=" << numberCoords
<< " maxSegmenthLength=" << maxSegmenthLength
<< " polylineOut.parts().part(0).pointCount()=" << polylineOut.parts().part(0).pointCount();
return polylineOut;
}
void TerrainProfileProcessor::displayUserInput()
{
displayInputLine();
displayInputVertices();
}
void TerrainProfileProcessor::removeUserInput()
{
removeInputLine();
removeInputVertices();
removeCurrentMarker();
}
void TerrainProfileProcessor::displayInputLine()
{
// create
if (!m_polyline)
{
m_polyline = m_mapImpl->objectFactory().create<Polyline>(m_toolsLayername,
QStringLiteral("TerrainProfileLineId%1").arg(m_id));
m_polyline->setLineStyle(LineStyle(m_color, 3));
m_polyline->setScaleEnable(true);
m_polyline->setPickable(false);
}
// apply data
m_polyline->setPositions(m_terrainProfileParameter.m_coordinates);
// update
if (!m_polyline->updateView())
ERROR_LOG(m_logger) << LOGFUNCTION << " polyline::updateView failed";
}
void TerrainProfileProcessor::removeInputLine()
{
if (m_polyline)
m_polyline->removeMySelf();
m_polyline.reset();
}
void TerrainProfileProcessor::displayInputVertices()
{
TRACE_LOG(m_logger) << LOGFUNCTION << " START";
PositionCont coordinates = m_terrainProfileParameter.m_coordinates;
const int size = coordinates.size();
if (size < 1)
return;
m_markerCont.resize(size);
int idx = 0;
QMutableVectorIterator<RefPointer<GeoImage>> it(m_markerCont);
while (it.hasNext())
{
RefPointer<GeoImage> &marker = it.next();
if (!marker.valid())
{
marker = m_mapImpl->objectFactory().create<GeoImage>(m_toolsLayername,
QStringLiteral("TerrainProfileLineId%1_idx%2").arg(m_id).arg(idx));
marker->setProxyMarker(MarkerSymbolType::Circle);
marker->setProxyMarkerColor(m_color);
marker->setProxyMarkerSize(7);
marker->setPickable(false);
}
marker->setOrigin(coordinates[idx]);
// update
if (!marker->updateView())
ERROR_LOG(m_logger) << LOGFUNCTION << " marker::updateView failed";
++idx;
} // while
TRACE_LOG(m_logger) << LOGFUNCTION << " END";
}
void TerrainProfileProcessor::removeInputVertices()
{
QMutableVectorIterator<RefPointer<GeoImage>> it(m_markerCont);
while (it.hasNext())
{
RefPointer<GeoImage> &marker = it.next();
if (marker)
marker->removeMySelf();
}
m_markerCont.clear();
}
void TerrainProfileProcessor::displayCurrentMarker(const Point3D &pointGeo)
{
// create
if (!m_currentMarker)
{
m_currentMarker = m_mapImpl->objectFactory().create<GeoImage>(m_toolsLayername,
QStringLiteral("TerrainProfileLineId%1_currentMarker").arg(m_id));
m_currentMarker->setProxyMarker(MarkerSymbolType::Circle);
m_currentMarker->setProxyMarkerColor(Qt::blue);
m_currentMarker->setProxyMarkerSize(10);
m_currentMarker->setPickable(false);
}
// apply data
m_currentMarker->setOrigin(pointGeo);
// update
if (!m_currentMarker->updateView())
ERROR_LOG(m_logger) << LOGFUNCTION << " m_currentMarker::updateView failed";
}
void TerrainProfileProcessor::removeCurrentMarker()
{
if (m_currentMarker)
m_currentMarker->removeMySelf();
m_currentMarker.reset();
}
void TerrainProfileProcessor::onLocationsToElevationsCompleted()
{
TRACE_LOG(m_logger) << LOGFUNCTION << " START" << " m_locationToElevationBulk.size()=" << m_locationToElevationBulk.size();
const QVector<QPair<QPointF, double>> &results = m_locationToElevationBulk.results();
if (m_logger.isDebugEnabled())
for (const QPair<QPointF, double> &item : qAsConst(results))
DEBUG_LOG(m_logger) << LOGFUNCTION << " location = " << item.first << " elevation = " << item.second;
TRACE_LOG(m_logger) << LOGFUNCTION << " START" << " results.size()=" << results.size();
// The caller should set TerrainProfileDialog on this signal:
emit locationsToElevationsCompleted(m_id);
// maybe (better hopefully) the caller (via finishedCallback of TerrainProfileImpl)
// has updated our m_terrainProfileParameter !?!
if (m_terrainProfileDialog)
{
m_terrainProfileDialog->setData(this->results());
QVector<QPointF> marks;
marks.reserve(m_terrainProfileParameter.m_coordinates.size());
for (const Point3D &coord : qAsConst(m_terrainProfileParameter.m_coordinates))
{
// geo to map
const Point3D &p3D = m_mapImpl->coordTranslationFunctor()->geographicToMap(coord);
marks.append(p3D.toPointF());
}
m_terrainProfileDialog->setMarks(marks);
} else {
ERROR_LOG(m_logger) << LOGFUNCTION << " no dialog";
}
m_inProgress = false;
}
void TerrainProfileProcessor::onDialogMousePositionChanged(const QPointF &curPos)
{
const Point3D &curPosGeo = Point3D::fromQPointF( m_mapImpl->coordTranslationFunctor()->mapToGeographic(curPos) );
displayCurrentMarker(curPosGeo);
}
} // namespace SituationMap