371 lines
10 KiB
C++
Executable File
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
|