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

324 lines
10 KiB
C++
Executable File

/**
* @RDE_HEADER@
* GraphicalObjectPath
* $Id$
* $HeadURL$
* $Author$
*/
// Own
#include "graphical_object_multi_path.h"
#include <Map/situation_map_utils.h> // operator<<
// ESRI
#include <arcgis/GraphicsOverlay.h>
#include <arcgis/PolygonBuilder.h>
#include <arcgis/PolylineBuilder.h>
#include <arcgis/SimpleLineSymbol.h>
#include <arcgis/SimpleFillSymbol.h>
#include <arcgis/GeoView.h>
#include <arcgis/GeometryEngine.h>
// Qt
namespace SituationMap
{
GraphicalObjectMultiPath::GraphicalObjectMultiPath(const GraphicalObjectPathType type
, const Esri::ArcGISRuntime::GeoView *geoView
, Esri::ArcGISRuntime::GraphicsOverlay *graphicsLayer
, const QString &debugInfo
, UniqueMapId uniqueMapId)
: BaseClass(geoView, graphicsLayer, debugInfo, uniqueMapId)
, m_pathType(type)
, m_logger(getLogger("GraphicalObjectMultiPath"))
{
TRACE_LOG(m_logger) << LOGFUNCTION << " START, debugInfo='" << m_debugInfo << "'"
<< " m_pathType=" << m_pathType;
TRACE_LOG(m_logger) << LOGFUNCTION << " END, debugInfo='" << m_debugInfo << "'"
<< " m_pathType=" << m_pathType;
}
GraphicalObjectMultiPath::~GraphicalObjectMultiPath()
{
TRACE_LOG(m_logger) << LOGFUNCTION << " START, debugInfo='" << m_debugInfo << "'"
<< " m_pathType=" << m_pathType;
TRACE_LOG(m_logger) << LOGFUNCTION << " END, debugInfo='" << m_debugInfo << "'"
<< " m_pathType=" << m_pathType;
}
PositionCont GraphicalObjectMultiPath::path(int pathIndex) const
{
TRACE_LOG(m_logger) << LOGFUNCTION << " START, debugInfo='" << m_debugInfo << "'"
<< " pathIndex=" << pathIndex;
if (hasPosCont(pathIndex))
return getPosCont(pathIndex).value();
return {};
}
void GraphicalObjectMultiPath::setPath(int pathIndex, const PositionCont &positions)
{
TRACE_LOG(m_logger) << LOGFUNCTION << " START, debugInfo='" << m_debugInfo << "'"
<< " pathIndex=" << pathIndex
<< " positions=" << positions;
m_positionsCont[pathIndex] = positions;
TRACE_LOG(m_logger) << LOGFUNCTION << " END, debugInfo='" << m_debugInfo << "'";
}
void GraphicalObjectMultiPath::clearPath(int pathIndex)
{
TRACE_LOG(m_logger) << LOGFUNCTION << " START, debugInfo='" << m_debugInfo << "'"
<< " pathIndex=" << pathIndex;
if (pathIndex == -1)
{
m_positions.refValue().clear();
m_positionsCont.clear();
}
else
{
if (hasPosCont(pathIndex))
{
// Do not remove the whole entry to let changed() work
m_positionsCont[pathIndex].refValue().clear();
}
}
TRACE_LOG(m_logger) << LOGFUNCTION << " END, debugInfo='" << m_debugInfo << "'";
}
void GraphicalObjectMultiPath::clearAllPaths()
{
TRACE_LOG(m_logger) << LOGFUNCTION << " START, debugInfo='" << m_debugInfo << "'";
m_positions.refValue().clear();
m_positionsCont.clear();
TRACE_LOG(m_logger) << LOGFUNCTION << " END, debugInfo='" << m_debugInfo << "'";
}
void GraphicalObjectMultiPath::reduceTo(const QList<int> &remainingPathIndexes)
{
TRACE_LOG(m_logger) << LOGFUNCTION << " START, debugInfo='" << m_debugInfo << "'"
<< " remainingPathIndexes=" << remainingPathIndexes;
QList<int> keys = m_positionsCont.keys();
for (int key : qAsConst(keys))
{
if (!remainingPathIndexes.contains(key))
{
// Do not remove the whole entry to let chanded() work
m_positionsCont[key].refValue().clear();
}
}
TRACE_LOG(m_logger) << LOGFUNCTION << " END, debugInfo='" << m_debugInfo << "'";
}
QList<int> GraphicalObjectMultiPath::pathIndexInUse()
{
TRACE_LOG(m_logger) << LOGFUNCTION << " START, debugInfo='" << m_debugInfo << "'";
QList<int> ret;
///// ret << 0; // pathIndex=0 -> m_positions
QMapIterator<int, SimpleValue<PositionCont> > mapIt(m_positionsCont);
while (mapIt.hasNext())
{
mapIt.next();
const SimpleValue<PositionCont> &posData = mapIt.value();
const PositionCont &posCont = posData.value();
if (! posCont.isEmpty())
ret += mapIt.key();
} // while
TRACE_LOG(m_logger) << LOGFUNCTION << " END, debugInfo='" << m_debugInfo << "'";
return ret;
}
bool GraphicalObjectMultiPath::create()
{
TRACE_LOG(m_logger) << LOGFUNCTION << " START, debugInfo='" << m_debugInfo << "'";
bool success = BaseClass::create();
if (!success)
{
ERROR_LOG(m_logger) << LOGFUNCTION << " debugInfo='" << m_debugInfo << "'"
<< " create failed";
return false;
}
TRACE_LOG(m_logger) << LOGFUNCTION << " END, debugInfo='" << m_debugInfo << "'";
return success;
}
bool GraphicalObjectMultiPath::updateViewImpl()
{
TRACE_LOG(m_logger) << LOGFUNCTION << " START, debugInfo='" << m_debugInfo << "'";
bool success = create();
if (!success)
{
ERROR_LOG(m_logger) << LOGFUNCTION << " debugInfo='" << m_debugInfo << "'"
<< " create failed";
return false;
}
success = BaseClass::updateViewImpl();
if (!success)
{
ERROR_LOG(m_logger) << LOGFUNCTION << " debugInfo='" << m_debugInfo << "'"
<< " updateView failed";
return false;
}
success = updatePositions();
TRACE_LOG(m_logger) << LOGFUNCTION << " END, debugInfo='" << m_debugInfo << "'"
<< " success = " << success
<< " drawOrder = " << m_graphic->zIndex();
return success;
}
bool GraphicalObjectMultiPath::updatePositions()
{
TRACE_LOG(m_logger) << LOGFUNCTION << " START, debugInfo='" << m_debugInfo << "'";
bool success = true;
int pathIdxToInsert = 0;
const int minPoints = this->pathType() == GraphicalObjectPathType::Polyline ? 2 : 3;
QSharedPointer<Esri::ArcGISRuntime::MultipartBuilder> builder;
// some preparations: ( do no check isMultiPoint / isArea: m_positions should typically be empty!!!
switch (m_pathType)
{
case GraphicalObjectPathType::Polyline:
builder = QSharedPointer<Esri::ArcGISRuntime::PolylineBuilder>(new Esri::ArcGISRuntime::PolylineBuilder(spatialReference()));
break;
case GraphicalObjectPathType::Polygon:
builder = QSharedPointer<Esri::ArcGISRuntime::PolygonBuilder>(new Esri::ArcGISRuntime::PolygonBuilder(spatialReference()));
break;
} // switch
QSharedPointer<Esri::ArcGISRuntime::PartCollection> partCollection =
QSharedPointer<Esri::ArcGISRuntime::PartCollection>(new Esri::ArcGISRuntime::PartCollection(builder->spatialReference()));
TRACE_LOG(m_logger) << LOGFUNCTION << " START, debugInfo='" << m_debugInfo << "'"
<< ", m_positionsCont.size() /#rings=" << m_positionsCont.size();
QMutableMapIterator<int, SimpleValue<PositionCont> > mapIt(m_positionsCont);
//
// LOOP PER SINGLE POLY
//
while (mapIt.hasNext())
{
mapIt.next();
const int key = mapIt.key();
const SimpleValue<PositionCont> &posData = mapIt.value();
const PositionCont &posCont = posData.value();
TRACE_LOG(m_logger) << LOGFUNCTION << " START, debugInfo='" << m_debugInfo << "'"
<< ", key / #ring=" << key
<< ", rings.size()=" << posCont.size();
// maybe some pathIdx are cleared by clearPath() or similar:
if (posCont.isEmpty())
{
DEBUG_LOG(m_logger) << LOGFUNCTION
<< " posCont empty, cleared? -> remove/cleanup"
<< " pathIdxToInsert = " << pathIdxToInsert
<< " mapIt.key() = " << key;
mapIt.remove();
continue;
}
if (posCont.count() < minPoints)
{
ERROR_LOG(m_logger) << LOGFUNCTION
<< " incorrect number of positions"
<< " (" << posCont.count() << ")"
<< ", minPoints=" << minPoints
<< ", pathIdxToInsert = " << pathIdxToInsert
<< ", mapIt.key() = " << key
<< ", m_debugInfo = " << m_debugInfo;
success = false;
}
else
{
Esri::ArcGISRuntime::Part part(builder->spatialReference());
//
// LOOP PER POINT
//
for (auto pos : qAsConst(posCont))
{
part.addPoint(pos.x(), pos.y(), pos.z());
TRACE_LOG(m_logger) << LOGFUNCTION << " START, debugInfo='" << m_debugInfo << "'"
<< ", key / #ring=" << key
<< ", addPoint=" << pos;
}
partCollection->addPart(&part);
} // if (posCont.count() < minPoints)
} // while
builder->setParts(partCollection.get());
//
// builder to geometry;
//
switch (m_pathType)
{
case GraphicalObjectPathType::Polyline:
{
const Esri::ArcGISRuntime::Polyline &multipartPolyline =
static_cast<Esri::ArcGISRuntime::PolylineBuilder *>(builder.data())->toPolyline();
m_graphic->setGeometry(multipartPolyline);
assignLineStyleToGraphic();
}
break;
case GraphicalObjectPathType::Polygon:
{
const Esri::ArcGISRuntime::Polygon &multipartPolygon =
static_cast<Esri::ArcGISRuntime::PolygonBuilder *>(builder.data())->toPolygon();
m_graphic->setGeometry(multipartPolygon);
//assignLineStyleToGraphic();
assignFillStyleToGraphic();
}
break;
} // switch
DEBUG_LOG(m_logger) << LOGFUNCTION << " debugInfo='" << m_debugInfo << "'";
success = addUpdateGraphic();
TRACE_LOG(m_logger) << LOGFUNCTION << " END, debugInfo='" << m_debugInfo << "'"
<< " success = " << success
<< " drawOrder = " << m_graphic->zIndex();
return success;
}
bool GraphicalObjectMultiPath::hasPosCont(int idx) const
{
return m_positionsCont.contains(idx);
}
SimpleValue<PositionCont> &GraphicalObjectMultiPath::getPosCont(int idx)
{
return m_positionsCont[idx];
}
const SimpleValue<PositionCont> GraphicalObjectMultiPath::getPosCont(int idx) const
{
return m_positionsCont[idx];
}
} // namespace SituationMap