Files
qt5-legatus-legacy/Lts/Viewer/SituationMap/MapObjectsImpl/path_container.cpp
T
2026-08-13 18:33:10 +02:00

371 lines
10 KiB
C++
Executable File

/**
* @RDE_HEADER@
* PathContainer
* $Id$
* $HeadURL$
* $Author$
*/
// Own
#include "path_container.h"
#include <MapImpl/coordinate_translation.h>
#include <GraphicalObjects/graphical_object_multi_path.h>
#include <MapImpl/coordinate_translation_thread.h>
// ESRI
#include <arcgis/GeoView.h>
#include <arcgis/PictureMarkerSymbol.h>
// Qt
#include <QElapsedTimer>
namespace SituationMap
{
//-----------------------------------------------------------------------------
// class PathData
//-----------------------------------------------------------------------------
class PathData
{
public:
PathData() = default;
PositionsTranslated &pathTrans() { return m_path; }
bool setPath(const PositionCont &path)
{
if (m_path.positions() != path)
m_changed = true;
m_path.setPositions(path);
return m_changed;
}
bool visibility() const { return m_visibility.value(); }
void setVisibility(bool onOff) { m_visibility = onOff; }
bool changed() const { return m_changed || m_visibility.changed(); }
void resetChanged() { m_changed = false; m_visibility.reset(); }
~PathData()
{
}
public:
private:
PositionsTranslated m_path;
SimpleValue<bool> m_visibility{true};
bool m_changed{true};
};
class PathContainer::Private
{
public:
Private() = default;
~Private() = default;
// ESRI data:
Esri::ArcGISRuntime::GeoView *m_geoView{nullptr};
Esri::ArcGISRuntime::GraphicsOverlay *m_graphicsLayer{nullptr};
// Own data:
CoordTranslationFunctor *m_coordTransFunctor{nullptr};
QString m_debugInfo; // will be appended by consecutive number
UniqueMapId m_uniqueMapId;
SimpleValue<LineStyle> m_lineStyle;
SimpleValue<FillStyle> m_fillStyle;
SimpleValue<int> m_drawOrder{0};
SimpleValue<bool> m_selected{false};
QSharedPointer<GraphicalObjectMultiPath> m_multiPath;
#ifdef LTS_DEBUG
static long m_counter;
#endif
private:
QHash<int, QSharedPointer<PathData>> m_map;
public:
QSharedPointer<PathData> getPathData(int key)
{
auto it = m_map.find(key);
if (it != m_map.end())
return it.value();
auto ret = QSharedPointer<PathData>(new PathData());
m_map[key] = ret;
return ret;
}
bool remove(int key)
{
auto it = m_map.find(key);
if (it == m_map.end())
return false;
m_map.erase(it);
return true;
}
void clear() { m_map.clear(); }
int size() const { return m_map.size(); }
QList<int> keys() const { return m_map.keys(); }
bool contains(int key) const { return m_map.contains(key); }
const QHash<int, QSharedPointer<PathData>> &container() const { return m_map; }
}; // class PathContainer::Private
#ifdef LTS_DEBUG
long PathContainer::Private::m_counter = 0;
#endif
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
// class PathContainer
//-----------------------------------------------------------------------------
PathContainer::PathContainer(const Esri::ArcGISRuntime::GeoView *geoView,
Esri::ArcGISRuntime::GraphicsOverlay *graphicsLayer,
CoordTranslationFunctor *coordTransFunctor,
const UniqueMapId &uniqueMapId)
: QObject()
, m_logger(getLogger("PathContainer"))
, d(new Private)
{
TRACE_LOG(m_logger) << LOGFUNCTION << " START";
d->m_geoView = const_cast<Esri::ArcGISRuntime::GeoView *>(geoView);
d->m_graphicsLayer = graphicsLayer;
d->m_coordTransFunctor = coordTransFunctor;
d->m_uniqueMapId = uniqueMapId;
QString debugInfo = QStringLiteral("%1#PathContainerPolyline").arg(d->m_debugInfo);
DEBUG_LOG(m_logger) << LOGFUNCTION << " create new Object: " << debugInfo;
d->m_multiPath = QSharedPointer<GraphicalObjectMultiPath>
(new GraphicalObjectMultiPath(GraphicalObjectPathType::Polyline,
d->m_geoView,
d->m_graphicsLayer,
debugInfo,
d->m_uniqueMapId));
#ifdef LTS_DEBUG
INFO_LOG(m_logger) << " ctor PathContainer-Polyline counter = " << d->m_counter++
<< ", debugInfo = " << debugInfo;
#endif // LTS_DEBUG
TRACE_LOG(m_logger) << LOGFUNCTION << " END";
}
PathContainer::PathContainer(const GraphicalObjectPathType pathType,
const Esri::ArcGISRuntime::GeoView *geoView,
Esri::ArcGISRuntime::GraphicsOverlay *graphicsLayer,
CoordTranslationFunctor *coordTransFunctor,
const UniqueMapId &uniqueMapId)
: QObject()
, m_logger(getLogger("PathContainer"))
, d(new Private)
{
TRACE_LOG(m_logger) << LOGFUNCTION << " START";
d->m_geoView = const_cast<Esri::ArcGISRuntime::GeoView *>(geoView);
d->m_graphicsLayer = graphicsLayer;
d->m_coordTransFunctor = coordTransFunctor;
d->m_uniqueMapId = uniqueMapId;
QString debugInfo = QStringLiteral("%1#PathContainerPolygon").arg(d->m_debugInfo);
DEBUG_LOG(m_logger) << LOGFUNCTION << " create new Object: " << debugInfo;
d->m_multiPath = QSharedPointer<GraphicalObjectMultiPath>
(new GraphicalObjectMultiPath(pathType,
d->m_geoView,
d->m_graphicsLayer,
debugInfo,
d->m_uniqueMapId));
#ifdef LTS_DEBUG
INFO_LOG(m_logger) << " ctor PathContainer-Polygon counter = " << d->m_counter++
<< ", debugInfo = " << debugInfo;
#endif // LTS_DEBUG
TRACE_LOG(m_logger) << LOGFUNCTION << " END";
}
PathContainer::~PathContainer()
{
TRACE_LOG(m_logger) << LOGFUNCTION << " START";
d->clear();
delete d;
#ifdef LTS_DEBUG
INFO_LOG(m_logger) << " dtor PathContainer counter =" << --d->m_counter;
#endif // LTS_DEBUG
TRACE_LOG(m_logger) << LOGFUNCTION << " END";
}
QString PathContainer::debugInfo() const
{
return d->m_debugInfo;
}
void PathContainer::setDebugInfo(const QString &debugInfo)
{
d->m_debugInfo = debugInfo;
d->m_multiPath->setDebugInfo(QStringLiteral("%1#PathContainer").arg(d->m_debugInfo));
}
PositionCont PathContainer::path(int idx) const
{
return d->getPathData(idx)->pathTrans().positions();
}
bool PathContainer::setPath(int idx, const PositionCont &path)
{
TRACE_LOG(m_logger) << LOGFUNCTION << " START"
<< " idx=" << idx
<< " path.size=" << path.size();
bool hasChanged = false;
if (path.isEmpty())
hasChanged = d->remove(idx);
else
hasChanged = d->getPathData(idx)->setPath(path);
TRACE_LOG(m_logger) << LOGFUNCTION << " END";
return hasChanged;
}
void PathContainer::clear(int idx)
{
d->remove(idx);
}
void PathContainer::clearAll()
{
d->clear();
}
LineStyle PathContainer::lineStyle() const
{
return d->m_lineStyle.value();
}
void PathContainer::setLineStyle(const LineStyle &lineStyle)
{
d->m_lineStyle = lineStyle;
}
FillStyle PathContainer::fillStyle() const
{
return d->m_fillStyle.value();
}
void PathContainer::setFillStyle(const FillStyle &fillStyle)
{
d->m_fillStyle = fillStyle;
}
int PathContainer::drawOrder() const
{
return d->m_drawOrder.value();
}
void PathContainer::setDrawOrder(int drawOrder)
{
d->m_drawOrder = drawOrder;
}
bool PathContainer::selected() const
{
return d->m_selected.value();
}
void PathContainer::setSelected(bool selected)
{
d->m_selected = selected;
}
bool PathContainer::visibility(int idx) const
{
return d->getPathData(idx)->visibility();
}
void PathContainer::setVisibility(int idx, bool onOff)
{
d->getPathData(idx)->setVisibility(onOff);
}
int PathContainer::getPathCount() const
{
return d->size();
}
QList<int> PathContainer::getIndicationIndexList() const
{
return d->keys();
}
bool PathContainer::updateView()
{
TRACE_LOG(m_logger) << LOGFUNCTION << " START"
<< ", debugInfo='" << d->m_debugInfo << "'"
<< ", d->m_map.size()= " << d->size();
bool success = true;
bool bDoUpdateView = false;
if (d->m_lineStyle.changed() || d->m_fillStyle.changed() || d->m_drawOrder.changed() || d->m_selected.changed())
{
d->m_multiPath->setLineStyle(d->m_lineStyle.value());
d->m_multiPath->setFillStyle(d->m_fillStyle.value());
d->m_multiPath->setDrawOrder(d->m_drawOrder.value());
d->m_multiPath->setSelected(d->m_selected.value());
bDoUpdateView = true;
}
// is something removed?
if (d->m_multiPath->pathIndexInUse() != d->keys())
{
d->m_multiPath->reduceTo(d->keys());
bDoUpdateView = true;
}
for (auto it = d->container().begin(); it != d->container().end(); ++it)
{
QSharedPointer<PathData> pathData = it.value();
if (pathData->changed())
{
const int idx = it.key();
pathData->pathTrans().setCoordTransFunctor(d->m_coordTransFunctor);
if (pathData->visibility())
{
const PositionCont &pathTrans = pathData->pathTrans().positionsTranslated();
d->m_multiPath->setPath(idx, pathTrans);
} else {
// a cleared path will not be transfered to ESRI::Graphic, see GraphicalObjectMultiPath
// So clearPath is sufficiant
d->m_multiPath->clearPath(idx);
}
bDoUpdateView = true;
pathData->resetChanged();
}
} // for
if (bDoUpdateView)
{
bool updated = d->m_multiPath->updateView();
success = updated;
}
// reset
d->m_lineStyle.reset();
d->m_fillStyle.reset();
d->m_drawOrder.reset();
d->m_selected.reset();
TRACE_LOG(m_logger) << LOGFUNCTION << " END"
<< " debugInfo='" << d->m_debugInfo << "'"
<< " success=" << success;
return success;
}
}
// namespace SituationMap