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

1206 lines
35 KiB
C++
Executable File

/**
* @RDE_HEADER@
* Interface-Implementation of AbstractMapObject
* $Id$
* $HeadURL$
* $Author$
*/
// Own
#include "abstract_map_object_impl.h"
#include "map_impl.h"
#include "object_container_impl.h"
#include <Map/party_id_to_color_functor.h>
#include <MathUtils/geometry_engine.h>
#include <GraphicalObjects/abstract_graphical_object.h>
#include <GraphicalObjects/graphical_object_text.h>
#include <GraphicalObjects/graphical_object_cube.h>
#include <GraphicalObjects/graphical_object_path.h>
#include <GraphicalObjects/tactical_appearance.h>
#include <Map/bounding_box.h>
// ESRI
#include <arcgis/Graphic.h>
#include <arcgis/GraphicsOverlay.h>
#include <arcgis/LayerSceneProperties.h>
// Qt
namespace SituationMap
{
struct ExtraData
{
QVector<QByteArray> propertyNames;
QVector<QVariant> propertyValues;
};
AbstractMapObjectImpl::AbstractMapObjectImpl(const QString &debugInfo)
: AbstractMapObject()
, m_uniqueMapId(SituationMap::INVALID_MAP_ID)
, m_logger(getLogger("AbstractMapObjectImpl"))
{
TRACE_LOG(m_logger) << LOGFUNCTION << " START" << " debugInfo='" << debugInfo << "'";
m_debugInfo = debugInfo;
TRACE_LOG(m_logger) << LOGFUNCTION << " END" << " debugInfo='" << debugInfo << "'";
} // AbstractMapObjectImpl::AbstractMapObjectImpl
AbstractMapObjectImpl::~AbstractMapObjectImpl()
{
TRACE_LOG(m_logger) << LOGFUNCTION << " START"
<< " debugInfo=" << m_debugInfo
<< " uniqueMapId=" << m_uniqueMapId;
delete m_mapConnector;
m_mapConnector = nullptr;
resetPin();
delete m_tacticalAppearance;
m_tacticalAppearance = nullptr;
delete m_mainGraphicalObjectText;
m_mainGraphicalObjectText = nullptr;
resetGraphicalObjectExtrusion();
delete m_mainGraphicalObject;
m_mainGraphicalObject = nullptr;
delete m_extraData;
m_extraData = nullptr;
TRACE_LOG(m_logger) << LOGFUNCTION << " END"
<< " debugInfo=" << m_debugInfo
<< " uniqueMapId=" << m_uniqueMapId;
} // AbstractMapObjectImpl::~AbstractMapObjectImpl
void AbstractMapObjectImpl::removeMySelf()
{
TRACE_LOG(m_logger) << LOGFUNCTION << " START"
<< " debugInfo=" << m_debugInfo;
// To avoid accessing already deleted variables make some local copies 2016/01/08 JT
QString debugInfo = m_debugInfo;
UniqueMapId uid = m_uniqueMapId;
SituationMap::LOGGER_T logger(m_logger);
if (m_mapImpl)
{
TRACE_LOG(m_logger) << "removeObject, uniqueMapId = " << m_uniqueMapId;
m_uniqueMapId = SituationMap::INVALID_MAP_ID;
m_mapImpl->objectContainer().removeObject(uid);
}
else
ERROR_LOG(m_logger) << LOGFUNCTION << " m_mapImpl does not exist.";
// Attention CRASH here if AbstractMapObject is not been referenced by a RefPointer. In this case the this-object has been deleted immediately 2016/01/08 JT
TRACE_LOG(logger) << LOGFUNCTION << " END"
<< " debugInfo=" << debugInfo;
}
bool AbstractMapObjectImpl::setProperty(const char *name, const QVariant &value)
{
// following setProperty/property approach is take from qt4.8.5:
if (!m_extraData)
m_extraData = new ExtraData;
const int idx = m_extraData->propertyNames.indexOf(name);
if (!value.isValid())
{
if (idx == -1)
return false;
m_extraData->propertyNames.removeAt(idx);
m_extraData->propertyValues.removeAt(idx);
}
else
{
if (idx == -1)
{
m_extraData->propertyNames.append(name);
m_extraData->propertyValues.append(value);
}
else
m_extraData->propertyValues[idx] = value;
}
return true;
}
QVariant AbstractMapObjectImpl::property(const char *name) const
{
if (!m_extraData)
return QVariant();
const int i = m_extraData->propertyNames.indexOf(name);
return m_extraData->propertyValues.value(i);
}
UniqueMapId AbstractMapObjectImpl::uniqueMapId() const
{
return m_uniqueMapId;
}
QString AbstractMapObjectImpl::debugInfo() const
{
return m_debugInfo;
}
void AbstractMapObjectImpl::setDebugInfo(const QString &debugInfo)
{
m_debugInfo = debugInfo;
if (m_mainGraphicalObject)
m_mainGraphicalObject->setDebugInfo(m_debugInfo + QLatin1String("#mainGO"));
else
ERROR_LOG(m_logger) << LOGFUNCTION << " no object";
if (m_mainGraphicalObjectText)
m_mainGraphicalObjectText->setDebugInfo(m_debugInfo + QLatin1String("#Text"));
if (m_tacticalAppearance)
m_tacticalAppearance->setDebugInfo(m_debugInfo + QLatin1String("#TactApp"));
}
QString AbstractMapObjectImpl::toString() const
{
QString str;
if (!m_debugInfo.isEmpty())
str.append(QStringLiteral("debugInfo='%1'").arg(m_debugInfo));
str.append(QStringLiteral("uniqueMapId='%1'").arg(m_uniqueMapId));
if ((m_mainGraphicalObjectText) &&
(! m_mainGraphicalObjectText->text().isEmpty())
)
str.append(QStringLiteral(" identifier='%1'").arg(m_mainGraphicalObjectText->text()));
if (!m_logicalLayerName.isEmpty())
str.append(QStringLiteral(" logicalLayerName='%1'").arg(m_logicalLayerName));
str.append(QStringLiteral(" partyId=%1").arg(m_party.partyId.value()));
str.append(QStringLiteral(" aesState=%1").arg(SituationMap::toString(m_aesState.value())));
if (m_mainGraphicalObject)
str.append(QStringLiteral(" scale='%1'").arg(m_mainGraphicalObject->scale()));
str.append(QStringLiteral(" visibility='%1'").arg(m_visibility));
str.append(QStringLiteral(" visibilityTech='%1'").arg(m_visibilityTechnical));
str.append(QStringLiteral(" visibilityTact='%1'").arg(m_visibilityTactical));
str.append(QStringLiteral(" visibilityTechGeo='%1'").arg(m_visibilityTechnicalGeometry));
str.append(QStringLiteral(" identiferVisible=%1").arg(m_identiferVisible.value()));
str.append(QStringLiteral(" selected='%1'").arg(m_selected));
str.append(QStringLiteral(" pickable='%1'").arg(m_pickable));
str.append(QStringLiteral(" majorColor='%1'").arg(this->majorColor().name(QColor::HexArgb)));
return str;
}
void AbstractMapObjectImpl::boundingBox(SituationMap::BoundingBox &) const
{
// leave it empty and invalid. Method has to be overloaded if required.
}
void AbstractMapObjectImpl::setForceMajorColor(const QColor &majorColor)
{
m_forcedMajorColor = majorColor;
}
QColor AbstractMapObjectImpl::majorColor() const
{
if (m_forcedMajorColor.isValid())
return m_forcedMajorColor;
if (m_mainGraphicalObject)
return m_mainGraphicalObject->lineStyle().lineColor();
return QColor();
}
double AbstractMapObjectImpl::extrusionHeight() const
{
return m_extrusionHeight;
}
void AbstractMapObjectImpl::setExtrusionHeight(double extrusionHeight)
{
if (m_mapImpl->mode() != Mode::Mode_3D)
return;
m_extrusionHeight = extrusionHeight;
if (extrusionHeightValid())
createGraphicalObjectExtrusion();
else
resetGraphicalObjectExtrusion();
}
bool AbstractMapObjectImpl::extrusionHeightValid() const
{
return !std::isnan(m_extrusionHeight);
}
const QString AbstractMapObjectImpl::extrusionColorName() const
{
return m_extrusionColorName;
}
void AbstractMapObjectImpl::setExtrusionColorName(const QString &extrusionColorName)
{
m_extrusionColorName = extrusionColorName;
}
QString AbstractMapObjectImpl::identifier() const
{
if (m_mainGraphicalObjectText)
return m_mainGraphicalObjectText->text();
// else
// ERROR_LOG(m_logger) << LOGFUNCTION
// << " debugInfo=" << m_debugInfo
// << " no object"
// ;
return QString();
}
void AbstractMapObjectImpl::createGraphicalObjectText()
{
TRACE_LOG(m_logger) << LOGFUNCTION << " START"
<< " debugInfo=" << m_debugInfo;
if (!m_mainGraphicalObjectText)
{
m_mainGraphicalObjectText = new GraphicalObjectText(m_mapImpl->getEsriGeoView()
, m_graphicsLayer
, m_debugInfo + QLatin1String("#Text")
, uniqueMapId());
// Set default text style for all MapObjects:
m_mainGraphicalObjectText->setTextStyle(defaultTextStyle());
m_mainGraphicalObjectText->setXOffset(10); // use as initial default
}
TRACE_LOG(m_logger) << LOGFUNCTION << " END"
<< " debugInfo=" << m_debugInfo;
}
void AbstractMapObjectImpl::createTacticalAppearance()
{
TRACE_LOG(m_logger) << LOGFUNCTION << " START"
<< " debugInfo=" << m_debugInfo;
if (!m_tacticalAppearance)
{
m_tacticalAppearance = new TacticalAppearance(m_mapImpl,
m_logicalLayerName,
m_debugInfo + QStringLiteral("#TactApp"),
m_uniqueMapId
);
}
TRACE_LOG(m_logger) << LOGFUNCTION << " END"
<< " debugInfo=" << m_debugInfo;
}
void AbstractMapObjectImpl::resetTacticalAppearanceDrawOrderOffset()
{
m_tacticalAppearanceDrawOrderOffset = 0;
}
void AbstractMapObjectImpl::createPin()
{
TRACE_LOG(m_logger) << LOGFUNCTION << " START"
<< " debugInfo=" << m_debugInfo;
if (!m_graphicalObjectPin)
{
m_graphicalObjectPin = new GraphicalObjectPath(SituationMap::GraphicalObjectPathType::Polyline,
m_mapImpl->getEsriGeoView(),
m_graphicsLayer,
m_debugInfo + QStringLiteral("#Pin"),
m_uniqueMapId
);
}
TRACE_LOG(m_logger) << LOGFUNCTION << " END"
<< " debugInfo=" << m_debugInfo;
}
void AbstractMapObjectImpl::resetPin()
{
delete m_graphicalObjectPin;
m_graphicalObjectPin = nullptr;
}
void AbstractMapObjectImpl::setIdentifier(const QString &identifier)
{
if (identifier.isEmpty())
{
delete m_mainGraphicalObjectText;
m_mainGraphicalObjectText = nullptr;
}
else
{
createGraphicalObjectText();
if (m_mainGraphicalObjectText)
m_mainGraphicalObjectText->setText(identifier);
}
}
bool AbstractMapObjectImpl::identifierVisible() const
{
return m_identiferVisible.value();
}
void AbstractMapObjectImpl::setIdentifierVisible(bool identifierVisible)
{
m_identiferVisible = identifierVisible;
}
int AbstractMapObjectImpl::partyId() const
{
return m_party.partyId.value();
}
bool AbstractMapObjectImpl::isPartyIdValid() const
{
return m_party.partyId.value() >= 0;
}
void AbstractMapObjectImpl::setPartyId(int partyId)
{
m_party.partyId = partyId;
}
bool AbstractMapObjectImpl::setPartyIdChanged(int partyId)
{
if ((partyId < 0) || (m_party.partyId.value() == partyId))
{
m_party.partyId.setChanged();
return true;
}
return false;
}
const QColor &AbstractMapObjectImpl::partyColor() const
{
if (m_party.forcedPartyColor.value().isValid())
return m_party.forcedPartyColor.value();
if (m_party.partyId.changed() || m_party.useLightColor.changed() || !m_party.partyColor.isValid())
{
m_party.partyColor =
m_mapImpl->partyIdToColorFunctor().partyIdToColor(m_party.partyId.value(),
m_party.useLightColor.value());
}
return m_party.partyColor;
}
QColor AbstractMapObjectImpl::partyColor(int partyId, bool useLightColor) const
{
return m_mapImpl->partyIdToColorFunctor().partyIdToColor(partyId, useLightColor);
}
void AbstractMapObjectImpl::forcePartyColor(const QColor &partyColorToForce)
{
m_party.forcedPartyColor = partyColorToForce;
}
bool AbstractMapObjectImpl::useLightColor() const
{
return m_party.useLightColor.value();
}
void AbstractMapObjectImpl::setUseLightColor(bool useLightColor)
{
m_party.useLightColor = useLightColor;
}
AdvancedSymbology::Role AbstractMapObjectImpl::partyRole(bool roleIdentityAssumed) const
{
return m_mapImpl->partyIdToColorFunctor().partyIdToRole(m_party.partyId.value(), roleIdentityAssumed);
}
AesEffectState AbstractMapObjectImpl::aesState() const
{
return m_aesState.value();
}
void AbstractMapObjectImpl::setAesState(AesEffectState aesState)
{
m_aesState = aesState;
}
TextStyle AbstractMapObjectImpl::textStyle() const
{
if (m_mainGraphicalObjectText)
return m_mainGraphicalObjectText->textStyle();
else
return TextStyle();
}
TextStyle &AbstractMapObjectImpl::rTextStyle()
{
createGraphicalObjectText();
return m_mainGraphicalObjectText->rTextStyle();
}
void AbstractMapObjectImpl::setTextStyle(const TextStyle &textStyle)
{
createGraphicalObjectText();
m_mainGraphicalObjectText->setTextStyle(textStyle);
}
LineStyle AbstractMapObjectImpl::lineStyle() const
{
return (m_mainGraphicalObject) ? m_mainGraphicalObject->lineStyle() : LineStyle();
}
LineStyle &AbstractMapObjectImpl::rLineStyle()
{
static LineStyle dummy;
return (m_mainGraphicalObject) ? m_mainGraphicalObject->rLineStyle() : dummy;
}
void AbstractMapObjectImpl::setLineStyle(const LineStyle &lineStyle)
{
if (m_mainGraphicalObject) m_mainGraphicalObject->setLineStyle(lineStyle);
}
FillStyle AbstractMapObjectImpl::fillStyle() const
{
return (m_mainGraphicalObject) ? m_mainGraphicalObject->fillStyle() : FillStyle();
}
FillStyle &AbstractMapObjectImpl::rFillStyle()
{
static FillStyle dummy;
return (m_mainGraphicalObject) ? m_mainGraphicalObject->rFillStyle() : dummy;
}
void AbstractMapObjectImpl::setFillStyle(const FillStyle &fillStyle)
{
if (m_mainGraphicalObject) m_mainGraphicalObject->setFillStyle(fillStyle);
}
QString AbstractMapObjectImpl::layer() const
{
return logicalLayerName();
}
void AbstractMapObjectImpl::setDrawOrder(int drawOrder)
{
m_drawOrder = drawOrder;
m_internalDrawOrder = m_drawOrder * 10;
}
int AbstractMapObjectImpl::drawOrder() const
{
return m_drawOrder;
}
bool AbstractMapObjectImpl::visibility() const
{
return m_visibility;
}
void AbstractMapObjectImpl::setVisibility(bool visibility)
{
TRACE_LOG(m_logger) << LOGFUNCTION << " START"
<< " debugInfo=" << m_debugInfo
<< " visi old=" << m_visibility;
m_visibility = visibility;
TRACE_LOG(m_logger) << LOGFUNCTION << " END"
<< " debugInfo=" << m_debugInfo
<< " visi new=" << m_visibility;
}
bool AbstractMapObjectImpl::visibility(ObjectAppearance appearance) const
{
bool visi = true;
switch (appearance)
{
case SituationMap::ObjectAppearance::Technical:
visi = m_visibilityTechnical;
break;
case SituationMap::ObjectAppearance::Tactical:
visi = m_visibilityTactical;
break;
}
return visi;
}
void AbstractMapObjectImpl::setVisibility(ObjectAppearance appearance, bool visibility)
{
switch (appearance)
{
case SituationMap::ObjectAppearance::Technical:
m_visibilityTechnical = visibility;
break;
case SituationMap::ObjectAppearance::Tactical:
m_visibilityTactical = visibility;
break;
default:
ERROR_LOG(m_logger) << LOGFUNCTION << " ObjectAppearance not found";
break;
}
TRACE_LOG(m_logger) << LOGFUNCTION
<< " debugInfo=" << m_debugInfo
<< " m_visibilityTechnical=" << m_visibilityTechnical
<< " m_visibilityTactical=" << m_visibilityTactical;
}
bool AbstractMapObjectImpl::visibilityOfGeometry() const
{
return m_visibilityTechnicalGeometry;
}
void AbstractMapObjectImpl::setVisibilityOfGeometry(bool visiGeometry)
{
m_visibilityTechnicalGeometry = visiGeometry;
}
bool AbstractMapObjectImpl::selected() const
{
return m_selected;
}
void AbstractMapObjectImpl::setSelected(bool selected)
{
m_selected = selected;
}
bool AbstractMapObjectImpl::pickable() const
{
return m_pickable;
}
void AbstractMapObjectImpl::setPickable(bool pickable)
{
m_pickable = pickable;
}
float AbstractMapObjectImpl::scale() const
{
return (m_mainGraphicalObject) ? m_mainGraphicalObject->scale() : 0.0f;
}
void AbstractMapObjectImpl::setScale(float scale)
{
if (!m_enableScale)
return;
// typically the mainGraphicalObject does NOT need any scale values,
// but keep it similar to identifier, textStyle, fillStyle etc.
// mainGraphicalObjectText will receive the value within ::updateView()
if (m_mainGraphicalObject) m_mainGraphicalObject->setScale(scale);
}
bool AbstractMapObjectImpl::isScaleEnabled() const
{
return m_enableScale;
}
void AbstractMapObjectImpl::setScaleEnable(bool enabled)
{
m_enableScale = enabled;
}
SymbolData AbstractMapObjectImpl::symbol() const
{
return m_symbol.value();
}
void AbstractMapObjectImpl::setSymbol(const SymbolData &symbol)
{
m_symbol = symbol;
}
void AbstractMapObjectImpl::reRenderSymbol()
{
m_symbol.setChanged();
}
SymbolDataToRender AbstractMapObjectImpl::symbolDataToRender() const
{
return m_symbol.value().getDefaultRenderData();
}
SymbolImage AbstractMapObjectImpl::symbolImage() const
{
TRACE_LOG(m_logger) << LOGFUNCTION << " START";
TRACE_LOG(m_logger) << LOGFUNCTION << " END";
return m_symbolImage;
}
QImage AbstractMapObjectImpl::previewImage() const
{
return previewImageTypical();
}
QImage AbstractMapObjectImpl::previewImageTypical() const
{
return m_symbolImage.image();
}
QImage AbstractMapObjectImpl::previewImageSpecific() const
{
return m_symbolImage.image();
}
TextStyle AbstractMapObjectImpl::defaultTextStyle()
{
TextStyle ts; // Define default text style for all MapObjects
ts.setTextOutlineColor(Qt::white); // Define default text style for all MapObjects
ts.setTextOutlineWidth(0.5); // Define default text style for all MapObjects
return ts;
}
bool AbstractMapObjectImpl::updateTacticalAppearance()
{
bool successTactAppearance = true;
if (m_tacticalAppearance)
{
m_tacticalAppearance->setUniqueDesignation(identifier());
m_tacticalAppearance->setDrawOrder(m_internalDrawOrder + m_tacticalAppearanceDrawOrderOffset); // m_tacticalAppearanceDrawOrderOffset == 2
m_tacticalAppearance->setVisibility(m_visibility && m_visibilityTactical);
m_tacticalAppearance->setSelected(m_selected);
m_tacticalAppearance->setPickable(m_pickable);
if (m_symbol.changed())
m_tacticalAppearance->setSymbol(m_symbol.value());
if (m_mainGraphicalObject)
m_tacticalAppearance->setScale(m_mainGraphicalObject->scale());
else
ERROR_LOG(m_logger) << LOGFUNCTION << " m_mainGraphicalObject missing!!!";
successTactAppearance = m_tacticalAppearance->updateView();
}
return successTactAppearance;
}
void AbstractMapObjectImpl::createGraphicalObjectExtrusion()
{
TRACE_LOG(m_logger) << LOGFUNCTION << " START"
<< " debugInfo=" << m_debugInfo;
if (m_mapImpl->mode() != Mode::Mode_3D)
return;
if (!m_graphicalObjectExtrusion)
{
Esri::ArcGISRuntime::GraphicsOverlay *graphicsLayer = m_mapImpl->getGraphicsLayer3DExtrusion(m_logicalLayerName);
if (!graphicsLayer)
{
ERROR_LOG(m_logger) << LOGFUNCTION << " debugInfo='" << m_debugInfo << "'"
<< " getGraphicsLayer3DExtrusion failed";
return;
}
m_graphicalObjectExtrusion = new GraphicalObjectCube(m_mapImpl->getEsriGeoView(),
graphicsLayer, // ESRI-Layer, not logical
m_debugInfo + QStringLiteral("#GO3D"),
m_uniqueMapId
);
}
TRACE_LOG(m_logger) << LOGFUNCTION << " END"
<< " debugInfo=" << m_debugInfo;
}
void AbstractMapObjectImpl::resetGraphicalObjectExtrusion()
{
delete m_graphicalObjectExtrusion;
m_graphicalObjectExtrusion = nullptr;
}
bool AbstractMapObjectImpl::updateGraphicalObjectExtrusion()
{
bool successGo3D = true;
if (m_graphicalObjectExtrusion)
{
m_graphicalObjectExtrusion->setUniqueMapId(m_uniqueMapId);
// geometry:
if (m_mainGraphicalObject)
m_graphicalObjectExtrusion->setPositions(m_mainGraphicalObject->positions()); // translated / maybe they are densified?
m_graphicalObjectExtrusion->setDrawOrder(m_internalDrawOrder);
m_graphicalObjectExtrusion->setVisibility(m_visibility && m_visibilityTechnical);
m_graphicalObjectExtrusion->setSelected(m_selected);
m_graphicalObjectExtrusion->setPickable(m_pickable);
if (m_extrusionColorName.isEmpty())
{
// Fallback
const QColor &partyColor = m_mapImpl->partyIdToColorFunctor().partyIdToColor(m_party.partyId.value());
m_graphicalObjectExtrusion->setExtrusionColorName(partyColor.name());
} else {
m_graphicalObjectExtrusion->setExtrusionColorName(m_extrusionColorName);
}
m_graphicalObjectExtrusion->setHeight(m_extrusionHeight);
// scale....??
successGo3D = m_graphicalObjectExtrusion->updateView();
}
return successGo3D;
}
bool AbstractMapObjectImpl::updatePin()
{
TRACE_LOG(m_logger) << LOGFUNCTION << " START, m_debugInfo=" << m_debugInfo;
if (m_graphicalObjectPin)
{
m_graphicalObjectPin->setDrawOrder(m_internalDrawOrder + 5); // m_tacticalAppearanceDrawOrderOffset == 2
m_graphicalObjectPin->setVisibility(m_visibility);
m_graphicalObjectPin->setSelected(m_selected);
m_graphicalObjectPin->setPickable(m_pickable);
if (m_mainGraphicalObject)
{
m_graphicalObjectPin->setLineStyle(LineStyle(Qt::black, 3, LinePattern::DashDotDot));
m_graphicalObjectPin->setScale(m_mainGraphicalObject->scale());
}
else
ERROR_LOG(m_logger) << LOGFUNCTION << " m_mainGraphicalObject missing!!!";
//
// m_graphicalObjectPin->setPositions and updateView is called at GeoImageImpl::onMapExtentChanged()
//
}
TRACE_LOG(m_logger) << LOGFUNCTION << " END, m_debugInfo=" << m_debugInfo;
return true;
}
void AbstractMapObjectImpl::updateIdentifierPosition()
{
m_identifierPositionCandidateTranslated = m_mainGraphicalObject->origin();
}
bool AbstractMapObjectImpl::updateViewImplPre()
{
//
// createTacticalAppearance onDemand
//
if (!m_symbol.value().sidc.isEmpty())
createTacticalAppearance();
//
// partyId (and its resulting color) has priority to lineColor, fillColor:
//
if (isPartyIdValid() && partyChanged())
{
const QColor &partyCol = partyColor();
if (m_mainGraphicalObject)
{
if (m_lineColorFromParty)
m_mainGraphicalObject->rLineStyle().setLineColor(partyCol);
QColor fillColor(partyCol);
fillColor.setAlpha(m_fillColorAlpha);
m_mainGraphicalObject->rFillStyle().setFillColor(fillColor);
}
if (m_mainGraphicalObjectText)
m_mainGraphicalObjectText->rTextStyle().setTextColor(partyCol);
// maybe continued for TacticalAppearance
}
//
// if state!=Unknown -> its resulting pattern has priority to fillPattern:
//
if ((m_aesState.value() != AesEffectState::Unknown) && m_aesState.changed())
{
if (m_mainGraphicalObject)
{
FillPattern pattern = m_mapImpl->partyIdToColorFunctor().aesStateToPattern(m_aesState.value());
m_mainGraphicalObject->rFillStyle().setFillPattern(pattern);
}
}
return true;
}
inline bool isSurfacePlacementRelevant(Esri::ArcGISRuntime::GraphicsOverlay *graphicsLayer)
{
if (!graphicsLayer)
return false;
// maybe also SurfacePlacement::RelativeToScene ???
return (graphicsLayer->sceneProperties().surfacePlacement() == Esri::ArcGISRuntime::SurfacePlacement::Relative);
}
bool AbstractMapObjectImpl::updateViewImpl()
{
bool success = true;
bool successTactAppearance = true;
TRACE_LOG(m_logger) << LOGFUNCTION << " START"
<< " debugInfo =" << m_debugInfo
<< " uniqueMapId =" << m_uniqueMapId
<< " m_pickable=" << m_pickable;
// drawOrder :
// The LayerOrder could be added if required like...
// finalDrawOrder = m_mapImpl->layerFactory()-> indexOf(m_logicalLayerName);
if (m_mainGraphicalObjectText)
{
m_mainGraphicalObjectText->setDrawOrder(m_internalDrawOrder + 2); // +2 to provide space for indicationCont (e.g. mines of MineField)
m_mainGraphicalObjectText->setScale(m_mainGraphicalObject->scale());
}
// : drawOrder
if (m_mainGraphicalObject)
{
m_mainGraphicalObject->setDrawOrder(m_internalDrawOrder);
m_mainGraphicalObject->setVisibility(m_visibility && m_visibilityTechnical && m_visibilityTechnicalGeometry);
m_mainGraphicalObject->setSelected(m_selected);
m_mainGraphicalObject->setPickable(m_pickable);
success = m_mainGraphicalObject->updateView();
if (m_mainGraphicalObjectText)
{
this->updateIdentifierPosition();
m_mainGraphicalObjectText->setScale(m_mainGraphicalObject->scale());
// m_mainGraphicalObjectText->setSelected(m_selected); // Text should NEVER be selected
m_mainGraphicalObjectText->setPickable(m_pickable);
// mainGraphicalObjectText->updateView() will be called within following 'onMapExtentChanged()':
// successGoText = m_mainGraphicalObjectText->updateView();
}
}
successTactAppearance = updateTacticalAppearance();
bool successGoExtrusion = true;
if (m_graphicalObjectExtrusion && (m_mapImpl->mode() == Mode::Mode_3D))
{
successGoExtrusion = updateGraphicalObjectExtrusion();
if (!successGoExtrusion)
ERROR_LOG(m_logger) << LOGFUNCTION << " failure updateGraphicalObjectExtrusion " << " debugInfo =" << m_debugInfo << " uniqueMapId =" << m_uniqueMapId;
}
bool successUpdatePin = true;
if (m_graphicalObjectPin && (this->mapImpl()->mode() == Mode::Mode_3D) && isSurfacePlacementRelevant(m_graphicsLayer))
{
successUpdatePin = updatePin();
if (!successUpdatePin)
ERROR_LOG(m_logger) << LOGFUNCTION << " failure0 (updatePin) " << " debugInfo =" << m_debugInfo << " uniqueMapId =" << m_uniqueMapId;
}
bool successMapExtendChanged = this->onMapExtentChanged();
if (!success)
ERROR_LOG(m_logger) << LOGFUNCTION << " failure1 " << " debugInfo =" << m_debugInfo << " uniqueMapId =" << m_uniqueMapId;
if (!successTactAppearance)
ERROR_LOG(m_logger) << LOGFUNCTION << " failure2 " << " debugInfo =" << m_debugInfo << " uniqueMapId =" << m_uniqueMapId;
if (!successGoExtrusion)
ERROR_LOG(m_logger) << LOGFUNCTION << " failure3 " << " debugInfo =" << m_debugInfo << " uniqueMapId =" << m_uniqueMapId;
if (!successMapExtendChanged)
ERROR_LOG(m_logger) << LOGFUNCTION << " failure4 " << " debugInfo =" << m_debugInfo << " uniqueMapId =" << m_uniqueMapId;
TRACE_LOG(m_logger) << LOGFUNCTION << " START"
<< " debugInfo =" << m_debugInfo
<< " uniqueMapId =" << m_uniqueMapId;
return success && successTactAppearance && successGoExtrusion && successUpdatePin && successMapExtendChanged;
}
bool AbstractMapObjectImpl::updateViewImplPost()
{
partyReset();
m_aesState.reset();
m_symbol.reset();
m_identiferVisible.reset();
if (m_updateObjectIndicator)
{
for (auto *ptr : qAsConst(m_originPositionChangedCb))
ptr->onOriginPositionChanged();
}
m_updateObjectIndicator = false;
return true;
}
int AbstractMapObjectImpl::numberOfValuesChanged()
{
int count = 0;
if (m_party.changed()) { WARNING_LOG(m_logger) << LOGFUNCTION << " START "; ++count; }
if (m_aesState.changed()) { WARNING_LOG(m_logger) << LOGFUNCTION << " START "; ++count; }
if (m_symbol.changed()) { WARNING_LOG(m_logger) << LOGFUNCTION << " START "; ++count; }
if (m_identiferVisible.changed()) { WARNING_LOG(m_logger) << LOGFUNCTION << " START "; ++count; }
return count;
}
void AbstractMapObjectImpl::addChangedCallback(OriginPositionChangedCallback *cb)
{
m_originPositionChangedCb.push_back(cb);
}
void AbstractMapObjectImpl::removeChangedCallback(OriginPositionChangedCallback *cb)
{
m_originPositionChangedCb.removeAll(cb);
}
bool AbstractMapObjectImpl::init(MapImpl *mapImpl, const QString &logicalLayerName)
{
TRACE_LOG(m_logger) << LOGFUNCTION << " START"
<< " debugInfo=" << m_debugInfo;
bool success = true;
if (mapImpl)
m_mapImpl = mapImpl;
else
{
success = false;
ERROR_LOG(m_logger) << LOGFUNCTION
<< " debugInfo=" << m_debugInfo
<< " no mapImpl";
}
m_mapConnector = new SituationMap::MapConnector();
success = success && m_mapConnector->connectMapObject(m_mapImpl, this);
if (success)
{
success = this->setLogicalLayerName(logicalLayerName);
if (!success)
{
ERROR_LOG(m_logger) << LOGFUNCTION
<< " debugInfo=" << m_debugInfo
<< " setLogicalLayerName failed"
<< ", logicalLayerName='" << logicalLayerName << "'";
}
}
else
{
ERROR_LOG(m_logger) << LOGFUNCTION
<< " debugInfo=" << m_debugInfo
<< " MapConnector->connectObject failed";
}
// take static scaleHasVisibilityValue;
m_visibilityScaleRange.setInitial(s_scaleHasVisibilityValue); // static mamber of interface class.
TRACE_LOG(m_logger) << LOGFUNCTION << " END"
<< " debugInfo=" << m_debugInfo
<< " success=" << success;
return success;
}
void AbstractMapObjectImpl::setUniqueId(const UniqueMapId &uniqueId)
{
m_uniqueMapId = uniqueId;
if (m_mainGraphicalObject)
m_mainGraphicalObject->setUniqueMapId(m_uniqueMapId);
if (m_mainGraphicalObjectText)
m_mainGraphicalObjectText->setUniqueMapId(m_uniqueMapId);
if (m_tacticalAppearance)
m_tacticalAppearance->setUniqueMapId(m_uniqueMapId);
}
bool AbstractMapObjectImpl::onMapExtentChanged()
{
TRACE_LOG(m_logger) << LOGFUNCTION << " START" << " debugInfo=" << m_debugInfo;
bool success = true;
// Some MapObjects like ParticipantImpl do NOT use m_mainGraphicalObjectText:
if (m_mainGraphicalObjectText && m_mapImpl)
{
// hide identifier on zoom out???
// old approach:
// double meterPerPixel = -1.0;
// if (m_mapImpl)
// meterPerPixel = m_mapImpl->pixelSize();
// bool textVisi = meterPerPixel < 3000;
// new approach:
// double curScale = m_mapImpl->scale();
// bool textVisi = m_visibilityScaleRange.scaleHasVisibility(curScale);
// m_mainGraphicalObjectText->setVisibility(m_visibility && m_visibilityTechnical && textVisi);
// TRACE_LOG(m_logger) << LOGFUNCTION << " START"
// << " debugInfo=" << m_debugInfo << "'"
// << " meterPerPixel=" << m_mapImpl->pixelSize()
// << " newScale=" << m_mapImpl->scale()
// << " newExtent = " << SituationMap::toString(m_mapImpl->extent());
// m_mainGraphicalObjectText->setVisibility(m_visibility && m_visibilityTechnical && textVisi);
// do NOT hide identifier on zoom out:
m_mainGraphicalObjectText->setVisibility(m_visibility && m_visibilityTechnical && m_identiferVisible.value());
m_mainGraphicalObjectText->setOrigin(m_identifierPositionCandidateTranslated);
success = m_mainGraphicalObjectText->updateView();
}
TRACE_LOG(m_logger) << LOGFUNCTION << " END"
<< " debugInfo=" << m_debugInfo << "'"
<< " success=" << success;
return true;
}
QString AbstractMapObjectImpl::logicalLayerName() const
{
return m_logicalLayerName;
}
bool AbstractMapObjectImpl::setLogicalLayerName(const QString &logicalLayerName)
{
TRACE_LOG(m_logger) << LOGFUNCTION << " START"
<< " debugInfo='" << m_debugInfo << "'"
<< " logicalLayerName='" << logicalLayerName << "'";
m_logicalLayerName = logicalLayerName;
bool success = false;
m_graphicsLayer = m_mapImpl->getGraphicsLayer(logicalLayerName);
if (m_graphicsLayer)
success = true;
else
{
ERROR_LOG(m_logger) << LOGFUNCTION
<< " debugInfo=" << m_debugInfo << "'"
<< ", no layer found";
}
TRACE_LOG(m_logger) << LOGFUNCTION << " END"
<< " debugInfo='" << m_debugInfo << "'"
<< " logicalLayerName='" << logicalLayerName << "'"
<< " success=" << success;
return success;
}
bool AbstractMapObjectImpl::geometryIntersect(const MathUtils::GeometryEngine::Geometry &intersector_polyline) const
{
if (intersector_polyline.isEmpty())
return false;
if (m_mainGraphicalObject)
{
Esri::ArcGISRuntime::GraphicsOverlay *esriLayer = m_mainGraphicalObject->graphicsLayer();
if ((esriLayer) && (esriLayer->isVisible()))
{
// former: if (m_mainGraphicalObject->visibility())
// MineField stores the ountline/boundary in m_mainGraphicalObject to transfer this to m_tacticalAppearance
// That m_mainGraphicalObject is NOT visible, because of that fillPattern.
// to 'find' that MineField, anaylze just m_visibility && m_visibilityTechnical, and not m_visibilityTechnicalGeometry
if (m_visibility && m_visibilityTechnical)
{
if (MathUtils::GeometryEngine::intersect(m_mainGraphicalObject->getGraphicGeometry(), intersector_polyline))
return true;
}
}
}
// m_mainGraphicalObjectText
if (m_tacticalAppearance)
{
Esri::ArcGISRuntime::GraphicsOverlay *esriLayer = m_tacticalAppearance->graphicsLayer();
if ((esriLayer) && (esriLayer->isVisible()))
{
if (m_tacticalAppearance->visibility())
{
if (MathUtils::GeometryEngine::intersect(m_tacticalAppearance->getGraphicGeometry(), intersector_polyline))
return true;
}
}
}
return false;
} // bool AbstractMapObjectImpl::geometryIntersect( const MathUtils::GeometryEngine::Geometry & geom )
bool AbstractMapObjectImpl::geometryIsInHull(const MathUtils::GeometryEngine::Geometry &hull_polygon) const
{
if (hull_polygon.isEmpty())
return false;
if (m_mainGraphicalObject)
{
Esri::ArcGISRuntime::GraphicsOverlay *esriLayer = m_mainGraphicalObject->graphicsLayer();
if ((esriLayer) && (esriLayer->isVisible()))
{
// former: if (m_mainGraphicalObject->visibility())
// MineField stores the ountline/boundary in m_mainGraphicalObject to transfer this to m_tacticalAppearance
// That m_mainGraphicalObject is NOT visible, because of that fillPattern.
// to 'find' that MineField, anaylze just m_visibility && m_visibilityTechnical, and not m_visibilityTechnicalGeometry
if (m_visibility && m_visibilityTechnical)
{
if (MathUtils::GeometryEngine::contains(m_mainGraphicalObject->getGraphicGeometry(), hull_polygon))
return true;
}
}
}
// m_mainGraphicalObjectText
if (m_tacticalAppearance)
{
Esri::ArcGISRuntime::GraphicsOverlay *esriLayer = m_tacticalAppearance->graphicsLayer();
if ((esriLayer) && (esriLayer->isVisible()))
{
if (m_tacticalAppearance->visibility())
{
if (MathUtils::GeometryEngine::contains(m_tacticalAppearance->getGraphicGeometry(), hull_polygon))
return true;
}
}
}
return false;
}
Esri::ArcGISRuntime::Geometry AbstractMapObjectImpl::getEsriGeometry() const
{
if (!m_mainGraphicalObject)
return Esri::ArcGISRuntime::Geometry();
return m_mainGraphicalObject->getGraphicGeometry();
}
} // namespace SituationMap