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

+110
View File
@@ -0,0 +1,110 @@
#
# $Id$
# $HeadURL$
# $Author$
#
FIND_PACKAGE(ArcGIS REQUIRED)
# LIBRARY
SET(MapObj_SRCS
# geometry.cpp
)
SET(MapObj_HDRS
situation_map_objects_export.h
)
SET(MapObjImpl_SRCS
abstract_multi_point_map_object_impl.cpp
abstract_single_point_map_object_impl.cpp
air_support_impl.cpp
area_fire_impl.cpp
basic_path_object_impl.cpp
biological_agent_impl.cpp
building_outline_impl.cpp
chemical_agent_impl.cpp
cube_impl.cpp
danger_area_impl.cpp
functional_area_impl.cpp
geo_image_impl.cpp
hit_line_impl.cpp
line_of_sight_impl.cpp
indication_container.cpp
mine_impl.cpp
map_object_attributes_impl.cpp
map_object_indicator_impl.cpp
mine_field_impl.cpp
nine_liner_impl.cpp
nuclear_agent_impl.cpp
path_container.cpp
path_container.h
participant_impl.cpp
polygon_impl.cpp
polyline_impl.cpp
single_fire_impl.cpp
# single_fire_central_impl.cpp
sound_area_impl.cpp
text_impl.cpp
virtual_mine_impl.cpp
)
SET(MapObjImpl_HDRS
abstract_multi_point_map_object_impl.h
abstract_single_point_map_object_impl.h
air_support_impl.h
area_fire_impl.h
basic_path_object_impl.h
biological_agent_impl.h
building_outline_impl.h
chemical_agent_impl.h
cube_impl.h
danger_area_impl.h
functional_area_impl.h
geo_image_impl.h
hit_line_impl.h
line_of_sight_impl.h
indication_container.h
map_object_attributes_impl.h
map_object_indicator_impl.h
mine_field_impl.h
mine_impl.h
nuclear_agent_impl.h
nine_liner_impl.h
participant_impl.h
polygon_impl.h
polyline_impl.h
single_fire_impl.h
# single_fire_central_impl.h
sound_area_impl.h
text_impl.h
virtual_mine_impl.h
situation_map_objects_export.h
)
SOURCE_GROUP(FunctionDialog FILES ${FunctionDialog_SRCS})
SOURCE_GROUP(MapObjectsImpl FILES ${MapObj_SRCS} ${MapObj_HDRS} ${MapObjImpl_SRCS} ${MapObjImpl_HDRS})
NGL_ADD_LIBRARY(WS situationMapObjects SHARED ${MapObj_SRCS} ${MapObj_HDRS} ${MapObjImpl_SRCS} ${MapObjImpl_HDRS})
NGL_TARGET_INCLUDE_DIRECTORIES(situationMapObjects
PUBLIC
${CMAKE_CURRENT_SOURCE_DIR}
${CMAKE_CURRENT_SOURCE_DIR}/..
)
NGL_TARGET_LINK_LIBRARIES(situationMapObjects
PRIVATE
NGLLogger
ArcGIS::ArcGIS
LtsCoordTrans
PUBLIC
situationMap
Qt5::Core
Qt5::Widgets
)
NGL_INSTALL_TARGET(situationMapObjects)
@@ -0,0 +1,415 @@
/**
* @RDE_HEADER@
* Interface-Implementation of SingleFire
* $Id$
* $HeadURL$
* $Author$
*/
// Own
#include "single_fire_central_impl.h"
#include "single_fire_impl.h"
#include <MapImpl/map_impl.h>
#include <Map/party_id_to_color_functor.h>
#include <GraphicalObjects/graphical_object_ellipse.h>
#include <GraphicalObjects/tactical_appearance.h>
#include <Symbology/sidc_codec.h>
// ESRI
#include <arcgis/GraphicsOverlay.h>
#include <arcgis/GraphicListModel.h>
#include <arcgis/GeometryEngine.h>
// Qt
#include <QPainter>
#include <QPen>
#include <QVariantAnimation>
#include <QTimer>
namespace SituationMap
{
class MyAnimation : public QVariantAnimation
{
public:
MyAnimation(GraphicalObjectSceneMarker *detonationSceneMarker)
: m_detonationSceneMarker(detonationSceneMarker)
{}
~MyAnimation() = default;
void updateCurrentValue(const QVariant &value)
{
if (!m_detonationSceneMarker)
return;
fs = m_detonationSceneMarker->fillStyle();
col = fs.fillColor();
col.setAlphaF(value.toFloat());
fs.setFillColor(col);
m_detonationSceneMarker->setFillStyle(fs);
m_detonationSceneMarker->updateView();
}
private:
GraphicalObjectSceneMarker *m_detonationSceneMarker{nullptr};
FillStyle fs;
QColor col;
};
//-----------------------------------------------------------------------------
// class SingleFireCentralImpl
//-----------------------------------------------------------------------------
SingleFireCentralImpl::SingleFireCentralImpl(const QString &debugInfo)
: SingleFireCentral() // Interface
, BaseClass(debugInfo) // Implementation
, m_logger(getLogger("SingleFireCentralImpl"))
{
TRACE_LOG(m_logger) << LOGFUNCTION << " START";
m_fillColorAlpha = 200;
TRACE_LOG(m_logger) << LOGFUNCTION << " END";
}
SingleFireCentralImpl::~SingleFireCentralImpl()
{
TRACE_LOG(m_logger) << LOGFUNCTION << " START";
delete m_animation;
delete m_centerImage;
delete m_detonationPath;
delete m_detonationSceneMarker;
TRACE_LOG(m_logger) << LOGFUNCTION << " END";
}
QString SingleFireCentralImpl::toString() const
{
QString str;
str.append(BaseClass::toString());
str.append(BasicPathObjectImpl::toString());
return str;
}
Point3D SingleFireCentralImpl::impactOrigin() const
{
return BaseClass::tacticalOrigin();
}
void SingleFireCentralImpl::setImpactOrigin(const Point3D &impactOrigin)
{
BaseClass::setTacticalOrigin(impactOrigin);
}
void SingleFireCentralImpl::setDetonation(const SingleFireCentral::DetonationData &detonationData)
{
if (m_detonationOrigin.value().origin() != detonationData.m_origin)
m_detonationOrigin.refValue().setOrigin(detonationData.m_origin);
m_detonationRadius = detonationData.m_radius;
}
SingleFireCentral::DetonationData SingleFireCentralImpl::detonation() const
{
return {m_detonationOrigin.value().origin(), m_detonationRadius.value()};
}
bool SingleFireCentralImpl::startDetonationAnimation()
{
if (!m_detonationSceneMarker)
return false;
if (!m_animation)
{
m_animation = new MyAnimation(m_detonationSceneMarker);
m_animation->setDuration(500);
m_animation->setKeyValueAt(0.0 , 1.0);
m_animation->setKeyValueAt(0.2 , 0.5);
m_animation->setKeyValueAt(1.0 , 0.1);
// m_animation.setEasingCurve(QEasingCurve::InOutQuart);
}
m_animation->stop();
m_animation->start();
if (!m_symbol3D)
{
qCritical() << " ModelSceneSymbol: ....:";
// m_symbol3D = new Esri::ArcGISRuntime::ModelSceneSymbol(QUrl(QLatin1Literal("/shd/CTC/TOOLS/ArcGIS/Runtime/Data/3D/Bristol/Collada/Bristol.dae")), 5.0); // works
// m_symbol3D = new Esri::ArcGISRuntime::ModelSceneSymbol(QUrl(QLatin1Literal("/shd/CTC/TOOLS/ArcGIS/Proof_of_concept_Explosion_DAE/Proof_of_concept_Explosion_DAE_01.dae")), 10.0);
// m_symbol3D = new Esri::ArcGISRuntime::ModelSceneSymbol(QUrl(QLatin1Literal("/shd/CTC/TOOLS/ArcGIS/Proof_of_concept_Explosion_DAE/Proof_of_concept_Explosion_DAE_02_60FPS.dae")), 10.0);
// m_symbol3D = new Esri::ArcGISRuntime::ModelSceneSymbol(QUrl(QLatin1Literal("/shd/CTC/TOOLS/ArcGIS/Proof_of_concept_Explosion_DAE/Proof_of_concept_Explosion_DAE_Sampled.dae")), 10.0);
// m_symbol3D = new Esri::ArcGISRuntime::ModelSceneSymbol(QUrl(QLatin1Literal("/shd/CTC/TOOLS/ArcGIS/Proof_of_concept_Explosion_DAE/Proof_of_concept_Explosion_DAE_unbaked.dae")), 10.0);
// m_symbol3D = new Esri::ArcGISRuntime::ModelSceneSymbol(QUrl(QLatin1Literal("/shd/CTC/TOOLS/ArcGIS/Proof_of_concept_Explosion_DAE/Proof_of_concept_Explosion_3ds_NoAnimation.3ds")), 10.0);
// m_symbol3D = new Esri::ArcGISRuntime::ModelSceneSymbol(QUrl(QLatin1Literal("/shd/CTC/TOOLS/ArcGIS/Runtime/Data/3D/3dexport/explosion/explosionFBX.fbx")), 10.0);
// m_symbol3D = new Esri::ArcGISRuntime::ModelSceneSymbol(QUrl(QLatin1Literal("/shd/CTC/TOOLS/ArcGIS/Runtime/Data/3D/3dexport/JetAnim/jet anim.fbx")), 10.0); // works
// m_symbol3D = new Esri::ArcGISRuntime::ModelSceneSymbol(QUrl(QLatin1Literal("/shd/CTC/TOOLS/ArcGIS/Runtime/Data/3D/bradley_low_3ds/bradle.3ds")), 10.0); // works
m_symbol3D = new Esri::ArcGISRuntime::ModelSceneSymbol(QUrl(QStringLiteral("/shd/CTC/TOOLS/ArcGIS/Runtime/Data/3D/dolmus_3ds/dolmus.3ds")), 10.0);
QObject::connect(m_symbol3D, &Esri::ArcGISRuntime::ModelSceneSymbol::errorOccurred,
m_animation, [](const Esri::ArcGISRuntime::Error &loadError){
qCritical() << " Error: : isEmpty:" << loadError.isEmpty();
qCritical() << " Error: : code:" << loadError.code();
qCritical() << " Error: : loadError:" << loadError.message();
});
QObject::connect(m_symbol3D, &Esri::ArcGISRuntime::ModelSceneSymbol::doneLoading,
m_animation, [](const Esri::ArcGISRuntime::Error &loadError){
qCritical() << " ModelSceneSymbol: doneLoading: isEmpty:" << loadError.isEmpty();
qCritical() << " ModelSceneSymbol: doneLoading: code:" << loadError.code();
qCritical() << " ModelSceneSymbol: doneLoading: loadError:" << loadError.message();
});
m_symbol3D->load();
if (!m_graphic3D)
{
Point3D pos = m_detonationOrigin.value().originTranslated();
m_graphic3D = new Esri::ArcGISRuntime::Graphic( Esri::ArcGISRuntime::Point(pos.x(), pos.y(), 20, m_mapImpl->getEsriSpatialReference()), m_symbol3D);
m_graphicsLayer->graphics()->append(m_graphic3D);
}
}
return true;
}
AesEffectState SingleFireCentralImpl::aesState() const
{
return BaseClass::aesState();
}
void SingleFireCentralImpl::setAesState(AesEffectState aesState)
{
BaseClass::setAesState(aesState);
}
SymbolImage SingleFireCentralImpl::symbolImage() const
{
SymbolImage symImage = m_tacticalAppearance->symbolImage();
return symImage;
}
bool SingleFireCentralImpl::updateViewImpl()
{
TRACE_LOG(m_logger) << LOGFUNCTION << " START"
<< " positions =" << this->positions()
<< " radius =" << this->radius()
<< " partyId =" << this->partyId()
<< " visibility=" << m_visibility
<< " visiTechn=" << m_visibilityTechnical
<< " visiTact=" << m_visibilityTactical;
if (m_tacticalAppearance)
{
if (partyChanged())
m_symbol.refValue().color = partyColor();
}
// centerImage:
if (!m_centerImage)
{
m_centerImage =
new GraphicalObjectPictureMarker(m_mapImpl->getEsriGeoView(),
m_graphicsLayer,
m_debugInfo + QLatin1String("#CenterImage"),
m_uniqueMapId);
}
if (partyChanged())
{
QImage img = SingleFireImpl::renderImpactSymbol(partyColor(), 20, true); // filled
m_centerImage->setImage(img);
}
// m_centerImage->setScale(m_mainGraphicalObject->scale()); // do not scale centerImage, equal to mine of MineArea
m_centerImage->setOrigin(m_tacticalOrigin.value().originTranslated());
m_centerImage->setVisibility(m_visibility && m_visibilityTechnical);
bool success = BaseClass::updateViewImpl(); // will call onMapExtentChanged and therefore m_centerImage->updateView
bool successDetonationSceneMarker = true;
switch (m_mapImpl->mode())
{
case Mode::Mode_2D:
successDetonationSceneMarker = updateDetonationPath();
break;
case Mode::Mode_3D:
successDetonationSceneMarker = updateDetonationSceneMarker();
break;
case Mode::Undefined:
// empty
break;
}
success = success && successDetonationSceneMarker;
if (!success)
ERROR_LOG(m_logger) << LOGFUNCTION << " updateViewImpl failed";
TRACE_LOG(m_logger) << LOGFUNCTION << " END, success=" << success;
return success;
}
bool SingleFireCentralImpl::updateDetonationPath()
{
TRACE_LOG(m_logger) << LOGFUNCTION << " START";
bool success = true;
// do we have a detonationPoint / impactOrigin?
if (m_detonationOrigin.value().origin().isNull() && (m_detonationRadius.value() < 1.0))
{
delete m_detonationPath;
m_detonationPath = nullptr;
} else {
if (!m_detonationPath)
{
m_detonationPath =
new GraphicalObjectEllipse(m_mapImpl->getEsriGeoView(),
m_graphicsLayer,
m_debugInfo + QLatin1String("#DetonationEllipse"),
m_uniqueMapId);
}
{
EllipseParameters ellipsePara;
ellipsePara.setLengthX(m_detonationRadius.value());
ellipsePara.setLengthY(m_detonationRadius.value());
ellipsePara.setMaxSegmentLength(1);
ellipsePara.setMaxPointCount(30); // limit to 30 to reduce the number of vertices. If to high, keep performance impact to 3D in mind!!!
m_detonationPath->setEllipseParameters(ellipsePara);
}
m_detonationPath->setOrigin(m_detonationOrigin.value().originTranslated());
m_detonationPath->setPickable(m_pickable);
// path == 0; indicationCont == 1; Marker == 2
m_detonationPath->setDrawOrder(m_internalDrawOrder+2);
QColor col = partyColor();
m_detonationPath->setLineStyle(LineStyle(col, 2));
col.setAlphaF(col.alphaF() / 2.0);
m_detonationPath->setFillStyle(FillStyle(col,
m_mainGraphicalObject->fillStyle().fillPattern())); // take fillpattern
m_detonationPath->setScale(this->scale());
success = m_detonationPath->updateView();
}
TRACE_LOG(m_logger) << LOGFUNCTION << " END, success=" << success;
return success;
}
bool SingleFireCentralImpl::updateDetonationSceneMarker()
{
TRACE_LOG(m_logger) << LOGFUNCTION << " START";
bool success = true;
// do we have a detonationPoint / impactOrigin?
if (m_detonationOrigin.value().origin().isNull() && (m_detonationRadius.value() < 1.0))
{
delete m_detonationSceneMarker;
m_detonationSceneMarker = nullptr;
} else {
if (!m_detonationSceneMarker)
{
m_detonationSceneMarker =
new GraphicalObjectSceneMarker(m_mapImpl->getEsriGeoView(),
m_graphicsLayer,
m_debugInfo + QLatin1String("#DetonationSceneMarker"),
m_uniqueMapId);
}
m_detonationSceneMarker->setOrigin(m_detonationOrigin.value().originTranslated());
m_detonationSceneMarker->setDiameter(m_detonationRadius.value()*2.0);
m_detonationSceneMarker->setPickable(m_pickable);
// path == 0; indicationCont == 1; Marker == 2
m_detonationSceneMarker->setDrawOrder(m_internalDrawOrder+2);
QColor col = partyColor();
col.setAlphaF(col.alphaF() / 2.0);
m_detonationSceneMarker->setFillStyle(FillStyle(col, FillPattern::Solid));
success = m_detonationSceneMarker->updateView();
}
// DEBUG: Animation in a loop
startDetonationAnimation();
// check intersect
if (m_detonationSceneMarker && m_mainGraphicalObject ){
Esri::ArcGISRuntime::GeometryEngine* geoEngine = Esri::ArcGISRuntime::GeometryEngine::instance();
Esri::ArcGISRuntime::Geometry geoLine = m_mainGraphicalObject->getGraphicGeometry();
qCritical() << " geoLine " << geoLine.toJson();
Esri::ArcGISRuntime::Geometry geoSphere = m_detonationSceneMarker->getGraphicGeometry();
qCritical() << " geoSphere " << geoSphere.toJson();
Esri::ArcGISRuntime::Geometry resultGeometry =
geoEngine->intersection(geoLine, geoSphere);
qCritical() << " resultGeometry " << resultGeometry.toJson();
}
if (m_animation)
QObject::connect(m_animation, &QVariantAnimation::finished, [this]()
{
QTimer::singleShot(2000, m_animation, [this]() {
m_animation->start();
});
});
TRACE_LOG(m_logger) << LOGFUNCTION << " END, success=" << success;
return success;
}
bool SingleFireCentralImpl::init(MapImpl *mapImpl, const QString &logicalLayerName)
{
TRACE_LOG(m_logger) << LOGFUNCTION << " START";
bool success = BaseClass::init(mapImpl, logicalLayerName, GraphicalObjectPathType::Polyline);
if (!success)
ERROR_LOG(m_logger) << LOGFUNCTION << " init failed";
setLineStyle(LineStyle(Qt::black, 2));
m_detonationOrigin.refValue().setMapObjectImpl(this);
TRACE_LOG(m_logger) << LOGFUNCTION << " END, success=" << success;
return success;
}
bool SingleFireCentralImpl::onMapExtentChanged()
{
TRACE_LOG(m_logger) << LOGFUNCTION << " START";
bool successCenterImage = true;
bool visiScale = m_visibilityScaleRange.scaleHasVisibility(m_mapImpl->scale());
if (m_centerImage)
{
m_centerImage->setVisibility(visiScale && m_visibility && m_visibilityTechnical);
successCenterImage = m_centerImage->updateView();
}
bool successDetonationSceneMarker = true;
if (m_detonationSceneMarker)
{
m_detonationSceneMarker->setVisibility(visiScale && m_visibility && m_visibilityTechnical);
successCenterImage = m_detonationSceneMarker->updateView();
}
bool success = BaseClass::onMapExtentChanged() && successCenterImage && successDetonationSceneMarker;
TRACE_LOG(m_logger) << LOGFUNCTION << " END, success=" << success;
return success;
}
} // namespace SituationMap
@@ -0,0 +1,116 @@
/**
* @RDE_HEADER@
* Interface-Implementation of SingleFire
* $Id$
* $HeadURL$
* $Author$
*/
#pragma once
// Own
#include "basic_path_object_impl.h"
#include <MapObjects/single_fire_central.h> // Interface
#include <GraphicalObjects/graphical_object_picture_marker.h>
#include <GraphicalObjects/graphical_object_ellipse.h>
#include <GraphicalObjects/graphical_object_scene_marker.h>
#include <arcgis/ModelSceneSymbol.h>
// Qt
//----------------------------------------------------------------------------
namespace SituationMap
{
class MyAnimation;
/**
* @brief The SingleFireCentralImpl class displays a single impact.
*
* A class instance consists of the following logical elements:
* - mainGraphicalObject (displaying a polyline)
* - mainGraphicalObjectText (displaying the text/name)
* - tacticalAppearance (displaying the tact. Appearance)
*/
// inherent 'public', to get that implementation
// inherent 'public virtual' to get that interface
class SITUATIONMAPOBJECTS_EXPORT SingleFireCentralImpl : public BasicPathObjectImpl, public virtual SingleFireCentral
{
using BaseClass = BasicPathObjectImpl;
template <typename> friend class GenericObjectFactory;
protected:
explicit SingleFireCentralImpl(const QString &debugInfo = QString());
virtual ~SingleFireCentralImpl();
public:
SingleFireCentralImpl(const SingleFireCentralImpl &other) = delete;
SingleFireCentralImpl &operator=(SingleFireCentralImpl &other) = delete;
QString toString() const override;
// some set/get methods:
//@{
void setDetonation(const DetonationData &detonationData) override;
DetonationData detonation() const override;
bool startDetonationAnimation() override;
// required???
Point3D impactOrigin() const override;
void setImpactOrigin(const Point3D &impactOrigin) override;
//@}
// Delegate to BaseClass:
AesEffectState aesState() const override;
void setAesState(AesEffectState aesState) override;
SymbolImage symbolImage() const override;
protected:
bool updateViewImpl() override;
bool updateViewImplPost() override
{
BaseClass::updateViewImplPost();
m_detonationOrigin.reset();
m_detonationRadius.reset();
return true;
}
bool updateDetonationPath();
bool updateDetonationSceneMarker();
friend class MapImpl;
bool init(MapImpl *mapImpl, const QString &logicalLayerName) override;
bool onMapExtentChanged() override;
// internal/admin
// logical
private:
LOGGER_T m_logger; ///< Interface of the Logging-Facility
GraphicalObjectPictureMarker *m_centerImage{nullptr};
SimpleValue<OriginTranslated> m_detonationOrigin;
SimpleValue<double> m_detonationRadius{0.0};
GraphicalObjectEllipse *m_detonationPath{nullptr}; // 2D
GraphicalObjectSceneMarker *m_detonationSceneMarker{nullptr}; // 3D
MyAnimation *m_animation{nullptr};
Esri::ArcGISRuntime::Graphic *m_graphic3D{nullptr};
Esri::ArcGISRuntime::ModelSceneSymbol *m_symbol3D{nullptr};
};
} // namespace SituationMap
@@ -0,0 +1,287 @@
/**
* @RDE_HEADER@
* Interface-Implementation of AbstractMultiPointMapObject
* $Id$
* $HeadURL$
* $Author$
*/
// Own
#include "abstract_multi_point_map_object_impl.h"
#include <MapImpl/map_impl.h>
#include <Map/bounding_box.h>
#include <GraphicalObjects/abstract_graphical_object.h>
#include <GraphicalObjects/graphical_object_text.h>
#include <LtsCoordTrans/lts_coord_trans.h>
// ESRI
// Qt
#include <QPainter>
#include <QBrush>
namespace SituationMap
{
// taken from AreaEffectSimulation::Icons::imageFromPolygon()
QImage imageFromForm(const PositionCont &polyAbsGeoPos,
QColor lineColor,
bool closed,
Qt::BrushStyle style,
QColor fillColor = Qt::black,
const int width = 100)
{
if (polyAbsGeoPos.isEmpty())
return QImage();
QPolygonF polyInUtmCoords;
polyInUtmCoords.reserve(polyAbsGeoPos.size());
int zone = LtsCoordTrans::UtmCoordinate::fromGeographic(polyAbsGeoPos.first().toPointF()).zone;
for (const Point3D &point : polyAbsGeoPos)
{
const LtsCoordTrans::UtmCoordinate &coord = LtsCoordTrans::UtmCoordinate::fromGeographic(point.toPointF(), zone);
polyInUtmCoords << QPointF(coord.x, coord.y);
}
const QPolygonF bounding = polyInUtmCoords.boundingRect();
// center to center / Todo:: Does it always work?
const QTransform mTrans(QTransform::fromTranslate(-bounding.boundingRect().bottomLeft().x(), -bounding.boundingRect().bottomLeft().y()));
qreal w = bounding.boundingRect().width();
qreal h = bounding.boundingRect().height();
double scale = w > h ? width / w : width / h;
w *= scale;
h *= scale;
scale *= 0.90; // Leave 10% border (i.e. 5% each side)
const QTransform mScale(QTransform::fromScale(scale, -scale));
const QTransform mTransSmall(QTransform::fromTranslate(0.05 * width + (width - w) / 2, 0.05 * width + (width - h) / 2));
QImage img(width, width, QImage::Format_ARGB32);
img.fill(Qt::transparent);
QPainter painter(&img);
painter.setRenderHint(QPainter::Antialiasing, true);
painter.setPen(QPen(lineColor, 2));
QPolygonF mPoly = mTrans.map(polyInUtmCoords);
mPoly = mScale.map(mPoly);
mPoly = mTransSmall.map(mPoly);
if (closed && fillColor.isValid())
{
// polyGON / closed:
painter.setBrush(QBrush(fillColor, style));
painter.drawPolygon(mPoly);
}
else
{
// polyLINE / open:
painter.drawPolyline(mPoly);
}
painter.end();
return img;
}
//-----------------------------------------------------------------------------
// class AbstractMultiPointMapObjectImpl
//-----------------------------------------------------------------------------
AbstractMultiPointMapObjectImpl::AbstractMultiPointMapObjectImpl(const QString &debugInfo)
: AbstractMultiPointMapObject() // Interface
, BaseClass(debugInfo) // Implementation
, m_logger(getLogger("AbstractMultiPointMapObjectImpl"))
{
TRACE_LOG(m_logger) << LOGFUNCTION << " START";
m_positions.setMapObjectImpl(this);
TRACE_LOG(m_logger) << LOGFUNCTION << " END";
}
AbstractMultiPointMapObjectImpl::~AbstractMultiPointMapObjectImpl()
{
TRACE_LOG(m_logger) << LOGFUNCTION << " START";
TRACE_LOG(m_logger) << LOGFUNCTION << " END";
}
PositionCont AbstractMultiPointMapObjectImpl::positions() const
{
return m_positions.positions();
}
PositionCont AbstractMultiPointMapObjectImpl::positionsTranslated() const
{
return m_positions.positionsTranslated();
}
bool AbstractMultiPointMapObjectImpl::setPositionsTranslated(const PositionCont &positions)
{
m_updateObjectIndicator = m_positions.setPositionsTranslated(positions) || m_updateObjectIndicator;
return m_updateObjectIndicator;
}
bool AbstractMultiPointMapObjectImpl::setPositions(const PositionCont &positions)
{
m_updateObjectIndicator = m_positions.setPositions(positions) || m_updateObjectIndicator;
return m_updateObjectIndicator;
}
LineStyle AbstractMultiPointMapObjectImpl::lineStyle() const
{
return BaseClass::lineStyle();
}
LineStyle &AbstractMultiPointMapObjectImpl::rLineStyle()
{
return BaseClass::rLineStyle();
}
void AbstractMultiPointMapObjectImpl::setLineStyle(const LineStyle &lineStyle)
{
BaseClass::setLineStyle(lineStyle);
}
FillStyle AbstractMultiPointMapObjectImpl::fillStyle() const
{
return BaseClass::fillStyle();
}
FillStyle &AbstractMultiPointMapObjectImpl::rFillStyle()
{
return BaseClass::rFillStyle();
}
void AbstractMultiPointMapObjectImpl::setFillStyle(const FillStyle &fillStyle)
{
BaseClass::setFillStyle(fillStyle);
}
void AbstractMultiPointMapObjectImpl::updateIdentifierPosition()
{
// NOTICE_LOG(m_logger) << LOGFUNCTION << " START" << " debugInfo=" << m_debugInfo;
if (!m_mainGraphicalObject)
return;
if (m_positions.isEmpty())
return;
// find right coordinate:
Point3D resultPos;
const PositionCont &posCont = m_positions.positionsTranslated();
for (const Point3D &pos : qAsConst(posCont))
if (pos.x() > resultPos.x())
resultPos = pos;
if (!qFuzzyIsNull(resultPos.x()))
m_identifierPositionCandidateTranslated = resultPos;
}
QString AbstractMultiPointMapObjectImpl::toString() const
{
QString str;
str.append(BaseClass::toString());
str.append(QStringLiteral(" positions.count='%1'").arg(m_positions.positions().count()));
return str;
}
void AbstractMultiPointMapObjectImpl::boundingBox(BoundingBox &bbox) const
{
bbox.reset();
const PositionCont &posCont = m_positions.positions();
if (posCont.isEmpty())
return;
QVectorIterator<Point3D> it(posCont);
const Point3D &pos = it.next();
double xmin = pos.x();
double ymin = pos.y();
double xmax = pos.x();
double ymax = pos.y();
while (it.hasNext())
{
const Point3D &pos2 = it.next();
xmin = std::min(xmin, pos2.x());
ymin = std::min(ymin, pos2.y());
xmax = std::max(xmax, pos2.x());
ymax = std::max(ymax, pos2.y());
}
double width = xmax - xmin;
double height = ymax - ymin;
QPointF center(xmin + width / 2.0,
ymin + height / 2.0);
bbox = BoundingBox(BoundingBox::ExtentType::Sim, Point3D::fromQPointF(center), width, height);
}
QImage AbstractMultiPointMapObjectImpl::previewImage() const
{
return previewImageSpecific();
}
Qt::BrushStyle fillPatternToBrushStyle(const FillPattern &fillPattern)
{
Qt::BrushStyle bs = Qt::SolidPattern;
switch (fillPattern) {
case FillPattern::BackwardDiagonal: // /
bs = Qt::BDiagPattern;
break;
case FillPattern::Cross:
bs = Qt::CrossPattern;
break;
case FillPattern::DiagonalCross:
bs = Qt::DiagCrossPattern;
break;
case FillPattern::ForwardDiagonal: // '\'
bs = Qt::FDiagPattern;
break;
case FillPattern::Horizontal:
bs = Qt::HorPattern;
break;
case FillPattern::Null:
bs = Qt::NoBrush;
break;
case FillPattern::Solid:
bs = Qt::SolidPattern;
break;
case FillPattern::Vertical:
bs = Qt::VerPattern;
break;
default:
bs = Qt::SolidPattern;
break;
}
return bs;
}
QImage AbstractMultiPointMapObjectImpl::previewImageSpecific() const
{
if (m_mainGraphicalObject)
{
FillStyle fs = m_mainGraphicalObject->fillStyle();
Qt::BrushStyle bs = fillPatternToBrushStyle(fs.fillPattern());
return imageFromForm(this->positions(),
m_mainGraphicalObject->lineStyle().lineColor(),
m_isClosed,
bs,
fs.fillColor());
}
QColor lineColor = this->majorColor();
if (!lineColor.isValid())
lineColor = Qt::black;
return imageFromForm(this->positions(), lineColor, m_isClosed, Qt::BrushStyle::SolidPattern);
}
} // namespace SituationMap
@@ -0,0 +1,83 @@
/**
* @RDE_HEADER@
* Interface-Implementation of AbstractMultiPointMapObject
* $Id$
* $HeadURL$
* $Author$
*/
#pragma once
// Own
#include <MapImpl/abstract_map_object_impl.h>
#include <MapImpl/coordinate_translation.h>
#include <MapObjects/abstract_multi_point_map_object.h> // Interface
#include "situation_map_objects_export.h"
// Qt
//----------------------------------------------------------------------------
namespace SituationMap
{
/**
* @brief The AbstractMultiPointMapObjectImpl class adds a unlimited number of positions (PositionCont) to the AbstractMapObjectImpl.
* By this a polyline and a polygon can be described. Accordingly a LineStyle and a FillStyle is added also.
*/
// inherent 'public', to get that implementation
// inherent 'public virtual' to get that interface
class SITUATIONMAPOBJECTS_EXPORT AbstractMultiPointMapObjectImpl : public AbstractMapObjectImpl, public virtual AbstractMultiPointMapObject
{
using BaseClass = AbstractMapObjectImpl;
public:
explicit AbstractMultiPointMapObjectImpl(const QString &debugInfo = QString());
virtual ~AbstractMultiPointMapObjectImpl();
AbstractMultiPointMapObjectImpl(const AbstractMultiPointMapObjectImpl &other) = delete;
AbstractMultiPointMapObjectImpl &operator=(AbstractMultiPointMapObjectImpl &other) = delete;
QString toString() const override;
PositionCont positions() const override;
bool setPositions(const PositionCont &positions) override;
PositionCont positionsTranslated() const override;
bool setPositionsTranslated(const PositionCont &positions) override;
void boundingBox(BoundingBox &bbox) const override;
QImage previewImage() const override;
QImage previewImageSpecific() const override;
LineStyle lineStyle() const override;
LineStyle &rLineStyle() override;
void setLineStyle(const LineStyle &lineStyle) override;
FillStyle fillStyle() const override;
FillStyle &rFillStyle() override;
void setFillStyle(const FillStyle &fillStyle) override;
protected:
// internal/admin
void updateIdentifierPosition() override;
// logical
PositionsTranslated m_positions;
bool m_isClosed = true;
private:
LOGGER_T m_logger; ///< Interface of the Logging-Facility
};
} // namespace SituationMap
@@ -0,0 +1,175 @@
/**
* @RDE_HEADER@
* Interface-Implementation of AbstractSinglePointMapObject
* $Id$
* $HeadURL$
* $Author$
*/
// Own
#include "abstract_single_point_map_object_impl.h"
#include <MapImpl/map_impl.h>
#include <Map/bounding_box.h>
#include <GraphicalObjects/graphical_object_picture_marker.h>
#include <GraphicalObjects/graphical_object_text.h>
// ESRI
// Qt
namespace SituationMap
{
//-----------------------------------------------------------------------------
// class AbstractSinglePointMapObjectImpl
//-----------------------------------------------------------------------------
AbstractSinglePointMapObjectImpl::AbstractSinglePointMapObjectImpl(const QString &debugInfo)
: BaseClass(debugInfo) // Implementation
, m_logger(getLogger("AbstractSinglePointMapObjectImpl"))
{
TRACE_LOG(m_logger) << LOGFUNCTION << " START";
m_origin.setMapObjectImpl(this);
TRACE_LOG(m_logger) << LOGFUNCTION << " END";
}
AbstractSinglePointMapObjectImpl::~AbstractSinglePointMapObjectImpl()
{
TRACE_LOG(m_logger) << LOGFUNCTION << " START";
TRACE_LOG(m_logger) << LOGFUNCTION << " END";
}
QString AbstractSinglePointMapObjectImpl::toString() const
{
QString str;
str.append(BaseClass::toString());
std::ostringstream stream;
stream << " " << m_origin.origin();
str.append(QLatin1String(stream.str().c_str()));
str.append(QStringLiteral(" radius=%1").arg(m_radius.value()));
return str;
}
Point3D AbstractSinglePointMapObjectImpl::origin() const
{
return m_origin.origin();
}
Point3D AbstractSinglePointMapObjectImpl::originTranslated() const
{
return m_origin.originTranslated();
}
bool AbstractSinglePointMapObjectImpl::setOrigin(const Point3D &origin)
{
m_updateObjectIndicator = m_origin.setOrigin(origin) || m_updateObjectIndicator;
return m_updateObjectIndicator;
}
void AbstractSinglePointMapObjectImpl::boundingBox(BoundingBox &bbox) const
{
if (m_radius.value() > 0)
bbox = BoundingBox(BoundingBox::ExtentType::Sim, m_origin.origin(), 2 * m_radius.value(), 2 * m_radius.value());
else
{
GraphicalObjectPictureMarker *goPicture = dynamic_cast<GraphicalObjectPictureMarker *>(m_mainGraphicalObject);
if (goPicture)
{
// ToDo: offset of goPicture has to be honored...
if (!goPicture->image().isNull())
{
// goPicture has Image
const QSize &imgSize = goPicture->currentSize(); // currentSize
bbox = BoundingBox(BoundingBox::ExtentType::Pixel,
m_origin.origin(), // Sim
imgSize.width(), imgSize.height() // pixel
);
} else
{
// goPicture has Marker
int markerSize = goPicture->markerSymbolSize();
bbox = BoundingBox(BoundingBox::ExtentType::Pixel,
m_origin.origin(), // Sim
markerSize, markerSize // pixel
);
}
}
else
bbox = BoundingBox(BoundingBox::ExtentType::Sim, m_origin.origin()); // widht and heigth will be 0!
}
}
float AbstractSinglePointMapObjectImpl::radius() const
{
return m_radius.value();
}
void AbstractSinglePointMapObjectImpl::setRadius(float radius)
{
m_radius = radius;
}
LineStyle AbstractSinglePointMapObjectImpl::lineStyle() const
{
return BaseClass::lineStyle();
}
LineStyle &AbstractSinglePointMapObjectImpl::rLineStyle()
{
return BaseClass::rLineStyle();
}
void AbstractSinglePointMapObjectImpl::setLineStyle(const LineStyle &lineStyle)
{
BaseClass::setLineStyle(lineStyle);
}
FillStyle AbstractSinglePointMapObjectImpl::fillStyle() const
{
return BaseClass::fillStyle();
}
FillStyle &AbstractSinglePointMapObjectImpl::rFillStyle()
{
return BaseClass::rFillStyle();
}
void AbstractSinglePointMapObjectImpl::setFillStyle(const FillStyle &fillStyle)
{
BaseClass::setFillStyle(fillStyle);
}
void AbstractSinglePointMapObjectImpl::updateIdentifierPosition()
{
DEBUG_LOG(m_logger) << LOGFUNCTION << " START" << " debugInfo=" << m_debugInfo;
if (m_mainGraphicalObjectText)
{
SituationMap::BoundingBox bbox;
this->boundingBox(bbox);
if (bbox.isValid() && bbox.extentType() == BoundingBox::ExtentType::Pixel)
{
DEBUG_LOG(m_logger) << LOGFUNCTION << " START" << " bbox=" << bbox;
m_mainGraphicalObjectText->setXOffset((bbox.width() / 2.0) + 10);
}
else
m_mainGraphicalObjectText->setXOffset(10);
}
BaseClass::updateIdentifierPosition(); // calculating the origin
}
} // namespace SituationMap
@@ -0,0 +1,82 @@
/**
* @RDE_HEADER@
* Interface-Implementation of AbstractSinglePointMapObject
* $Id$
* $HeadURL$
* $Author$
*/
#pragma once
// Own
#include <MapImpl/abstract_map_object_impl.h>
#include <MapImpl/coordinate_translation.h>
#include <MapObjects/abstract_single_point_map_object.h> // Interface
#include "situation_map_objects_export.h"
// Qt
//----------------------------------------------------------------------------
namespace SituationMap
{
/**
* @brief The AbstractSinglePointMapObjectImpl class adds excatly one positions (QPointF) to the AbstractMapObjectImpl.
* For convenience a radius can also be parametrized. Accordingly a LineStyle and a FillStyle is added also.
* \note Maybe the radius be be removed in future.
*/
// inherent 'public', to get that implementation
// inherent 'public virtual' to get that interface
class SITUATIONMAPOBJECTS_EXPORT AbstractSinglePointMapObjectImpl : public AbstractMapObjectImpl, public virtual AbstractSinglePointMapObject
{
using BaseClass = AbstractMapObjectImpl;
public:
explicit AbstractSinglePointMapObjectImpl(const QString &debugInfo = QString());
virtual ~AbstractSinglePointMapObjectImpl();
AbstractSinglePointMapObjectImpl(const AbstractSinglePointMapObjectImpl &other) = delete;
AbstractSinglePointMapObjectImpl &operator=(AbstractSinglePointMapObjectImpl &other) = delete;
QString toString() const override;
Point3D origin() const override;
bool setOrigin(const Point3D &origin) override;
virtual Point3D originTranslated() const;
virtual float radius() const;
virtual void setRadius(float radius);
void boundingBox(BoundingBox &bbox) const override;
LineStyle lineStyle() const override;
LineStyle &rLineStyle() override;
void setLineStyle(const LineStyle &lineStyle) override;
FillStyle fillStyle() const override;
FillStyle &rFillStyle() override;
void setFillStyle(const FillStyle &fillStyle) override;
protected:
// internal/admin
void updateIdentifierPosition() override;
// logical
OriginTranslated m_origin;
SimpleValue<float> m_radius = -1;
private:
LOGGER_T m_logger; ///< Interface of the Logging-Facility
};
} // namespace SituationMap
+587
View File
@@ -0,0 +1,587 @@
/**
* @RDE_HEADER@
* Interface-Implementation of AirSupport
* $Id$
* $HeadURL$
* $Author$
*/
// Own
#include "air_support_impl.h"
#include <MapImpl/map_impl.h>
#include <MapImpl/object_container_impl.h>
#include <MapImpl/layer_factory_impl.h>
#include <GraphicalObjects/graphical_object_path.h>
#include <GraphicalObjects/graphical_object_text.h>
#include <MapObjectsImpl/participant_impl.h>
// ESRI
#include <arcgis/GeometryEngine.h>
#include <arcgis/PolylineBuilder.h>
// Qt
namespace SituationMap
{
const int AIR_SUPPORT_LINE_WIDTH = 2;
class AirSupportImpl::Private
{
public:
Private() = default;
~Private()
{
removeAesBuffer();
removeAFP();
removeALP();
m_pm_AFP = nullptr;
m_pm_ALP = nullptr;
m_aesBuffer = nullptr;
}
// ESRI data:
Esri::ArcGISRuntime::GraphicsOverlay *m_graphicsLayer = nullptr;
// Own data:
MapImpl *m_mapImpl = nullptr;
UniqueMapId m_referencedObject = INVALID_MAP_ID;
QString m_debugInfo; // will be appended by consecutive number
UniqueMapId m_uniqueMapId;
QColor m_color = Qt::black;
GraphicalObjectPictureMarker *m_pm_AFP = nullptr;
GraphicalObjectPictureMarker *m_pm_ALP = nullptr;
GraphicalObjectPath *m_aesBuffer = nullptr;
QMap<int, QSharedPointer<GraphicalObjectPath> > m_cont; /// one polyline per subsidiary line
typedef QMapIterator<int, QSharedPointer<GraphicalObjectPath>> MAP_IT_T;
// int m_drawOrder = 0;
GraphicalObjectPictureMarker *getAFP()
{
if (!m_pm_AFP)
{
QString debugInfo = QStringLiteral("%1#Marker(AFP)").arg(m_debugInfo);
m_pm_AFP = new GraphicalObjectPictureMarker(m_mapImpl->getEsriGeoView(),
m_graphicsLayer,
debugInfo,
m_uniqueMapId);
m_pm_AFP->setMarkerSymbol(MarkerSymbolType::Circle, 10, Qt::black);
}
return m_pm_AFP;
}
void removeAFP()
{
delete m_pm_AFP;
m_pm_AFP = nullptr;
}
GraphicalObjectPictureMarker *getALP()
{
if (!m_pm_ALP)
{
QString debugInfo = QStringLiteral("%1#Marker(ALP)").arg(m_debugInfo);
m_pm_ALP = new GraphicalObjectPictureMarker(m_mapImpl->getEsriGeoView(),
m_graphicsLayer,
debugInfo,
m_uniqueMapId);
m_pm_ALP->setMarkerSymbol(MarkerSymbolType::Circle, 10, Qt::black);
}
return m_pm_ALP;
}
void removeALP()
{
delete m_pm_ALP;
m_pm_ALP = nullptr;
}
GraphicalObjectPath *getAesBuffer()
{
if (!m_aesBuffer)
{
QString debugInfo = QStringLiteral("%1#AesBuffer").arg(m_debugInfo);
m_aesBuffer = new GraphicalObjectPath(GraphicalObjectPathType::Polygon,
m_mapImpl->getEsriGeoView(),
m_graphicsLayer,
debugInfo,
m_uniqueMapId);
m_aesBuffer->setFillStyle(FillStyle(FillPattern::Null));
}
return m_aesBuffer;
}
void removeAesBuffer()
{
delete m_aesBuffer;
m_aesBuffer = nullptr;
}
bool hasPathObject(int key) { return m_cont.contains(key); }
QList<int> keysInUse() { return m_cont.keys(); }
void removePathObject(int key) { m_cont.remove(key); }
void clearPathObjects() { m_cont.clear(); }
QSharedPointer<GraphicalObjectPath> getPathObject(int key)
{
if (m_cont[key].isNull())
{
QString debugInfo = QStringLiteral("%1#SubsidiaryLine(%2)").arg(m_debugInfo).arg(key);
GraphicalObjectPath *temp = new GraphicalObjectPath(GraphicalObjectPathType::Polyline,
m_mapImpl->getEsriGeoView(),
m_graphicsLayer,
debugInfo,
m_uniqueMapId);
if (temp)
m_cont[key] = QSharedPointer<GraphicalObjectPath>(temp);
}
return m_cont[key];
}
}; // class AirSupportImpl::Private
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
// class AirSupportImpl
//-----------------------------------------------------------------------------
AirSupportImpl::AirSupportImpl(const QString &debugInfo)
: AirSupport() // Interface
, BaseClass(debugInfo) // Implementation
, d(new Private)
, m_logger(getLogger("AirSupportImpl"))
{
TRACE_LOG(m_logger) << LOGFUNCTION << " START";
TRACE_LOG(m_logger) << LOGFUNCTION << " END";
}
AirSupportImpl::~AirSupportImpl()
{
TRACE_LOG(m_logger) << LOGFUNCTION << " START";
delete d;
TRACE_LOG(m_logger) << LOGFUNCTION << " END";
}
void AirSupportImpl::setUniqueId(const UniqueMapId &uniqueId)
{
BaseClass::setUniqueId(uniqueId);
d->m_uniqueMapId = m_uniqueMapId;
}
void AirSupportImpl::setReferencedObject(const UniqueMapId &referencedObject)
{
d->m_referencedObject = referencedObject;
}
bool AirSupportImpl::updateViewImpl()
{
TRACE_LOG(m_logger) << LOGFUNCTION << " START"
<< " m_debugInfo=" << m_debugInfo
<< " symbol=" << m_symbol.value().sidc
<< " visibility=" << m_visibility
<< " visiTechn=" << m_visibilityTechnical
<< " visiTact=" << m_visibilityTactical
<< " this->drawOrder=" << this->drawOrder()
<< " this->positions()=" << this->positions();
// m_mainGraphicalObject stores the outline/'bounding box' (techn and tact)
// Those geometry should never be visible.
// The text of should be visible.
this->setVisibilityOfGeometry(false);
if (this->positions().size() < 2)
{
ERROR_LOG(m_logger) << LOGFUNCTION << " number of coordinates is not sufficiant"
<< " (#coord=" << this->positions().size() << ")";
return false;
}
if (m_mainGraphicalObject)
d->m_color = m_mainGraphicalObject->lineStyle().lineColor();
bool success = BaseClass::updateViewImpl();
if (!success)
ERROR_LOG(m_logger) << LOGFUNCTION << " updateViewImpl failed";
// real work:
//
// First, draw AFP and ALP
//
// AFP
{
Point3D coordTranslated = getCoordinateTranslated(COORD_INDEX_AFP);
if (coordTranslated.isNull())
{
d->removeAFP();
} else {
GraphicalObjectPictureMarker *pm = d->getAFP();
pm->setMarkerSymbol(MarkerSymbolType::Circle, 10, d->m_color);
pm->setOrigin(coordTranslated);
pm->setVisibility(m_visibility && m_visibilityTechnical);
pm->setScale(m_mainGraphicalObject->scale());
pm->setDrawOrder(m_mainGraphicalObject->drawOrder());
if (!pm->updateView())
ERROR_LOG(m_logger) << LOGFUNCTION << " updateView failed";
}
}
// ALP
{
Point3D coordTranslated = getCoordinateTranslated(COORD_INDEX_ALP);
if (coordTranslated.isNull())
{
d->removeALP();
} else {
GraphicalObjectPictureMarker *pm = d->getALP();
pm->setMarkerSymbol(MarkerSymbolType::Circle, 10, d->m_color);
pm->setOrigin(coordTranslated);
pm->setVisibility(m_visibility && m_visibilityTechnical);
pm->setScale(m_mainGraphicalObject->scale());
pm->setDrawOrder(m_mainGraphicalObject->drawOrder());
if (!pm->updateView())
ERROR_LOG(m_logger) << LOGFUNCTION << " updateView failed";
}
}
//
// delegate remaining to onMapExtentChanged
//
TRACE_LOG(m_logger) << LOGFUNCTION << " END, success=" << success;
return success;
}
bool AirSupportImpl::onMapExtentChanged()
{
TRACE_LOG(m_logger) << LOGFUNCTION << " START";
bool success = BaseClass::onMapExtentChanged();
if (!m_mainGraphicalObject)
{
ERROR_LOG(m_logger) << LOGFUNCTION << " no m_mainGraphicalObject yet";
return false;
}
// 1. create aesBuffer;
updateViewImplBuffer();
// 2. and see, if Alp is within:
bool contains = bufferContainsAlp(); // buffer and alp must exist!!!
DEBUG_LOG(m_logger) << LOGFUNCTION << " buffer contains Alp: " << contains;
// Line Afp Alp
Point3D start = this->getCoordinateTranslated(COORD_INDEX_AFP);
Point3D end = this->getCoordinateTranslated(COORD_INDEX_ALP);
if (end.isNull())
updateViewImplLineAfpAlp(false, Point3D(), Point3D());
else
updateViewImplLineAfpAlp(true, start, end);
// Line Alp Aes
start = this->getCoordinateTranslated(COORD_INDEX_ALP);
end = this->getCoordinateTranslated(COORD_INDEX_AES);
// try to replace end by intersection with Aes:
Point3D intersection = this->intersectionAesAndLineAlpAes();
DEBUG_LOG(m_logger) << " intersectionAes " << intersection;
if (!intersection.isNull())
end = intersection;
// try to replace end by intersection with buffer of Aes:
if (d->m_aesBuffer)
{
intersection = this->intersectionBufferAndLineAlpAes();
DEBUG_LOG(m_logger) << " intersectionBuffer " << intersection;
if (!intersection.isNull())
end = intersection;
}
// Maybe 3rd coordinate is not provided?
if (start.isNull() || end.isNull())
updateViewImplLineAlpAes(false, Point3D(), Point3D());
else
updateViewImplLineAlpAes(!contains, start, end);
TRACE_LOG(m_logger) << LOGFUNCTION << " END";
return success;
}
bool AirSupportImpl::updateViewImplBuffer()
{
TRACE_LOG(m_logger) << LOGFUNCTION << " START";
DEBUG_LOG(m_logger) << LOGFUNCTION << " pixelSize= " << m_mapImpl->pixelSizeMeter();
if (m_mapImpl->pixelSizeMeter() < 1)
{
d->removeAesBuffer();
TRACE_LOG(m_logger) << LOGFUNCTION << " END";
return true;
}
double bufferDistance = m_mapImpl->pixelSizeMeter() * 100;
DEBUG_LOG(m_logger) << LOGFUNCTION << " bufferDistance= " << bufferDistance;
if (bufferDistance > 2000)
bufferDistance = 2000;
// AesBuffer of referenced object
if (!isUniqueMapIdValid(d->m_referencedObject))
{
// This can happen, if the object is just created:
DEBUG_LOG(m_logger) << LOGFUNCTION << " m_referencedObject is invalid"
<< " (m_referencedObject=" << d->m_referencedObject << ")";
return false;
}
AbstractMapObject *amo = d->m_mapImpl->objectContainer().getObject(d->m_referencedObject);
if (!amo)
{
ERROR_LOG(m_logger) << LOGFUNCTION << " m_referencedObject not found"
<< " (m_referencedObject=" << d->m_referencedObject << ")";
return false;
}
QVector<Point3D> resultVec = MathUtils::GeometryEngine::buffer(amo, bufferDistance);
GraphicalObjectPath *buffer = d->getAesBuffer();
if (buffer)
{
buffer->setVisibility(m_visibility && m_visibilityTechnical);
buffer->setScale(m_mainGraphicalObject->scale());
buffer->setLineStyle(LineStyle(d->m_color, AIR_SUPPORT_LINE_WIDTH, LinePattern::Solid));
buffer->setPositions(resultVec);
buffer->setDrawOrder(m_mainGraphicalObject->drawOrder());
if (!buffer->updateView())
ERROR_LOG(m_logger) << LOGFUNCTION << " updateView failed";
}
TRACE_LOG(m_logger) << LOGFUNCTION << " END";
return true;
}
void AirSupportImpl::updateViewImplLineAfpAlp(bool show, const Point3D &start, const Point3D &end)
{
TRACE_LOG(m_logger) << LOGFUNCTION << " START";
if (show)
{
QSharedPointer<GraphicalObjectPath> line = d->getPathObject(LINE_INDEX_AFP_ALP);
if (line)
{
line->setVisibility(m_visibility && m_visibilityTechnical);
line->setScale(m_mainGraphicalObject->scale());
line->setDrawOrder(m_mainGraphicalObject->drawOrder());
line->setLineStyle(LineStyle(d->m_color, AIR_SUPPORT_LINE_WIDTH, LinePattern::Dash));
PositionCont posCont;
posCont.reserve(2);
posCont.append(start);
posCont.append(end);
line->setPositions(posCont);
if (!line->updateView())
ERROR_LOG(m_logger) << LOGFUNCTION << " updateView failed";
}
TRACE_LOG(m_logger) << LOGFUNCTION << " END";
}
else
d->removePathObject(LINE_INDEX_AFP_ALP);
}
void AirSupportImpl::updateViewImplLineAlpAes(bool show, const Point3D &start, const Point3D &end)
{
TRACE_LOG(m_logger) << LOGFUNCTION << " START";
if (show)
{
QSharedPointer<GraphicalObjectPath> line = d->getPathObject(LINE_INDEX_ALP_AES);
if (line)
{
line->setVisibility(m_visibility && m_visibilityTechnical);
line->setScale(m_mainGraphicalObject->scale());
line->setDrawOrder(m_mainGraphicalObject->drawOrder());
line->setLineStyle(LineStyle(d->m_color, AIR_SUPPORT_LINE_WIDTH, LinePattern::Solid));
PositionCont posCont;
posCont.reserve(2);
posCont.append(start);
posCont.append(end);
line->setPositions(posCont);
if (!line->updateView())
ERROR_LOG(m_logger) << LOGFUNCTION << " updateView failed";
}
}
else
d->removePathObject(LINE_INDEX_ALP_AES);
TRACE_LOG(m_logger) << LOGFUNCTION << " END";
}
bool AirSupportImpl::bufferContainsAlp()
{
TRACE_LOG(m_logger) << LOGFUNCTION << " START";
Esri::ArcGISRuntime::Geometry geoHull;
if (d->m_aesBuffer)
geoHull = d->m_aesBuffer->getGraphicGeometry();
Esri::ArcGISRuntime::Geometry pntToCheck;
if (d->getALP())
pntToCheck = d->getALP()->getGraphicGeometry();
bool contains = false;
if (!geoHull.isEmpty() && !pntToCheck.isEmpty())
contains = Esri::ArcGISRuntime::GeometryEngine::contains(geoHull, pntToCheck);
TRACE_LOG(m_logger) << LOGFUNCTION << " END, contains" << contains;
return contains;
}
Point3D AirSupportImpl::intersectionBufferAndLineAlpAes()
{
Esri::ArcGISRuntime::Geometry geo1;
if (d->m_aesBuffer)
geo1 = d->m_aesBuffer->getGraphicGeometry();
if (geo1.isEmpty())
return Point3D();
Esri::ArcGISRuntime::Geometry geo2 = geometryOfLine(getCoordinateTranslated(COORD_INDEX_ALP),
getCoordinateTranslated(COORD_INDEX_AES));
if (geo2.isEmpty())
return Point3D();
return intersection(geo1, geo2);
}
Point3D AirSupportImpl::intersectionAesAndLineAlpAes()
{
AbstractMapObject *amo = d->m_mapImpl->objectContainer().getObject(d->m_referencedObject);
AbstractMapObjectImpl *mapObjImpl = dynamic_cast<AbstractMapObjectImpl *>(amo);
if (!mapObjImpl)
{
DEBUG_LOG(m_logger) << LOGFUNCTION << " m_referencedObject not found/dynamic_cast failed"
<< " (m_referencedObject=" << d->m_referencedObject << ")";
return Point3D();
}
Esri::ArcGISRuntime::Geometry geo1;
if (mapObjImpl)
geo1 = mapObjImpl->getEsriGeometry();
if (geo1.isEmpty())
return Point3D();
Esri::ArcGISRuntime::Geometry geo2 = geometryOfLine(getCoordinateTranslated(COORD_INDEX_ALP),
getCoordinateTranslated(COORD_INDEX_AES));
if (geo2.isEmpty())
return Point3D();
return intersection(geo1, geo2);
}
Point3D AirSupportImpl::intersection(const Esri::ArcGISRuntime::Geometry &geo1, const Esri::ArcGISRuntime::Geometry &geo2)
{
if (geo1.isEmpty() || geo2.isEmpty())
return Point3D();
Esri::ArcGISRuntime::Geometry geoResult =
Esri::ArcGISRuntime::GeometryEngine::intersection(geo1, geo2);
DEBUG_LOG(m_logger) << LOGFUNCTION << " geoInter = " << geoResult.toJson();
DEBUG_LOG(m_logger) << LOGFUNCTION << " geoInter dimension = " << geoResult.dimension();
Esri::ArcGISRuntime::Point intersectPoint;
if (geoResult.dimension() == 1) // dim 1 -> Lines and Polyline
{
Esri::ArcGISRuntime::Polyline polylineResult(geoResult);
if (polylineResult.parts().part(0).pointCount() > 0)
intersectPoint = polylineResult.parts().part(0).startPoint();
}
else if (geoResult.dimension() == 0)
{
intersectPoint = Esri::ArcGISRuntime::Point(geoResult); // This is not tested yet
}
DEBUG_LOG(m_logger) << LOGFUNCTION << " intersectPoint = " << intersectPoint.toJson();
if (std::isnan(intersectPoint.x()) ||
std::isnan(intersectPoint.y()) ||
std::isnan(intersectPoint.z()))
return Point3D();
Point3D intersection(intersectPoint.x(),
intersectPoint.y(),
intersectPoint.z());
return intersection;
}
Esri::ArcGISRuntime::Geometry AirSupportImpl::geometryOfLine(const Point3D &start, const Point3D &end)
{
Esri::ArcGISRuntime::PolylineBuilder polylineBuilder(m_mapImpl->getEsriSpatialReference());
polylineBuilder.addPoint(Esri::ArcGISRuntime::Point(start.x(), start.y()));
polylineBuilder.addPoint(Esri::ArcGISRuntime::Point(end.x(), end.y()));
const Esri::ArcGISRuntime::Geometry &geo = polylineBuilder.toGeometry();
return geo;
}
bool AirSupportImpl::init(MapImpl *mapImpl, const QString &logicalLayerName)
{
TRACE_LOG(m_logger) << LOGFUNCTION << " START";
// no symbol required
bool success = BaseClass::init(mapImpl, logicalLayerName, GraphicalObjectPathType::Polyline);
setLineStyle(LineStyle(Qt::black, 1));
if (!success)
ERROR_LOG(m_logger) << LOGFUNCTION << " init failed";
// set some values to Private:
d->m_mapImpl = m_mapImpl;
d->m_debugInfo = m_debugInfo;
d->m_uniqueMapId = m_uniqueMapId;
d->m_graphicsLayer = m_graphicsLayer;
TRACE_LOG(m_logger) << LOGFUNCTION << " END, success=" << success;
return success;
}
Point3D AirSupportImpl::getCoordinateTranslated(int idx) const
{
if (idx < 0 || idx > 2)
return Point3D();
const PositionCont &posContTranslated = m_positions.positionsTranslated();
if (idx >= posContTranslated.size())
return Point3D();
return posContTranslated[idx];
}
} // namespace SituationMap
+119
View File
@@ -0,0 +1,119 @@
/**
* @RDE_HEADER@
* Interface-Implementation of AirSupport
* $Id$
* $HeadURL$
* $Author$
*/
#pragma once
// Own
#include "abstract_multi_point_map_object_impl.h"
#include "basic_path_object_impl.h"
#include <MapObjects/air_support.h> // Interface
// Qt
#include <QString>
/*
o AFP (Anflugpunkt)
\
\
o ALP (Ausloesepunkt)
|
|
|
-------
| | AesItem / Buffer (Waffeneinsatzflaeche)
-------
*/
//----------------------------------------------------------------------------
namespace SituationMap
{
// forward:
class ParticipantImpl;
/**
* @brief The AirSupportImpl class displays (guez) air support, aka AerialOrdenance
*
* A class instance consists of the following logical elements:
* - mainGraphicalObject (GraphicalObjectPath displaying the main techn. Appearance)
* Line from 'Anflugpunkt' (AFP) over 'Ausloesepunkt' (ALP)
* to target (center of EffectSimulation)
* - mainGraphicalObjectText (displaying the text/name)
* - tacticalAppearance (displaying the tact. Appearance)
*
*/
// inherent 'public', to get that implementation
// inherent 'public virtual' to get that interface
class SITUATIONMAPOBJECTS_EXPORT AirSupportImpl : public BasicPathObjectImpl, public virtual AirSupport
{
using BaseClass = BasicPathObjectImpl;
template <typename> friend class GenericObjectFactory;
protected:
explicit AirSupportImpl(const QString &debugInfo = QString());
virtual ~AirSupportImpl();
void setUniqueId(const UniqueMapId &uniqueId) override;
public:
AirSupportImpl(const AirSupportImpl &other) = delete;
AirSupportImpl &operator=(AirSupportImpl &other) = delete;
void setReferencedObject(const UniqueMapId &referencedObject) override;
protected:
bool updateViewImpl() override;
bool onMapExtentChanged() override;
bool updateViewImplBuffer();
void updateViewImplLineAfpAlp(bool show, const Point3D &start, const Point3D &end);
void updateViewImplLineAlpAes(bool show, const Point3D &start, const Point3D &end);
bool bufferContainsAlp();
Point3D intersectionBufferAndLineAlpAes();
Point3D intersectionAesAndLineAlpAes();
Point3D intersection(const Esri::ArcGISRuntime::Geometry &geo1, const Esri::ArcGISRuntime::Geometry &geo2);
Esri::ArcGISRuntime::Geometry geometryOfLine(const Point3D &start, const Point3D &end);
friend class MapImpl;
bool init(MapImpl *mapImpl, const QString &logicalLayerName) override;
// internal/admin
static const int COORD_INDEX_AFP = 0; // Anflugpunkt
static const int COORD_INDEX_ALP = 1; // Ausloesepunkt
static const int COORD_INDEX_AES = 2; // target / EffectSimulation
static const int LINE_INDEX_AFP_ALP = 0; // Anflugpunkt
static const int LINE_INDEX_ALP_AES = 1; // Ausloesepunkt
Point3D getCoordinateTranslated(int idx) const;
// logical
private:
// logical
class Private;
/**
* The private d->pointer to not break BC when changing internals of this class
*/
Private *d = nullptr;
LOGGER_T m_logger; ///< Interface of the Logging-Facility
};
} // namespace SituationMap
+820
View File
@@ -0,0 +1,820 @@
/**
* @RDE_HEADER@
* Interface-Implementation of AreaFire
* $Id$
* $HeadURL$
* $Author$
*/
// Own
#include "area_fire_impl.h"
#include <MapImpl/map_impl.h>
#include <GraphicalObjects/graphical_object_path.h>
#include <GraphicalObjects/graphical_object_scene_marker.h>
#include <GraphicalObjects/graphical_object_renderer_attributes.h>
#include "single_fire_impl.h"
#include <Symbology/sidc_codec.h>
// ESRI
#ifdef LTS_DEBUG
#include <QMessageBox>
#include <arcgis/Graphic.h>
#endif // LTS_DEBUG
// Qt
//#define USE_MARKER
namespace SituationMap
{
static int s_gunToTargetLine3DKEY = -1;
static int s_gunToTargetLineSurfaceKEY = 0;
static int s_nonLethalAreaKEY = 1;
class AreaFireImpl::Private
{
public:
Private() = default;
~Private() = default;
// ESRI data:
// Esri::ArcGISRuntime::GraphicsOverlay *m_graphicsLayer = nullptr;
// Own data:
MapImpl *m_mapImpl = nullptr;
QString m_logicalLayer;
QString m_debugInfo; // will be appended by consecutive number
UniqueMapId m_uniqueMapId = INVALID_MAP_ID;
SimpleValue<QColor> m_scheduledImpactsExplcitColor; // by default invalid color
struct Detonations
{
PositionsTranslated m_detonationPositions;
SimpleValue<double> m_detonationRadius{5};
bool m_detonationChanged{true};
bool changed() const { return m_detonationRadius.changed() || m_detonationChanged; }
void reset() { m_detonationRadius.reset(); m_detonationChanged = false; }
} m_detonationsAbsolute, m_detonationsDraped;
//
// ABSOLUTE using SceneMarker
//
struct ValueDataGOSM_Abs
{
QSharedPointer<GraphicalObjectSceneMarker> m_goSceneMarker;
};
QVector<ValueDataGOSM_Abs> m_cont_VDGOSM_Abs;
void resizeGOSM_Abs(int newSize) { m_cont_VDGOSM_Abs.resize(newSize); }
ValueDataGOSM_Abs& getObjectGOSM_abs(int idx)
{
ValueDataGOSM_Abs &retRef = m_cont_VDGOSM_Abs[idx];
if (retRef.m_goSceneMarker.isNull())
{
Esri::ArcGISRuntime::GraphicsOverlay *graphicsLayer = m_mapImpl->getGraphicsLayer3D_SpAbsolute(m_logicalLayer);
if (!graphicsLayer)
{
qCritical() << LOGFUNCTION << " debugInfo='" << m_debugInfo << "'"
<< " getGraphicsLayer3D_SpAbsolute failed";
}
QString debugInfo = QStringLiteral("%1#ModelSceneMarkerAbs(%2)").arg(m_debugInfo).arg(idx);
GraphicalObjectSceneMarker *temp = new GraphicalObjectSceneMarker(SituationMap::SceneMarkerType::SPHERE,
m_mapImpl->getEsriGeoView(),
graphicsLayer,
debugInfo,
m_uniqueMapId);
temp->setUniqueMapId(m_uniqueMapId);
retRef.m_goSceneMarker = QSharedPointer<GraphicalObjectSceneMarker>(temp);
}
return retRef;
}
//
// DRAPED a) using renderer approach
//
#ifdef AREA_FIRE_DRAPED_RENDERER // GUEZE_2933
struct ValueDataGORA_Drpd
{
QSharedPointer<GraphicalObjectRendererAttributes> m_goRendererAtt;
};
QVector<ValueDataGORA_Drpd> m_cont_GORA_drpd;
void resizeDraped_GORA(int newSize)
{
m_cont_GORA_drpd.resize(newSize);
}
ValueDataGORA_Drpd& getObjectDraped_GORA(int idx, Esri::ArcGISRuntime::GraphicsOverlay *graphicsLayer)
{
Q_ASSERT(graphicsLayer);
ValueDataGORA_Drpd &retRef = m_cont_GORA_drpd[idx];
if (retRef.m_goRendererAtt.isNull())
{
QString debugInfo = QStringLiteral("%1#Drpd_goRendererAtt_%2").arg(m_debugInfo).arg(idx);
retRef.m_goRendererAtt = QSharedPointer<GraphicalObjectRendererAttributes>
(new GraphicalObjectRendererAttributes(m_mapImpl->getEsriGeoView()
, graphicsLayer
, debugInfo
, m_uniqueMapId)
);
retRef.m_goRendererAtt->setUniqueMapId(m_uniqueMapId);
}
return retRef;
}
static QVariantMap createGORA_AttributeMap(const QColor &majorColor, double radius)
{
QVariantMap attribMap;
QString attribValue;
{
attribValue = QString(QStringLiteral("Impact_Color_%1")).arg(majorColor.name());
attribMap.insert(QStringLiteral("IMPACT_COLOR"), attribValue);
}
{
const double radiusWithMin = std::max(radius, 1.0); // at least 1 meter
attribValue = QString(QStringLiteral("Impact_Radius_%1")).arg(radiusWithMin);
attribMap.insert(QStringLiteral("IMPACT_RADIUS"), attribValue);
}
{
LayerFactory::UniqueValueDataAesCentral::TYPE type{LayerFactory::UniqueValueDataAesCentral::TYPE::SPHERE};
attribValue = QString(QStringLiteral("Impact_Type_%1")).arg(LayerFactory::toString(type));
attribMap.insert(QStringLiteral("IMPACT_TYPE"), attribValue);
}
// {
// // SceneProperties: HEADING, PITCH, ROLL
// int heading = 0;
// if (data.rotationAngle().is_set())
// heading = static_cast<int>(data.rotationAngle().get());
// attribMap.insert(QStringLiteral("HEADING"), ((heading+90)%360)); // data.rotationAngle()
// attribMap.insert(QStringLiteral("PITCH"), 0);
// attribMap.insert(QStringLiteral("ROLL"), 90);
// }
// qCritical() << " ident " << ", " << attribMap;
return attribMap;
}
#else
//
// DRAPED b) using SceneMarker (see also GUEZE_2933)
//
struct ValueDataGOSM_Drpd
{
QSharedPointer<GraphicalObjectSceneMarker> m_goSceneMarker;
};
QVector<ValueDataGOSM_Drpd> m_cont_GOSM_drpd;
void resizeDraped_GOSM(int newSize)
{
m_cont_GOSM_drpd.resize(newSize);
}
ValueDataGOSM_Drpd& getObjectDraped_GOSM(int idx, Esri::ArcGISRuntime::GraphicsOverlay *graphicsLayer)
{
Q_ASSERT(graphicsLayer);
ValueDataGOSM_Drpd &retRef = m_cont_GOSM_drpd[idx];
if (retRef.m_goSceneMarker.isNull())
{
QString debugInfo = QStringLiteral("%1#Drpd_GOSM_%2").arg(m_debugInfo).arg(idx);
GraphicalObjectSceneMarker *temp = new GraphicalObjectSceneMarker(SituationMap::SceneMarkerType::SPHERE,
m_mapImpl->getEsriGeoView(),
graphicsLayer,
debugInfo,
m_uniqueMapId);
temp->setUniqueMapId(m_uniqueMapId);
retRef.m_goSceneMarker = QSharedPointer<GraphicalObjectSceneMarker>(temp);
}
return retRef;
}
#endif // AREA_FIRE_DRAPED_RENDERER
}; // class AreaFireImpl::Private
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
// class AreaFireImpl
//-----------------------------------------------------------------------------
AreaFireImpl::AreaFireImpl(const QString &debugInfo)
: AreaFire() // Interface
, BaseClass(debugInfo) // Implementation
, d(new Private)
, m_logger(getLogger("AreaFireImpl"))
{
TRACE_LOG(m_logger) << LOGFUNCTION << " START, debugInfo=" << m_debugInfo;
m_fillColorAlpha = 200;
TRACE_LOG(m_logger) << LOGFUNCTION << " END, debugInfo=" << m_debugInfo;
}
AreaFireImpl::~AreaFireImpl()
{
TRACE_LOG(m_logger) << LOGFUNCTION << " START, debugInfo=" << m_debugInfo;
delete d;
TRACE_LOG(m_logger) << LOGFUNCTION << " END, debugInfo=" << m_debugInfo;
}
void AreaFireImpl::setUniqueId(const UniqueMapId &uniqueId)
{
BaseClass::setUniqueId(uniqueId);
d->m_uniqueMapId = m_uniqueMapId;
}
PositionCont AreaFireImpl::scheduledImpacts() const
{
TRACE_LOG(m_logger) << LOGFUNCTION << " START";
TRACE_LOG(m_logger) << LOGFUNCTION << " END";
return this->rIndicationContainer().positions(1);
}
void AreaFireImpl::setScheduledImpacts(const PositionCont &posCont, const QColor &explicitColor)
{
TRACE_LOG(m_logger) << LOGFUNCTION << " START"
<< " scheduledImpactsSize=" << posCont.size()
<< " explicitColor=" << explicitColor
;
IndicationContainer &drapedImpactsIC = this->rIndicationContainer();
drapedImpactsIC.setDebugInfo(m_debugInfo + QStringLiteral("DefaultSpDraped"));
drapedImpactsIC.setPositions(1, posCont);
d->m_scheduledImpactsExplcitColor = explicitColor;
}
PositionCont AreaFireImpl::impacts() const
{
TRACE_LOG(m_logger) << LOGFUNCTION << " START";
TRACE_LOG(m_logger) << LOGFUNCTION << " END";
return this->rIndicationContainer().positions(0);
}
void AreaFireImpl::setImpacts(const PositionCont &posCont)
{
TRACE_LOG(m_logger) << LOGFUNCTION << " START"
<< ", impactSize=" << posCont.size();
IndicationContainer &drapedImpactsIC = this->rIndicationContainer();
drapedImpactsIC.setDebugInfo(m_debugInfo + QStringLiteral("DefaultSpDraped"));
drapedImpactsIC.setPositions(0, posCont);
#ifdef USE_MARKER
drapedImpactsIC.setMarker(0, MarkerSymbolType::X, 20, partyColor());
#endif
TRACE_LOG(m_logger) << LOGFUNCTION << " END";
}
PositionCont AreaFireImpl::impactsAbsoluteHeight() const
{
TRACE_LOG(m_logger) << LOGFUNCTION << " START";
TRACE_LOG(m_logger) << LOGFUNCTION << " END";
return this->rIndicationContainerAbsolute().positions(0);
}
void AreaFireImpl::setImpactsAbsoluteHeight(const PositionCont &posCont)
{
TRACE_LOG(m_logger) << LOGFUNCTION << " START"
<< " impactSize=" << posCont.size()
<< " lineStyle().lineColor()=" << lineStyle().lineColor();
IndicationContainer &impactsAbsolute = this->rIndicationContainerAbsolute();
impactsAbsolute.setDebugInfo(m_debugInfo + QStringLiteral("SpAbso"));
impactsAbsolute.setPositions(0, posCont);
#ifdef USE_MARKER
impacts.setMarker(0, MarkerSymbolType::X, 20, partyColor());
#endif
TRACE_LOG(m_logger) << LOGFUNCTION << " END";
}
PositionCont AreaFireImpl::detonationsAbsolute() const
{
TRACE_LOG(m_logger) << LOGFUNCTION << " START";
TRACE_LOG(m_logger) << LOGFUNCTION << " END";
return d->m_detonationsAbsolute.m_detonationPositions.positions();
}
bool AreaFireImpl::setDetonationsAbsolute(const PositionCont &detonationsPositions, int detonationRadius)
{
TRACE_LOG(m_logger) << LOGFUNCTION << " START" << ", set detonationsPositions = " << detonationsPositions
<< ", radius=" << detonationRadius;
bool bHasChanged = d->m_detonationsAbsolute.m_detonationPositions.setPositions(detonationsPositions);
d->m_detonationsAbsolute.m_detonationRadius = detonationRadius;
d->m_detonationsAbsolute.m_detonationChanged = d->m_detonationsAbsolute.m_detonationChanged || bHasChanged; // Do not reset of changed==true; (maybe it was already changed)
TRACE_LOG(m_logger) << LOGFUNCTION << " END" << ", bHasChanged=" << d->m_detonationsAbsolute.changed();
return d->m_detonationsAbsolute.changed();
}
PositionCont AreaFireImpl::detonationsDraped() const
{
TRACE_LOG(m_logger) << LOGFUNCTION << " START";
TRACE_LOG(m_logger) << LOGFUNCTION << " END";
return d->m_detonationsDraped.m_detonationPositions.positions();
}
bool AreaFireImpl::setDetonationsDraped(const PositionCont &detonationsPositions, int detonationRadius)
{
TRACE_LOG(m_logger) << LOGFUNCTION << " START" << ", set detonationsPositions = " << detonationsPositions
<< ", radius=" << detonationRadius;
bool bHasChanged = d->m_detonationsDraped.m_detonationPositions.setPositions(detonationsPositions);
d->m_detonationsDraped.m_detonationRadius = detonationRadius;
d->m_detonationsDraped.m_detonationChanged = d->m_detonationsDraped.m_detonationChanged || bHasChanged; // Do not reset of changed==true; (maybe it was already changed)
TRACE_LOG(m_logger) << LOGFUNCTION << " END" << ", bHasChanged=" << d->m_detonationsDraped.changed();
return d->m_detonationsDraped.changed();
}
void AreaFireImpl::setGunToTargetLineSurface(const Point3D &start, const Point3D &end)
{
TRACE_LOG(m_logger) << LOGFUNCTION << " START"
<< ", start=" << start << ", end=" << end << ", debugInfo=" << m_debugInfo;
PathContainer &path = this->rPathContainer(); // should be SP::Draped
path.setDebugInfo(m_debugInfo + QStringLiteral("SpDraped"));
if (start.isNull() && end.isNull())
{
path.clear(s_gunToTargetLineSurfaceKEY); // 0
} else {
LineStyle ls = m_mainGraphicalObject->lineStyle();
ls.setLinePattern(LinePattern::Dot);
ls.setLineWidth(2);
path.setLineStyle(ls);
path.setPath(s_gunToTargetLineSurfaceKEY, {start, end});
}
TRACE_LOG(m_logger) << LOGFUNCTION << " END"
<< ", start=" << start << ", end=" << end << ", debugInfo=" << m_debugInfo;
}
void AreaFireImpl::setGunToTargetTrajectory3D(const PositionCont &gunToTargetPath)
{
TRACE_LOG(m_logger) << LOGFUNCTION << " START"
<< ", gunToTargetPath=" << gunToTargetPath.size()
<< ", debugInfo=" << m_debugInfo;
PathContainer &path3D_Abs = this->rPathContainerSpAbsolute2(); // should be SP::Absolute
path3D_Abs.setDebugInfo(m_debugInfo + QStringLiteral("Absolute"));
path3D_Abs.setDrawOrder(5);
if (gunToTargetPath.isEmpty())
{
path3D_Abs.clear(s_gunToTargetLine3DKEY); // -1
} else {
LineStyle ls = m_mainGraphicalObject->lineStyle();
// Try to reduce z-Fighting between gunToTarget and trajectory.
// by reducing the opacity (GUEZE-2722)
QColor lCol = ls.lineColor();
lCol.setAlphaF(0.99);
ls.setLineColor(lCol);
ls.setLinePattern(LinePattern::Dot);
ls.setLineWidth(1);
path3D_Abs.setLineStyle(ls);
path3D_Abs.setPath(s_gunToTargetLine3DKEY, gunToTargetPath);
}
TRACE_LOG(m_logger) << LOGFUNCTION << " END"
<< ", gunToTargetPath=" << gunToTargetPath.size()
<< ", debugInfo=" << m_debugInfo;
}
void AreaFireImpl::setNonLethalArea(const PositionCont &nonLethalArea)
{
TRACE_LOG(m_logger) << LOGFUNCTION << " START"
<< ", nonLethalArea=" << nonLethalArea.size()
<< ", debugInfo=" << m_debugInfo;
// avoid creating PathContainer in case of non-existing data:
if (nonLethalArea.size() < 3)
{
clearPathContainerSpDrapedPolygon(s_nonLethalAreaKEY);
return;
}
PathContainer &path = this->rPathContainerSpDrapedPolygon();
path.setDebugInfo(m_debugInfo + QStringLiteral("SpDrapedNonLethalArea"));
// LineStyle ls = m_mainGraphicalObject->lineStyle();
// ls.setLineColor(partyColor());
// ls.setLinePattern(LinePattern::Solid);
// ls.setLineWidth(2);
// path.setLineStyle(ls);
// const FillStyle &fs = m_mainGraphicalObject->fillStyle();
// path.setFillStyle(fs);
path.setPath(s_nonLethalAreaKEY, nonLethalArea); // 1
TRACE_LOG(m_logger) << LOGFUNCTION << " END"
<< ", nonLethalArea=" << nonLethalArea.size()
<< ", debugInfo=" << m_debugInfo;
}
PositionCont AreaFireImpl::trajectory(int index) const
{
TRACE_LOG(m_logger) << LOGFUNCTION << " START" << ", index=" << index;
TRACE_LOG(m_logger) << LOGFUNCTION << " END" << ", index=" << index;
return this->rPathContainerSpAbsolute1().path(index);
}
bool AreaFireImpl::setTrajectory(int index, const PositionCont &trajectoryPath)
{
TRACE_LOG(m_logger) << LOGFUNCTION << " START"
<< " index=" << index
<< ", trajectoryPath.size=" << trajectoryPath.size()
<< ", lineStyle().lineColor()=" << lineStyle().lineColor();
PathContainer &path = this->rPathContainerSpAbsolute1(); // Trajectory -> Absolute
path.setDebugInfo(m_debugInfo + QStringLiteral("Draped"));
path.setDrawOrder(6); // 'above' guntToTargetLine/guntToTargetCurve
LineStyle ls = this->lineStyle();
ls.setLinePattern(LinePattern::Solid);
ls.setLineWidth(2);
path.setLineStyle(ls);
return path.setPath(index, trajectoryPath);
}
bool AreaFireImpl::updateViewImpl()
{
DEBUG_LOG(m_logger) << LOGFUNCTION << " START"
<< ", m_debugInfo=" << m_debugInfo
<< ", visibility=" << m_visibility
<< ", visiTechn=" << m_visibilityTechnical
<< ", visiTact=" << m_visibilityTactical
// IndicationContainer &drapedImpactsIC = this->rIndicationContainer();
// IndicationContainer &impactsAbsolute = this->rIndicationContainerAbsolute();
<< ", d->m_detonationsAbsolute.changed() = " << d->m_detonationsAbsolute.changed()
<< ", d->m_detonationsAbsolute.size() = " << d->m_detonationsAbsolute.m_detonationPositions.size()
<< ", d->m_detonationsDraped.changed() = " << d->m_detonationsDraped.changed()
<< ", d->m_detonationsDraped.size() = " << d->m_detonationsDraped.m_detonationPositions.size();
for (IndicationContainer *indCont : {m_indicationCont, m_indicationContSpAbsolute})
{
if (!indCont)
continue;
if (m_mainGraphicalObject)
{
#ifdef USE_MARKER
indCont->setMarker(0, col);
#else
if (indCont->image(0).isNull() || m_party.partyId.changed())
{
const QColor &col = m_mainGraphicalObject->lineStyle().lineColor();
indCont->setImage(0, SingleFireImpl::renderImpactSymbol(col, 20, true)); // filled for impacts
}
if (indCont->image(1).isNull() || m_party.partyId.changed() || d->m_scheduledImpactsExplcitColor.changed())
{
d->m_scheduledImpactsExplcitColor.reset();
QColor col = d->m_scheduledImpactsExplcitColor.value();
if (!col.isValid())
col = m_mainGraphicalObject->lineStyle().lineColor();
indCont->setImage(1, SingleFireImpl::renderImpactSymbol(col, 20, false)); // open for scheduledImpacts
}
#endif
}
indCont->setSelected(0, m_selected);
indCont->setPickable(0, m_pickable);
indCont->setVisible(0, m_visibility);
indCont->setSelected(1, m_selected);
indCont->setPickable(1, m_pickable);
indCont->setVisible(1, m_visibility);
} // for (IndicationContainer *indCont...
// control selection
if (m_pathCont_SpDraped)
{
m_pathCont_SpDraped->setSelected(m_selected);
// m_pathCont_SpDraped->setPickable(0, m_pickable);
m_pathCont_SpDraped->setVisibility(s_gunToTargetLineSurfaceKEY, m_visibility); // 0 -> GunToTargetLineSurface
}
if (m_pathCont_SpDrapedPolygon)
{
m_pathCont_SpDrapedPolygon->setSelected(m_selected);
// m_pathCont->setPickable(0, m_pickable);
m_pathCont_SpDrapedPolygon->setVisibility(s_nonLethalAreaKEY, m_visibility);
LineStyle ls = m_mainGraphicalObject->lineStyle();
ls.setLinePattern(LinePattern::Solid);
ls.setLineWidth(2);
m_pathCont_SpDrapedPolygon->setLineStyle(ls);
FillStyle fs = m_mainGraphicalObject->fillStyle();
m_pathCont_SpDrapedPolygon->setFillStyle(fs);
}
if (m_pathCont_SpAbsolute1)
{
const auto &keys = m_pathCont_SpAbsolute1->getIndicationIndexList();
for (auto keyIndex : qAsConst(keys))
m_pathCont_SpAbsolute1->setVisibility(keyIndex, m_visibility); // trajectories
m_pathCont_SpAbsolute1->setSelected(m_selected);
// m_pathCont->setPickable(0, m_pickable);
}
if (m_pathCont_SpAbsolute2)
{
m_pathCont_SpAbsolute2->setSelected(m_selected);
// m_pathCont->setPickable(0, m_pickable);
m_pathCont_SpAbsolute2->setVisibility(s_gunToTargetLine3DKEY, m_visibility); // -1 -> GunToTargetLine3D
}
const bool mgoVisiOld = m_mainGraphicalObject->visibility();
bool success = BaseClass::updateViewImpl();
if (!success)
ERROR_LOG(m_logger) << LOGFUNCTION << " updateViewImpl failed";
// Detonations (3D)
bool successDetonationsAbs = true;
if ( (m_mapImpl->mode() == Mode::Mode_3D) &&
(d->m_detonationsAbsolute.changed() || (mgoVisiOld != m_mainGraphicalObject->visibility()))
)
{
const PositionCont &positionsTranslated = d->m_detonationsAbsolute.m_detonationPositions.positionsTranslated();
const int newSize = positionsTranslated.size();
DEBUG_LOG(m_logger) << LOGFUNCTION << " resizeGOSM_Abs" << d->m_cont_VDGOSM_Abs.size() << " to " << newSize;
d->resizeGOSM_Abs(newSize);
int idx = 0;
for(const Point3D &point3DTranslated : qAsConst(positionsTranslated))
{
Private::ValueDataGOSM_Abs &vdGOSM_absRef = d->getObjectGOSM_abs(idx);
QSharedPointer<GraphicalObjectSceneMarker> goSceneMarker = vdGOSM_absRef.m_goSceneMarker;
goSceneMarker->setOrigin(point3DTranslated);
goSceneMarker->setDiameter(d->m_detonationsAbsolute.m_detonationRadius.value() * 2);
goSceneMarker->setPickable(false);
goSceneMarker->setSelected(false);
QColor col = partyColor();
col.setAlphaF(col.alphaF() / 2.0);
goSceneMarker->setFillStyle(FillStyle(col, FillPattern::Solid));
goSceneMarker->setVisibility(m_visibility);
if (!goSceneMarker->updateView())
successDetonationsAbs = false;
++idx;
} // for
if (!successDetonationsAbs)
ERROR_LOG(m_logger) << LOGFUNCTION << " updateView m_goSceneMarker failed, m_debugInfo = " << m_debugInfo;
d->m_detonationsAbsolute.reset();
} else {
// To simplifiy debugging:
d->m_detonationsAbsolute.reset();
}
DEBUG_LOG(m_logger) << LOGFUNCTION << " START"
<< ", m_debugInfo=" << m_debugInfo
<< ", d->m_detonationsDraped.changed = " << d->m_detonationsDraped.changed();
bool successDetonationsDrpd = true;
if ( (m_mapImpl->mode() == Mode::Mode_3D) &&
(d->m_detonationsDraped.changed() || (mgoVisiOld != m_mainGraphicalObject->visibility())) )
{
#ifdef AREA_FIRE_DRAPED_RENDERER
successDetonationsDrpd = updateViewImplDetonation3dDraped_RendererApproach();
#else
successDetonationsDrpd = updateViewImplDetonation3dDraped_SceneMarkerApproach();
#endif // AREA_FIRE_DRAPED_RENDERER
} else {
// to simplify debugging:
d->m_detonationsDraped.reset();
}
success = success && successDetonationsAbs && successDetonationsDrpd;
#ifdef LTS_DEBUG
const bool afVisi = m_visibility;
const bool mgoVisi = m_mainGraphicalObject->visibility();
const bool esriGraphicVisi = m_mainGraphicalObject->graphic()->isVisible();
// REGG-5360 - Wenn man beim Beobachten der Live-Lage über den Wirksimulationsfilter alle gepla..
// ... sind Flächenfeuer entgegen dem Filter sichtbar
if ( (afVisi != mgoVisi) || (afVisi != esriGraphicVisi) )
{
for (int i = 0; i < 100; ++i)
FATAL_LOG(m_logger) << LOGFUNCTION << " INKONSISTENCY!!!!!!!!!!!!!!";
FATAL_LOG(m_logger) << LOGFUNCTION << " INKONSISTENCY!!!!!!!!!!!!!!"
<< ", afVisi=" << afVisi
<< ", mgoVisi=" << mgoVisi
<< ", esriGraphicVisi" << esriGraphicVisi;
QMessageBox::critical(nullptr,
QLatin1String("INKONSISTENCY"),
QLatin1String("INKONSISTENCY, corefile wil be created ; check logfile regarding REGG-5360.."));
abort();
}
#endif // LTS_DEBUG
TRACE_LOG(m_logger) << LOGFUNCTION << " END, success=" << success;
return success;
}
#ifdef AREA_FIRE_DRAPED_RENDERER
bool AreaFireImpl::updateViewImplDetonation3dDraped_RendererApproach() // GUEZE_2933
{
DEBUG_LOG(m_logger) << LOGFUNCTION << " START"
<< ", m_debugInfo=" << m_debugInfo
<< ", visibility=" << m_visibility
<< ", visiTechn=" << m_visibilityTechnical
<< ", visiTact=" << m_visibilityTactical
<< ", d->m_detonationsDraped.changed() = " << d->m_detonationsDraped.changed()
<< ", d->m_detonationsDraped.size() = " << d->m_detonationsDraped.m_detonationPositions.size();
bool successDetonationsDrpd = true;
if ((m_mapImpl->mode() == Mode::Mode_3D) && d->m_detonationsDraped.changed())
{
const PositionCont &positionsTranslated_drpdTrans = d->m_detonationsDraped.m_detonationPositions.positionsTranslated();
const int newSize = positionsTranslated_drpdTrans.size();
d->resizeDraped_GORA(newSize);
int idx = 0;
for(const Point3D &point3DTranslated : qAsConst(positionsTranslated_drpdTrans))
{
Private::ValueDataGORA_Drpd &vdGORA_drpdRef = d->getObjectDraped_GORA(idx, m_graphicsLayer);
QSharedPointer<GraphicalObjectRendererAttributes> goRendererAtt = vdGORA_drpdRef.m_goRendererAtt;
goRendererAtt->setOrigin(point3DTranslated);
const QVariantMap &attribMap = d->createGORA_AttributeMap(m_mainGraphicalObject->lineStyle().lineColor(), d->m_detonationsDraped.m_detonationRadius.value());
if (m_logger.isDebugEnabled())
qCritical() << LOGFUNCTION << " START"
<< ", m_debugInfo=" << m_debugInfo
<< ", attribMap = " << attribMap
<< ", point3DTranslated = " << point3DTranslated.x() << " / " << point3DTranslated.y() << " / " << point3DTranslated.z()
<< ", m_visibility = " << m_visibility;
goRendererAtt->setAttributeMap(attribMap);
goRendererAtt->setVisibility(m_visibility);
goRendererAtt->setPickable(false);
goRendererAtt->setSelected(false);
if (!goRendererAtt->updateView())
successDetonationsDrpd = false;
++idx;
} // for
if (!successDetonationsDrpd)
ERROR_LOG(m_logger) << LOGFUNCTION << " updateViewImpl m_goRendererAtt failed, m_debugInfo=" << m_debugInfo;
d->m_detonationsDraped.reset();
}
TRACE_LOG(m_logger) << LOGFUNCTION << " END, successDetonationsDrpd=" << successDetonationsDrpd;
return successDetonationsDrpd;
}
#else // AREA_FIRE_DRAPED_RENDERER // GUEZE_2933
bool AreaFireImpl::updateViewImplDetonation3dDraped_SceneMarkerApproach() // GUEZE_2933
{
DEBUG_LOG(m_logger) << LOGFUNCTION << " START"
<< ", m_debugInfo=" << m_debugInfo
<< ", visibility=" << m_visibility
<< ", visiTechn=" << m_visibilityTechnical
<< ", visiTact=" << m_visibilityTactical
<< ", d->m_detonationsDraped.changed() = " << d->m_detonationsDraped.changed()
<< ", d->m_detonationsDraped.size() = " << d->m_detonationsDraped.m_detonationPositions.size();
bool successDetonationsDrpd = true;
if ((m_mapImpl->mode() == Mode::Mode_3D) && d->m_detonationsDraped.changed())
{
const PositionCont &positionsTranslated_drpdTrans = d->m_detonationsDraped.m_detonationPositions.positionsTranslated();
const int newSize = positionsTranslated_drpdTrans.size();
d->resizeDraped_GOSM(newSize);
int idx = 0;
for(const Point3D &point3DTranslated : qAsConst(positionsTranslated_drpdTrans))
{
Private::ValueDataGOSM_Drpd &GOSM_drpdRef = d->getObjectDraped_GOSM(idx, m_graphicsLayer);
QSharedPointer<GraphicalObjectSceneMarker> goSceneMarker = GOSM_drpdRef.m_goSceneMarker;
goSceneMarker->setOrigin(point3DTranslated);
goSceneMarker->setDiameter(d->m_detonationsDraped.m_detonationRadius.value() * 2);
goSceneMarker->setPickable(false);
goSceneMarker->setSelected(false);
QColor col = partyColor();
col.setAlphaF(col.alphaF() / 2.0);
goSceneMarker->setFillStyle(FillStyle(col, FillPattern::Solid));
goSceneMarker->setVisibility(m_visibility);
if (!goSceneMarker->updateView())
successDetonationsDrpd = false;
++idx;
} // for
if (!successDetonationsDrpd)
ERROR_LOG(m_logger) << LOGFUNCTION << " updateViewImpl GOSM_drpdRef failed, m_debugInfo=" << m_debugInfo;
d->m_detonationsDraped.reset();
}
TRACE_LOG(m_logger) << LOGFUNCTION << " END, successDetonationsDrpd=" << successDetonationsDrpd;
return successDetonationsDrpd;
}
#endif // AREA_FIRE_DRAPED_RENDERER
bool AreaFireImpl::init(MapImpl *mapImpl, const QString &logicalLayerName)
{
TRACE_LOG(m_logger) << LOGFUNCTION << " START";
if (mapImpl)
{
switch (mapImpl->symbologyType())
{
case AdvancedSymbology::SymbologyType::APP6D:
case AdvancedSymbology::SymbologyType::MIL2525D:
m_symbol.refValue().sidc = AdvancedSymbology::SidcCodec::encodeComplete(mapImpl->symbologyType(), "10012500002408010000"); // SymbolSet = 25 240801
break;
case AdvancedSymbology::SymbologyType::MIL2525C:
// m_symbol.refValue().m_sidc = QLatin1String("GHFPATB---"); // GHFPATB--- 0879, Area Target Bomb
m_symbol.refValue().sidc = AdvancedSymbology::SidcCodec::encodeComplete(mapImpl->symbologyType(), "GHFPATS---"); // GHFPATB--- 0879, Area Target Smoke
break;
case AdvancedSymbology::SymbologyType::APP6B:
m_symbol.refValue().sidc = AdvancedSymbology::SidcCodec::encodeComplete(mapImpl->symbologyType(), "GHCPFLKS--"); // APP6B: 3965: GHCPFLKS-- -> Polygon
break;
case AdvancedSymbology::SymbologyType::None:
// empty
break;
} // switch
} // if (mapImpl)
bool success = BaseClass::init(mapImpl, logicalLayerName, GraphicalObjectPathType::Polygon);
setLineStyle(LineStyle(Qt::black, 2));
// setup Private:
d->m_mapImpl = mapImpl;
d->m_logicalLayer = logicalLayerName;
d->m_debugInfo = this->debugInfo();
d->m_detonationsAbsolute.m_detonationPositions.setMapObjectImpl(this);
d->m_detonationsDraped.m_detonationPositions.setMapObjectImpl(this);
if (!success)
ERROR_LOG(m_logger) << LOGFUNCTION << " init failed";
TRACE_LOG(m_logger) << LOGFUNCTION << " END, success=" << success;
return success;
}
bool AreaFireImpl::onMapExtentChanged()
{
TRACE_LOG(m_logger) << LOGFUNCTION << " START";
for (auto item : {m_indicationCont, m_indicationContSpAbsolute})
{
const bool visiScale = m_visibilityScaleRange.scaleHasVisibility(m_mapImpl->scale());
if (item)
{
item->setVisible(0, m_visibility && m_visibilityTechnical && visiScale);
item->setVisible(1, m_visibility && m_visibilityTechnical && visiScale);
}
}
bool success = BaseClass::onMapExtentChanged();
TRACE_LOG(m_logger) << LOGFUNCTION << " END, success=" << success;
return success;
}
} // namespace SituationMap
+108
View File
@@ -0,0 +1,108 @@
/**
* @RDE_HEADER@
* Interface-Implementation of AreaFire
* $Id$
* $HeadURL$
* $Author$
*/
#pragma once
// Own
#include "abstract_multi_point_map_object_impl.h"
#include "basic_path_object_impl.h"
#include <MapObjects/area_fire.h> // Interface
// Qt
#include <QString>
//----------------------------------------------------------------------------
namespace SituationMap
{
// GUEZE_2933
// // #define AREA_FIRE_DRAPED_RENDERER
/**
* @brief The AreaFireImpl class displays a area of impacts.
*
* A class instance consists of the following logical elements:
* - mainGraphicalObject (GraphicalObjectPath displaying the main techn. Appearance)
* - mainGraphicalObjectText (displaying the text/name)
* - tacticalAppearance (displaying the tact. Appearance)
* - an infinite number indication objects for displaying impacts (inherented from BasicPathObjectImpl)
*/
// inherent 'public', to get that implementation
// inherent 'public virtual' to get that interface
class SITUATIONMAPOBJECTS_EXPORT AreaFireImpl : public BasicPathObjectImpl, public virtual AreaFire
{
using BaseClass = BasicPathObjectImpl;
public:
explicit AreaFireImpl(const QString &debugInfo = QString());
virtual ~AreaFireImpl();
AreaFireImpl(const AreaFireImpl &other) = delete;
AreaFireImpl &operator=(AreaFireImpl &other) = delete;
void setUniqueId(const UniqueMapId &uniqueId) override;
PositionCont scheduledImpacts() const override;
void setScheduledImpacts(const PositionCont &posCont, const QColor &explicitColor = QColor()) override;
PositionCont impacts() const override;
void setImpacts(const PositionCont &posCont) override;
PositionCont impactsAbsoluteHeight() const override;
void setImpactsAbsoluteHeight(const PositionCont &posCont) override;
PositionCont detonationsAbsolute() const override;
bool setDetonationsAbsolute(const PositionCont &detonationsPositions, int detonationRadius) override;
PositionCont detonationsDraped() const override;
bool setDetonationsDraped(const PositionCont &detonationsPositions, int detonationRadius) override;
void setGunToTargetLineSurface(const Point3D &start, const Point3D &end) override;
void setGunToTargetTrajectory3D(const PositionCont &gunToTargetPath) override;
void setNonLethalArea(const PositionCont &nonLethalArea) override;
PositionCont trajectory(int index) const override;
bool setTrajectory(int index, const PositionCont &trajectoryPath) override;
protected:
virtual bool updateViewImpl() override;
#ifdef AREA_FIRE_DRAPED_RENDERER
virtual bool updateViewImplDetonation3dDraped_RendererApproach();
#else
virtual bool updateViewImplDetonation3dDraped_SceneMarkerApproach();
#endif // AREA_FIRE_DRAPED_RENDERER
friend class MapImpl;
bool init(MapImpl *mapImpl, const QString &logicalLayerName) override;
bool onMapExtentChanged() override;
// internal/admin
// logical
class Private;
/**
* The private d->pointer to not break BC when changing internals of this class
*/
Private *d = nullptr;
private:
LOGGER_T m_logger; ///< Interface of the Logging-Facility
};
} // namespace SituationMap
File diff suppressed because it is too large. Load diff
@@ -0,0 +1,295 @@
/**
* @RDE_HEADER@
* Interface-Implementation of BasicPathObjectImpl
* $Id$
* $HeadURL$
* $Author$
*/
#pragma once
// Own
#include "abstract_multi_point_map_object_impl.h"
#include "indication_container.h"
#include "path_container.h"
#include <MapImpl/abstract_effect_simulation_impl.h>
#include <MapImpl/coordinate_translation.h>
#include <GraphicalObjects/graphical_object_path.h>
#include <GraphicalObjects/graphical_object_picture_marker.h>
// Qt
#include <QString>
#include <QColor>
//----------------------------------------------------------------------------
namespace SituationMap
{
class GraphicalObjectSceneMarker;
// inherent 'public', to get that implementation
// inherent 'public virtual' to get that interface
/**
* @brief The BasicPathObjectImpl class combines a couple of usefull features required by path objects.
*
* These features are:
* - For convenience an origin and radius can also be parametrized. This will be transformed into a polygon during updateView().
* - an arrowHead at the start and/or at the end of that path (both polyline and polygon)
* - m_arrowHeadStart, m_arrowHeadEnd of type ArrowHead / GraphicalObjectPictureMarker / Image
*
* - text positioned on the line segments
* - m_textDataCont of type TextData / GraphicalObjectText
*
* - an infinite number of different indication objects for displaying impacts, mines etc.
* - m_indicationCont of type IndicationContainer / GraphicalObjectPictureMarker / Image
* - m_pathCont of type PathContainer (on main Layer)
* - m_pathCont_SpAbsolute of type PathContainer (on subLayer with SurfacePlacementMode::Absolute)
*/
class SITUATIONMAPOBJECTS_EXPORT BasicPathObjectImpl : public AbstractMultiPointMapObjectImpl, public AbstractEffectSimulationImpl
{
using BaseClass = AbstractMultiPointMapObjectImpl;
public:
/*! \name Construction, Destruction */
//@{
explicit BasicPathObjectImpl(const QString &debugInfo = QString());
virtual ~BasicPathObjectImpl();
BasicPathObjectImpl(const BasicPathObjectImpl &other) = delete;
BasicPathObjectImpl &operator=(BasicPathObjectImpl &other) = delete;
//@}
QString toString() const override;
virtual Point3D tacticalOrigin() const;
virtual void setTacticalOrigin(const Point3D &tacticalOrigin);
/*! \name Set origin and radius as alternative to 'setPositions' */
//@{
virtual Point3D origin() const;
virtual void setOrigin(const Point3D &origin);
virtual float radius() const;
virtual void setRadius(float radius, unsigned int maxPointCount = 0);
//@}
#ifdef SUPPORT_SUBSIDIARY_LINES
/*! \name Subsidiary polyline/polygons */
//@{
/**
* @brief Get positions at pathIndex.
* @param pathIndex to be retrieved (if '0' identical to positions();)
* @return positions at index
*/
virtual PositionCont subsidiaryPositions(int pathIndex) const;
/**
* @brief Set positions at pathIndex.
* @param pathIndex to be set.
* @param positions values to be set.
*/
virtual void setSubsidiaryPositions(int pathIndex, const PositionCont &positions);
virtual QList<int> subsidiaryPathIndexInUse();
/**
* @brief Clear positions.
* @param pathIndex to be cleared.
* @note if not pathIndex is specified, ALL are cleared!)
*/
virtual void clearSubsidiaryPositions(int pathIndex);
/**
* @brief Clear all subsidiaryPositions.
*/
virtual void clearSubsidiaryPositions();
//@}
#endif // SUPPORT_SUBSIDIARY_LINES
GraphicalObjectPathType pathType() const;
virtual int segmentCount() const;
// Delegate to BaseClass:
virtual AesEffectState aesState() const override;
virtual void setAesState(AesEffectState aesState) override;
/*! \name Indication (for displaying impacts, mines etc.) */
//@{
virtual IndicationContainer &rIndicationContainer() const;
virtual IndicationContainer &rIndicationContainerAbsolute() const;
//@}
/*! \name Path (for displaying paths like trajectories) */
//@{
virtual PathContainer &rPathContainer() const;
virtual PathContainer &rPathContainerSpDrapedPolygon() const;
virtual void clearPathContainerSpDrapedPolygon(int idx);
virtual PathContainer &rPathContainerSpAbsolute1() const;
virtual PathContainer &rPathContainerSpAbsolute2() const;
//@}
/*! \name ArrowHeads */
//@{
//@}
/*! \name ArrowHeads */
//@{
virtual bool arrowHeadStart() const;
virtual void setArrowHeadStart(bool enable);
virtual bool arrowHeadEnd() const;
virtual void setArrowHeadEnd(bool enable);
virtual void setArrowHeadsSelected(bool select);
//@}
/*! \name Single Detonation */
//@{
void setDetonation(const Point3D &origin, double radius);
bool hasDetonation() const;
void resetDetonation();
//@}
/*! \name Text on lineSegments */
//@{
virtual QString textOnSegment(uint segment) const;
virtual void setTextOnSegment(uint segment, const QString &segmentText);
virtual void clearTextOnSegment(uint segment);
//@}
static QImage renderArrowHeadSymbol(const QColor &color, int length, int halfWidth);
protected:
bool updateViewImplPost() override
{
BaseClass::updateViewImplPost();
m_tacticalOrigin.reset();
m_origin.reset();
m_radius.reset();
m_maxPointCount.reset();
// Single Detonation by SingleSceneMarker
m_detonationOrigin.reset();
m_detonationRadius.reset();
return true;
}
bool updateViewImpl() override;
bool updateSingleSceneMarker(bool newVisibility);
friend class MapImpl;
virtual bool init(MapImpl *mapImpl,
const QString &logicalLayerName,
GraphicalObjectPathType pathType,
double maxSegmentLength = -1);
double maxSegmentLength() const;
bool onMapExtentChanged() override;
// internal/admin
// logical
SimpleValue<OriginTranslated> m_tacticalOrigin; // has priority if set (related to mainGO->positions - SingleFire)
// origin, radius as alternative to 'setPositions' :
SimpleValue<Point3D> m_origin;
SimpleValue<float> m_radius = 0;
SimpleValue<unsigned int> m_maxPointCount = 0;
// : origin, radius as alternative to 'setPositions'
// Indication :
mutable IndicationContainer *m_indicationCont{nullptr};
mutable IndicationContainer *m_indicationContSpAbsolute{nullptr}; // SurfacePlacementMode::Absolute
// : Indication
// Paths :
mutable PathContainer *m_pathCont_SpDraped{nullptr};
mutable PathContainer *m_pathCont_SpDrapedPolygon{nullptr}; // SurfacePlacementMode::Draped
mutable PathContainer *m_pathCont_SpAbsolute1{nullptr}; // SurfacePlacementMode::Absolute
mutable PathContainer *m_pathCont_SpAbsolute2{nullptr}; // SurfacePlacementMode::Absolute
// : Paths
// Single Scene Marker
// (arbitrary geometry like detonations of nContamination makes it impossible to use renderer approach)
SimpleValue<OriginTranslated> m_detonationOrigin;
SimpleValue<double> m_detonationRadius{0.0};
QSharedPointer<GraphicalObjectSceneMarker> m_detonationSceneMarker; // 3D
// : Single Scene Marker
// ArrowHeads :
struct ArrowHead
{
bool enable = false;
QSharedPointer<GraphicalObjectPictureMarker> pmArrowHead;
};
ArrowHead m_arrowHeadStart;
ArrowHead m_arrowHeadEnd;
int m_arrowHeadLengthHeight = 20;
int m_arrowHeadHalfWidth = 7;
bool updateArrowHead(ArrowHead &arrowHead, bool start);
// : ArrowHeads
// Text on line segments :
struct TextData
{
QString text;
QSharedPointer<GraphicalObjectText> goText;
};
QMap< uint, TextData > m_textDataCont;
bool updateSegmentText();
// : Text on line segments
#ifdef SUPPORT_SUBSIDIARY_LINES
QMap<int, PositionsTranslated> m_subsidiaryPositionsCont;
#endif // SUPPORT_SUBSIDIARY_LINES
private:
LOGGER_T m_logger; ///< Interface of the Logging-Facility
};
// Under special circumstances we have to instanciate BasicPathObjectImpl.
// Think of subsidiaryliens at VirtualMines.
// To to so, create 'LocalBasicPathObject'
// to get access to 'init'
class LocalBasicPathObject final : public BasicPathObjectImpl
{
public:
using BasicPathObjectImpl::BasicPathObjectImpl;
using BasicPathObjectImpl::init;
using BasicPathObjectImpl::setUniqueId;
};
} // namespace SituationMap
@@ -0,0 +1,156 @@
/**
* @RDE_HEADER@
* Interface-Implementation of BiologicalAgent
* $Id$
* $HeadURL$
* $Author$
*/
// Own
#include "biological_agent_impl.h"
#include <MapImpl/map_impl.h>
#include <Map/party_id_to_color_functor.h>
#include <GraphicalObjects/graphical_object_ellipse.h>
#include <GraphicalObjects/tactical_appearance.h>
#include <Symbology/sidc_codec.h>
// ESRI
// Qt
namespace SituationMap
{
//-----------------------------------------------------------------------------
// class BiologicalAgentImpl
//-----------------------------------------------------------------------------
BiologicalAgentImpl::BiologicalAgentImpl(const QString &debugInfo)
: BiologicalAgent() // Interface
, BaseClass(debugInfo) // Implementation
, m_logger(getLogger("BiologicalAgentImpl"))
{
TRACE_LOG(m_logger) << LOGFUNCTION << " START";
m_lineColorFromParty = false;
m_fillColorAlpha = 200;
TRACE_LOG(m_logger) << LOGFUNCTION << " END";
}
BiologicalAgentImpl::~BiologicalAgentImpl()
{
TRACE_LOG(m_logger) << LOGFUNCTION << " START";
TRACE_LOG(m_logger) << LOGFUNCTION << " END";
}
QString BiologicalAgentImpl::toString() const
{
QString str;
str.append(BaseClass::toString());
str.append(BasicPathObjectImpl::toString());
return str;
}
Point3D BiologicalAgentImpl::origin() const
{
return BaseClass::origin();
}
void BiologicalAgentImpl::setOrigin(const Point3D &origin)
{
BaseClass::setOrigin(origin);
}
float BiologicalAgentImpl::radius() const
{
return BaseClass::radius();
}
void BiologicalAgentImpl::setRadius(float radius)
{
BaseClass::setRadius(radius);
}
AesEffectState BiologicalAgentImpl::aesState() const
{
return BaseClass::aesState();
}
void BiologicalAgentImpl::setAesState(AesEffectState aesState)
{
BaseClass::setAesState(aesState);
}
SymbolImage BiologicalAgentImpl::symbolImage() const
{
SymbolImage symImage = m_tacticalAppearance->symbolImage();
return symImage;
}
bool BiologicalAgentImpl::updateViewImpl()
{
TRACE_LOG(m_logger) << LOGFUNCTION << " START"
<< " origin =" << this->origin() //.x() << ", " << this->origin().y()
<< " radius =" << this->radius()
<< " visibility=" << m_visibility
<< " visiTechn=" << m_visibilityTechnical
<< " visiTact=" << m_visibilityTactical;
bool success = BaseClass::updateViewImpl();
if (!success)
ERROR_LOG(m_logger) << LOGFUNCTION << " updateViewImpl failed";
TRACE_LOG(m_logger) << LOGFUNCTION << " END, success=" << success;
return success;
}
bool BiologicalAgentImpl::init(MapImpl *mapImpl, const QString &logicalLayerName)
{
TRACE_LOG(m_logger) << LOGFUNCTION << " START";
if (mapImpl)
{
switch (mapImpl->symbologyType())
{
case AdvancedSymbology::SymbologyType::APP6D:
case AdvancedSymbology::SymbologyType::MIL2525D:
m_symbol.refValue().sidc = AdvancedSymbology::SidcCodec::encodeComplete(mapImpl->symbologyType(), "10012500002717000000"); // SymbolSet = 25 271700
// ^^ ^^^^^^
break;
case AdvancedSymbology::SymbologyType::MIL2525C:
// m_symbol.refValue().m_sidc = QLatin1String("GUMPNB----"); // 0953 GUMPNB---- -> Polygon -> Image WITH Area // small icon and big border
m_symbol.refValue().sidc = AdvancedSymbology::SidcCodec::encodeComplete(mapImpl->symbologyType(), "GFMPNEB---"); // 0081 GFMPNEB--- -> Point -> Image WITHOUT Area // not 'centered'
break;
case AdvancedSymbology::SymbologyType::APP6B:
// m_symbol.refValue().m_sidc = QLatin1String("GHCPBWC---"); // APP6B: 3937 GHCPBWC--- -> Polygon
m_symbol.refValue().sidc = AdvancedSymbology::SidcCodec::encodeComplete(mapImpl->symbologyType(), "GUCPBWK---"); // APP6B: 2875 GUCPBWK--- -> Point
break;
case AdvancedSymbology::SymbologyType::None:
// empty
break;
} // switch
} // if (mapImpl)
bool success = BaseClass::init(mapImpl, logicalLayerName, GraphicalObjectPathType::Polygon);
if (!success)
ERROR_LOG(m_logger) << LOGFUNCTION << " init failed";
setLineStyle(LineStyle(Qt::yellow, 2));
setFillStyle(FillStyle(Qt::yellow, FillPattern::Null));
TRACE_LOG(m_logger) << LOGFUNCTION << " END, success=" << success;
return success;
}
} // namespace SituationMap
@@ -0,0 +1,83 @@
/**
* @RDE_HEADER@
* Interface-Implementation of BiologicalAgent
* $Id$
* $HeadURL$
* $Author$
*/
#pragma once
// Own
#include "abstract_multi_point_map_object_impl.h"
#include "basic_path_object_impl.h"
#include <MapObjects/biological_agent.h> // Interface
// Qt
//----------------------------------------------------------------------------
namespace SituationMap
{
/**
* @brief The BiologicalAgentImpl class can be described by an origin and a radius.
* \note Maybe this will be changed in future to be consistent to the ChemicalAgent.
*
* A class instance consists of the following logical elements:
* - mainGraphicalObject (GraphicalObjectPath/Polyline, displaying the main techn. Appearance)
* - mainGraphicalObjectText (displaying the text/name)
* - tacticalAppearance (displaying the tact. Appearance)
*/
// inherent 'public', to get that implementation
// inherent 'public virtual' to get that interface
class SITUATIONMAPOBJECTS_EXPORT BiologicalAgentImpl : public BasicPathObjectImpl, public virtual BiologicalAgent
{
using BaseClass = BasicPathObjectImpl;
template <typename> friend class GenericObjectFactory;
protected:
explicit BiologicalAgentImpl(const QString &debugInfo = QString());
virtual ~BiologicalAgentImpl();
public:
BiologicalAgentImpl(const BiologicalAgentImpl &other) = delete;
BiologicalAgentImpl &operator=(BiologicalAgentImpl &other) = delete;
QString toString() const override;
// some set/get methods:
Point3D origin() const override;
void setOrigin(const Point3D &origin) override;
float radius() const override;
void setRadius(float radius) override;
// Delegate to BaseClass:
AesEffectState aesState() const override;
void setAesState(AesEffectState aesState) override;
SymbolImage symbolImage() const override;
protected:
bool updateViewImpl() override;
friend class MapImpl;
bool init(MapImpl *mapImpl, const QString &logicalLayerName) override;
// internal/admin
// logical
private:
LOGGER_T m_logger; ///< Interface of the Logging-Facility
};
} // namespace SituationMap
@@ -0,0 +1,269 @@
/**
* @RDE_HEADER@
* Interface-Implementation of BuildingOutline
* $Id$
* $HeadURL$
* $Author$
*/
// Own
#include "building_outline_impl.h"
#include <MapImpl/map_impl.h>
#include <GraphicalObjects/graphical_object_path.h>
#include <Map/bounding_box.h>
#include "Map/object_factory.h"
#include<Symbology/sidc_codec.h>
// ESRI
// Qt
namespace SituationMap
{
//-----------------------------------------------------------------------------
// class BuildingOutlineImpl
//-----------------------------------------------------------------------------
BuildingOutlineImpl::BuildingOutlineImpl(const QString &debugInfo)
: BuildingOutline() // Interface
, BaseClass(debugInfo) // Implementation
, m_logger(getLogger("BuildingOutlineImpl"))
{
TRACE_LOG(m_logger) << LOGFUNCTION << " START";
m_markerOrigin.setMapObjectImpl(this);
TRACE_LOG(m_logger) << LOGFUNCTION << " END";
}
BuildingOutlineImpl::~BuildingOutlineImpl()
{
TRACE_LOG(m_logger) << LOGFUNCTION << " START";
delete m_marker;
delete m_modelSceneMarker;
TRACE_LOG(m_logger) << LOGFUNCTION << " END";
}
PositionCont BuildingOutlineImpl::positions() const
{
return BaseClass::positions();
}
bool BuildingOutlineImpl::setPositions(const PositionCont &posCont)
{
return BaseClass::setPositions(posCont);
}
QColor BuildingOutlineImpl::majorColor() const
{
if (m_forcedMajorColor.isValid())
return m_forcedMajorColor;
// use fillColor here:
return (m_mainGraphicalObject) ? m_mainGraphicalObject->fillStyle().fillColor() : BaseClass::majorColor();
}
LineStyle BuildingOutlineImpl::lineStyle() const
{
return BaseClass::lineStyle();
}
LineStyle &BuildingOutlineImpl::rLineStyle()
{
return BaseClass::rLineStyle();
}
void BuildingOutlineImpl::setLineStyle(const LineStyle &lineStyle)
{
BaseClass::setLineStyle(lineStyle);
}
FillStyle BuildingOutlineImpl::fillStyle() const
{
return BaseClass::fillStyle();
}
FillStyle &BuildingOutlineImpl::rFillStyle()
{
return BaseClass::rFillStyle();
}
void BuildingOutlineImpl::setFillStyle(const FillStyle &fillStyle)
{
BaseClass::setFillStyle(fillStyle);
}
void BuildingOutlineImpl::setMarker(const Point3D &markerOrigin)
{
m_markerOrigin.setOrigin(markerOrigin);
}
BuildingOutline::ModelSceneSymbolData BuildingOutlineImpl::getModelSceneSymbolData()
{
return m_modelSceneSymolData;
}
void BuildingOutlineImpl::setModelSceneSymbolData(const BuildingOutline::ModelSceneSymbolData &modelSceneSymbolData)
{
m_modelSceneSymolData = modelSceneSymbolData;
}
bool BuildingOutlineImpl::updateViewImpl()
{
TRACE_LOG(m_logger) << LOGFUNCTION << " START"
<< " visibility=" << m_visibility
<< " visiTechn=" << m_visibilityTechnical
<< " visiTact=" << m_visibilityTactical
<< " scale=" << m_mainGraphicalObject->scale()
<< " posCont=" << m_positions.positions()
<< " url=" << m_modelSceneSymolData.url.toString()
<< " scale=" << m_modelSceneSymolData.scale
<< " m_heading=" << m_modelSceneSymolData.heading;
bool success = BaseClass::updateViewImpl();
updateViewImplMarker();
if (m_mapImpl->mode() == Mode::Mode_3D)
updateModelSceneSymbol();
if (!success)
ERROR_LOG(m_logger) << LOGFUNCTION << " updateViewImpl failed";
TRACE_LOG(m_logger) << LOGFUNCTION << " END, success=" << success;
return success;
}
bool BuildingOutlineImpl::updateViewImplMarker()
{
if (m_markerOrigin.isEmpty())
{
delete m_marker;
m_marker = nullptr;
}
else
{
if (!m_marker)
{
m_marker = new GraphicalObjectPictureMarker(m_mapImpl->getEsriGeoView(),
m_graphicsLayer,
m_debugInfo + QLatin1String("#Marker"),
m_uniqueMapId);
}
const float scale = m_mainGraphicalObject->scale() * m_mainGraphicalObject->lineStyle().lineWidth() * 0.5f;
m_marker->setMarkerSymbol(MarkerSymbolType::Triangle, qRound(5.0f * scale), m_mainGraphicalObject->rLineStyle().lineColor());
m_marker->setPickable(m_mainGraphicalObject->pickable());
m_marker->setDrawOrder(m_internalDrawOrder+1);
m_marker->setOrigin(m_markerOrigin.originTranslated());
m_marker->setVisibility(m_visibility && m_visibilityTechnical);
if (!m_marker->updateView())
ERROR_LOG(m_logger) << LOGFUNCTION << " debugInfo='" << m_debugInfo << "'"
<< " updateView failed";
}
return true;
}
bool BuildingOutlineImpl::updateModelSceneSymbol()
{
TRACE_LOG(m_logger) << LOGFUNCTION << " START"
<< " debugInfo='" << m_debugInfo << "'"
<< " url=" << m_modelSceneSymolData.url.toString()
<< " scale=" << m_modelSceneSymolData.scale
<< " m_heading=" << m_modelSceneSymolData.heading;
bool success = false;
if (m_markerOrigin.isEmpty())
{
ERROR_LOG(m_logger) << LOGFUNCTION << " no markerOrigin"
<< " debugInfo='" << m_debugInfo << "'";
return false;
}
if (m_modelSceneSymolData.url.isEmpty())
{
delete m_modelSceneMarker;
m_modelSceneMarker= nullptr;
} else {
if (!m_modelSceneMarker)
m_modelSceneMarker = new GraphicalObjectModelSceneMarker(m_mapImpl->getEsriGeoView(),
m_graphicsLayer,
m_debugInfo + QLatin1String("#ModelSceneMarker"),
m_uniqueMapId);
// Symbol:
m_modelSceneMarker->setUrl(m_modelSceneSymolData.url);
m_modelSceneMarker->setOrigin(m_markerOrigin.originTranslated());
m_modelSceneMarker->setHeading(m_modelSceneSymolData.heading);
m_modelSceneMarker->setScale(m_modelSceneSymolData.scale); // use scale of m_modelSceneSymolData, not of m_mainGraphicalObject
m_modelSceneMarker->setVisibility(m_visibility && m_visibilityTechnical);
success = m_modelSceneMarker->updateView();
if (!success)
ERROR_LOG(m_logger) << LOGFUNCTION << " updateView failed"
<< " debugInfo='" << m_debugInfo << "'";
}
TRACE_LOG(m_logger) << LOGFUNCTION << " END"
<< " debugInfo='" << m_debugInfo << "'";
return success;
}
bool BuildingOutlineImpl::init(MapImpl *mapImpl, const QString &logicalLayerName)
{
TRACE_LOG(m_logger) << LOGFUNCTION << " START";
if (mapImpl)
{
switch (mapImpl->symbologyType())
{
case AdvancedSymbology::SymbologyType::APP6D:
case AdvancedSymbology::SymbologyType::MIL2525D:
m_symbol.refValue().sidc = AdvancedSymbology::SidcCodec::encodeComplete(mapImpl->symbologyType(), "10042500002701000000"); // SymbolSet = 25 270100
break;
case AdvancedSymbology::SymbologyType::MIL2525C:
m_symbol.refValue().sidc = AdvancedSymbology::SidcCodec::encodeComplete(mapImpl->symbologyType(), "G*MPOGZ---****X");
break;
case AdvancedSymbology::SymbologyType::APP6B:
m_symbol.refValue().sidc = AdvancedSymbology::SidcCodec::encodeComplete(mapImpl->symbologyType(), "GFCPBOGB--"); // APP6B: 3845: GFCPBOGB-- -> Polygon
break;
case AdvancedSymbology::SymbologyType::None:
// empty
break;
} // switch
} // if (mapImpl)
bool success = BaseClass::init(mapImpl, logicalLayerName, GraphicalObjectPathType::Polygon);
setLineStyle(LineStyle(Qt::black, 2));
if (!success)
ERROR_LOG(m_logger) << LOGFUNCTION << " init failed";
TRACE_LOG(m_logger) << LOGFUNCTION << " END, success=" << success;
return success;
}
void BuildingOutlineImpl::updateIdentifierPosition()
{
if (m_positions.isEmpty())
return;
BoundingBox bbox;
this->boundingBox(bbox);
if (!bbox.isValid())
return BaseClass::updateIdentifierPosition();
OriginTranslated objCenterPoint;
objCenterPoint.setMapObjectImpl(this);
objCenterPoint.setOrigin(bbox.center());
m_identifierPositionCandidateTranslated = objCenterPoint.originTranslated();
}
} // namespace SituationMap
@@ -0,0 +1,94 @@
/**
* @RDE_HEADER@
* Interface-Implementation of BuildingOutline
* $Id$
* $HeadURL$
* $Author$
*/
#pragma once
// Own
#include "basic_path_object_impl.h"
#include <MapObjects/building_outline.h> // Interface
#include <GraphicalObjects/graphical_object_model_scene_marker.h>
// Qt
#include <QString>
#include <QUrl>
//----------------------------------------------------------------------------
namespace SituationMap
{
/**
* @brief The BuildingOutlineImpl class displays the outline of a building.
*
* A class instance consists of the following logical elements:
* - mainGraphicalObject (GraphicalObjectPath displaying the main techn. Appearance)
* - mainGraphicalObjectText (displaying the text/name)
* - tacticalAppearance (displaying the tact. Appearance)
*/
// inherent 'public', to get that implementation
// inherent 'public virtual' to get that interface
class SITUATIONMAPOBJECTS_EXPORT BuildingOutlineImpl : public BasicPathObjectImpl, public virtual BuildingOutline
{
using BaseClass = BasicPathObjectImpl;
template <typename> friend class GenericObjectFactory;
protected:
explicit BuildingOutlineImpl(const QString &debugInfo = QString());
virtual ~BuildingOutlineImpl();
public:
BuildingOutlineImpl(const BuildingOutlineImpl &other) = delete;
BuildingOutlineImpl &operator=(BuildingOutlineImpl &other) = delete;
PositionCont positions() const override;
bool setPositions(const PositionCont &posCont) override;
QColor majorColor() const override;
LineStyle lineStyle() const override;
LineStyle &rLineStyle() override;
void setLineStyle(const LineStyle &lineStyle) override;
FillStyle fillStyle() const override;
FillStyle &rFillStyle() override;
void setFillStyle(const FillStyle &fillStyle) override;
void setMarker(const Point3D &markerOrigin) override;
ModelSceneSymbolData getModelSceneSymbolData() override;
void setModelSceneSymbolData(const ModelSceneSymbolData &modelSceneSymbolData) override;
protected:
bool updateViewImpl() override;
bool updateViewImplMarker();
bool updateModelSceneSymbol();
friend class MapImpl;
bool init(MapImpl *mapImpl, const QString &logicalLayerName) override;
// internal/admin
void updateIdentifierPosition() override;
// logical
private:
LOGGER_T m_logger; ///< Interface of the Logging-Facility
GraphicalObjectPictureMarker *m_marker{nullptr};
OriginTranslated m_markerOrigin;
ModelSceneSymbolData m_modelSceneSymolData;
GraphicalObjectModelSceneMarker *m_modelSceneMarker{nullptr};
};
} // namespace SituationMap
@@ -0,0 +1,129 @@
/**
* @RDE_HEADER@
* Interface-Implementation of ChemicalAgent
* $Id$
* $HeadURL$
* $Author$
*/
// Own
#include "chemical_agent_impl.h"
#include <MapImpl/map_impl.h>
#include <GraphicalObjects/graphical_object_path.h>
#include <GraphicalObjects/graphical_object_text.h>
#include <Symbology/sidc_codec.h>
// ESRI
// Qt
namespace SituationMap
{
//-----------------------------------------------------------------------------
// class ChemicalAgentImpl
//-----------------------------------------------------------------------------
ChemicalAgentImpl::ChemicalAgentImpl(const QString &debugInfo)
: ChemicalAgent() // Interface
, BaseClass(debugInfo) // Implementation
, m_logger(getLogger("ChemicalAgentImpl"))
{
TRACE_LOG(m_logger) << LOGFUNCTION << " START";
m_lineColorFromParty = false;
m_fillColorAlpha = 200;
TRACE_LOG(m_logger) << LOGFUNCTION << " END";
}
ChemicalAgentImpl::~ChemicalAgentImpl()
{
TRACE_LOG(m_logger) << LOGFUNCTION << " START";
TRACE_LOG(m_logger) << LOGFUNCTION << " END";
}
Point3D ChemicalAgentImpl::origin() const
{
return BaseClass::origin();
}
void ChemicalAgentImpl::setOrigin(const Point3D &origin)
{
BaseClass::setOrigin(origin);
}
float ChemicalAgentImpl::radius() const
{
return BaseClass::radius();
}
void ChemicalAgentImpl::setRadius(float radius, unsigned int maxPointCount)
{
BaseClass::setRadius(radius, maxPointCount);
}
bool ChemicalAgentImpl::updateViewImpl()
{
TRACE_LOG(m_logger) << LOGFUNCTION << " START"
<< " symbol=" << m_symbol.value().sidc
<< " visibility=" << m_visibility
<< " visiTechn=" << m_visibilityTechnical
<< " visiTact=" << m_visibilityTactical;
bool success = BaseClass::updateViewImpl();
if (!success)
ERROR_LOG(m_logger) << LOGFUNCTION << " updateViewImpl failed";
TRACE_LOG(m_logger) << LOGFUNCTION << " END, success=" << success;
return success;
}
bool ChemicalAgentImpl::init(MapImpl *mapImpl, const QString &logicalLayerName)
{
TRACE_LOG(m_logger) << LOGFUNCTION << " START";
if (mapImpl)
{
switch (mapImpl->symbologyType())
{
case AdvancedSymbology::SymbologyType::APP6D:
case AdvancedSymbology::SymbologyType::MIL2525D:
m_symbol.refValue().sidc = AdvancedSymbology::SidcCodec::encodeComplete(mapImpl->symbologyType(), "10012500002718000000"); // SymbolSet = 25 271800
// ^^ ^^^^^^
break;
case AdvancedSymbology::SymbologyType::MIL2525C:
m_symbol.refValue().sidc = AdvancedSymbology::SidcCodec::encodeComplete(mapImpl->symbologyType(), "GUMPNC----"); // 0985 GUMPNC---- -> Polygon
// m_symbol.refValue().sidc = AdvancedSymbology::SidcCodec::encodeComplete(mapImpl->symbologyType(),"GFMPNEC---"); // MIL2525D: 0115: GFMPNEC--- "Chemical F"s
break;
case AdvancedSymbology::SymbologyType::APP6B:
m_symbol.refValue().sidc = AdvancedSymbology::SidcCodec::encodeComplete(mapImpl->symbologyType(), "GUCPBWH---"); // APP6B: 3943 GUCPBWH--- -> Polygon
// m_symbol.refValue().sidc = AdvancedSymbology::SidcCodec::encodeComplete(mapImpl->symbologyType(),"GUCPBWK---"); // APP6B: 2879: GUCPBWK--- -> Point "Chemical Attack, Release Event U"
break;
case AdvancedSymbology::SymbologyType::None:
// empty
break;
} // switch
} // if (mapImpl)
bool success = BaseClass::init(mapImpl, logicalLayerName, GraphicalObjectPathType::Polygon);
setLineStyle(LineStyle(Qt::yellow, 2));
setFillStyle(FillStyle(Qt::yellow, FillPattern::Null));
if (!success)
ERROR_LOG(m_logger) << LOGFUNCTION << " init failed";
TRACE_LOG(m_logger) << LOGFUNCTION << " END, success=" << success;
return success;
}
} // namespace SituationMap
@@ -0,0 +1,78 @@
/**
* @RDE_HEADER@
* Interface-Implementation of ChemicalAgent
* $Id$
* $HeadURL$
* $Author$
*/
#pragma once
// Own
#include "abstract_multi_point_map_object_impl.h"
#include "basic_path_object_impl.h"
#include <MapObjects/chemical_agent.h> // Interface
// Qt
#include <QString>
#include <QPointF>
//----------------------------------------------------------------------------
namespace SituationMap
{
/**
* @brief The ChemicalAgentImpl class can be described by an unlimited number of positions (PositionCont).
* For convenience an origin and radius can also be parametrized (inherented from BasicPathObjectImpl)
* A class instance consists of the following logical elements:
* - mainGraphicalObject (GraphicalObjectPath displaying the main techn. Appearance)
* - mainGraphicalObjectText (displaying the text/name)
* - tacticalAppearance (displaying the tact. Appearance)
* - an infinite number indication objects for displaying impacts (inherented from BasicPathObjectImpl).
*/
// inherent 'public', to get that implementation
// inherent 'public virtual' to get that interface
class SITUATIONMAPOBJECTS_EXPORT ChemicalAgentImpl : public BasicPathObjectImpl, public virtual ChemicalAgent
{
using BaseClass = SituationMap::BasicPathObjectImpl;
template <typename> friend class GenericObjectFactory;
protected:
explicit ChemicalAgentImpl(const QString &debugInfo = QString());
virtual ~ChemicalAgentImpl();
public:
ChemicalAgentImpl(const ChemicalAgentImpl &other) = delete;
ChemicalAgentImpl &operator=(ChemicalAgentImpl &other) = delete;
Point3D origin() const override;
void setOrigin(const Point3D &origin) override;
float radius() const override;
void setRadius(float radius, unsigned int maxPointCount = 0) override;
protected:
bool updateViewImpl() override;
friend class MapImpl;
bool init(MapImpl *mapImpl, const QString &logicalLayerName) override;
// internal/admin
// logical
private:
LOGGER_T m_logger; ///< Interface of the Logging-Facility
};
} // namespace SituationMap
+166
View File
@@ -0,0 +1,166 @@
/**
* @RDE_HEADER@
* Interface-Implementation of DangerArea
* $Id$
* $HeadURL$
* $Author$
*/
// Own
#include "cube_impl.h"
#include <Map/coord_translation_functor.h>
#include <Map/party_id_to_color_functor.h>
#include <MapImpl/map_impl.h>
#include <GraphicalObjects/graphical_object_cube.h>
// ESRI
#include <arcgis/GraphicsOverlay.h>
#include <arcgis/Renderer.h>
#include <arcgis/PolygonBuilder.h>
// Qt
namespace SituationMap
{
//-----------------------------------------------------------------------------
// class CubeImpl
//-----------------------------------------------------------------------------
CubeImpl::CubeImpl(const QString &debugInfo)
: Cube() // Interface
, BaseClass(debugInfo) // Implementation
, m_logger(getLogger("CubeImpl"))
{
TRACE_LOG(m_logger) << LOGFUNCTION << " START";
TRACE_LOG(m_logger) << LOGFUNCTION << " END";
}
CubeImpl::~CubeImpl()
{
TRACE_LOG(m_logger) << LOGFUNCTION << " START";
TRACE_LOG(m_logger) << LOGFUNCTION << " END";
}
double CubeImpl::height() const
{
return m_height;
}
void CubeImpl::setHeight(double height)
{
m_height = height;
}
bool CubeImpl::updateViewImpl()
{
TRACE_LOG(m_logger) << LOGFUNCTION << " START"
<< " symbol=" << m_symbol.value().sidc
<< " visibility=" << m_visibility
<< " visiTechn=" << m_visibilityTechnical
<< " visiTact=" << m_visibilityTactical;
// pre-condition
Esri::ArcGISRuntime::Renderer *curRenderer = nullptr;
if (m_graphicsLayer)
curRenderer = m_graphicsLayer->renderer();
if (!curRenderer)
{
ERROR_LOG(m_logger) << LOGFUNCTION << " no ArcGISRuntime::Renderer, layername='" << m_logicalLayerName << "'";
return false;
}
// Destroy if invisible :
// 13.09.2018, Norbert Thoden
// Regarding ESRI Case #02170796 - [BOS] Crash with Destruction of 3D Scene
// To reduce likelihood of crash:
// Destroy GraphicalObject (GO, m_mainGraphicalObject) if it becomes invisible
// With V100.3.0 the behaviour does not change.
// (switching cubes for 180 bldgs on and off)
//
if (m_visibility)
{
if (!m_mainGraphicalObject)
{
m_mainGraphicalObject = new GraphicalObjectCube(m_mapImpl->getEsriGeoView(),
m_graphicsLayer,
m_debugInfo + QStringLiteral("#GOCube"),
m_uniqueMapId);
}
} else {
delete m_mainGraphicalObject;
m_mainGraphicalObject = nullptr;
return true;
}
// : Destroy if invisible
GraphicalObjectCube *goCube = static_cast<GraphicalObjectCube *>(m_mainGraphicalObject);
if (goCube)
{
// in former times: partyName was used
// it´s replaced by more flexible ExtrusionColorName:
// const QString &partyName = m_mapImpl->partyIdToColorFunctor().partyIdToName(m_party.partyId.value());
// goCube->setPartyName(partyName);
const QColor &partyColor= m_mapImpl->partyIdToColorFunctor().partyIdToColor(m_party.partyId.value());
if (m_party.partyId.value() > -2) //Use Default: White or TeamColor
{
goCube->setExtrusionColorName( partyColor.name() );
}
else // Use given Color //need to be prepared in layerfactory!
{
goCube->setExtrusionColorName( majorColor().name() );
}
goCube->setPositions(m_positions.positionsTranslated());
goCube->setHeight(m_height);
}
else
{
ERROR_LOG(m_logger) << LOGFUNCTION << " no m_mainGraphicalObject";
return false;
}
bool success = BaseClass::updateViewImpl();
if (!success)
ERROR_LOG(m_logger) << LOGFUNCTION << " updateViewImpl failed";
TRACE_LOG(m_logger) << LOGFUNCTION << " END";
return true;
}
bool CubeImpl::init(MapImpl *mapImpl, const QString &logicalLayerName)
{
TRACE_LOG(m_logger) << LOGFUNCTION << " START";
bool success = BaseClass::init(mapImpl, logicalLayerName);
// create underlying object (to save most attributes only there)
if (!m_mainGraphicalObject)
{
m_mainGraphicalObject = new GraphicalObjectCube(m_mapImpl->getEsriGeoView(),
m_graphicsLayer,
m_debugInfo + QStringLiteral("#GOCube"),
m_uniqueMapId);
//this MapObject is not very typical, therefore set some attributes:
this->setPickable(false);
this->setScaleEnable(false);
}
TRACE_LOG(m_logger) << LOGFUNCTION << " END";
return success;
}
} // namespace SituationMap
+76
View File
@@ -0,0 +1,76 @@
/**
* @RDE_HEADER@
* Interface-Implementation of DangerArea
* $Id$
* $HeadURL$
* $Author$
*/
#pragma once
// Own
#include "abstract_multi_point_map_object_impl.h"
#include "basic_path_object_impl.h"
#include <MapObjects/cube.h> // Interface
// ESRI
#include <arcgis/Graphic.h>
// Qt
#include <QString>
//----------------------------------------------------------------------------
namespace SituationMap
{
/**
* @brief The CubeImpl class a cube if the UniqueValueRenderer is set.
*
* A class instance consists of the following logical elements:
* - mainGraphicalObject (GraphicalObjectPath displaying the main techn. Appearance, the cube)
* - mainGraphicalObjectText not used
* - tacticalAppearance not used
*/
// inherent 'public', to get that implementation
// inherent 'public virtual' to get that interface
class SITUATIONMAPOBJECTS_EXPORT CubeImpl : public AbstractMultiPointMapObjectImpl, public virtual Cube
{
using BaseClass = AbstractMultiPointMapObjectImpl;
template <typename> friend class GenericObjectFactory;
protected:
explicit CubeImpl(const QString &debugInfo = QString());
virtual ~CubeImpl();
public:
CubeImpl(const CubeImpl &other) = delete;
CubeImpl &operator=(CubeImpl &other) = delete;
double height() const override;
void setHeight(double height) override;
protected:
bool updateViewImpl() override;
bool init(MapImpl *mapImpl, const QString &logicalLayerName) override;
// internal/admin
// logical
private:
double m_height;
LOGGER_T m_logger; ///< Interface of the Logging-Facility
};
} // namespace SituationMap
+105
View File
@@ -0,0 +1,105 @@
/**
* @RDE_HEADER@
* Interface-Implementation of DangerArea
* $Id$
* $HeadURL$
* $Author$
*/
// Own
#include "danger_area_impl.h"
#include <MapImpl/map_impl.h>
#include <GraphicalObjects/graphical_object_path.h>
#include <GraphicalObjects/graphical_object_text.h>
#include <Symbology/sidc_codec.h>
// ESRI
// Qt
namespace SituationMap
{
//-----------------------------------------------------------------------------
// class DangerAreaImpl
//-----------------------------------------------------------------------------
DangerAreaImpl::DangerAreaImpl(const QString &debugInfo)
: DangerArea() // Interface
, BaseClass(debugInfo) // Implementation
, m_logger(getLogger("DangerAreaImpl"))
{
TRACE_LOG(m_logger) << LOGFUNCTION << " START";
TRACE_LOG(m_logger) << LOGFUNCTION << " END";
}
DangerAreaImpl::~DangerAreaImpl()
{
TRACE_LOG(m_logger) << LOGFUNCTION << " START";
TRACE_LOG(m_logger) << LOGFUNCTION << " END";
}
bool DangerAreaImpl::updateViewImpl()
{
TRACE_LOG(m_logger) << LOGFUNCTION << " START"
<< " symbol=" << m_symbol.value().sidc
<< " visibility=" << m_visibility
<< " visiTechn=" << m_visibilityTechnical
<< " visiTact=" << m_visibilityTactical;
bool success = BaseClass::updateViewImpl();
if (!success)
ERROR_LOG(m_logger) << LOGFUNCTION << " updateViewImpl failed";
TRACE_LOG(m_logger) << LOGFUNCTION << " END, success=" << success;
return success;
}
bool DangerAreaImpl::init(MapImpl *mapImpl, const QString &logicalLayerName)
{
TRACE_LOG(m_logger) << LOGFUNCTION << " START";
if (mapImpl)
{
switch (mapImpl->symbologyType())
{
case AdvancedSymbology::SymbologyType::APP6D:
case AdvancedSymbology::SymbologyType::MIL2525D:
m_symbol.refValue().sidc = AdvancedSymbology::SidcCodec::encodeComplete(mapImpl->symbologyType(), "10012500001511000000"); // SymbolSet = 25 151100
break;
case AdvancedSymbology::SymbologyType::MIL2525C:
m_symbol.refValue().sidc = AdvancedSymbology::SidcCodec::encodeComplete(mapImpl->symbologyType(), "GUMPNC----"); // Image WITH Area // small icon and big border
break;
case AdvancedSymbology::SymbologyType::APP6B:
m_symbol.refValue().sidc = AdvancedSymbology::SidcCodec::encodeComplete(mapImpl->symbologyType(), "GUCPMGASM-"); // APP6B: 3556: GUCPMGASM- -> Polygon
// m_symbol.refValue().sidc = AdvancedSymbology::SidcCodec::encodeComplete(mapImpl->symbologyType(),"GUCPBWC---"); // APP6B: 3939: GUCPBWC---- -> Polygon
break;
case AdvancedSymbology::SymbologyType::None:
// empty
break;
} // switch
} // if (mapImpl)
bool success = BaseClass::init(mapImpl, logicalLayerName, GraphicalObjectPathType::Polygon);
setLineStyle(LineStyle(Qt::yellow, 2));
setFillStyle(FillStyle(Qt::yellow, FillPattern::Null));
if (!success)
ERROR_LOG(m_logger) << LOGFUNCTION << " init failed";
TRACE_LOG(m_logger) << LOGFUNCTION << " END, success=" << success;
return success;
}
} // namespace SituationMap
+68
View File
@@ -0,0 +1,68 @@
/**
* @RDE_HEADER@
* Interface-Implementation of DangerArea
* $Id$
* $HeadURL$
* $Author$
*/
#pragma once
// Own
#include "abstract_multi_point_map_object_impl.h"
#include "basic_path_object_impl.h"
#include <MapObjects/danger_area.h> // Interface
// Qt
#include <QString>
//----------------------------------------------------------------------------
namespace SituationMap
{
/**
* @brief The DangerAreaImpl class displays an area of undefined danger.
*
* A class instance consists of the following logical elements:
* - mainGraphicalObject (GraphicalObjectPath displaying the main techn. Appearance)
* - mainGraphicalObjectText (displaying the text/name)
* - tacticalAppearance (displaying the tact. Appearance)
*/
// inherent 'public', to get that implementation
// inherent 'public virtual' to get that interface
class SITUATIONMAPOBJECTS_EXPORT DangerAreaImpl : public BasicPathObjectImpl, public virtual DangerArea
{
using BaseClass = BasicPathObjectImpl;
template <typename> friend class GenericObjectFactory;
protected:
explicit DangerAreaImpl(const QString &debugInfo = QString());
virtual ~DangerAreaImpl();
public:
DangerAreaImpl(const DangerAreaImpl &other) = delete;
DangerAreaImpl &operator=(DangerAreaImpl &other) = delete;
protected:
bool updateViewImpl() override;
friend class MapImpl;
bool init(MapImpl *mapImpl, const QString &logicalLayerName) override;
// internal/admin
// logical
private:
LOGGER_T m_logger; ///< Interface of the Logging-Facility
};
} // namespace SituationMap
@@ -0,0 +1,179 @@
/**
* @RDE_HEADER@
* Interface-Implementation of FunctionalArea
* $Id$
* $HeadURL$
* $Author$
*/
// Own
#include "functional_area_impl.h"
#include <MapImpl/map_impl.h>
#include <GraphicalObjects/graphical_object_path.h>
#include <GraphicalObjects/graphical_object_text.h>
#include <MapObjectsImpl/participant_impl.h>
// ESRI
// Qt
namespace SituationMap
{
//-----------------------------------------------------------------------------
// class FunctionalAreaImpl
//-----------------------------------------------------------------------------
FunctionalAreaImpl::FunctionalAreaImpl(const QString &debugInfo)
: FunctionalArea() // Interface
, BaseClass(debugInfo) // Implementation
, m_logger(getLogger("FunctionalAreaImpl"))
{
TRACE_LOG(m_logger) << LOGFUNCTION << " START";
m_pointSymbolData.origin.setMapObjectImpl(this);
TRACE_LOG(m_logger) << LOGFUNCTION << " END";
}
FunctionalAreaImpl::~FunctionalAreaImpl()
{
TRACE_LOG(m_logger) << LOGFUNCTION << " START";
delete m_pointSymbol;
TRACE_LOG(m_logger) << LOGFUNCTION << " END";
}
void FunctionalAreaImpl::reRenderSymbol()
{
BaseClass::reRenderSymbol();
if (m_pointSymbol)
m_pointSymbol->reRenderSymbol();
}
Point3D FunctionalAreaImpl::pointSymbolOrigin() const
{
return m_pointSymbolData.origin.origin();
}
void FunctionalAreaImpl::setPointSymbolOrigin(const Point3D &pointSymbolOrigin)
{
m_pointSymbolData.origin.setOrigin(pointSymbolOrigin);
}
const QString &FunctionalAreaImpl::pointSymbolSidc() const
{
return m_pointSymbolData.symbolData.sidc;
}
void FunctionalAreaImpl::setPointSymbolSidc(const QString &pointSymbolOriginSidc)
{
m_pointSymbolData.symbolData.sidc = pointSymbolOriginSidc;
}
bool FunctionalAreaImpl::updateViewImpl()
{
TRACE_LOG(m_logger) << LOGFUNCTION << " START"
<< " symbol=" << m_symbol.value().sidc
<< " visibility=" << m_visibility
<< " visiTechn=" << m_visibilityTechnical
<< " visiTact=" << m_visibilityTactical;
bool success = BaseClass::updateViewImpl();
if (!success)
ERROR_LOG(m_logger) << LOGFUNCTION << " updateViewImpl failed";
if (!updateViewImplPointSymbolData())
ERROR_LOG(m_logger) << LOGFUNCTION << " updateViewImplPointSymbolData failed";
TRACE_LOG(m_logger) << LOGFUNCTION << " END, success=" << success;
return success;
}
bool FunctionalAreaImpl::updateViewImplPointSymbolData()
{
TRACE_LOG(m_logger) << LOGFUNCTION << " START";
// sidc empty?
if (m_pointSymbolData.symbolData.sidc.isEmpty())
{
delete m_pointSymbol;
m_pointSymbol = nullptr;
return true;
}
// ok, sidc available:
if (!m_pointSymbol)
{
m_pointSymbol = new ParticipantImpl(m_debugInfo + QStringLiteral("#PntSymblTactApp"));
m_pointSymbol->init(m_mapImpl, m_logicalLayerName); // use same layer as mainGraphicalObj/TECHN. Appearance
m_pointSymbol->setUniqueId(m_uniqueMapId);
}
if (m_party.partyId.changed())
m_pointSymbol->setPartyIdChanged(m_party.partyId.value());
// The drawOrder should be above the m_mainGraphicalObject (==Path)
m_pointSymbol->setDrawOrder(this->drawOrder() + 1); // since m_pointSymbol is a participant, use drawOrder instead of m_internalDrawOrder
AbstractMapObjectImpl *amoImp = static_cast<AbstractMapObjectImpl*>(m_pointSymbol);
amoImp->setVisibility((m_mainGraphicalObject) ? m_mainGraphicalObject->visibility() : false);
m_pointSymbol->setOrigin(m_pointSymbolData.origin.origin());
m_pointSymbol->setPartyId(this->partyId());
// m_pointSymbolData.symbolData.color = this->partyColor();
// return m_mapImpl->partyIdToColorFunctor().partyIdToRole(m_party.partyId.value(), identityAssumed);
// AdvancedSymbology::Role role = this->partyRole();
// SymbolData symbolData = m_pointSymbolData.symbolData;
// symbolData = m_pointSymbolData.symbolData;
m_pointSymbol->setSymbol(m_pointSymbolData.symbolData);
m_pointSymbol->setScale(this->scale());
// add m_userSymbolOpacity???
bool success = m_pointSymbol->updateView();
if (!success)
ERROR_LOG(m_logger) << LOGFUNCTION << " updateViewImpl failed, m_debugInfo =" << m_debugInfo;
TRACE_LOG(m_logger) << LOGFUNCTION << " END, success=" << success;
return success;
}
bool FunctionalAreaImpl::init(MapImpl *mapImpl, const QString &logicalLayerName)
{
TRACE_LOG(m_logger) << LOGFUNCTION << " START";
// if (mapImpl)
// {
// switch (mapImpl->symbologyType()) {
// case AdvancedSymbology::SymbologyType::MIL2525C:
// m_symbol.refValue().sidc = QLatin1String("GUMPNC----"); // Image WITH Area // small icon and big border
// break;
// case AdvancedSymbology::SymbologyType::APP6B:
// m_symbol.refValue().sidc = QLatin1String("GUCPMGASM-"); // APP6B: 3556: GUCPMGASM- -> Polygon
// break;
// } // switch
// } // if (mapImpl)
bool success = BaseClass::init(mapImpl, logicalLayerName, GraphicalObjectPathType::Polygon);
setLineStyle(LineStyle(Qt::black, 2));
if (!success)
ERROR_LOG(m_logger) << LOGFUNCTION << " init failed";
TRACE_LOG(m_logger) << LOGFUNCTION << " END, success=" << success;
return success;
}
} // namespace SituationMap
@@ -0,0 +1,97 @@
/**
* @RDE_HEADER@
* Interface-Implementation of FunctionalArea
* $Id$
* $HeadURL$
* $Author$
*/
#pragma once
// Own
#include "abstract_multi_point_map_object_impl.h"
#include "basic_path_object_impl.h"
#include <MapObjects/functional_area.h> // Interface
// Qt
#include <QString>
//----------------------------------------------------------------------------
namespace SituationMap
{
// forward:
class ParticipantImpl;
/**
* @brief The FunctionalAreaImpl class displays an functional area (e.g. medical area).
*
* A class instance consists of the following logical elements:
* - mainGraphicalObject (GraphicalObjectPath displaying the main techn. Appearance)
* - mainGraphicalObjectText (displaying the text/name)
* - tacticalAppearance (displaying the tact. Appearance)
*/
// inherent 'public', to get that implementation
// inherent 'public virtual' to get that interface
class SITUATIONMAPOBJECTS_EXPORT FunctionalAreaImpl : public BasicPathObjectImpl, public virtual FunctionalArea
{
using BaseClass = BasicPathObjectImpl;
template <typename> friend class GenericObjectFactory;
protected:
explicit FunctionalAreaImpl(const QString &debugInfo = QString());
virtual ~FunctionalAreaImpl();
public:
FunctionalAreaImpl(const FunctionalAreaImpl &other) = delete;
FunctionalAreaImpl &operator=(FunctionalAreaImpl &other) = delete;
void reRenderSymbol() override;
/*! \name Point symbol */
//@{
Point3D pointSymbolOrigin() const override;
void setPointSymbolOrigin(const Point3D &pointSymbolOrigin) override;
const QString &pointSymbolSidc() const override;
void setPointSymbolSidc(const QString &pointSymbolOriginSidc) override;
//@}
protected:
bool updateViewImpl() override;
bool updateViewImplPointSymbolData();
friend class MapImpl;
bool init(MapImpl *mapImpl, const QString &logicalLayerName) override;
// internal/admin
// logical
private:
// logical
struct PointSymbolData
{
OriginTranslated origin;
SymbolData symbolData;
};
PointSymbolData m_pointSymbolData;
ParticipantImpl *m_pointSymbol = nullptr;
LOGGER_T m_logger; ///< Interface of the Logging-Facility
};
} // namespace SituationMap
+371
View File
@@ -0,0 +1,371 @@
/**
* @RDE_HEADER@
* Interface-Implementation of GeoImage
* $Id$
* $HeadURL$
* $Author$
*/
// Own
#include "geo_image_impl.h"
#include <MapImpl/map_impl.h>
#include <GraphicalObjects/graphical_object_picture_marker.h>
#include <GraphicalObjects/graphical_object_path.h>
// ESRI
// Qt
#include <QWidget>
#include <QVBoxLayout>
#include <QLabel>
#include <QPushButton>
#include <GraphicalObjects/graphical_object_picture_marker.h>
namespace SituationMap
{
class GeoImageImpl::Private
{
public:
Private() = default;
~Private() = default;
// ESRI data:
// Own data:
SimpleValue<GeoImageData> m_geoImageData;
QSharedPointer<GraphicalObjectPictureMarker> m_gopmPin;
}; // class GeoImageImpl::Private
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
// class GeoImageImpl
//-----------------------------------------------------------------------------
GeoImageImpl::GeoImageImpl(const QString &debugInfo)
: GeoImage() // Interface
, BaseClass(debugInfo) // Implementation
, d(new Private)
, m_logger(getLogger("GeoImageImpl"))
{
TRACE_LOG(m_logger) << LOGFUNCTION << " START";
TRACE_LOG(m_logger) << LOGFUNCTION << " END";
}
GeoImageImpl::~GeoImageImpl()
{
TRACE_LOG(m_logger) << LOGFUNCTION << " START";
delete d;
TRACE_LOG(m_logger) << LOGFUNCTION << " END";
}
QString GeoImageImpl::toString() const
{
QString str;
str.append(BaseClass::toString());
str.append(d->m_geoImageData.value().toString());
return str;
}
GeoImage::GeoImageData GeoImageImpl::geoImageData() const { return d->m_geoImageData.value(); }
void GeoImageImpl::setGeoImageData(const GeoImageData &geoImageData) { d->m_geoImageData = geoImageData; }
MarkerSymbolType GeoImageImpl::proxyMarker() const { return d->m_geoImageData.value().proxyMarker; }
void GeoImageImpl::setProxyMarker(const MarkerSymbolType &proxyMarker)
{
if (d->m_geoImageData.value().proxyMarker != proxyMarker)
d->m_geoImageData.refValue().proxyMarker = proxyMarker;
}
int GeoImageImpl::proxyMarkerSize() const { return d->m_geoImageData.value().proxyMarkerSize; }
void GeoImageImpl::setProxyMarkerSize(int proxyMarkerSize)
{
if (d->m_geoImageData.value().proxyMarkerSize != proxyMarkerSize)
d->m_geoImageData.refValue().proxyMarkerSize = proxyMarkerSize;
}
QColor GeoImageImpl::proxyMarkerColor() const { return d->m_geoImageData.value().proxyMarkerColor; }
void GeoImageImpl::setProxyMarkerColor(const QColor &proxyMarkerColor)
{
if (d->m_geoImageData.value().proxyMarkerColor != proxyMarkerColor)
d->m_geoImageData.refValue().proxyMarkerColor = proxyMarkerColor;
}
QImage GeoImageImpl::proxyImage() const { return d->m_geoImageData.value().proxyImage; }
void GeoImageImpl::setProxyImage(const QImage &proxyImage, const QSize &proxyImageDefaultSize)
{
if (d->m_geoImageData.value().proxyImage != proxyImage)
d->m_geoImageData.refValue().proxyImage = proxyImage;
if (d->m_geoImageData.value().proxyImageDefaultSize != proxyImageDefaultSize)
d->m_geoImageData.refValue().proxyImageDefaultSize = proxyImageDefaultSize;
}
QSize GeoImageImpl::proxyImageDefaultSize() const { return d->m_geoImageData.value().proxyImageDefaultSize; }
QImage GeoImageImpl::mainImage() const { return d->m_geoImageData.value().mainImage; }
void GeoImageImpl::setMainImage(const QImage &mainImage)
{
if (d->m_geoImageData.value().mainImage != mainImage)
d->m_geoImageData.refValue().mainImage = mainImage;
}
QImage GeoImageImpl::previewImageTypical() const
{
if (!d->m_geoImageData.value().proxyImage.isNull())
return d->m_geoImageData.value().proxyImage;
if (!d->m_geoImageData.value().mainImage.isNull())
return d->m_geoImageData.value().mainImage;
return QImage();
}
QString GeoImageImpl::description() const { return d->m_geoImageData.value().description; }
void GeoImageImpl::setDescription(const QString &description)
{
if (d->m_geoImageData.value().description != description)
d->m_geoImageData.refValue().description = description;
}
void GeoImageImpl::setPinEnabled(bool enablePin)
{
if (d->m_geoImageData.value().pinEnabled != enablePin)
d->m_geoImageData.refValue().pinEnabled = enablePin;
}
bool GeoImageImpl::isPinEnabled() const { return d->m_geoImageData.value().pinEnabled; }
QWidget *GeoImageImpl::createWidget(QWidget *parent) const
{
const GeoImageData &geoImageData = d->m_geoImageData.value();
if (geoImageData.mainImage.isNull())
return nullptr;
QWidget *widget = new QWidget(parent);
widget->setLayout(new QVBoxLayout());
QLabel *img = new QLabel();
img->setPixmap(QPixmap::fromImage(geoImageData.mainImage));
widget->layout()->addWidget(img);
widget->layout()->addWidget(new QLabel(geoImageData.description));
// CloseButton
QPushButton *pbClose = new QPushButton(QLatin1String("Close"));
widget->layout()->addWidget(pbClose);
pbClose->connect(pbClose, &QPushButton::clicked, widget, [widget]()
{
widget->deleteLater();
});
return widget;
}
bool GeoImageImpl::updateViewImpl()
{
TRACE_LOG(m_logger) << LOGFUNCTION << " START"
<< " origin =" << this->origin() //.x() << ", " << this->origin().y()
<< " visibility=" << m_visibility
<< " visiTechn=" << m_visibilityTechnical
<< " visiTact=" << m_visibilityTactical;
if (!m_graphicsLayer)
{
ERROR_LOG(m_logger) << LOGFUNCTION << " no graphicsLayer";
return false;
}
if (!m_mainGraphicalObject)
{
ERROR_LOG(m_logger) << LOGFUNCTION << " no m_mainGraphicalObject";
return false;
}
// Marker:
GraphicalObjectPictureMarker *pMarker = static_cast<GraphicalObjectPictureMarker *>(m_mainGraphicalObject);
if (d->m_geoImageData.changed())
{
const GeoImageData &geoImageData = d->m_geoImageData.value();
if (geoImageData.proxyImage.isNull())
{
if (geoImageData.proxyMarker == MarkerSymbolType::Undefined)
pMarker->setMarkerSymbol(MarkerSymbolType::Diamond, 20, Qt::red);
else
pMarker->setMarkerSymbol(geoImageData.proxyMarker,
geoImageData.proxyMarkerSize,
geoImageData.proxyMarkerColor);
}
else
pMarker->setImage(geoImageData.proxyImage, geoImageData.proxyImageDefaultSize);
// Pin
if (m_mapImpl->mode() == Mode::Mode_3D)
{
if (geoImageData.pinEnabled)
createPin();
else
resetPin();
}
}
updateIdentifierPosition();
pMarker->setOrigin(this->originTranslated());
bool success = BaseClass::updateViewImpl();
// reset changed:
d->m_geoImageData.reset();
onMapExtentChanged();
TRACE_LOG(m_logger) << LOGFUNCTION << " END, success=" << success;
return success;
}
bool GeoImageImpl::init(MapImpl *mapImpl, const QString &logicalLayerName)
{
TRACE_LOG(m_logger) << LOGFUNCTION << " START";
bool success = BaseClass::init(mapImpl, logicalLayerName);
if (success)
{
// create underlying object (to save most attributes only there)
if (!m_mainGraphicalObject)
m_mainGraphicalObject = new GraphicalObjectPictureMarker(m_mapImpl->getEsriGeoView(),
m_graphicsLayer,
m_debugInfo + QLatin1String("#Image"),
m_uniqueMapId);
}
else
ERROR_LOG(m_logger) << LOGFUNCTION << " init failed";
TRACE_LOG(m_logger) << LOGFUNCTION << " END, success=" << success;
return success;
}
bool GeoImageImpl::onMapExtentChanged()
{
TRACE_LOG(m_logger) << " onMapExtentChanged";
if (m_graphicalObjectPin && m_mainGraphicalObject) // m_graphicalObjectPin exists only at Mode_3D
{
if (!d->m_gopmPin)
{
d->m_gopmPin = QSharedPointer<GraphicalObjectPictureMarker>
(new GraphicalObjectPictureMarker(m_mapImpl->getEsriGeoView()
, m_graphicsLayer
, m_debugInfo + QStringLiteral("#PictureMarkerPin")
, m_uniqueMapId)
);
GraphicalObjectPictureMarker *pMarker = static_cast<GraphicalObjectPictureMarker *>(m_mainGraphicalObject);
if (pMarker)
{
const GeoImageData &geoImageData = d->m_geoImageData.value();
d->m_gopmPin->setImage(pMarker->image(), geoImageData.proxyImageDefaultSize);
}
}
d->m_gopmPin->setScale(m_mainGraphicalObject->scale());
Point3D originTranslated = this->originTranslated();
DEBUG_LOG(m_logger) << " XXX originTranslatedORG = " << originTranslated;
// GUEZE-2620 3D Sicht SOS Symbole
// Bisher wurde die Höhe des SOS-Images und -Textes quasi getuned, wobei ja nun
// unter bestimmten Umständen leider zu einem Höhenwert ausserhalb des
// Sichtfensters kam.
// Daher:
// - Pflicht: SOS-Symbol und Text auf den Boden
// - Kuer: Zudem versucht die SW, eine zweite Instanz des Images
// (inkl. Verbindungslinie) zu positionieren.
// Und zwar grob mittig zw. Erdoberfläche und oberen Kante des Sichtbereichs.
// Leider funktioniert des dafür genutzte ESRI-Befehl nicht immer zuverlässig.
// Meist dann, wenn sich der Augenpunkt (ViewPoint) dicht am Objekt befinden...
// Noch ein bisschen Tuning, aber es verbleiben leider Fehlersituationen.
if (m_mapImpl->scale() > 1500)
{
const double zVal = m_mapImpl->scale() * m_mapImpl->scale() * 0.0001;
DEBUG_LOG(m_logger) << " zVal = " << zVal;
originTranslated.rz() = zVal;
// 1 ... 10000 (qBound ~ std::clamp)
originTranslated.rz() = qBound(1.0, originTranslated.rz(), 10000.0);
// check viewPort:
// Note: unfortunately its dows not work perfect :-(
int cnt = 0;
static int s_counterMax = 10;
while (m_mapImpl->mapCoordinateToViewPortWindowPoint3D(originTranslated).isNull() && (originTranslated.rz() > 1) && (cnt <= s_counterMax))
{
originTranslated.rz() /= 2.0;
++cnt;
}
if (cnt == s_counterMax)
originTranslated.rz() = 0;
else
originTranslated.rz() *= 0.5; // try to show in the middle between baseSurface and upper edge of window
d->m_gopmPin->setVisibility(true);
} else {
// GUEZE-3460 - SOS Meldungen werden nicht korrekt angezeigt
if (m_mapImpl->scale() < 500)
originTranslated.rz() = 1.0; // meter
else if (m_mapImpl->scale() < 1000)
originTranslated.rz() = 2.5; // meter
else
originTranslated.rz() = 10.0; // meter
d->m_gopmPin->setVisibility(true);
}
DEBUG_LOG(m_logger) << " originTranslated = " << originTranslated;
d->m_gopmPin->setOrigin(originTranslated);
if (!d->m_gopmPin->updateView())
ERROR_LOG(m_logger) << LOGFUNCTION << " updateView failed" << m_mainGraphicalObject->debugInfo();
// update m_identifierPositionCandidateTranslated ,
// it will be transfered to m_mainGraphicalObject via BaseClass::onMapExtentChanged()
// m_identifierPositionCandidateTranslated = originTranslated;
Point3D centerEarth = originTranslated;
centerEarth.rz() = -100; // hopefully lower than lowest level of training area
m_graphicalObjectPin->setPositions({originTranslated, centerEarth});
m_graphicalObjectPin->setVisibility(d->m_gopmPin->visibility());
if (!m_graphicalObjectPin->updateView())
ERROR_LOG(m_logger) << LOGFUNCTION << " updateView failed" << m_graphicalObjectPin->debugInfo();
} // if (m_graphicalObjectPin && m_mainGraphicalObject)
return BaseClass::onMapExtentChanged();
}
} // namespace SituationMap
+101
View File
@@ -0,0 +1,101 @@
/**
* @RDE_HEADER@
* Interface-Implementation of GeoImage
* $Id$
* $HeadURL$
* $Author$
*/
#pragma once
// Own
#include "abstract_single_point_map_object_impl.h"
#include <MapObjects/geo_image.h> // Interface
// Qt
//----------------------------------------------------------------------------
namespace SituationMap
{
// inherent 'public', to get that implementation
// inherent 'public virtual' to get that interface
class SITUATIONMAPOBJECTS_EXPORT GeoImageImpl : public AbstractSinglePointMapObjectImpl, public virtual GeoImage
{
using BaseClass = AbstractSinglePointMapObjectImpl;
template <typename> friend class GenericObjectFactory;
protected:
explicit GeoImageImpl(const QString &debugInfo = QString());
virtual ~GeoImageImpl();
public:
GeoImageImpl(const GeoImageImpl &other) = delete;
GeoImageImpl &operator=(GeoImageImpl &other) = delete;
QString toString() const override;
GeoImageData geoImageData() const override;
void setGeoImageData(const GeoImageData &geoImageData) override;
MarkerSymbolType proxyMarker() const override;
void setProxyMarker(const MarkerSymbolType &proxyMarker) override;
int proxyMarkerSize() const override;
void setProxyMarkerSize(int proxyMarkerSize) override;
QColor proxyMarkerColor() const override;
void setProxyMarkerColor(const QColor &proxyMarkerColor) override;
QImage proxyImage() const override;
QSize proxyImageDefaultSize() const override;
void setProxyImage(const QImage &proxyImage, const QSize &proxyImageDefaultSize) override;
QImage mainImage() const override;
void setMainImage(const QImage &mainImage) override;
QImage previewImageTypical() const override;
QString description() const override;
void setDescription(const QString &description) override;
void setPinEnabled(bool enablePin) override;
bool isPinEnabled() const override;
QWidget *createWidget(QWidget *parent = nullptr) const override;
protected:
virtual bool updateViewImpl() override;
friend class MapImpl;
bool init(MapImpl *mapImpl, const QString &logicalLayerName) override;
bool onMapExtentChanged() override;
// internal/admin
// logical
class Private;
/**
* The private d-pointer to not break BC when changing internals of this class
*/
Private *d = nullptr;
private:
LOGGER_T m_logger; ///< Interface of the Logging-Facility
};
} // namespace SituationMap
+177
View File
@@ -0,0 +1,177 @@
/**
* @RDE_HEADER@
* Interface-Implementation of HitLine
* $Id$
* $HeadURL$
* $Author$
*/
// Own
#include "hit_line_impl.h"
#include <MapImpl/map_impl.h>
#include <GraphicalObjects/graphical_object_path.h>
#include <GraphicalObjects/graphical_object_text.h>
#include <Symbology/sidc_codec.h>
// ESRI
// Qt
#include <cassert>
namespace SituationMap
{
//-----------------------------------------------------------------------------
// class HitLineImpl
//-----------------------------------------------------------------------------
HitLineImpl::HitLineImpl(const QString &debugInfo)
: HitLine() // Interface
, BaseClass(debugInfo) // Implementation
, m_logger(getLogger("HitLineImpl"))
{
TRACE_LOG(m_logger) << LOGFUNCTION << " START, debugInfo=" << m_debugInfo;
setArrowHeadStart(true);
TRACE_LOG(m_logger) << LOGFUNCTION << " END, debugInfo=" << m_debugInfo;
}
HitLineImpl::~HitLineImpl()
{
TRACE_LOG(m_logger) << LOGFUNCTION << " START, debugInfo=" << m_debugInfo;
TRACE_LOG(m_logger) << LOGFUNCTION << " END, debugInfo=" << m_debugInfo;
}
QString HitLineImpl::identifier() const
{
return this->textOnSegment(0);
}
void HitLineImpl::setIdentifier(const QString &identifier)
{
this->setTextOnSegment(0, identifier);
}
Point3D HitLineImpl::startPoint() const
{
// !!! see setStartAndEndPoint() !!!
const PositionCont &pos = m_positions.positions();
if (pos.size() < 2)
return Point3D();
else
return pos[1]; // !!! see setStartAndEndPoint() !!!
}
Point3D HitLineImpl::endPoint() const
{
// !!! see setStartAndEndPoint() !!!
const PositionCont &pos = m_positions.positions();
if (pos.size() < 2)
return Point3D();
else
return pos[0]; // !!! see setStartAndEndPoint() !!!
}
void HitLineImpl::setStartAndEndPoint(const Point3D &start, const Point3D &end)
{
TRACE_LOG(m_logger) << LOGFUNCTION << " START"
<< " start=" << start
<< " end=" << end
<< ", debugInfo=" << m_debugInfo;
// According MIL2525 a line (like attack) starts with an arrow.
// But in this context (HitLine)
// start == shooter -> no arrowHead
// end == target -> with arrowHead
// Therefore we have to add the 'end'/target point first:
m_positions.setPositions(PositionCont() << end << start);
TRACE_LOG(m_logger) << LOGFUNCTION << " END";
}
bool HitLineImpl::updateViewImpl()
{
TRACE_LOG(m_logger) << LOGFUNCTION << " START"
<< " symbol=" << m_symbol.value().sidc
<< " visibility=" << m_visibility
<< " visiTechn=" << m_visibilityTechnical
<< " visiTact=" << m_visibilityTactical
<< ", debugInfo=" << m_debugInfo;
setArrowHeadsSelected(m_selected);
bool success = BaseClass::updateViewImpl();
if (!success)
ERROR_LOG(m_logger) << LOGFUNCTION << " updateViewImpl failed";
TRACE_LOG(m_logger) << LOGFUNCTION << " END, success=" << success;
return success;
}
bool HitLineImpl::init(MapImpl *mapImpl, const QString &logicalLayerName)
{
TRACE_LOG(m_logger) << LOGFUNCTION << " START";
if (mapImpl)
{
switch (mapImpl->symbologyType())
{
case AdvancedSymbology::SymbologyType::APP6D:
case AdvancedSymbology::SymbologyType::MIL2525D:
m_symbol.refValue().sidc = AdvancedSymbology::SidcCodec::encodeComplete(mapImpl->symbologyType(), "10032500001406030000"); // SymbolSet = 25 140602
// ^^ ^^^^^^
break;
case AdvancedSymbology::SymbologyType::MIL2525C:
m_symbol.refValue().sidc = AdvancedSymbology::SidcCodec::encodeComplete(mapImpl->symbologyType(), "GFGPOLKGS-"); // 1047 - Direction Of Attack Ground Supporting Attack F
// m_symbol.refValue().sidc = AdvancedSymbology::SidcCodec::encodeComplete(mapImpl->symbologyType(),"GHGPOLKA--"); //
// m_symbol.refValue().sidc = AdvancedSymbology::SidcCodec::encodeComplete(mapImpl->symbologyType(),"GHGPOLKGM-"); //
break;
case AdvancedSymbology::SymbologyType::APP6B:
m_symbol.refValue().sidc = AdvancedSymbology::SidcCodec::encodeComplete(mapImpl->symbologyType(), "GFCPMOLDS-"); // APP6B-3733 GFCPMOLDS- -> Direction Of Attack Ground Supporting Attack F
break;
case AdvancedSymbology::SymbologyType::None:
// empty
break;
} // switch
} // if (mapImpl)
double maxSegmentLength = -1; // -> GeometryEngine::densifyGeodetic
if (mapImpl && (mapImpl->mode() == Mode::Mode_3D))
maxSegmentLength = 10; // -> GeometryEngine::densifyGeodetic
bool success = BaseClass::init(mapImpl, logicalLayerName, GraphicalObjectPathType::Polyline, maxSegmentLength);
if (!success)
ERROR_LOG(m_logger) << LOGFUNCTION << " init failed";
m_mainGraphicalObject->rLineStyle().setLinePattern(LinePattern::Dash);
TRACE_LOG(m_logger) << LOGFUNCTION << " END, success=" << success;
return success;
}
bool HitLineImpl::setPositions(const PositionCont &)
{
FATAL_LOG(m_logger) << LOGFUNCTION << " DO NOT CALL!!!";
assert(false);
return false;
}
} // namespace SituationMap
+82
View File
@@ -0,0 +1,82 @@
/**
* @RDE_HEADER@
* Interface-Implementation of HitLine
* $Id$
* $HeadURL$
* $Author$
*/
#pragma once
// Own
#include "abstract_multi_point_map_object_impl.h"
#include "basic_path_object_impl.h"
#include <MapObjects/hit_line.h> // Interface
// Qt
#include <QString>
#include <QPointF>
//----------------------------------------------------------------------------
namespace SituationMap
{
/**
* @brief The HitLineImpl class displays shot from a startpoint to an endpoint.
*
* A class instance consists of the following logical elements:
* - mainGraphicalObject (GraphicalObjectPath displaying the main techn. Appearance)
* - mainGraphicalObjectText (displaying the text/name/identifier)
* - tacticalAppearance (displaying the tact. Appearance)
*/
// inherent 'public', to get that implementation
// inherent 'public virtual' to get that interface
class SITUATIONMAPOBJECTS_EXPORT HitLineImpl : public BasicPathObjectImpl, public virtual HitLine
{
using BaseClass = BasicPathObjectImpl;
template <typename> friend class GenericObjectFactory;
protected:
explicit HitLineImpl(const QString &debugInfo = QString());
virtual ~HitLineImpl();
public:
HitLineImpl(const HitLineImpl &other) = delete;
HitLineImpl &operator=(HitLineImpl &other) = delete;
QString identifier() const override;
void setIdentifier(const QString &identifier) override;
Point3D startPoint() const override;
Point3D endPoint() const override;
void setStartAndEndPoint(const Point3D &start, const Point3D &end) override;
protected:
bool updateViewImpl() override;
friend class MapImpl;
bool init(MapImpl *mapImpl, const QString &logicalLayerName) override;
// internal/admin
// logical
private:
bool setPositions(const PositionCont &) override; //SHOULD NEVER BE CALLED
private:
LOGGER_T m_logger; ///< Interface of the Logging-Facility
};
} // namespace SituationMap
@@ -0,0 +1,575 @@
/**
* @RDE_HEADER@
* IndicationContainer
* $Id$
* $HeadURL$
* $Author$
*/
// Own
#include "indication_container.h"
#include <MapImpl/coordinate_translation.h>
#include <GraphicalObjects/graphical_object_picture_marker.h>
#include <MapImpl/coordinate_translation_thread.h>
// ESRI
#include <arcgis/GeoView.h>
#include <arcgis/PictureMarkerSymbol.h>
// Qt
#include <QElapsedTimer>
namespace SituationMap
{
//-----------------------------------------------------------------------------
// class IndicationData
//-----------------------------------------------------------------------------
class IndicationData
{
public:
const QImage &image() const { return m_image;}
void setImage(const QImage &image) { if (m_image != image) m_changed = true; m_image = image; }
MarkerSymbolType markerSymbolType() const { return m_markerSymbolType; }
void setMarkerSymbolType(const MarkerSymbolType &markerSymbolType) { if (m_markerSymbolType != markerSymbolType) m_changed = true; m_markerSymbolType = markerSymbolType; }
const QColor &markerColor() const { return m_markerColor; }
void setMarkerColor(const QColor &markerColor) { if (m_markerColor != markerColor) m_changed = true; m_markerColor = markerColor; }
int markerSize() const { return m_markerSize; }
void setMarkerSize(int markerSize) { if (m_markerSize != markerSize) m_changed = true; m_markerSize = markerSize; }
bool markerSelected() const { return m_markerSelected; }
void setMarkerSelected(bool markerSelected) { if (m_markerSelected != markerSelected) m_changed = true; m_markerSelected = markerSelected; }
bool markerPickable() const { return m_markerPickable; }
void setMarkerPickable(bool markerPickable) { if (m_markerPickable != markerPickable) m_changed = true; m_markerPickable = markerPickable; }
PositionsTranslated &positionsTrans() { return m_positions; }
void setPositions(const PositionCont &positions) { if (m_positions.positions() != positions) m_changed = true; m_positions.setPositions(positions); }
bool markerVisible() const { return m_markerVisible; }
void setMarkerVisible(bool markerVisible) { if (m_markerVisible != markerVisible) m_changed = true; m_markerVisible = markerVisible; }
bool changed() const { return m_changed; }
void resetChanged() { m_changed = false; }
IndicationData()
{}
~IndicationData()
{
m_pictureMarker.clear();
}
public:
QSharedPointer<CoordTranslationThread> m_coordTranslationThread;
QSharedPointer<GraphicalObjectPictureMarker> m_pictureMarker;
private:
QImage m_image;
PositionsTranslated m_positions;
MarkerSymbolType m_markerSymbolType = MarkerSymbolType::Undefined;
int m_markerSize = 20;
QColor m_markerColor = Qt::black;
bool m_markerVisible = true;
bool m_markerSelected = false;
bool m_markerPickable = true;
bool m_changed = true;
};
class IndicationContainer::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<int> m_drawOrder = 0;
private:
// TODO: use sorted vector - only max. 10 elements in there, so qhash/qmap is overkill
QHash<int, QSharedPointer<IndicationData>> m_map;
public:
QSharedPointer<IndicationData> getIndicationData(int key)
{
auto it = m_map.find(key);
if (it != m_map.end())
return it.value();
auto ret = QSharedPointer<IndicationData>(new IndicationData());
m_map[key] = ret;
return ret;
}
void remove(int key) // attention, will remove the provides image/marker...
{
auto it = m_map.find(key);
if (it == m_map.end())
return;
const QSharedPointer<IndicationData> &indicationData = it.value();
if (indicationData && indicationData->m_coordTranslationThread)
indicationData->m_coordTranslationThread->wait();
m_map.erase(it);
}
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<IndicationData>> &container() const { return m_map; }
}; // class IndicationContainer::Private
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
// class IndicationContainer
//-----------------------------------------------------------------------------
IndicationContainer::IndicationContainer(const Esri::ArcGISRuntime::GeoView *geoView,
Esri::ArcGISRuntime::GraphicsOverlay *graphicsLayer,
CoordTranslationFunctor *coordTransFunctor,
const UniqueMapId &uniqueMapId)
: QObject()
, m_logger(getLogger("IndicationContainer"))
, 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;
TRACE_LOG(m_logger) << LOGFUNCTION << " END";
}
IndicationContainer::~IndicationContainer()
{
TRACE_LOG(m_logger) << LOGFUNCTION << " START";
// Thread::wait():
for (const QSharedPointer<IndicationData> &id : d->container())
{
if (id && id->m_coordTranslationThread)
{
id->m_coordTranslationThread->quit();
id->m_coordTranslationThread->wait();
}
} // for
d->clear();
delete d;
TRACE_LOG(m_logger) << LOGFUNCTION << " END";
}
QString IndicationContainer::debugInfo() const
{
return d->m_debugInfo;
}
void IndicationContainer::setDebugInfo(const QString &debugInfo)
{
d->m_debugInfo = debugInfo;
}
PositionCont IndicationContainer::positions(int idx) const
{
return d->getIndicationData(idx)->positionsTrans().positions();
}
void IndicationContainer::setPositions(int idx, const PositionCont &positions)
{
TRACE_LOG(m_logger) << LOGFUNCTION << " START"
<< ", debugInfo='" << d->m_debugInfo << "'"
<< ", m_uniqueMapId = " << d->m_uniqueMapId
<< ", idx=" << idx
<< ", positions.size=" << positions.size();
d->getIndicationData(idx)->setPositions(positions);
// // d->remove(idx); // attention: remove will implicit rmove the provided image...
TRACE_LOG(m_logger) << LOGFUNCTION << " END";
}
void IndicationContainer::setMarker(int idx, MarkerSymbolType mst, int size, const QColor &color)
{
d->getIndicationData(idx)->setMarkerSymbolType(mst);
d->getIndicationData(idx)->setMarkerSize(size);
d->getIndicationData(idx)->setMarkerColor(color);
}
void IndicationContainer::setMarker(int idx, int size)
{
d->getIndicationData(idx)->setMarkerSize(size);
}
void IndicationContainer::setMarker(int idx, const QColor &color)
{
d->getIndicationData(idx)->setMarkerColor(color);
}
const QImage &IndicationContainer::image(int idx) const
{
return d->getIndicationData(idx)->image();
}
void IndicationContainer::setImage(int idx, const QImage &image)
{
auto id = d->getIndicationData(idx);
if (id->image() == image)
return;
id->setImage(image);
}
void IndicationContainer::clear(int idx)
{
d->remove(idx);
}
void IndicationContainer::clearAll()
{
d->clear();
}
int IndicationContainer::drawOrder() const
{
return d->m_drawOrder.value();
}
void IndicationContainer::setDrawOrder(int drawOrder)
{
d->m_drawOrder = drawOrder;
}
bool IndicationContainer::visible(int idx) const
{
return d->getIndicationData(idx)->markerVisible();
}
void IndicationContainer::setVisible(int idx, bool visible)
{
d->getIndicationData(idx)->setMarkerVisible(visible);
}
bool IndicationContainer::selected(int idx) const
{
return d->getIndicationData(idx)->markerSelected();
}
void IndicationContainer::setSelected(int idx, bool selected)
{
d->getIndicationData(idx)->setMarkerSelected(selected);
}
bool IndicationContainer::pickable(int idx) const
{
return d->getIndicationData(idx)->markerPickable();
}
void IndicationContainer::setPickable(int idx, bool pickable)
{
d->getIndicationData(idx)->setMarkerPickable(pickable);
}
int IndicationContainer::getIndicationCount() const
{
return d->size();
}
QList<int> IndicationContainer::getIndicationIndexList() const
{
return d->keys();
}
bool IndicationContainer::updateView()
{
TRACE_LOG(m_logger) << LOGFUNCTION << " START"
<< ", debugInfo='" << d->m_debugInfo << "'"
<< ", m_uniqueMapId = " << d->m_uniqueMapId
<< " , d->m_map.size()=" << d->size();
bool success = true;
// int outterSize = d->m_map.size();
for (auto it = d->container().begin(); it != d->container().end(); ++it)
{
const QSharedPointer<IndicationData> &indicationData = it.value();
// per single dimension:
// nothing changed?
if ((!indicationData->changed()) && (!d->m_drawOrder.changed()))
{
DEBUG_LOG(m_logger) << LOGFUNCTION << " no change -> continue... "
<< ", debugInfo='" << d->m_debugInfo << "'";
continue;
}
// set
indicationData->positionsTrans().setCoordTransFunctor(d->m_coordTransFunctor);
int idx = it.key();
#define SYNC
#ifdef SYNC
bool updated = updateIndicationContainer(idx);
success = success && updated;
#else
// skip thread and do call sync if:
if (indicationData->positionsTrans().isTranslated()
|| ! indicationData->markerVisible()
)
{
// call sync:
updateIndicationContainer(idx); // update of invisible marker is cheap :-)
}
else
{
// ok, thread is requested:
// another thread prepared/running or finished/deleted?
if (indicationData->m_coordTranslationThread.isNull())
{
// move time consuming work to worker thread:
// apply Deleter to SharedPointer (to avoid simple 'delete')
indicationData->m_coordTranslationThread =
QSharedPointer<CoordTranslationThread> (new CoordTranslationThread(d->m_debugInfo), &QObject::deleteLater);
indicationData->m_coordTranslationThread->setUserData(idx);
indicationData->m_coordTranslationThread->setPositions(& (indicationData->positionsTrans()));
// QObject::connect(indicationData.m_coordTranslationThread.data(), &CoordTranslationThread::finished, indicationData.m_coordTranslationThread.data(), &QObject::deleteLater);
QObject::connect(indicationData->m_coordTranslationThread.data(), &CoordTranslationThread::finished, this, &IndicationContainer::onThreadFinished);
QObject::connect(indicationData->m_coordTranslationThread.data(), &CoordTranslationThread::resultReady, this, &IndicationContainer::onResultReady);
qWarning() << " start workerThread, idx=" << idx;
indicationData->m_coordTranslationThread->start();
}
else
{
FATAL_LOG(m_logger) << LOGFUNCTION
<< " new Translation via Thread requested, but still exists...";
}
}
#endif // SYNC
indicationData->resetChanged();
} // while
d->m_drawOrder.reset();
TRACE_LOG(m_logger) << LOGFUNCTION << " END"
<< " debugInfo='" << d->m_debugInfo << "'"
<< " success=" << success;
return success;
}
bool IndicationContainer::onResultReady(const QVariant &userData)
{
TRACE_LOG(m_logger) << LOGFUNCTION << " START"
<< " debugInfo='" << d->m_debugInfo << "'"
<< "threadId: " << QThread::currentThreadId();
bool success = false;
bool bOk = false;
int idx = userData.toInt(&bOk);
if (bOk)
{
if (d->contains(idx))
{
QSharedPointer<IndicationData> indicationData = d->getIndicationData(idx);
if (! indicationData->positionsTrans().isTranslated())
{
ERROR_LOG(m_logger) << LOGFUNCTION << " NOT TRANSLATED, should not happen!!!"
<< " debugInfo='" << d->m_debugInfo << "'"
<< " idx=" << idx;
}
}
success = updateIndicationContainer(idx);
}
else
ERROR_LOG(m_logger) << LOGFUNCTION << " QVariant toInt failed!!!";
TRACE_LOG(m_logger) << LOGFUNCTION << " END"
<< " debugInfo='" << d->m_debugInfo << "'"
<< " success = " << success;
return success;
}
void IndicationContainer::onThreadFinished(const QVariant &userData)
{
TRACE_LOG(m_logger) << LOGFUNCTION << " START"
<< " debugInfo='" << d->m_debugInfo << "'";
bool bOk = false;
int idx = userData.toInt(&bOk);
if (bOk)
{
if (d->contains(idx))
d->getIndicationData(idx)->m_coordTranslationThread.clear(); // will call the Deleter which is 'deleteLater'
}
else
qWarning() << "resultReady: QVariant toInt failed!!!";
TRACE_LOG(m_logger) << LOGFUNCTION << " END"
<< " debugInfo='" << d->m_debugInfo << "'";
}
bool IndicationContainer::updateIndicationContainer(int idx)
{
TRACE_LOG(m_logger) << LOGFUNCTION << " START"
<< " debugInfo='" << d->m_debugInfo << "'"
<< " idx=" << idx;
QElapsedTimer timer;
if (m_logger.isInfoEnabled())
timer.start();
if (! d->contains(idx))
{
ERROR_LOG(m_logger) << LOGFUNCTION << " idx does not exist: idx=" << idx;
return false;
}
bool successPM = true;
QSharedPointer<IndicationData> indicationData = d->getIndicationData(idx);
// do we have positions or is PositionCont empty?
const PositionsTranslated &posTransRef = indicationData->positionsTrans();
int numberOfPositions = posTransRef.size();
if (posTransRef.isEmpty())
{
QSharedPointer<GraphicalObjectPictureMarker> &picMarker = indicationData->m_pictureMarker;
picMarker.clear();
}
else
{
successPM = updateIndicationContainerPictureMarker(idx);
}
bool success = successPM;
INFO_LOG(m_logger) << LOGFUNCTION << " END"
<< " debugInfo='" << d->m_debugInfo << "'"
<< " success=" << success
<< " successPM=" << successPM
<< " numberOfPositions = " << numberOfPositions
<< " took[ms] " << timer.elapsed();
TRACE_LOG(m_logger) << LOGFUNCTION << " END"
<< " debugInfo='" << d->m_debugInfo << "'"
<< " numberOfPositions = " << numberOfPositions
<< " successPM=" << successPM
<< " success=" << success;
return success;
}
bool IndicationContainer::updateIndicationContainerPictureMarker(int idx)
{
TRACE_LOG(m_logger) << LOGFUNCTION << " START"
<< " debugInfo='" << d->m_debugInfo << "'"
<< " idx=" << idx;
QElapsedTimer timer;
if (m_logger.isInfoEnabled())
timer.start();
bool success = true;
int numberOfPositions = -1;
QSharedPointer<IndicationData> indicationData = d->getIndicationData(idx);
QSharedPointer<GraphicalObjectPictureMarker> &picMarker = indicationData->m_pictureMarker;
const MarkerSymbolType &mst = indicationData->markerSymbolType();
const bool bPicMarkerNeeded = (mst != MarkerSymbolType::Undefined) || !indicationData->image().isNull();
if (bPicMarkerNeeded)
{
if (picMarker.isNull())
{
QString debugInfo = QStringLiteral("%1#Indication_idx(%2)_PM").arg(d->m_debugInfo).arg(idx);
DEBUG_LOG(m_logger) << LOGFUNCTION << " create new Object: " << debugInfo;
picMarker = QSharedPointer<GraphicalObjectPictureMarker>
(new GraphicalObjectPictureMarker(d->m_geoView,
d->m_graphicsLayer,
debugInfo,
d->m_uniqueMapId));
}
// set parameter:
// [GUEZE-496] RPL Nr 770: 3D Lagedarstellung Einfrieren der SW Appl.
// GraphicalObjectPictureMarker supports multipoint geometry now
// do we have an mst or image?
if (mst != MarkerSymbolType::Undefined)
{
// Marker:
picMarker->setMarkerSymbol(mst,
indicationData->markerSize(),
indicationData->markerColor());
}
else
{
// Image:
picMarker->setImage(indicationData->image());
}
bool visible = indicationData->markerVisible();
picMarker->setDrawOrder(d->m_drawOrder.value());
picMarker->setVisibility(visible);
picMarker->setSelected(indicationData->markerSelected());
picMarker->setPickable(indicationData->markerPickable());
// Geometry/Positions
const PositionCont &positionsTrans = indicationData->positionsTrans().positionsTranslated();
picMarker->setPositions(positionsTrans);
numberOfPositions = positionsTrans.size();
success = picMarker->updateView();
} else {
picMarker.clear();
}
INFO_LOG(m_logger) << LOGFUNCTION << " END"
<< " debugInfo='" << d->m_debugInfo << "'"
<< " success=" << success
<< " numberOfPositions = " << numberOfPositions
<< " took[ms] " << timer.elapsed();
TRACE_LOG(m_logger) << LOGFUNCTION << " END"
<< " debugInfo='" << d->m_debugInfo << "'"
<< " numberOfPositions = " << numberOfPositions
<< " success=" << success;
return success;
}
} // namespace SituationMap
@@ -0,0 +1,115 @@
/**
* @RDE_HEADER@
* IndicationContainer
* $Id$
* $HeadURL$
* $Author$
*/
#pragma once
// Own
#include <Map/situation_map_types.h>
#include <Common/situation_map_logging.h>
// Qt
#include <QImage>
#include <QMap>
#include <QVariant>
// forward:
namespace Esri
{
namespace ArcGISRuntime
{
class GeoView;
class GraphicsOverlay;
}
}
//----------------------------------------------------------------------------
namespace SituationMap
{
// Forward:
class CoordTranslationFunctor;
class IndicationData;
class IndicationContainer : public QObject
{
Q_OBJECT
public:
explicit IndicationContainer(const Esri::ArcGISRuntime::GeoView *geoView,
Esri::ArcGISRuntime::GraphicsOverlay *graphicsLayer,
CoordTranslationFunctor *coordTransFunctor,
const UniqueMapId &uniqueMapId);
virtual ~IndicationContainer();
IndicationContainer(const IndicationContainer &other) = delete;
IndicationContainer &operator=(IndicationContainer &other) = delete;
QString debugInfo() const;
void setDebugInfo(const QString &debugInfo);
// Marker :
virtual PositionCont positions(int idx) const;
virtual void setPositions(int idx, const PositionCont &positions);
virtual void setMarker(int idx, MarkerSymbolType mst, int size, const QColor &color);
virtual void setMarker(int idx, int size);
virtual void setMarker(int idx, const QColor &color);
virtual const QImage &image(int idx) const;
virtual void setImage(int idx, const QImage &image);
virtual void clear(int idx);
virtual void clearAll();
virtual int drawOrder() const;
virtual void setDrawOrder(int drawOrder);
virtual bool visible(int idx) const;
virtual void setVisible(int idx, bool visible);
virtual bool selected(int idx) const;
virtual void setSelected(int idx, bool selected);
virtual bool pickable(int idx) const;
virtual void setPickable(int idx, bool pickable);
virtual int getIndicationCount() const;
virtual QList<int> getIndicationIndexList() const;
virtual bool updateView();
virtual bool updateIndicationContainer(int idx);
virtual bool updateIndicationContainerPictureMarker(int idx);
// virtual bool updateIndicationContainerSceneMarker(int idx);
public slots:
virtual void onThreadFinished(const QVariant &userData);
virtual bool onResultReady(const QVariant &userData);
private:
LOGGER_T m_logger; ///< Interface of the Logging-Facility
class Private;
/**
* The private d->pointer to not break BC when changing internals of this class
*/
Private *d = nullptr;
};
} // namespace SituationMap
@@ -0,0 +1,205 @@
/**
* @RDE_HEADER@
* Interface-Implementation of HitLine
* $Id$
* $HeadURL$
* $Author$
*/
// Own
#include "line_of_sight_impl.h"
#include <MapImpl/map_impl.h>
#include <GraphicalObjects/graphical_object_path.h>
#include <GraphicalObjects/graphical_object_text.h>
#include <Symbology/sidc_codec.h>
// ESRI
// Qt
#include <cassert>
namespace SituationMap
{
//-----------------------------------------------------------------------------
// class LineOfSightImpl
//-----------------------------------------------------------------------------
LineOfSightImpl::LineOfSightImpl(const QString &debugInfo)
: LineOfSight() // Interface
, BaseClass(debugInfo) // Implementation
, m_logger(getLogger("LineOfSightImpl"))
{
TRACE_LOG(m_logger) << LOGFUNCTION << " START";
m_extensionLineCoordinate.setMapObjectImpl(this);
TRACE_LOG(m_logger) << LOGFUNCTION << " END";
}
LineOfSightImpl::~LineOfSightImpl()
{
TRACE_LOG(m_logger) << LOGFUNCTION << " START";
delete m_extensionLine;
m_extensionLine = nullptr;
TRACE_LOG(m_logger) << LOGFUNCTION << " END";
}
QString LineOfSightImpl::identifier() const
{
return this->textOnSegment(0);
}
void LineOfSightImpl::setIdentifier(const QString &identifier)
{
this->setTextOnSegment(0, identifier);
}
void LineOfSightImpl::setPoints(const Point3D &observer,
const Point3D &obstacle,
const Point3D &target,
const QColor &visibleColor, // green,
const QColor &obstructedColor) // red
{
TRACE_LOG(m_logger) << LOGFUNCTION << " START"
<< " observer=" << observer
<< " obstacle=" << obstacle
<< " target=" << target
<< " visibleColor=" << visibleColor
<< " obstructedColor=" << obstructedColor;
// some checks
if (observer.isNull() || target.isNull())
{
ERROR_LOG(m_logger) << LOGFUNCTION << " start of end is null";
return;
}
if (obstacle.isNull())
{
// no obstacle -> just a single (green) line:
m_positions.setPositions(PositionCont() << observer << target);
m_extensionLineCoordinate.clear();
}
else
{
// obstacle -> first (green) line:
m_positions.setPositions(PositionCont() << observer << obstacle);
m_extensionLineCoordinate.setOrigin(target);
}
// handle color:
if (visibleColor.isValid())
{
LineStyle ls = this->lineStyle();
ls.setLineColor(visibleColor);
this->setLineStyle(ls);
}
if (obstructedColor.isValid())
m_extensionLineColor = obstructedColor;
TRACE_LOG(m_logger) << LOGFUNCTION << " END";
}
bool LineOfSightImpl::updateViewImpl()
{
TRACE_LOG(m_logger) << LOGFUNCTION << " START"
<< " symbol=" << m_symbol.value().sidc
<< " visibility=" << m_visibility
<< " visiTechn=" << m_visibilityTechnical
<< " visiTact=" << m_visibilityTactical
<< " m_positions=" << m_positions.positions()
<< " m_additionalCoordinate=" << m_extensionLineCoordinate.origin();
//
//
// maybe the line(s) are densified @ GraphicalObjectPath::updateViewImpl()
// to use more vertices (for 3D) !?
//
//
bool success = BaseClass::updateViewImpl();
updateExtensionLine();
if (!success)
ERROR_LOG(m_logger) << LOGFUNCTION << " updateViewImpl failed";
TRACE_LOG(m_logger) << LOGFUNCTION << " END, success=" << success;
return success;
}
void LineOfSightImpl::updateExtensionLine()
{
if (!m_extensionLineCoordinate.isEmpty())
{
if (!m_extensionLine)
{
QString debugInfo = QStringLiteral("%1#ExtensionLine").arg(m_debugInfo);
m_extensionLine = new GraphicalObjectPath(GraphicalObjectPathType::Polyline,
m_mapImpl->getEsriGeoView(),
m_graphicsLayer,
debugInfo,
m_uniqueMapId);
}
m_extensionLine->setVisibility(m_visibility && m_visibilityTechnical);
m_extensionLine->setScale(m_mainGraphicalObject->scale());
m_extensionLine->setDrawOrder(m_mainGraphicalObject->drawOrder());
LineStyle ls = m_mainGraphicalObject->lineStyle();
ls.setLineColor(m_extensionLineColor);
m_extensionLine->setLineStyle(ls);
// positions:
PositionsTranslated tempPosTrans;
tempPosTrans.setPositionsTranslated(PositionCont() <<
m_extensionLineCoordinate.originTranslated() // obstaclePosition
<< m_positions.positionsTranslated()[1]); // end/targetPosition
m_extensionLine->setPositions(tempPosTrans.positionsTranslated());
m_extensionLine->updateView();
}
else
{
// no m_extensionLineCoordinate -> remove extensionLine
delete m_extensionLine;
m_extensionLine = nullptr;
}
}
bool LineOfSightImpl::init(MapImpl *mapImpl, const QString &logicalLayerName)
{
TRACE_LOG(m_logger) << LOGFUNCTION << " START";
bool success = BaseClass::init(mapImpl, logicalLayerName, GraphicalObjectPathType::Polyline);
if (!success)
ERROR_LOG(m_logger) << LOGFUNCTION << " init failed";
// default: green, 3px
LineStyle ls = this->lineStyle();
ls.setLineColor(Qt::green);
ls.setLineWidth(3);
this->setLineStyle(ls);
TRACE_LOG(m_logger) << LOGFUNCTION << " END, success=" << success;
return success;
}
bool LineOfSightImpl::setPositions(const PositionCont &)
{
FATAL_LOG(m_logger) << LOGFUNCTION << " DO NOT CALL!!!";
assert(false);
return false;
}
} // namespace SituationMap
@@ -0,0 +1,82 @@
/**
* @RDE_HEADER@
* Interface-Implementation of HitLine
* $Id$
* $HeadURL$
* $Author$
*/
#pragma once
// Own
#include "abstract_multi_point_map_object_impl.h"
#include "basic_path_object_impl.h"
#include <MapObjects/line_of_sight.h> // Interface
#include <GraphicalObjects/graphical_object_path.h>
// Qt
#include <QString>
#include <QPointF>
//----------------------------------------------------------------------------
namespace SituationMap
{
/**
* @brief The LineOfSightImpl class supports a "single" line with two colors.
* The method setPositions() should never be called.
* A class instance consists of the following logical elements:
* - mainGraphicalObject (GraphicalObjectPath displaying the main techn. Appearance)
* - mainGraphicalObjectText (displaying the text/name/identifier)
* - tacticalAppearance (displaying the tact. Appearance)
*/
// inherent 'public', to get that implementation
// inherent 'public virtual' to get that interface
class SITUATIONMAPOBJECTS_EXPORT LineOfSightImpl : public BasicPathObjectImpl, public virtual LineOfSight
{
using BaseClass = SituationMap::BasicPathObjectImpl;
template <typename> friend class GenericObjectFactory;
protected:
explicit LineOfSightImpl(const QString &debugInfo = QString());
virtual ~LineOfSightImpl();
public:
QString identifier() const override;
void setIdentifier(const QString &identifier) override;
void setPoints(const Point3D &observer,
const Point3D &obstacle,
const Point3D &target,
const QColor &visibleColor = Qt::green,
const QColor &obstructedColor = Qt::red) override;
protected:
bool updateViewImpl() override;
void updateExtensionLine();
friend class MapImpl;
bool init(MapImpl *mapImpl, const QString &logicalLayerName) override;
// internal/admin
OriginTranslated m_extensionLineCoordinate;
GraphicalObjectPath *m_extensionLine = nullptr;
QColor m_extensionLineColor = Qt::red;
// logical
private:
bool setPositions(const PositionCont &) override; //SHOULD NEVER BE CALLED
private:
LOGGER_T m_logger; ///< Interface of the Logging-Facility
};
} // namespace SituationMap
@@ -0,0 +1,111 @@
/**
* @RDE_HEADER@
* Interface-Implementation of DangerArea
* $Id$
* $HeadURL$
* $Author$
*/
// Own
#include "map_object_attributes_impl.h"
#include <MapImpl/map_impl.h>
#include <GraphicalObjects/graphical_object_attributes.h>
#include <Symbology/sidc_codec.h>
// ESRI
// Qt
namespace SituationMap
{
//-----------------------------------------------------------------------------
// class MapObjectAttributesImpl
//-----------------------------------------------------------------------------
MapObjectAttributesImpl::MapObjectAttributesImpl(const QString &debugInfo)
: MapObjectAttributes() // Interface
, BaseClass(debugInfo) // Implementation
, m_logger(getLogger("MapObjectAttributesImpl"))
{
TRACE_LOG(m_logger) << LOGFUNCTION << " START";
TRACE_LOG(m_logger) << LOGFUNCTION << " END";
}
MapObjectAttributesImpl::~MapObjectAttributesImpl()
{
TRACE_LOG(m_logger) << LOGFUNCTION << " START";
TRACE_LOG(m_logger) << LOGFUNCTION << " END";
}
QVariantMap MapObjectAttributesImpl::attributes() const
{
if (!m_mainGraphicalObject)
return {};
GraphicalObjectAttributes *goa = static_cast<GraphicalObjectAttributes *>(m_mainGraphicalObject);
if (!goa)
return {};
return goa->attributes();
}
void MapObjectAttributesImpl::setAttributes(const QVariantMap &attributes)
{
if (!m_mainGraphicalObject)
return;
GraphicalObjectAttributes *goa = static_cast<GraphicalObjectAttributes *>(m_mainGraphicalObject);
if (!goa)
return;
goa->setAttributes(attributes);
}
bool MapObjectAttributesImpl::updateViewImpl()
{
TRACE_LOG(m_logger) << LOGFUNCTION << " START"
<< " symbol=" << m_symbol.value().sidc
<< " visibility=" << m_visibility
<< " visiTechn=" << m_visibilityTechnical
<< " visiTact=" << m_visibilityTactical;
m_mainGraphicalObject->setOrigin(this->originTranslated());
bool success = BaseClass::updateViewImpl();
if (!success)
ERROR_LOG(m_logger) << LOGFUNCTION << " updateViewImpl failed";
TRACE_LOG(m_logger) << LOGFUNCTION << " END, success=" << success;
return success;
}
bool MapObjectAttributesImpl::init(MapImpl *mapImpl, const QString &logicalLayerName)
{
TRACE_LOG(m_logger) << LOGFUNCTION << " START";
bool success = BaseClass::init(mapImpl, logicalLayerName);
if (!success)
ERROR_LOG(m_logger) << LOGFUNCTION << " init failed";
if (success)
{
// create underlying object (to save most attributes only there)
if (!m_mainGraphicalObject)
m_mainGraphicalObject = new GraphicalObjectAttributes(m_mapImpl,
m_graphicsLayer,
m_debugInfo + QLatin1String("#GOAttributes"),
m_uniqueMapId);
}
else
ERROR_LOG(m_logger) << LOGFUNCTION << " init failed";
TRACE_LOG(m_logger) << LOGFUNCTION << " END, success=" << success;
return success;
}
} // namespace SituationMap
@@ -0,0 +1,65 @@
/**
* @RDE_HEADER@
* Interface-Implementation of DangerArea
* $Id$
* $HeadURL$
* $Author$
*/
#pragma once
// Own
#include "situation_map_objects_export.h"
#include "abstract_single_point_map_object_impl.h"
#include <MapImpl/map_impl.h>
#include <MapObjects/map_object_attributes.h> // Interface
// Qt
#include <QString>
#include <QVariantMap>
//----------------------------------------------------------------------------
namespace SituationMap
{
// inherent 'public', to get that implementation
// inherent 'public virtual' to get that interface
class SITUATIONMAPOBJECTS_EXPORT MapObjectAttributesImpl : public AbstractSinglePointMapObjectImpl, public virtual MapObjectAttributes
{
using BaseClass = AbstractSinglePointMapObjectImpl;
template <typename> friend class GenericObjectFactory;
protected:
explicit MapObjectAttributesImpl(const QString &debugInfo = QString());
virtual ~MapObjectAttributesImpl();
public:
MapObjectAttributesImpl(const MapObjectAttributesImpl &other) = delete;
MapObjectAttributesImpl &operator=(MapObjectAttributesImpl &other) = delete;
QVariantMap attributes() const override;
void setAttributes(const QVariantMap &attributes) override;
protected:
bool updateViewImpl() override;
friend class MapImpl;
bool init(MapImpl *mapImpl, const QString &logicalLayerName) override;
// internal/admin
// logical
private:
LOGGER_T m_logger; ///< Interface of the Logging-Facility
};
} // namespace SituationMap
@@ -0,0 +1,289 @@
/**
* @RDE_HEADER@
* Interface-Implementation of MapObjectIndicator
* $Id$
* $HeadURL$
* $Author$
*/
// Own
#include "map_object_indicator_impl.h"
#include <MapImpl/map_impl.h>
#include <Map/object_factory.h>
#include <Map/bounding_box.h>
#include "abstract_single_point_map_object_impl.h"
#include <GraphicalObjects/graphical_object_path.h>
#include <GraphicalObjects/graphical_object_text.h>
// ESRI
// Qt
#include <cassert>
namespace SituationMap
{
//-----------------------------------------------------------------------------
// class MapObjectIndicatorImpl
//-----------------------------------------------------------------------------
MapObjectIndicatorImpl::MapObjectIndicatorImpl(const QString &debugInfo)
: MapObjectIndicator() // Interface
, BaseClass(debugInfo) // Implementation
, m_logger(getLogger("MapObjectIndicatorImpl"))
{
TRACE_LOG(m_logger) << LOGFUNCTION << " START";
setPickable(false);
setArrowHeadStart(true);
m_arrowHeadLengthHeight = 25; // size of arrow
m_arrowHeadHalfWidth = 7; // size of arrow
m_pictureMarkerSize = 10; // size of filled circle at the origin (indicating the center of the map)
m_lineWidth = 2; // lineWidth of (dahed) line from origin to target
TRACE_LOG(m_logger) << LOGFUNCTION << " END";
}
MapObjectIndicatorImpl::~MapObjectIndicatorImpl()
{
TRACE_LOG(m_logger) << LOGFUNCTION << " START";
// disconnect lambda!!! Otherwise it will be called with a dangling 'this'pointer.
QObject::disconnect(m_extentChangedConnection);
TRACE_LOG(m_logger) << LOGFUNCTION << " END";
}
Point3D MapObjectIndicatorImpl::startPoint() const
{
// !!! see setStartAndEndPoint() !!!
const PositionCont &pos = m_positions.positions();
if (pos.size() < 2)
return Point3D();
else
return pos[1]; // !!! see setStartAndEndPoint() !!!
}
Point3D MapObjectIndicatorImpl::endPoint() const
{
// !!! see setStartAndEndPoint() !!!
const PositionCont &pos = m_positions.positions();
if (pos.size() < 2)
return Point3D();
else
return pos[0]; // !!! see setStartAndEndPoint() !!!
}
void MapObjectIndicatorImpl::setStartAndEndPoint(const Point3D &start, const Point3D &end)
{
TRACE_LOG(m_logger) << LOGFUNCTION << " START"
<< " start=" << start
<< " end=" << end;
// According MIL2525 a line (like attack) starts with an arrow.
// But in this context (HitLine)
// start == shooter -> no arrowHead
// end == target -> with arrowHead
// Therefore we have to add the 'end'/target point first:
m_positions.setPositions(PositionCont() << end << start);
TRACE_LOG(m_logger) << LOGFUNCTION << " END";
}
UniqueMapId MapObjectIndicatorImpl::mapObjectToPointTo()
{
return m_uniqueIdToPointTo;
}
void MapObjectIndicatorImpl::setMapObjectToPointTo(UniqueMapId uniqueId)
{
TRACE_LOG(m_logger) << LOGFUNCTION << " START, uniqueId=" << uniqueId;
m_uniqueIdToPointTo = uniqueId;
TRACE_LOG(m_logger) << LOGFUNCTION << " END, uniqueId=" << uniqueId;
}
bool MapObjectIndicatorImpl::updateViewImpl()
{
TRACE_LOG(m_logger) << LOGFUNCTION << " START"
<< " symbol=" << m_symbol.value().sidc
<< " visibility=" << m_visibility
<< " visiTechn=" << m_visibilityTechnical
<< " visiTact=" << m_visibilityTactical;
// create PictureMarker here, to have m_uniqueMapId already set ( compared to init() )
if (m_pictureMarker.isNull())
{
QString debugInfo = QStringLiteral("%1#CenterMarker").arg(m_debugInfo);
m_pictureMarker = QSharedPointer<GraphicalObjectPictureMarker>
(new GraphicalObjectPictureMarker(m_mapImpl->getEsriGeoView()
, m_graphicsLayer
, debugInfo
, m_uniqueMapId));
}
setArrowHeadsSelected(m_selected);
// real work:
//
// point to desired obj now:
//
RefPointer<AbstractMapObject> objToPointTo;
if (SituationMap::isUniqueMapIdValid(m_uniqueIdToPointTo))
objToPointTo = m_mapImpl->objectFactory().get(m_uniqueIdToPointTo);
else
DEBUG_LOG(m_logger) << LOGFUNCTION << " m_uniqueIdToPointTo invalid: " << m_uniqueIdToPointTo;
// retrive values from objToPointTo:
PositionCont line;
QColor color;
if (objToPointTo.valid())
{
const QString &objToPointToDebugInfo = objToPointTo->debugInfo();
DEBUG_LOG(m_logger) << LOGFUNCTION
<< " objToPointTo is valid, uniqueIdToPointTo=" << m_uniqueIdToPointTo
<< " (objToPointToDebugInfo=" << objToPointToDebugInfo << ")";
// 1
AbstractMapObjectImpl *impl = dynamic_cast<AbstractMapObjectImpl *>(objToPointTo.get());
if (impl)
{
color = impl->majorColor();
// color.setAlpha(255); // no transperency
this->setDrawOrder(std::max(this->drawOrder(), impl->drawOrder()));
}
else
{
ERROR_LOG(m_logger) << LOGFUNCTION
<< " dynamic_cast failed, uniqueIdToPointTo=" << m_uniqueIdToPointTo
<< " (objToPointToDebugInfo=" << objToPointToDebugInfo << ")";
}
// get target position:
BoundingBox bbox;
objToPointTo->boundingBox(bbox);
if (!bbox.isValid())
WARNING_LOG(m_logger) << LOGFUNCTION << " boundingBox not valid: bbox=" << bbox;
line.append(bbox.center());
const QPointF &curCenterPoint = m_mapImpl->centerPoint();
const Point3D curCenterPoint3D(curCenterPoint.x(), curCenterPoint.y(), .0);
line.append(curCenterPoint3D);
// Color:
LineStyle ls = this->lineStyle();
ls.setLineColor(color);
this->setLineStyle(ls);
}
else // if (objToPointTo.valid())
{
WARNING_LOG(m_logger) << LOGFUNCTION << " objToPointTo not found";
const QPointF &curCenterPoint = m_mapImpl->centerPoint();
const Point3D curCenterPoint3D(curCenterPoint.x(), curCenterPoint.y(), .0);
line << curCenterPoint3D << curCenterPoint3D; // use curCenterPoint twice (to show a very 'short line');
color = Qt::magenta;
}
//
// transfer values:
//
if (line.size() == 2)
{
DEBUG_LOG(m_logger) << LOGFUNCTION << " setStartAndEndPoint, uniqueIdToPointTo=" << m_uniqueIdToPointTo
<< " line=" << line;
m_positions.setPositions(line);
}
else
ERROR_LOG(m_logger) << LOGFUNCTION << " size insufficiant, " << " objToPointTo is valid, uniqueIdToPointTo=" << m_uniqueIdToPointTo;
// update marker values:
const PositionCont &positionsTranslated = m_positions.positionsTranslated();
if (positionsTranslated.size() >= 2)
m_pictureMarker->setOrigin(m_positions.positionsTranslated()[1]);
color.setAlpha(255);
m_pictureMarker->setMarkerSymbol(MarkerSymbolType::Circle, m_pictureMarkerSize, color);
bool successBaseClass = BaseClass::updateViewImpl();
if (!successBaseClass)
ERROR_LOG(m_logger) << LOGFUNCTION << " updateViewImpl failed";
m_pictureMarker->setSelected(m_selected);
m_pictureMarker->setVisibility((m_mainGraphicalObject) ? m_mainGraphicalObject->visibility() : false);
bool successPictureMarker = m_pictureMarker->updateView();
if (!successPictureMarker)
ERROR_LOG(m_logger) << LOGFUNCTION << " m_pictureMarker->updateViewImpl failed";
bool success = successPictureMarker && successBaseClass;
TRACE_LOG(m_logger) << LOGFUNCTION << " END, success=" << success;
return success;
}
bool MapObjectIndicatorImpl::init(MapImpl *mapImpl, const QString &logicalLayerName)
{
TRACE_LOG(m_logger) << LOGFUNCTION << " START";
this->setVisibility(ObjectAppearance::Tactical, false);
bool success = BaseClass::init(mapImpl, logicalLayerName, GraphicalObjectPathType::Polyline);
if (!success)
{
ERROR_LOG(m_logger) << LOGFUNCTION << " init failed";
return false;
}
if (!m_mainGraphicalObject)
{
ERROR_LOG(m_logger) << LOGFUNCTION << "no m_mainGraphicalObject";
return false;
}
m_mainGraphicalObject->rLineStyle().setLinePattern(LinePattern::Dash);
m_mainGraphicalObject->rLineStyle().setLineWidth(m_lineWidth);
// connect to extentChanged...
// ! Must be disconnected in dtor !
m_extentChangedConnection = QObject::connect(m_mapImpl, &MapImpl::extentChangedDelayed, m_mapImpl, [this]()
// ^^^^ to avoid CLazy warning
{
this->updateView();
});
TRACE_LOG(m_logger) << LOGFUNCTION << " END, success=" << success;
return success;
}
bool MapObjectIndicatorImpl::setPositions(const PositionCont &)
{
FATAL_LOG(m_logger) << LOGFUNCTION << " DO NOT CALL!!!";
assert(false);
return false;
}
} // namespace SituationMap
@@ -0,0 +1,101 @@
/**
* @RDE_HEADER@
* Interface-Implementation of MapObjectIndicator
* $Id$
* $HeadURL$
* $Author$
*/
#pragma once
// Own
#include "abstract_multi_point_map_object_impl.h"
#include "basic_path_object_impl.h"
#include <MapObjects/map_object_indicator.h> // Interface
// Qt
#include <QString>
#include <QColor>
#include <QPointF>
#include <QSharedPointer>
//----------------------------------------------------------------------------
namespace SituationMap
{
// forward
class GraphicalObjectPictureMarker;
/**
* @brief The MapObjectIndicatorImpl can be used to ease the locating of an object.
* The MapObjectIndicatorImpl can by parametrized with just the UniqueMapId to point to.
* updateView() will do the rest for you:
* - retrieve the object to point to,
* - get the bounding box of that object and
* - create an indicator from the current center of the map to the object.
* \note <b> If the object to point to disappears, you are responsible for removing the MapObjectIndicatorImpl! </b>
*
* A class instance consists of the following logical elements:
* - mainGraphicalObject (GraphicalObjectPath displaying the line with arrowhead)
* - m_pictureMarker of type GraphicalObjectPictureMarker / Image to show circle at the center of the map.
* - mainGraphicalObjectText (displaying the text/name/identifier)
* - tacticalAppearance (irrelevant)
*/
// inherent 'public', to get that implementation
// inherent 'public virtual' to get that interface
class SITUATIONMAPOBJECTS_EXPORT MapObjectIndicatorImpl : public BasicPathObjectImpl, public virtual MapObjectIndicator
{
using BaseClass = BasicPathObjectImpl;
template <typename> friend class GenericObjectFactory;
protected:
explicit MapObjectIndicatorImpl(const QString &debugInfo = QString());
virtual ~MapObjectIndicatorImpl();
public:
MapObjectIndicatorImpl(const MapObjectIndicatorImpl &other) = delete;
MapObjectIndicatorImpl &operator=(MapObjectIndicatorImpl &other) = delete;
Point3D startPoint() const override;
Point3D endPoint() const override;
void setStartAndEndPoint(const Point3D &start, const Point3D &end) override;
UniqueMapId mapObjectToPointTo() override;
void setMapObjectToPointTo(UniqueMapId uniqueId) override;
protected:
bool updateViewImpl() override;
friend class MapImpl;
bool init(MapImpl *mapImpl, const QString &logicalLayerName) override;
// internal/admin
// logical
private:
bool setPositions(const PositionCont &) override; //SHOULD NEVER BE CALLED
private:
UniqueMapId m_uniqueIdToPointTo = INVALID_MAP_ID;
QSharedPointer<GraphicalObjectPictureMarker> m_pictureMarker; // circle at the center of the map
int m_pictureMarkerSize = 20;
int m_lineWidth = 4;
QMetaObject::Connection m_extentChangedConnection;
LOGGER_T m_logger; ///< Interface of the Logging-Facility
};
} // namespace SituationMap
+381
View File
@@ -0,0 +1,381 @@
/**
* @RDE_HEADER@
* Interface-Implementation of MineField
* $Id$
* $HeadURL$
* $Author$
*/
// Own
#include "mine_field_impl.h"
#include <MapImpl/map_impl.h>
#include "basic_path_object_impl.h"
#include <GraphicalObjects/stub_graphical_object.h>
#include "mine_impl.h"
#include <Symbology/sidc_codec.h>
// ESRI
// Qt
#include <QMap>
namespace SituationMap
{
// to get access to 'init'
class MineFieldLocalBasicPathObject final : public BasicPathObjectImpl
{
public:
using BasicPathObjectImpl::BasicPathObjectImpl;
using BasicPathObjectImpl::init;
using BasicPathObjectImpl::setUniqueId;
};
//-----------------------------------------------------------------------------
class MineFieldImpl::Private
{
public:
Private() = default;
~Private() = default;
// ESRI data:
Esri::ArcGISRuntime::GraphicsOverlay *m_graphicsLayer = nullptr;
// Own data:
MapImpl *m_mapImpl = nullptr;
QString m_logicalLayer;
QString m_debugInfo; // will be appended by consecutive number
UniqueMapId m_uniqueMapId = INVALID_MAP_ID;
QMap<int, bool> m_visibilityMines;
QMap<int, QSharedPointer<BasicPathObjectImpl> > m_cont;
using MAP_IT_T = QMapIterator<int, QSharedPointer<BasicPathObjectImpl>>;
// int m_drawOrder = 0;
bool hasPathObject(int key) const { return m_cont.contains(key); }
QList<int> keysInUse() const { return m_cont.keys(); }
void remove(int key) { m_cont.remove(key); }
void clear() { m_cont.clear(); }
QSharedPointer<BasicPathObjectImpl> getPathObject(int key)
{
auto ret = m_cont.value(key);
if (ret.isNull())
{
QString debugInfo = QStringLiteral("%1#MineFieldSeg(%2)").arg(m_debugInfo).arg(key);
MineFieldLocalBasicPathObject *temp = new MineFieldLocalBasicPathObject(debugInfo);
bool success = temp->init(m_mapImpl, m_logicalLayer, GraphicalObjectPathType::Polygon);
temp->setUniqueId(m_uniqueMapId);
temp->setFillStyle(FillStyle(FillPattern::Null)); // no fill by default
if (success)
{
ret = QSharedPointer<BasicPathObjectImpl>(static_cast<BasicPathObjectImpl *>(temp));
m_cont.insert(key, ret);
}
else
temp->removeMySelf();
}
return ret;
}
}; // class MineFieldImpl::Private
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
// class MineFieldImpl
//-----------------------------------------------------------------------------
MineFieldImpl::MineFieldImpl(const QString &debugInfo)
: MineField() // Interface
, BaseClass(debugInfo) // Implementation
, d(new Private)
, m_logger(getLogger("MineFieldImpl"))
{
TRACE_LOG(m_logger) << LOGFUNCTION << " START";
d->m_visibilityMines[static_cast<int>(MineState::Activated)] = true;
d->m_visibilityMines[static_cast<int>(MineState::DeActivated)] = true;
m_lineColorFromParty = false;
m_fillColorAlpha = 200;
TRACE_LOG(m_logger) << LOGFUNCTION << " END";
}
MineFieldImpl::~MineFieldImpl()
{
TRACE_LOG(m_logger) << LOGFUNCTION << " START";
delete d;
TRACE_LOG(m_logger) << LOGFUNCTION << " END";
}
void MineFieldImpl::setUniqueId(const UniqueMapId &uniqueId)
{
BaseClass::setUniqueId(uniqueId);
d->m_uniqueMapId = m_uniqueMapId;
}
PositionCont MineFieldImpl::segment(int key) const
{
if (d->hasPathObject(key))
return d->getPathObject(key)->positions();
else
return PositionCont();
}
void MineFieldImpl::setSegment(int key, const PositionCont &positions)
{
TRACE_LOG(m_logger) << LOGFUNCTION << " START"
<< " key=" << key
<< " positions.size=" << positions.size();
QSharedPointer<BasicPathObjectImpl> pathObj = d->getPathObject(key);
if (pathObj)
pathObj->setPositions(positions);
TRACE_LOG(m_logger) << LOGFUNCTION << " END";
}
void MineFieldImpl::removeSegment(int key)
{
TRACE_LOG(m_logger) << LOGFUNCTION << " START";
TRACE_LOG(m_logger) << LOGFUNCTION << " END";
return d->remove(key);
}
void MineFieldImpl::removeSegments()
{
TRACE_LOG(m_logger) << LOGFUNCTION << " START";
TRACE_LOG(m_logger) << LOGFUNCTION << " END";
return d->clear();
}
QList<int> MineFieldImpl::keysInUse() const
{
TRACE_LOG(m_logger) << LOGFUNCTION << " START";
TRACE_LOG(m_logger) << LOGFUNCTION << " END";
return d->keysInUse();
}
void MineFieldImpl::setPositionsMine(MineField::MineState mineState, const PositionCont &posCont)
{
TRACE_LOG(m_logger) << LOGFUNCTION << " START"
<< " mineState=" << static_cast<int>(mineState)
<< " posCont.size()=" << posCont.size();
IndicationContainer &mines = this->rIndicationContainer();
mines.setDebugInfo(m_debugInfo);
mines.setPositions(static_cast<int>(mineState), posCont);
TRACE_LOG(m_logger) << LOGFUNCTION << " END"
<< " mineState=" << static_cast<int>(mineState)
<< " posCont.size()=" << posCont.size();
}
bool MineFieldImpl::mineVisibility(MineField::MineState mineState) const
{
return d->m_visibilityMines[static_cast<int>(mineState)];
}
void MineFieldImpl::setMineVisibility(MineField::MineState mineState, bool visible)
{
d->m_visibilityMines[static_cast<int>(mineState)] = visible;
}
bool MineFieldImpl::updateViewImpl()
{
TRACE_LOG(m_logger) << LOGFUNCTION << " START"
<< " visibility=" << m_visibility
<< " visiTechn=" << m_visibilityTechnical
<< " visiTact=" << m_visibilityTactical
<< " mineVisibility(MineState::Activated)=" << this->mineVisibility(MineState::Activated)
<< " mineVisibility(MineState::DeActivated)=" << this->mineVisibility(MineState::DeActivated)
<< " m_positions->positions().count()=" << m_positions.positions().count()
<< " m_mainGraphicalObject->positions().count()=" << m_mainGraphicalObject->positions().count()
<< " m_mainGraphicalObject->fillStyle().fillPattern()=" << (int)m_mainGraphicalObject->fillStyle().fillPattern();
// indication :
if (nullptr == m_mainGraphicalObject)
{
ERROR_LOG(m_logger) << LOGFUNCTION << " no m_mainGraphicalObject";
return false;
}
if (m_indicationCont)
{
const QColor &col = m_mainGraphicalObject->lineStyle().lineColor();
const QList<int> idxInUse = m_indicationCont->getIndicationIndexList();
for (int idx : idxInUse)
{
// handle image on if not already set:
if (m_indicationCont->image(idx).isNull())
{
bool filled = (idx == static_cast<int>(MineState::DeActivated));
const QImage &img = MineImpl::renderMineSymbol(col, 20, filled); // filled
m_indicationCont->setImage(idx, img);
}
m_indicationCont->setSelected(idx, m_selected);
m_indicationCont->setPickable(idx, m_pickable);
}
}
// : indication
// m_mainGraphicalObject stores the outline/'bounding box' (techn and tact)
// Those geometry should never be visible.
// The text of should be visible.
this->setVisibilityOfGeometry(false);
bool success = BaseClass::updateViewImpl();
if (!success)
ERROR_LOG(m_logger) << LOGFUNCTION << " updateViewImpl failed";
// segment :
Private::MAP_IT_T mapIt(d->m_cont);
while (mapIt.hasNext())
{
mapIt.next();
QSharedPointer<BasicPathObjectImpl> pathObj = mapIt.value();
if (pathObj)
{
int idx = mapIt.key();
// pathObj->setDebugInfo(m_mainGraphicalObject->debugInfo()); // will overwrite complete string -> skip
pathObj->setLineStyle(m_mainGraphicalObject->lineStyle());
if (idx >= 0)
pathObj->setFillStyle(m_mainGraphicalObject->fillStyle());
pathObj->setVisibility(m_visibility);
pathObj->setVisibility(ObjectAppearance::Technical, m_visibilityTechnical);
// Do not Transfer symbol. Only m_mainGraphicalObject uses ObjectAppearance::Tactical:
// pathObj->setSymbol(this->symbol());
pathObj->setVisibility(ObjectAppearance::Tactical, false);
pathObj->setPickable(m_mainGraphicalObject->pickable());
pathObj->setSelected(m_mainGraphicalObject->selected());
pathObj->setDrawOrder(this->drawOrder()); // use m_drawOrder instead m_internalDrawOrder.
if (!pathObj->updateView())
{
int key = mapIt.key();
ERROR_LOG(m_logger) << LOGFUNCTION << " updateViewImpl failed, key=" << key;
}
}
} // while
// : segment
TRACE_LOG(m_logger) << LOGFUNCTION << " END"
<< " visibility=" << m_visibility
<< " visiTechn=" << m_visibilityTechnical
<< " visiTact=" << m_visibilityTactical
<< " mineVisibility(MineState::Activated)=" << this->mineVisibility(MineState::Activated)
<< " mineVisibility(MineState::DeActivated)=" << this->mineVisibility(MineState::DeActivated)
<< " m_positions->positions().count()=" << m_positions.positions().count()
<< " m_mainGraphicalObject->positions().count()=" << m_mainGraphicalObject->positions().count()
<< " m_mainGraphicalObject->fillStyle().fillPattern()=" << (int)m_mainGraphicalObject->fillStyle().fillPattern();
TRACE_LOG(m_logger) << LOGFUNCTION << " END, success=" << success;
return success;
}
bool MineFieldImpl::init(MapImpl *mapImpl, const QString &logicalLayerName)
{
TRACE_LOG(m_logger) << LOGFUNCTION << " START";
if (mapImpl)
{
switch (mapImpl->symbologyType())
{
case AdvancedSymbology::SymbologyType::APP6D:
case AdvancedSymbology::SymbologyType::MIL2525D:
// m_symbol.refValue().sidc = AdvancedSymbology::SidcCodec::encodeComplete(mapImpl->symbologyType(),"10012500002707060000"); // SymbolSet = 25 270701 , 270705, 270706, 270707
// Case #01977851 - Runitme SDK for Qt: IdentifyGraphicsOverlays crashes
// BUG-000107707 : IdentifyGraphicsOverlays crashes on military symbol "10012500002707060000"]
// -> use another:
m_symbol.refValue().sidc = AdvancedSymbology::SidcCodec::encodeComplete(mapImpl->symbologyType(), "10012500001511000000"); // SymbolSet = 25 151100
break;
case AdvancedSymbology::SymbologyType::MIL2525C:
m_symbol.refValue().sidc = AdvancedSymbology::SidcCodec::encodeComplete(mapImpl->symbologyType(), "GFMPOFA---"); // Mil2525C: 0843: GFMPOFA--- -> Polygon (Minefields Mined Area F)
break;
case AdvancedSymbology::SymbologyType::APP6B:
// m_symbol.refValue().sidc = AdvancedSymbology::SidcCodec::encodeComplete(mapImpl->symbologyType(),"GFCPBOAIL-"); // APP6B: 3852: GFCPBOAIL- -> Polygon (Minefield - Antipersonnel Mines)
// m_symbol.refValue().sidc = AdvancedSymbology::SidcCodec::encodeComplete(mapImpl->symbologyType(),"GFCPBOAIN-"); // APP6B: 3853: GFCPBOAIN- -> Polygon (Minefield - Antitank)
m_symbol.refValue().sidc = AdvancedSymbology::SidcCodec::encodeComplete(mapImpl->symbologyType(), "GFCPBOAIM-"); // APP6B: 3857: GFCPBOAIM- -> Polygon (Minefields Mined Area)
break;
case AdvancedSymbology::SymbologyType::None:
// empty
break;
} // switch
} // if (mapImpl)
bool success = BaseClass::init(mapImpl, logicalLayerName, GraphicalObjectPathType::Polygon);
if (!success)
ERROR_LOG(m_logger) << LOGFUNCTION << " init failed";
setLineStyle(LineStyle(Qt::green, 2));
setFillStyle(FillStyle(Qt::green, FillPattern::Null));
// set some values to Private:
d->m_mapImpl = m_mapImpl;
d->m_logicalLayer = m_logicalLayerName;
d->m_debugInfo = m_debugInfo;
d->m_uniqueMapId = m_uniqueMapId;
TRACE_LOG(m_logger) << LOGFUNCTION << " END, success=" << success;
return success;
}
bool MineFieldImpl::onMapExtentChanged()
{
TRACE_LOG(m_logger) << LOGFUNCTION << " START";
if (m_indicationCont)
{
bool visiScale = m_visibilityScaleRange.scaleHasVisibility(m_mapImpl->scale());
const QList<int> &idxInUse = m_indicationCont->getIndicationIndexList(); // idxInUse is representing all values of 'MineState'
for (int idx : qAsConst(idxInUse))
{
m_indicationCont->setVisible(idx, m_visibility && m_visibilityTechnical && d->m_visibilityMines.value(idx) && visiScale);
}
}
bool success = BaseClass::onMapExtentChanged();
TRACE_LOG(m_logger) << LOGFUNCTION << " END, success=" << success;
return success;
}
} // namespace SituationMap
+110
View File
@@ -0,0 +1,110 @@
/**
* @RDE_HEADER@
* Interface-Implementation of MineField
* $Id$
* $HeadURL$
* $Author$
*/
#pragma once
// Own
#include "abstract_multi_point_map_object_impl.h"
#include "basic_path_object_impl.h"
#include <MapObjects/mine_field.h> // Interface
// Qt
#include <QList>
//----------------------------------------------------------------------------
namespace SituationMap
{
enum class MinesState;
// inherent 'public', to get that implementation
// inherent 'public virtual' to get that interface
/**
* @brief The MineFieldImpl class supports MineFields with an unlimited number of segments.
* Additionally the positions of mines can be set.
* MineState::Activated and MineState::DeActivated are supported.
*
* The segments are implemented using a BasicPathObjectImpl.
* The subsidiary lines of the mainGraphicalObject (also of type BasicPathObjectImpl)
* are not used because the geometry part of the mainGraphicalObject is hidden (replaced by the segments.)
* But the envelope of the MineField is necessary to show the TacticalAppearance.
*
* The identifier of the MineFieldImpl is used, not the identifier of the segments.
*
* A class instance consists of the following logical elements:
* - mainGraphicalObject (GraphicalObjectPath displaying the main techn. Appearance (is hidden, see above)
* - mainGraphicalObjectText (displaying the text/name/identifier)
* - tacticalAppearance (displaying the tact. Appearance)
* - Container of BasicPathObjectImpl's to display the single segments.
*/
class SITUATIONMAPOBJECTS_EXPORT MineFieldImpl : public BasicPathObjectImpl, public virtual MineField
{
using BaseClass = BasicPathObjectImpl;
template <typename> friend class GenericObjectFactory;
protected:
explicit MineFieldImpl(const QString &debugInfo = QString());
virtual ~MineFieldImpl();
public:
MineFieldImpl(const MineFieldImpl &other) = delete;
MineFieldImpl &operator=(MineFieldImpl &other) = delete;
void setUniqueId(const UniqueMapId &uniqueId) override;
PositionCont segment(int key) const override;
/**
* @brief Set positions of one segment.
* @param key of segment to be set.
* @param posCont positions of segment.
* @note: is key is negativ, no fill pattern is aplied.
* If key is >=0, the pattern of the segments take over the main pattern.
*/
void setSegment(int key, const PositionCont &positions) override;
void removeSegment(int key) override;
void removeSegments() override;
QList<int> keysInUse() const override;
void setPositionsMine(MineState mineState, const PositionCont &posCont) override;
bool mineVisibility(MineState mineState) const override;
void setMineVisibility(MineState mineState, bool visible) override;
protected:
virtual bool updateViewImpl() override;
friend class MapImpl;
bool init(MapImpl *mapImpl, const QString &logicalLayerName) override;
bool onMapExtentChanged() override;
// internal/admin
// logical
private:
class Private;
/**
* The private d->pointer to not break BC when changing internals of this class
*/
Private *d = nullptr;
LOGGER_T m_logger; ///< Interface of the Logging-Facility
};
} // namespace SituationMap
+241
View File
@@ -0,0 +1,241 @@
/**
* @RDE_HEADER@
* Interface-Implementation of Mine
* $Id$
* $HeadURL$
* $Author$
*/
// Own
#include "mine_impl.h"
#include <MapImpl/map_impl.h>
#include <Map/party_id_to_color_functor.h>
#include <GraphicalObjects/graphical_object_ellipse.h>
#include <GraphicalObjects/graphical_object_picture_marker.h>
#include <GraphicalObjects/tactical_appearance.h>
#include <Symbology/sidc_codec.h>
// ESRI
// Qt
#include <QPainter>
#include <QPen>
namespace SituationMap
{
//-----------------------------------------------------------------------------
// constants
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
// Utils:
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
// class MineImpl
//-----------------------------------------------------------------------------
MineImpl::MineImpl(const QString &debugInfo)
: Mine() // Interface
, BaseClass(debugInfo) // Implementation
// , AbstractEffectSimulationImpl() // Secondary implementation
, m_logger(getLogger("MineImpl"))
{
TRACE_LOG(m_logger) << LOGFUNCTION << " START";
TRACE_LOG(m_logger) << LOGFUNCTION << " END";
}
MineImpl::~MineImpl()
{
TRACE_LOG(m_logger) << LOGFUNCTION << " START";
TRACE_LOG(m_logger) << LOGFUNCTION << " END";
}
QString MineImpl::toString() const
{
QString str;
str.append(BaseClass::toString());
// str.append( AbstractEffectSimulationImpl::toString() );
return str;
}
bool MineImpl::state() const
{
return m_state.value();
}
void MineImpl::setState(bool state)
{
m_state = state;
}
SymbolImage MineImpl::symbolImage() const
{
SymbolImage symImage;
GraphicalObjectPictureMarker *pMarker = static_cast<GraphicalObjectPictureMarker *>(m_mainGraphicalObject);
if (pMarker)
{
symImage.setImage(pMarker->image());
symImage.setValid(!symImage.image().isNull());
}
return symImage;
}
bool MineImpl::updateViewImpl()
{
TRACE_LOG(m_logger) << LOGFUNCTION << " START"
<< " origin =" << this->origin() //.x() << ", " << this->origin().y()
<< " radius =" << this->radius()
<< " visibility=" << m_visibility
<< " visiTechn=" << m_visibilityTechnical
<< " visiTact=" << m_visibilityTactical;
if (!m_graphicsLayer)
{
ERROR_LOG(m_logger) << LOGFUNCTION << " no graphicsLayer";
return false;
}
if (nullptr == m_mainGraphicalObject)
{
ERROR_LOG(m_logger) << LOGFUNCTION << " no m_mainGraphicalObject";
return false;
}
// image:
GraphicalObjectPictureMarker *pMarker = static_cast<GraphicalObjectPictureMarker *>(m_mainGraphicalObject);
if (m_state.changed())
{
const QImage &img = renderMineSymbol(partyColor(),
20,
m_state.value());
pMarker->setImage(img);
}
pMarker->setOrigin(this->originTranslated());
// tacticalAppearance:
if (m_tacticalAppearance)
{
if (partyChanged())
m_symbol.refValue().color = partyColor();
m_tacticalAppearance->setOrigin(this->originTranslated());
}
bool success = BaseClass::updateViewImpl();
// reset changed:
m_state.reset();
TRACE_LOG(m_logger) << LOGFUNCTION << " END, success=" << success;
return success;
}
bool MineImpl::init(MapImpl *mapImpl, const QString &logicalLayerName)
{
TRACE_LOG(m_logger) << LOGFUNCTION << " START";
if (mapImpl)
{
switch (mapImpl->symbologyType())
{
case AdvancedSymbology::SymbologyType::APP6D:
case AdvancedSymbology::SymbologyType::MIL2525D:
m_symbol.refValue().sidc = AdvancedSymbology::SidcCodec::encodeComplete(mapImpl->symbologyType(), "10011500002102000000"); // SymbolSet = 15 210100 ; 280000 -> Crash on Click
break;
case AdvancedSymbology::SymbologyType::MIL2525C:
// m_symbol.refValue().sidc = AdvancedSymbology::SidcCodec::encodeComplete(mapImpl->symbologyType(),"GHMPOB----"); // 0754 GHMPOMP--- (Antipersonnel (AP) Mines H) -> Point
m_symbol.refValue().sidc = AdvancedSymbology::SidcCodec::encodeComplete(mapImpl->symbologyType(), "GHMPOB----"); // 0760 GHMPOB---- (Booby Trap H) -> Point
break;
case AdvancedSymbology::SymbologyType::APP6B:
m_symbol.refValue().sidc = AdvancedSymbology::SidcCodec::encodeComplete(mapImpl->symbologyType(), "GUOPVY----"); // APP6B: 2549 GUOPVY---- (Booby Trap U) -> Point
break;
case AdvancedSymbology::SymbologyType::None:
// empty
break;
} // switch
} // if (mapImpl)
bool success = BaseClass::init(mapImpl, logicalLayerName);
if (success)
{
// create underlying object (to save most attributes only there)
if (!m_mainGraphicalObject)
m_mainGraphicalObject = new GraphicalObjectPictureMarker(m_mapImpl->getEsriGeoView(),
m_graphicsLayer,
m_debugInfo + QStringLiteral("#Image"),
m_uniqueMapId);
}
else
ERROR_LOG(m_logger) << LOGFUNCTION << " init failed";
TRACE_LOG(m_logger) << LOGFUNCTION << " END, success=" << success;
return success;
}
QImage MineImpl::renderMineSymbol(const QColor &color, int size, bool filled)
{
QImage image(size, size, QImage::Format_ARGB32);
image.fill(Qt::transparent);
QPainter painter(&image);
QPen pen(color);
pen.setWidth(2); // filled == deactivated == triggered
if (!filled)
pen.setWidth(1); // !filled == active == still armed
painter.setPen(pen);
const int sizeHalf = size / 2.0;
QPointF center(sizeHalf, sizeHalf);
// circle
if (filled)
painter.setBrush(color);
painter.drawEllipse(center, sizeHalf * 0.5, sizeHalf * 0.5);
// lines
QLine newLine(0, sizeHalf, size / 4.0, sizeHalf);
painter.drawLine(newLine);
QTransform trans;
trans.translate(sizeHalf, sizeHalf);
trans.rotate(90);
trans.translate(-sizeHalf, -sizeHalf);
newLine = trans.map(newLine);
painter.drawLine(newLine);
newLine = trans.map(newLine);
painter.drawLine(newLine);
newLine = trans.map(newLine);
painter.drawLine(newLine);
painter.end();
return image;
}
} // namespace SituationMap
+77
View File
@@ -0,0 +1,77 @@
/**
* @RDE_HEADER@
* Interface-Implementation of Mine
* $Id$
* $HeadURL$
* $Author$
*/
#pragma once
// Own
#include "abstract_single_point_map_object_impl.h"
//#include "abstract_effect_simulation_impl.h"
#include <MapObjects/mine.h> // Interface
// Qt
//----------------------------------------------------------------------------
namespace SituationMap
{
/**
* @brief The MineImpl class displays a mine impact.
*
* A class instance consists of the following logical elements:
* - mainGraphicalObject (GraphicalObjectPictureMarker / Image, displaying the main techn. Appearance)
* - mainGraphicalObjectText (displaying the text/name)
* - tacticalAppearance (displaying the tact. Appearance)
*/
// inherent 'public', to get that implementation
// inherent 'public virtual' to get that interface
class SITUATIONMAPOBJECTS_EXPORT MineImpl : public AbstractSinglePointMapObjectImpl, public virtual Mine
{
using BaseClass = AbstractSinglePointMapObjectImpl;
template <typename> friend class GenericObjectFactory;
protected:
explicit MineImpl(const QString &debugInfo = QString());
virtual ~MineImpl();
public:
MineImpl(const MineImpl &other) = delete;
MineImpl &operator=(MineImpl &other) = delete;
QString toString() const override;
bool state() const override;
void setState(bool state) override;
SymbolImage symbolImage() const override;
static QImage renderMineSymbol(const QColor &color, int size, bool filled);
protected:
virtual bool updateViewImpl() override;
friend class MapImpl;
bool init(MapImpl *mapImpl, const QString &logicalLayerName) override;
// internal/admin
// logical
SimpleValue<bool> m_state = false;
private:
LOGGER_T m_logger; ///< Interface of the Logging-Facility
};
} // namespace SituationMap
+388
View File
@@ -0,0 +1,388 @@
/**
* @RDE_HEADER@
* Interface-Implementation of NineLiner
* $Id$
* $HeadURL$
* $Author$
*/
// Own
#include "nine_liner_impl.h"
#include <MapImpl/map_impl.h>
#include <GraphicalObjects/graphical_object_path.h>
#include <GraphicalObjects/graphical_object_text.h>
#include <Symbology/sidc_codec.h>
#include <LtsCoordTrans/lts_coord_trans.h>
// ESRI
#include <arcgis/GeometryEngine.h>
// Qt
#include <cassert>
namespace SituationMap
{
double adaptScale(double scale)
{
if (scale<1.0)
return scale;
return (0.33 * scale) + 0.66;
}
//-----------------------------------------------------------------------------
// class NineLinerImpl
//-----------------------------------------------------------------------------
NineLinerImpl::NineLinerImpl(const QString &debugInfo)
: NineLiner() // Interface
, BaseClass(debugInfo) // Implementation
, m_logger(getLogger("NineLinerImpl"))
{
TRACE_LOG(m_logger) << LOGFUNCTION << " START";
m_color = Qt::blue;
m_otInitialPoint.setMapObjectImpl(this);
m_otTargetPosition.setMapObjectImpl(this);
m_otFriendliesPosition.setMapObjectImpl(this);
// setArrowHeadStart(true);
TRACE_LOG(m_logger) << LOGFUNCTION << " END";
}
NineLinerImpl::~NineLinerImpl()
{
TRACE_LOG(m_logger) << LOGFUNCTION << " START";
TRACE_LOG(m_logger) << LOGFUNCTION << " END";
}
QString NineLinerImpl::identifier() const
{
return this->textOnSegment(0);
}
void NineLinerImpl::setIdentifier(const QString &identifier)
{
this->setTextOnSegment(0, identifier);
}
void NineLinerImpl::setScale(float scale)
{
m_ownScale = scale; // to use m_ownScale.changed();
BaseClass::setScale(scale);
}
bool NineLinerImpl::updateViewInitialPoint()
{
bool success = false;
const NineLinerData &data = m_data.value();
// InitialPoint / square
const Point3D &ip = data.initialPoint;
if (ip.isNull())
{
m_pmInitialPoint.clear();
success = true;
} else {
if(!m_pmInitialPoint)
{
QString debugInfo = QStringLiteral("%1#InitialPointMarker").arg(m_debugInfo);
m_pmInitialPoint = QSharedPointer<GraphicalObjectPictureMarker>
(new GraphicalObjectPictureMarker(m_mapImpl->getEsriGeoView()
, m_graphicsLayer
, debugInfo
, m_uniqueMapId));
}
m_pmInitialPoint->setMarkerSymbol(MarkerSymbolType::Square,
20*adaptScale(m_mainGraphicalObject->scale()), // cover the lines less by reduced growing of pointSymbols
m_color.value());
m_otInitialPoint.setOrigin(ip);
m_pmInitialPoint->setOrigin(m_otInitialPoint.originTranslated());
m_pmInitialPoint->setPickable(m_mainGraphicalObject->pickable());
m_pmInitialPoint->setVisibility(m_mainGraphicalObject->visibility());
success = m_pmInitialPoint->updateView();
}
TRACE_LOG(m_logger) << LOGFUNCTION << " success=" << success;
return success;
}
bool NineLinerImpl::updateViewTargetPosition()
{
bool success = false;
const NineLinerData &data = m_data.value();
// TargetPosition / triangle
const Point3D &ip = data.targetPosition;
if (ip.isNull())
{
m_pmTargetPosition.clear();
success = true;
} else {
if(!m_pmTargetPosition)
{
QString debugInfo = QStringLiteral("%1#TargetPositionMarker").arg(m_debugInfo);
m_pmTargetPosition = QSharedPointer<GraphicalObjectPictureMarker>
(new GraphicalObjectPictureMarker(m_mapImpl->getEsriGeoView()
, m_graphicsLayer
, debugInfo
, m_uniqueMapId));
}
m_pmTargetPosition->setMarkerSymbol(MarkerSymbolType::Triangle,
20*adaptScale(m_mainGraphicalObject->scale()), // cover the lines less by reduced growing of pointSymbols
m_color.value());
m_otTargetPosition.setOrigin(ip);
m_pmTargetPosition->setOrigin(m_otTargetPosition.originTranslated());
m_pmTargetPosition->setPickable(m_mainGraphicalObject->pickable());
m_pmTargetPosition->setVisibility(m_mainGraphicalObject->visibility());
success = m_pmTargetPosition->updateView();
}
TRACE_LOG(m_logger) << LOGFUNCTION << " success=" << success;
return success;
}
Point3D movePoint(const Point3D& point, int length, int angle)
{
QList<Esri::ArcGISRuntime::Point> pColl;
constexpr double deg2rad = LtsCoordTrans::deg2rad();
constexpr double rad2deg = LtsCoordTrans::rad2deg();
// to wgs84 / degree
Esri::ArcGISRuntime::Point p(point.x()*rad2deg, point.y()*rad2deg, point.z()*rad2deg, Esri::ArcGISRuntime::SpatialReference::wgs84());
pColl = Esri::ArcGISRuntime::GeometryEngine::moveGeodetic({p},
length, Esri::ArcGISRuntime::LinearUnit::meters(),
angle, Esri::ArcGISRuntime::AngularUnit::degrees(),
Esri::ArcGISRuntime::GeodeticCurveType::Geodesic);
p = pColl.first();
// back to rad
const Point3D movedPoint (p.x()*deg2rad, p.y()*deg2rad, p.z()*deg2rad);
// qCritical() << " length = " << length << " angle= " << angle;
return movedPoint;
}
Point3D movePointFah(const Point3D& point, int length, int angle)
{
if (length < 1000)
length = 1000;
if (length > 100000)
length = 100000;
return movePoint(point, length, angle+180);
}
bool NineLinerImpl::updateViewFriendlies()
{
bool success = false;
const NineLinerData &data = m_data.value();
if (data.friendliesDistance < 0)
{
m_pmFriendlies.clear();
success = true;
}
else
{
const Point3D &tartgetPosition = m_otTargetPosition.origin();
const Point3D &friendliesOrigin = movePoint(tartgetPosition, static_cast<int>(data.friendliesDistance), data.friendliesBearing);
if(!m_pmFriendlies)
{
QString debugInfo = QStringLiteral("%1#FriendliesPositionMarker").arg(m_debugInfo);
m_pmFriendlies = QSharedPointer<GraphicalObjectPictureMarker>
(new GraphicalObjectPictureMarker(m_mapImpl->getEsriGeoView()
, m_graphicsLayer
, debugInfo
, m_uniqueMapId));
}
m_pmFriendlies->setMarkerSymbol(MarkerSymbolType::Circle,
15*adaptScale(m_mainGraphicalObject->scale()), // cover the lines less by reduced growing of pointSymbols
m_color.value());
m_otFriendliesPosition.setOrigin(friendliesOrigin);
m_pmFriendlies->setOrigin(m_otFriendliesPosition.originTranslated());
m_pmFriendlies->setPickable(m_mainGraphicalObject->pickable());
m_pmFriendlies->setVisibility(m_mainGraphicalObject->visibility());
success = m_pmFriendlies->updateView();
}
TRACE_LOG(m_logger) << LOGFUNCTION << " success=" << success;
return success;
}
bool NineLinerImpl::updateViewFinalAttackHeading(int length)
{
const NineLinerData &data = m_data.value();
const Point3D &tartgetPosition = m_otTargetPosition.origin();
const Point3D &fahOrigin = movePointFah(tartgetPosition, length, data.fah);
m_positions.setPositions(PositionCont() << fahOrigin << tartgetPosition);
return true;
}
bool NineLinerImpl::updateViewFahSector(QSharedPointer<GraphicalObjectPath> &path, const QString &debugInfo, int length, int angle)
{
const Point3D &tartgetPosition = m_otTargetPosition.origin();
const Point3D &origin = movePointFah(tartgetPosition, length, angle);
bool success = false;
if (angle < 0)
{
path.clear();
success = true;
} else {
if(!path)
{
path = QSharedPointer<GraphicalObjectPath>
(new GraphicalObjectPath(GraphicalObjectPathType::Polyline,
m_mapImpl->getEsriGeoView()
, m_graphicsLayer
, debugInfo
, m_uniqueMapId));
path->setDrawOrder(m_internalDrawOrder - 1);
}
path->setLineStyle(LineStyle(m_color.value(), 3, LinePattern::Dash));
PositionsTranslated positions;
positions.setMapObjectImpl(this);
positions.addSinglePosition(tartgetPosition);
positions.addSinglePosition(origin);
path->setPositions(positions.positionsTranslated());
path->setScale(m_mainGraphicalObject->scale());
path->setPickable(m_mainGraphicalObject->pickable());
path->setVisibility(m_mainGraphicalObject->visibility());
success = path->updateView();
}
TRACE_LOG(m_logger) << LOGFUNCTION << " success=" << success;
return success;
}
bool NineLinerImpl::updateViewImpl()
{
TRACE_LOG(m_logger) << LOGFUNCTION << " START"
<< " m_data=" << m_data.value().toString()
<< " visibility=" << m_visibility
<< " visiTechn=" << m_visibilityTechnical
<< " visiTact=" << m_visibilityTactical;
BaseClass::updateViewImpl();
m_color = partyColor();
// if (m_data.changed() || m_color.changed() || m_ownScale.changed())
{
updateViewInitialPoint();
updateViewTargetPosition();
updateViewFriendlies();
const int length = static_cast<int>(m_mapImpl->pixelSizeMeter() * 100);
updateViewFinalAttackHeading(length);
updateViewFahSector(m_pathFahSectorLow, QStringLiteral("%1#FahSectorLow").arg(m_debugInfo), length, m_data.value().fahLow);
updateViewFahSector(m_pathFahSectorHigh, QStringLiteral("%1#FahSectorHigh").arg(m_debugInfo), length, m_data.value().fahHigh);
}
setArrowHeadsSelected(m_selected);
bool success = BaseClass::updateViewImpl();
if (!success)
ERROR_LOG(m_logger) << LOGFUNCTION << " updateViewImpl failed";
// reset changed flag -> updateViewImplPost
TRACE_LOG(m_logger) << LOGFUNCTION << " END, success=" << success;
return success;
}
bool NineLinerImpl::onMapExtentChanged()
{
TRACE_LOG(m_logger) << LOGFUNCTION << " START";
bool success = BaseClass::onMapExtentChanged();
// to handle unchanged pixelSizeMeter
const int newFahLength = static_cast<int>(m_mapImpl->pixelSizeMeter() * 100);
if (m_fahLength == newFahLength)
return true;
// store new value
m_fahLength = newFahLength;
updateViewFinalAttackHeading(m_fahLength);
m_mainGraphicalObject->setPositions(m_positions.positionsTranslated());
if(!m_mainGraphicalObject->updateView())
ERROR_LOG(m_logger) << LOGFUNCTION << " updateViewImpl failed (m_mainGraphicalObject)";
if (!updateViewFahSector(m_pathFahSectorLow, QStringLiteral("%1#FahSectorLow").arg(m_debugInfo), m_fahLength, m_data.value().fahLow))
ERROR_LOG(m_logger) << LOGFUNCTION << " updateViewImpl failed (m_pathFahSectorLow)";
if (!updateViewFahSector(m_pathFahSectorHigh, QStringLiteral("%1#FahSectorHigh").arg(m_debugInfo), m_fahLength, m_data.value().fahHigh))
ERROR_LOG(m_logger) << LOGFUNCTION << " updateViewImpl failed (m_pathFahSectorHigh)";
TRACE_LOG(m_logger) << LOGFUNCTION << " END";
return success;
}
bool NineLinerImpl::init(MapImpl *mapImpl, const QString &logicalLayerName)
{
TRACE_LOG(m_logger) << LOGFUNCTION << " START";
if (mapImpl)
{
switch (mapImpl->symbologyType())
{
case AdvancedSymbology::SymbologyType::APP6D:
case AdvancedSymbology::SymbologyType::MIL2525D:
m_symbol.refValue().sidc = AdvancedSymbology::SidcCodec::encodeComplete(mapImpl->symbologyType(), "10032500001406030000"); // SymbolSet = 25 140602
// ^^ ^^^^^^
break;
case AdvancedSymbology::SymbologyType::MIL2525C:
m_symbol.refValue().sidc = AdvancedSymbology::SidcCodec::encodeComplete(mapImpl->symbologyType(), "GFGPOLKGS-"); // 1047 - Direction Of Attack Ground Supporting Attack F
// m_symbol.refValue().sidc = AdvancedSymbology::SidcCodec::encodeComplete(mapImpl->symbologyType(),"GHGPOLKA--"); //
// m_symbol.refValue().sidc = AdvancedSymbology::SidcCodec::encodeComplete(mapImpl->symbologyType(),"GHGPOLKGM-"); //
break;
case AdvancedSymbology::SymbologyType::APP6B:
m_symbol.refValue().sidc = AdvancedSymbology::SidcCodec::encodeComplete(mapImpl->symbologyType(), "GFCPMOLDS-"); // APP6B-3733 GFCPMOLDS- -> Direction Of Attack Ground Supporting Attack F
break;
case AdvancedSymbology::SymbologyType::None:
// empty
break;
} // switch
} // if (mapImpl)
bool success = BaseClass::init(mapImpl, logicalLayerName, GraphicalObjectPathType::Polyline);
if (!success)
ERROR_LOG(m_logger) << LOGFUNCTION << " init failed";
m_mainGraphicalObject->setLineStyle(LineStyle(Qt::cyan, 2, LinePattern::Solid));
TRACE_LOG(m_logger) << LOGFUNCTION << " END, success=" << success;
return success;
}
bool NineLinerImpl::setPositions(const PositionCont &)
{
FATAL_LOG(m_logger) << LOGFUNCTION << " DO NOT CALL!!!";
assert(false);
return false;
}
} // namespace SituationMap
+108
View File
@@ -0,0 +1,108 @@
/**
* @RDE_HEADER@
* Interface-Implementation of NineLiner
* $Id$
* $HeadURL$
* $Author$
*/
#pragma once
// Own
#include "abstract_multi_point_map_object_impl.h"
#include "basic_path_object_impl.h"
#include <MapObjects/nine_liner.h> // Interface
// Qt
#include <QString>
#include <QPointF>
//----------------------------------------------------------------------------
namespace SituationMap
{
// inherent 'public', to get that implementation
// inherent 'public virtual' to get that interface
class SITUATIONMAPOBJECTS_EXPORT NineLinerImpl : public BasicPathObjectImpl, public virtual NineLiner
{
using BaseClass = SituationMap::BasicPathObjectImpl;
template <typename> friend class GenericObjectFactory;
protected:
explicit NineLinerImpl(const QString &debugInfo = QString());
virtual ~NineLinerImpl();
public:
NineLinerImpl(const NineLinerImpl &other) = delete;
NineLinerImpl &operator=(NineLinerImpl &other) = delete;
QString identifier() const override;
void setIdentifier(const QString &identifier) override;
void setNineLinerData(const NineLinerData& data) override { m_data = data; }
void setScale(float scale) override;
protected:
bool updateViewInitialPoint();
bool updateViewTargetPosition();
bool updateViewFriendlies();
bool updateViewFinalAttackHeading(int length);
bool updateViewFahSector(QSharedPointer<GraphicalObjectPath> &path, const QString &debugInfo, int length, int angle);
bool updateViewImpl() override;
bool onMapExtentChanged() override;
bool updateViewImplPost() override
{
BaseClass::updateViewImplPost();
m_data.reset();
m_color.reset();
m_ownScale.reset();
return true;
}
friend class MapImpl;
bool init(MapImpl *mapImpl, const QString &logicalLayerName) override;
// internal/admin
// logical
private:
bool setPositions(const PositionCont &) override; //SHOULD NEVER BE CALLED
private:
// input:
SimpleValue<NineLinerData> m_data;
OriginTranslated m_otInitialPoint;
OriginTranslated m_otTargetPosition;
OriginTranslated m_otFriendliesPosition;
int m_fahLength = 1;
// display:
SimpleValue<float> m_ownScale;
SimpleValue<QColor> m_color;
QSharedPointer<GraphicalObjectPictureMarker> m_pmInitialPoint; // square
QSharedPointer<GraphicalObjectPictureMarker> m_pmTargetPosition; // triangle
QSharedPointer<GraphicalObjectPath> m_pathFahSectorLow;
QSharedPointer<GraphicalObjectPath> m_pathFahSectorHigh;
QSharedPointer<GraphicalObjectPictureMarker> m_pmFriendlies; // circle
LOGGER_T m_logger; ///< Interface of the Logging-Facility
};
} // namespace SituationMap
@@ -0,0 +1,428 @@
/**
* @RDE_HEADER@
* Interface-Implementation of NuclearAgent
* $Id$
* $HeadURL$
* $Author$
*/
// Own
#include "nuclear_agent_impl.h"
#include <MapImpl/map_impl.h>
#include <GraphicalObjects/graphical_object_path.h>
#include <GraphicalObjects/graphical_object_text.h>
#include <Symbology/sidc_codec.h>
// ESRI
// Qt
#include <QList>
#include <QPainter>
namespace SituationMap
{
// to get access to 'init'
using NAgentLocalBasicPathObject = LocalBasicPathObject;
QImage renderImpactSymbol(const QColor &color, int size, bool filled)
{
QImage image(size, size, QImage::Format_ARGB32);
image.fill(Qt::transparent);
QPainter painter(&image);
QPen pen(color);
int penWidth = size/10;
if (penWidth < 2)
penWidth = 2;
pen.setWidth(penWidth);
painter.setPen(pen);
const int sizeHalf = size / 2;
QPointF center(sizeHalf, sizeHalf);
// circle
if (filled)
painter.setBrush(color);
painter.drawEllipse(center, sizeHalf * 0.5, sizeHalf * 0.5);
// lines
QLine newLine(0, sizeHalf, size / 4.0, sizeHalf);
painter.drawLine(newLine);
QTransform trans;
trans.translate(sizeHalf, sizeHalf);
trans.rotate(45);
trans.translate(-sizeHalf, -sizeHalf);
// 8 are required, one is already draw, so 7:
for (int i=0; i<7; ++i)
{
newLine = trans.map(newLine);
painter.drawLine(newLine);
}
painter.end();
return image;
}
class NuclearAgentImpl::Private
{
public:
Private() = default;
~Private() = default;
// ESRI data:
// Esri::ArcGISRuntime::GraphicsOverlay *m_graphicsLayer = nullptr;
// Own data:
MapImpl *m_mapImpl{nullptr};
QString m_logicalLayer;
QString m_debugInfo; // will be appended by consecutive number
UniqueMapId m_uniqueMapId{INVALID_MAP_ID};
GraphicalObjectPictureMarker *m_centerImage{nullptr};
struct ValueDataNA
{
QSharedPointer<BasicPathObjectImpl> basicPathObj;
NuclearAgent::OptionalData optData;
};
QMap<int, ValueDataNA> m_cont; /// one polyline per subsidiary line
using MAP_IT_T = QMapIterator<int, ValueDataNA>;
// int m_drawOrder = 0;
bool hasPathObject(int key) const { return m_cont.contains(key); }
QList<int> keysInUse() const { return m_cont.keys(); }
void remove(int key) { m_cont.remove(key); }
void clear() { m_cont.clear(); }
ValueDataNA getPathObject(int key, const OptionalData &optData = OptionalData())
{
auto ret = m_cont.value(key); // copy
if (ret.basicPathObj.isNull())
{
QString debugInfo = QStringLiteral("%1#SubsidiaryLine(%2)").arg(m_debugInfo).arg(key);
NAgentLocalBasicPathObject *temp = new NAgentLocalBasicPathObject(debugInfo);
GraphicalObjectPathType pathType = GraphicalObjectPathType::Polyline;
if (optData.closed)
pathType = GraphicalObjectPathType::Polygon;
bool success = temp->init(m_mapImpl, m_logicalLayer, pathType);
temp->setUniqueId(m_uniqueMapId);
if (success)
ret.basicPathObj = QSharedPointer<BasicPathObjectImpl>(static_cast<BasicPathObjectImpl *>(temp));
else
temp->removeMySelf();
ret.optData.closed = optData.closed;
}
// transfer optional data (line|fill) to ret and then to container _if_ set:
if (optData.lineStyle)
ret.optData.lineStyle = optData.lineStyle;
if (optData.fillStyle)
ret.optData.fillStyle = optData.fillStyle;
m_cont.insert(key, ret);
return ret;
}
}; // class NuclearAgentImpl::Private
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
// class NuclearAgentImpl
//-----------------------------------------------------------------------------
NuclearAgentImpl::NuclearAgentImpl(const QString &debugInfo)
: NuclearAgent() // Interface
, BaseClass(debugInfo) // Implementation
, d(new Private)
, m_logger(getLogger("NuclearAgentImpl"))
{
TRACE_LOG(m_logger) << LOGFUNCTION << " START";
m_fillColorAlpha = 200;
TRACE_LOG(m_logger) << LOGFUNCTION << " END";
}
NuclearAgentImpl::~NuclearAgentImpl()
{
TRACE_LOG(m_logger) << LOGFUNCTION << " START";
delete d->m_centerImage;
delete d;
TRACE_LOG(m_logger) << LOGFUNCTION << " END";
}
void NuclearAgentImpl::setUniqueId(const UniqueMapId &uniqueId)
{
BaseClass::setUniqueId(uniqueId);
d->m_uniqueMapId = m_uniqueMapId;
}
PositionCont NuclearAgentImpl::subsidiaryLine(int key) const
{
TRACE_LOG(m_logger) << LOGFUNCTION << " START";
if (d->hasPathObject(key))
return d->getPathObject(key).basicPathObj->positions();
else
return PositionCont();
}
void NuclearAgentImpl::setSubsidiaryLine(int key, const PositionCont &positions, const OptionalData &optData)
{
TRACE_LOG(m_logger) << LOGFUNCTION << " START"
<< ", key=" << key
<< ", closed=" << optData.closed
<< ", positions.size=" << positions.size();
Private::ValueDataNA vd = d->getPathObject(key, optData);
QSharedPointer<BasicPathObjectImpl> pathObj = vd.basicPathObj;
if (pathObj)
pathObj->setPositions(positions);
TRACE_LOG(m_logger) << LOGFUNCTION << " END";
}
QList<int> NuclearAgentImpl::subsidiaryKeysInUse()
{
TRACE_LOG(m_logger) << LOGFUNCTION << " START";
TRACE_LOG(m_logger) << LOGFUNCTION << " END";
return d->keysInUse();
}
void NuclearAgentImpl::removeSubsidiaryLine(int key)
{
TRACE_LOG(m_logger) << LOGFUNCTION << " START";
TRACE_LOG(m_logger) << LOGFUNCTION << " END";
return d->remove(key);
}
void NuclearAgentImpl::removeSubsidiaryLines()
{
TRACE_LOG(m_logger) << LOGFUNCTION << " START";
TRACE_LOG(m_logger) << LOGFUNCTION << " END";
return d->clear();
}
Point3D NuclearAgentImpl::impactOrigin() const
{
return BaseClass::tacticalOrigin();
}
void NuclearAgentImpl::setImpactOrigin(const Point3D &impactOrigin)
{
BaseClass::setTacticalOrigin(impactOrigin);
}
void NuclearAgentImpl::setDetonation(const Point3D &origin, double radius)
{
TRACE_LOG(m_logger) << LOGFUNCTION << " START";
BaseClass::setDetonation(origin, radius);
TRACE_LOG(m_logger) << LOGFUNCTION << " END";
}
bool NuclearAgentImpl::hasDetonation() const
{
TRACE_LOG(m_logger) << LOGFUNCTION << " START";
TRACE_LOG(m_logger) << LOGFUNCTION << " END";
return BaseClass::hasDetonation();
}
void NuclearAgentImpl::resetDetonation()
{
TRACE_LOG(m_logger) << LOGFUNCTION << " START";
BaseClass::resetDetonation();
TRACE_LOG(m_logger) << LOGFUNCTION << " END";
}
bool NuclearAgentImpl::updateViewImpl()
{
DEBUG_LOG(m_logger) << LOGFUNCTION << " START"
<< " symbol=" << m_symbol.value().sidc
<< " visibility=" << m_visibility
<< " visiTechn=" << m_visibilityTechnical
<< " visiTact=" << m_visibilityTactical;
// centerImage:
if (!d->m_centerImage)
{
d->m_centerImage =
new GraphicalObjectPictureMarker(m_mapImpl->getEsriGeoView(),
m_graphicsLayer,
m_debugInfo + QLatin1String("#CenterImage"),
m_uniqueMapId);
}
// if (partyChanged())
{
// QImage img = renderImpactSymbol(partyColor(), 20, true); // filled
QImage img = renderImpactSymbol(m_mainGraphicalObject->lineStyle().lineColor(), 20, true); // filled
d->m_centerImage->setImage(img);
}
// m_centerImage->setScale(m_mainGraphicalObject->scale()); // do not scale centerImage, equal to mine of MineArea
d->m_centerImage->setOrigin(m_tacticalOrigin.value().originTranslated());
d->m_centerImage->setVisibility(m_visibility && m_visibilityTechnical);
bool success = BaseClass::updateViewImpl();
if (!success)
{
ERROR_LOG(m_logger) << LOGFUNCTION << " updateViewImpl failed";
return false;
}
if (nullptr == m_mainGraphicalObject)
{
ERROR_LOG(m_logger) << LOGFUNCTION << " no m_mainGraphicalObject";
return false;
}
// subsidiary :
Private::MAP_IT_T mapIt(d->m_cont);
while (mapIt.hasNext())
{
mapIt.next();
const Private::ValueDataNA &vd = mapIt.value();
QSharedPointer<BasicPathObjectImpl> pathObj = vd.basicPathObj;
const OptionalData &optData = vd.optData;
if (pathObj)
{
// pathObj->setDebugInfo(m_mainGraphicalObject->debugInfo()); // will overwrite complete string -> skip
if (optData.lineStyle)
pathObj->setLineStyle((*optData.lineStyle.data()));
else
pathObj->setLineStyle(m_mainGraphicalObject->lineStyle());
// transfer fillStyle only if relevant:
if (pathObj->pathType() == GraphicalObjectPathType::Polygon)
{
if (optData.fillStyle)
pathObj->setFillStyle((*optData.fillStyle.data()));
else
pathObj->setFillStyle(m_mainGraphicalObject->fillStyle());
}
pathObj->setVisibility(m_visibility);
pathObj->setVisibility(ObjectAppearance::Technical, m_visibilityTechnical);
// Do not Transfer symbol. Only m_mainGraphicalObject uses ObjectAppearance::Tactical:
// pathObj->setSymbol(this->symbol());
pathObj->setVisibility(ObjectAppearance::Tactical, false);
pathObj->setPickable(m_mainGraphicalObject->pickable());
pathObj->setSelected(m_mainGraphicalObject->selected());
pathObj->setDrawOrder(m_internalDrawOrder);
success = pathObj->updateView();
if (!success)
{
int key = mapIt.key();
ERROR_LOG(m_logger) << LOGFUNCTION << " updateViewImpl failed, key=" << key;
}
}
} // while
// : subsidiary
// singleSceneMarker :
updateSingleSceneMarker(m_visibility); // inclusive updateView()
// : singleSceneMarker
TRACE_LOG(m_logger) << LOGFUNCTION << " END, success=" << success;
return success;
}
bool NuclearAgentImpl::init(MapImpl *mapImpl, const QString &logicalLayerName)
{
TRACE_LOG(m_logger) << LOGFUNCTION << " START";
if (mapImpl)
{
switch (mapImpl->symbologyType())
{
case AdvancedSymbology::SymbologyType::APP6D:
case AdvancedSymbology::SymbologyType::MIL2525D:
m_symbol.refValue().sidc = AdvancedSymbology::SidcCodec::encodeComplete(mapImpl->symbologyType(), "10012500002719000000"); // SymbolSet = 25 271900
break;
case AdvancedSymbology::SymbologyType::MIL2525C:
m_symbol.refValue().sidc = AdvancedSymbology::SidcCodec::encodeComplete(mapImpl->symbologyType(), "GUMPNR----"); // MIL2525D: 1388 GUMPNR---- -> Polygon (Radioactive Area U)
// m_symbol.refValue().sidc = AdvancedSymbology::SidcCodec::encodeComplete(mapImpl->symbologyType(),"GUMPNZ----"); // MIL2525D: 0359 GUMPNZ---- -> Point (Nuclear Detonations Ground Zero U)
break;
case AdvancedSymbology::SymbologyType::APP6B:
m_symbol.refValue().sidc = AdvancedSymbology::SidcCodec::encodeComplete(mapImpl->symbologyType(), "GUCPBWR---"); // APP6B: 3935 GUCPBWR--- -> Polygon
// m_symbol.refValue().sidc = AdvancedSymbology::SidcCodec::encodeComplete(mapImpl->symbologyType(),"GUCPBWP---"); // APP6B: 2871 GUCPBWP--- -> Point (Fallout Producing U)
break;
case AdvancedSymbology::SymbologyType::None:
// empty
break;
} // switch
} // if (mapImpl)
bool success = BaseClass::init(mapImpl, logicalLayerName, GraphicalObjectPathType::Polygon);
setLineStyle(LineStyle(Qt::yellow, 2));
setFillStyle(FillStyle(Qt::yellow, FillPattern::Null));
if (!success)
ERROR_LOG(m_logger) << LOGFUNCTION << " init failed";
// set some values to Private:
d->m_mapImpl = m_mapImpl;
d->m_logicalLayer = m_logicalLayerName;
d->m_debugInfo = m_debugInfo;
d->m_uniqueMapId = m_uniqueMapId;
TRACE_LOG(m_logger) << LOGFUNCTION << " END, success=" << success;
return success;
}
bool NuclearAgentImpl::onMapExtentChanged()
{
TRACE_LOG(m_logger) << LOGFUNCTION << " START";
bool successCenterImage = true;
if (d->m_centerImage)
{
bool visiScale = m_visibilityScaleRange.scaleHasVisibility(m_mapImpl->scale());
d->m_centerImage->setVisibility(visiScale && m_visibility && m_visibilityTechnical);
successCenterImage = d->m_centerImage->updateView();
}
bool success = BaseClass::onMapExtentChanged() && successCenterImage;
TRACE_LOG(m_logger) << LOGFUNCTION << " END, success=" << success;
return success;
}
} // namespace SituationMap
+106
View File
@@ -0,0 +1,106 @@
/**
* @RDE_HEADER@
* Interface-Implementation of NuclearAgent
* $Id$
* $HeadURL$
* $Author$
*/
#pragma once
// Own
#include "abstract_multi_point_map_object_impl.h"
#include "basic_path_object_impl.h"
#include <MapObjects/nuclear_agent.h> // Interface
// Qt
#include <QString>
//----------------------------------------------------------------------------
namespace SituationMap
{
/**
* @brief The NuclearAgentImpl class displays a nuclear area. The outline is displayed as well a subsidiary lines.
*
* A class instance consists of the following logical elements:
* - mainGraphicalObject (GraphicalObjectPath displaying the main techn. Appearance / outline)
* - mainGraphicalObjectText (displaying the text/name)
* - tacticalAppearance (displaying the tact. Appearance)
* - Container of BasicPathObjectImpl's to display the subsidiary lines.
*/
// inherent 'public', to get that implementation
// inherent 'public virtual' to get that interface
class SITUATIONMAPOBJECTS_EXPORT NuclearAgentImpl : public BasicPathObjectImpl, public virtual NuclearAgent
{
using BaseClass = BasicPathObjectImpl;
template <typename> friend class GenericObjectFactory;
protected:
explicit NuclearAgentImpl(const QString &debugInfo = QString());
virtual ~NuclearAgentImpl();
public:
NuclearAgentImpl(const NuclearAgentImpl &other) = delete;
NuclearAgentImpl &operator=(NuclearAgentImpl &other) = delete;
void setUniqueId(const UniqueMapId &uniqueId) override;
/*! \name Subsidiary polylines, identified by an arbitrary choose key.*/
//@{
PositionCont subsidiaryLine(int key) const override;
void setSubsidiaryLine(int key, const PositionCont &positions, const OptionalData &optData = OptionalData()) override;
QList<int> subsidiaryKeysInUse() override;
void removeSubsidiaryLine(int key) override;
void removeSubsidiaryLines() override;
//@}
/*! \name Impact*/
//@{
Point3D impactOrigin() const override;
void setImpactOrigin(const Point3D &impactOrigin) override;
//@}
/*! \name Single Detonation */
//@{
void setDetonation(const Point3D &origin, double radius) override;
bool hasDetonation() const override;
void resetDetonation() override;
//@}
protected:
bool updateViewImpl() override;
friend class MapImpl;
bool init(MapImpl *mapImpl, const QString &logicalLayerName) override;
bool onMapExtentChanged() override;
// internal/admin
// logical
private:
class Private;
/**
* The private d->pointer to not break BC when changing internals of this class
*/
Private *d = nullptr;
LOGGER_T m_logger; ///< Interface of the Logging-Facility
};
} // namespace SituationMap
File diff suppressed because it is too large. Load diff
+293
View File
@@ -0,0 +1,293 @@
/**
* @RDE_HEADER@
* Interface-Implementation of Participant
* $Id$
* $HeadURL$
* $Author$
*/
#pragma once
// Own
#include <MapObjects/participant.h> // Interface
#include <MapImpl/abstract_map_object_impl.h>
#include <MapImpl/coordinate_translation.h>
#include <GraphicalObjects/graphical_object_range.h>
#include <GraphicalObjects/graphical_object_text.h>
#include <GraphicalObjects/graphical_object_path.h>
#include <GraphicalObjects/graphical_object_picture_marker.h>
#include <Common/simple_value.h>
#include "situation_map_objects_export.h"
// Qt
#include <QString>
#include <QColor>
#include <QSet>
#include <QSharedPointer>
// forward:
//----------------------------------------------------------------------------
namespace SituationMap
{
// forward:
class BasicPathObjectImpl;
class ParticipantImplMessage;
struct TextModifierData
{
QString text;
GraphicalObjectText *goText = nullptr;
QPoint offset;
HorizontalAlignment horizontalAlignment = HorizontalAlignment::Left;
VerticalAlignment verticalAlignment = VerticalAlignment::Bottom;
bool visible = true;
};
// inherent 'public', to get that implementation
// inherent 'public virtual' to get that interface
/**
* @brief The ParticipantImpl class implements the Participant.
*
* @internal Internal: Though this class derives from AbstractMapObject like many others this class is special.
* In contrast to most other sub classes the Participant does NOT call some baseclass methods (like updateView):
*/
class SITUATIONMAPOBJECTS_EXPORT ParticipantImpl : public AbstractMapObjectImpl, public virtual Participant
{
using BaseClass = AbstractMapObjectImpl;
template <typename> friend class GenericObjectFactory;
friend class FunctionalAreaImpl;
protected:
explicit ParticipantImpl(const QString &debugInfo = QString());
virtual ~ParticipantImpl();
public:
void initTextModifierData();
ParticipantImpl(const ParticipantImpl &other) = delete;
ParticipantImpl &operator=(ParticipantImpl &other) = delete;
void setDebugInfo(const QString &debugInfo) override;
QString toString() const override;
// Data access:
Point3D origin() const override;
bool setOrigin(const Point3D &origin) override;
/*! Just to enable using as AES item (template@AdapterDds) !*/
void setPositions(const PositionCont &posCont) override;
void boundingBox(BoundingBox &bbox) const override;
QColor majorColor() const override;
float userSymbolOpacity() const override;
void setUserSymbolOpacity(float userSymbolOpacity) override;
SymbolDataToRender symbolDataToRender(bool ignoreForcedColor = true) const override;
QImage actualImage() const override;
AdvancedSymbology::SymbologyType symbologyType() const override;
// Scale : ('overload' AbstractMapObjectImpl)
float scale() const override;
void setScale(float scale) override;
// : Scale
QString textModifier(TextModifier textModifier) const override;
void setTextModifier(TextModifier textModifier, const QString &text) override;
bool textModifierVisibility(TextModifier textModifier) const override;
void setTextModifierVisibility(TextModifier textModifier, bool visible) override;
Injury injury() const override;
QColor injuryColor() const override;
bool setInjury(Injury injury, const QColor &injuryColor) override; ///< Attention: 'Qt::red' is an int
int injuryPartyId() const override;
bool setInjury(Injury injury, int partyId) override; ///< Attention: 'Qt::red' is an int
bool setPartyIdChanged(int partyId = -1) override;
bool additionalSymbol(AdditionalSymbolType additionalSymbolType) const override;
bool setAdditionalSymbol(AdditionalSymbolType additionalSymbolType, bool newState) override;
bool isMarked() const override;
bool setMarked(bool marked) override;
/*! \name DirectionIndicator like Turret Alignment*/
//@{
void setDirectionIndicator(int key, const DirectionIndicatorData &data) override;
void removeDirectionIndicator(int key = -1) override;
bool isDirectionIndicatorsVisible() const override;
void setDirectionIndicatorsVisibility(bool visible) override;
//@}
QVector<int> ranges() const override;
bool setRanges(const QVector<int> &ranges) override;
bool isRangesVisible() const override;
void setRangesVisibility(bool visible) override;
bool setDesignations(const QVector<DesignationData> &designations) override;
bool isMovementTrackEnabled() const override;
void setMovementTrackEnabled(bool enable) override;
void setMovementTrack(const PositionCont &movementTrack) override;
void addToMovementTrack(const Point3D &addToMovementTrack) override;
PositionCont movementTrack() const override;
int sizeOfMovementTrack() const override;
bool isMovementTrackVisible() const override;
void setMovementTrackVisibility(bool enable) override;
// CHECK :
QString identifier() const override { return QString();}
virtual void setIdentifier(const QString &identifier) override { Q_UNUSED(identifier); }
void setVisibility(ObjectAppearance appearance, bool visibility) override { Q_UNUSED(appearance); Q_UNUSED(visibility);}
// : CHECK
int numberOfValuesChanged(); ///< For Unit/Module Test
protected:
friend class MapImpl;
private:
protected:
bool updateViewImplPre() override { return true; } // no tactical Appearance is necessary
bool updateViewImpl() override;
bool updateViewImplTextModifier();
bool updateViewImplDirectionIndicators();
bool updateViewImplRanges();
bool updateViewImplDesignation();
bool updateViewImplPost() override
{
// reset changed flags:
BaseClass::updateViewImplPost();
m_userSymbolOpacity.reset();
m_scale.reset();
m_injuryData.changed = false;
m_marked.reset();
m_directionIndicatorsVisibility.reset();
m_ranges.reset();
m_extensionsChanged = false;
m_designationData.reset();
return true;
}
bool init(MapImpl *mapImpl, const QString &logicalLayerName) override;
// internal/admin
void onSymbolResultReady();
// logical
OriginTranslated m_origin;
double m_height = 0;
SimpleValue<float> m_userSymbolOpacity = 1.0; // 0..1
SimpleValue<float> m_scale = 1.0; // 'overload' AbstractMapObjectImpl
public:
const QColor &partyColor() const override;
QColor partyColor(int partyId, bool isOutOfDate = false) const override;
protected:
TextModifierData m_textModifierCont[static_cast<int>(TextModifier::END)];
// Extensions :
struct InjuryData
{
SituationMap::Injury injury = SituationMap::Injury::NoInjury;
QColor injuryColor;
int injuryPartyId = -1;
bool changed = true;
void resetChanged() { changed = true; }
bool partyIdValid() const
{
return injuryPartyId >= 0;
}
};
InjuryData m_injuryData;
const QColor &injuryColorInternal();
QSet<AdditionalSymbolType> m_additionalSymbols;
SimpleValue<bool> m_marked = false;
SymbolDataToRender m_symDataToRender;
float m_scale4XmlSymbolWithSymbolSpecificScale = 0;
QMap<int, DirectionIndicatorData> m_directionIndicatorCont;
QSharedPointer<GraphicalObjectPictureMarker> m_directionIndicatorPms;
SimpleValue<bool> m_directionIndicatorsVisibility = true;
SimpleValue< QVector<int> > m_ranges;
bool m_rangesVisibility = false;
QVector< QSharedPointer<GraphicalObjectRange> > m_graphObjRanges;
SimpleValue< QVector<Participant::DesignationData> > m_designationData; // Key = PRF Code
QVector<QSharedPointer<BasicPathObjectImpl>> m_designationMapObjects;
PositionsTranslated m_movementTrackCoords;
bool m_movementTrackEnabled = false;
bool m_movementTrackVisibility = true;
QSharedPointer<GraphicalObjectPath> m_movementTrack;
bool m_extensionsChanged = true;
// : Extensions
AdvancedSymbology::SymbolDictionary *m_dictionary = nullptr;
AdvancedSymbology::SymbolResultWatcher m_symbolResultWatcher;
private:
LOGGER_T m_logger; ///< Interface of the Logging-Facility
// Forbid some overloaded methods without effects of this object:
// virtual QString identifier() const { return QString();};
// virtual void setIdentifier(const QString& identifier) { Q_UNUSED(identifier); };
// virtual bool visibility(ObjectAppearance appearance) const { Q_UNUSED(appearance); return true;};
// virtual void setVisibility(ObjectAppearance appearance, bool visibility) { Q_UNUSED(appearance); Q_UNUSED(appearance);};
};
} // namespace SituationMap
+370
View File
@@ -0,0 +1,370 @@
/**
* @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
+110
View File
@@ -0,0 +1,110 @@
/**
* @RDE_HEADER@
* PathContainer
* $Id$
* $HeadURL$
* $Author$
*/
#pragma once
// Own
#include <Map/situation_map_types.h>
#include <Common/situation_map_logging.h>
#include <Map/line_style.h>
#include <Map/fill_style.h>
// Qt
#include <QImage>
#include <QMap>
#include <QVariant>
// forward:
namespace Esri
{
namespace ArcGISRuntime
{
class GeoView;
class GraphicsOverlay;
}
}
//----------------------------------------------------------------------------
namespace SituationMap
{
// Forward:
class CoordTranslationFunctor;
class PathData;
enum class GraphicalObjectPathType;
class PathContainer : public QObject
{
Q_OBJECT
public:
explicit PathContainer(const Esri::ArcGISRuntime::GeoView *geoView,
Esri::ArcGISRuntime::GraphicsOverlay *graphicsLayer,
CoordTranslationFunctor *coordTransFunctor,
const UniqueMapId &uniqueMapId);
explicit PathContainer(const GraphicalObjectPathType pathType,
const Esri::ArcGISRuntime::GeoView *geoView,
Esri::ArcGISRuntime::GraphicsOverlay *graphicsLayer,
CoordTranslationFunctor *coordTransFunctor,
const UniqueMapId &uniqueMapId);
virtual ~PathContainer();
PathContainer(const PathContainer &other) = delete;
PathContainer &operator=(PathContainer &other) = delete;
QString debugInfo() const;
void setDebugInfo(const QString &debugInfo);
// Marker :
virtual PositionCont path(int idx) const;
virtual bool setPath(int idx, const PositionCont &path);
virtual void clear(int idx);
virtual void clearAll();
virtual LineStyle lineStyle() const;
virtual void setLineStyle(const LineStyle &lineStyle);
virtual FillStyle fillStyle() const;
virtual void setFillStyle(const FillStyle &fillStyle);
virtual int drawOrder() const;
virtual void setDrawOrder(int drawOrder);
virtual bool selected() const;
virtual void setSelected(bool selected);
virtual bool visibility(int idx) const;
virtual void setVisibility(int idx, bool onOff);
virtual int getPathCount() const;
virtual QList<int> getIndicationIndexList() const;
virtual bool updateView();
public slots:
private:
LOGGER_T m_logger; ///< Interface of the Logging-Facility
class Private;
/**
* The private d->pointer to not break BC when changing internals of this class
*/
Private *d = nullptr;
};
} // namespace SituationMap
+75
View File
@@ -0,0 +1,75 @@
/**
* @RDE_HEADER@
* Interface-Implementation of Polygon
* $Id$
* $HeadURL$
* $Author$
*/
// Own
#include "polygon_impl.h"
#include <MapImpl/map_impl.h>
#include <GraphicalObjects/graphical_object_path.h>
// ESRI
// Qt
namespace SituationMap
{
//-----------------------------------------------------------------------------
// class PolygonImpl
//-----------------------------------------------------------------------------
PolygonImpl::PolygonImpl(const QString &debugInfo)
: Polygon() // Interface
, BaseClass(debugInfo) // Implementation
, m_logger(getLogger("PolygonImpl"))
{
TRACE_LOG(m_logger) << LOGFUNCTION << " START";
TRACE_LOG(m_logger) << LOGFUNCTION << " END";
}
PolygonImpl::~PolygonImpl()
{
TRACE_LOG(m_logger) << LOGFUNCTION << " START";
TRACE_LOG(m_logger) << LOGFUNCTION << " END";
}
bool PolygonImpl::updateViewImpl()
{
TRACE_LOG(m_logger) << LOGFUNCTION << " START"
<< " visibility=" << m_visibility
<< " visiTechn=" << m_visibilityTechnical
<< " visiTact=" << m_visibilityTactical;
bool success = BaseClass::updateViewImpl();
if (!success)
ERROR_LOG(m_logger) << LOGFUNCTION << " updateViewImpl failed";
TRACE_LOG(m_logger) << LOGFUNCTION << " END, success=" << success;
return success;
}
bool PolygonImpl::init(MapImpl *mapImpl, const QString &logicalLayerName)
{
TRACE_LOG(m_logger) << LOGFUNCTION << " START";
bool success = BaseClass::init(mapImpl, logicalLayerName, GraphicalObjectPathType::Polygon);
if (!success)
ERROR_LOG(m_logger) << LOGFUNCTION << " init failed";
TRACE_LOG(m_logger) << LOGFUNCTION << " END, success=" << success;
return success;
}
} // namespace SituationMap
+69
View File
@@ -0,0 +1,69 @@
/**
* @RDE_HEADER@
* Interface-Implementation of Polygon
* $Id$
* $HeadURL$
* $Author$
*/
#pragma once
// Own
#include "abstract_multi_point_map_object_impl.h"
#include "basic_path_object_impl.h"
#include <MapObjects/polygon.h> // Interface
// Qt
#include <QString>
//----------------------------------------------------------------------------
namespace SituationMap
{
/**
* @brief The PolygonImpl class displays a polygon.
*
* A class instance consists of the following logical elements:
* - mainGraphicalObject (GraphicalObjectPath displaying the line)
*/
// inherent 'public', to get that implementation
// inherent 'public virtual' to get that interface
class SITUATIONMAPOBJECTS_EXPORT PolygonImpl : public BasicPathObjectImpl, public virtual Polygon
{
using BaseClass = BasicPathObjectImpl;
template <typename> friend class GenericObjectFactory;
protected:
explicit PolygonImpl(const QString &debugInfo = QString());
virtual ~PolygonImpl();
public:
PolygonImpl(const PolygonImpl &other) = delete;
PolygonImpl &operator=(PolygonImpl &other) = delete;
// void setScale(float) override {}
protected:
virtual bool updateViewImpl() override;
friend class MapImpl;
bool init(MapImpl *mapImpl, const QString &logicalLayerName) override;
// internal/admin
// logical
private:
LOGGER_T m_logger; ///< Interface of the Logging-Facility
};
} // namespace SituationMap
+115
View File
@@ -0,0 +1,115 @@
/**
* @RDE_HEADER@
* Interface-Implementation of Polyline
* $Id$
* $HeadURL$
* $Author$
*/
// Own
#include "polyline_impl.h"
#include <MapImpl/map_impl.h>
#include <GraphicalObjects/graphical_object_path.h>
// ESRI
// Qt
namespace SituationMap
{
//-----------------------------------------------------------------------------
// class PolylineImpl
//-----------------------------------------------------------------------------
PolylineImpl::PolylineImpl(const QString &debugInfo)
: Polyline() // Interface
, BaseClass(debugInfo) // Implementation
, m_logger(getLogger("PolylineImpl"))
{
TRACE_LOG(m_logger) << LOGFUNCTION << " START";
TRACE_LOG(m_logger) << LOGFUNCTION << " END";
}
PolylineImpl::~PolylineImpl()
{
TRACE_LOG(m_logger) << LOGFUNCTION << " START";
TRACE_LOG(m_logger) << LOGFUNCTION << " END";
}
bool PolylineImpl::arrowHeadStart() const
{
TRACE_LOG(m_logger) << LOGFUNCTION << " START";
TRACE_LOG(m_logger) << LOGFUNCTION << " END";
return BaseClass::arrowHeadStart();
}
void PolylineImpl::setArrowHeadStart(bool enable)
{
TRACE_LOG(m_logger) << LOGFUNCTION << " START";
BaseClass::setArrowHeadStart(enable);
TRACE_LOG(m_logger) << LOGFUNCTION << " END";
}
bool PolylineImpl::arrowHeadEnd() const
{
TRACE_LOG(m_logger) << LOGFUNCTION << " START";
TRACE_LOG(m_logger) << LOGFUNCTION << " END";
return BaseClass::arrowHeadEnd();
}
void PolylineImpl::setArrowHeadEnd(bool enable)
{
TRACE_LOG(m_logger) << LOGFUNCTION << " START";
BaseClass::setArrowHeadEnd(enable);
TRACE_LOG(m_logger) << LOGFUNCTION << " END";
}
QString PolylineImpl::textOnSegment(uint segment) const
{
return BaseClass::textOnSegment(segment);
}
void PolylineImpl::setTextOnSegment(uint segment, const QString &segmentText)
{
BaseClass::setTextOnSegment(segment, segmentText);
}
void PolylineImpl::clearTextOnSegment(uint segment)
{
BaseClass::clearTextOnSegment(segment);
}
bool PolylineImpl::updateViewImpl()
{
TRACE_LOG(m_logger) << LOGFUNCTION << " START"
<< " visibility=" << m_visibility
<< " visiTechn=" << m_visibilityTechnical
<< " visiTact=" << m_visibilityTactical;
bool success = BaseClass::updateViewImpl();
if (!success)
ERROR_LOG(m_logger) << LOGFUNCTION << " updateViewImpl failed";
TRACE_LOG(m_logger) << LOGFUNCTION << " END, success=" << success;
return success;
}
bool PolylineImpl::init(MapImpl *mapImpl, const QString &logicalLayerName)
{
TRACE_LOG(m_logger) << LOGFUNCTION << " START";
bool success = BaseClass::init(mapImpl, logicalLayerName, GraphicalObjectPathType::Polyline);
if (!success)
ERROR_LOG(m_logger) << LOGFUNCTION << " init failed";
TRACE_LOG(m_logger) << LOGFUNCTION << " END, success=" << success;
return success;
}
} // namespace SituationMap
+81
View File
@@ -0,0 +1,81 @@
/**
* @RDE_HEADER@
* Interface-Implementation of Polyline
* $Id$
* $HeadURL$
* $Author$
*/
#pragma once
// Own
#include "abstract_multi_point_map_object_impl.h"
#include "basic_path_object_impl.h"
#include <MapObjects/polyline.h> // Interface
// Qt
#include <QString>
//----------------------------------------------------------------------------
namespace SituationMap
{
/**
* @brief The PolylineImpl class displays a polyline.
*
* A class instance consists of the following logical elements:
* - mainGraphicalObject (GraphicalObjectPath displaying the line)
*/
// inherent 'public', to get that implementation
// inherent 'public virtual' to get that interface
class SITUATIONMAPOBJECTS_EXPORT PolylineImpl : public BasicPathObjectImpl, public virtual Polyline
{
using BaseClass = BasicPathObjectImpl;
template <typename> friend class GenericObjectFactory;
protected:
explicit PolylineImpl(const QString &debugInfo = QString());
virtual ~PolylineImpl();
public:
PolylineImpl(const PolylineImpl &other) = delete;
PolylineImpl &operator=(PolylineImpl &other) = delete;
// void setScale(float) override {}
/*! \name ArrowHeads */
//@{
bool arrowHeadStart() const override;
void setArrowHeadStart(bool enable) override;
bool arrowHeadEnd() const override;
void setArrowHeadEnd(bool enable) override;
//@}
QString textOnSegment(uint segment) const override;
void setTextOnSegment(uint segment, const QString &segmentText) override;
void clearTextOnSegment(uint segment) override;
protected:
virtual bool updateViewImpl() override;
friend class MapImpl;
bool init(MapImpl *mapImpl, const QString &logicalLayerName) override;
// internal/admin
// logical
private:
LOGGER_T m_logger; ///< Interface of the Logging-Facility
};
} // namespace SituationMap
+22
View File
@@ -0,0 +1,22 @@
/* XPM */
static const char * position_marker_xpm[] =
{
"15 15 2 1",
" c None",
". c #FB0000",
" . ",
" . ",
" . ",
" . ",
" . ",
" . ",
" . ",
"...............",
" . ",
" . ",
" . ",
" . ",
" . ",
" . ",
" . "
};
+323
View File
@@ -0,0 +1,323 @@
/**
* @RDE_HEADER@
* Interface-Implementation of SingleFire
* $Id$
* $HeadURL$
* $Author$
*/
// Own
#include "single_fire_impl.h"
#include <MapImpl/map_impl.h>
#include <Map/party_id_to_color_functor.h>
#include <GraphicalObjects/graphical_object_ellipse.h>
#include <GraphicalObjects/tactical_appearance.h>
#include <Symbology/sidc_codec.h>
// ESRI
// Qt
#include <QPainter>
#include <QPen>
namespace SituationMap
{
static int s_gunToTargetLine3DKEY = -1;
static int s_gunToTargetLineSurfaceKEY = 0;
static int s_nonLethalAreaKEY = 1;
//-----------------------------------------------------------------------------
// class SingleFireImpl
//-----------------------------------------------------------------------------
SingleFireImpl::SingleFireImpl(const QString &debugInfo)
: SingleFire() // Interface
, BaseClass(debugInfo) // Implementation
, m_logger(getLogger("SingleFireImpl"))
{
TRACE_LOG(m_logger) << LOGFUNCTION << " START";
m_fillColorAlpha = 200;
TRACE_LOG(m_logger) << LOGFUNCTION << " END";
}
SingleFireImpl::~SingleFireImpl()
{
TRACE_LOG(m_logger) << LOGFUNCTION << " START";
delete m_centerImage;
TRACE_LOG(m_logger) << LOGFUNCTION << " END";
}
QString SingleFireImpl::toString() const
{
QString str;
str.append(BaseClass::toString());
str.append(BasicPathObjectImpl::toString());
return str;
}
Point3D SingleFireImpl::impactOrigin() const
{
return BaseClass::tacticalOrigin();
}
void SingleFireImpl::setImpactOrigin(const Point3D &impactOrigin)
{
BaseClass::setTacticalOrigin(impactOrigin);
}
SingleFire::ImpactType SingleFireImpl::impactType() const
{
return m_impactType.value();
}
void SingleFireImpl::setImpactType(SingleFire::ImpactType impactType)
{
m_impactType = impactType;
}
Point3D SingleFireImpl::origin() const
{
return BaseClass::origin();
}
void SingleFireImpl::setOrigin(const Point3D &origin)
{
BaseClass::setOrigin(origin);
}
float SingleFireImpl::radius() const
{
return BaseClass::radius();
}
void SingleFireImpl::setRadius(float radius)
{
BaseClass::setRadius(radius);
}
void SingleFireImpl::setOriginatorToTargetLineSurface(const Point3D &start, const Point3D &end)
{
TRACE_LOG(m_logger) << LOGFUNCTION << " START"
<< ", start=" << start << ", end=" << end << ", debugInfo=" << m_debugInfo;
PathContainer &path = this->rPathContainer(); // should be SP::Draped
path.setDebugInfo(m_debugInfo + QStringLiteral("SpDraped"));
if (start.isNull() && end.isNull())
{
path.clear(s_gunToTargetLineSurfaceKEY);
} else {
LineStyle ls = m_mainGraphicalObject->lineStyle();
ls.setLinePattern(LinePattern::Dash);
ls.setLineWidth(2);
path.setLineStyle(ls);
path.setPath(s_gunToTargetLineSurfaceKEY, {start, end});
}
TRACE_LOG(m_logger) << LOGFUNCTION << " END"
<< ", start=" << start << ", end=" << end << ", debugInfo=" << m_debugInfo;
}
AesEffectState SingleFireImpl::aesState() const
{
return BaseClass::aesState();
}
void SingleFireImpl::setAesState(AesEffectState aesState)
{
BaseClass::setAesState(aesState);
}
SymbolImage SingleFireImpl::symbolImage() const
{
SymbolImage symImage = m_tacticalAppearance->symbolImage();
return symImage;
}
bool SingleFireImpl::updateViewImpl()
{
TRACE_LOG(m_logger) << LOGFUNCTION << " START"
<< " origin =" << this->origin() //.x() << ", " << this->origin().y()
<< " radius =" << this->radius()
<< " visibility=" << m_visibility
<< " visiTechn=" << m_visibilityTechnical
<< " visiTact=" << m_visibilityTactical;
if (m_tacticalAppearance)
{
if (partyChanged())
m_symbol.refValue().color = partyColor();
}
// centerImage:
if (!m_centerImage)
{
m_centerImage =
new GraphicalObjectPictureMarker(m_mapImpl->getEsriGeoView(),
m_graphicsLayer,
m_debugInfo + QLatin1String("#CenterImage"),
m_uniqueMapId);
m_impactType.setChanged();
}
if (m_impactType.changed() || partyChanged())
{
QImage img;
switch(m_impactType.value())
{
case SingleFire::ImpactType::normalImpact:
img = renderImpactSymbol(partyColor(), 20, true); // filled
break;
case SingleFire::ImpactType::doubleImpact:
img = renderDoubleImpactSymbol(partyColor(), 20, true); // filled
break;
} // switch
m_centerImage->setImage(img);
}
// m_centerImage->setScale(m_mainGraphicalObject->scale()); // do not scale centerImage, equal to mine of MineArea
m_centerImage->setOrigin(m_tacticalOrigin.value().originTranslated());
m_centerImage->setVisibility(m_visibility && m_visibilityTechnical);
bool success = BaseClass::updateViewImpl(); // will call onMapExtentChanged and therefore m_centerImage->updateView
if (!success)
ERROR_LOG(m_logger) << LOGFUNCTION << " updateViewImpl failed";
TRACE_LOG(m_logger) << LOGFUNCTION << " END, success=" << success;
return success;
}
bool SingleFireImpl::init(MapImpl *mapImpl, const QString &logicalLayerName)
{
TRACE_LOG(m_logger) << LOGFUNCTION << " START";
if (mapImpl)
{
switch (mapImpl->symbologyType())
{
case AdvancedSymbology::SymbologyType::MIL2525D:
m_symbol.refValue().sidc = AdvancedSymbology::SidcCodec::encodeComplete(mapImpl->symbologyType(), "10012500002108000000"); // SymbolSet = 21 270800 , 270900
break;
case AdvancedSymbology::SymbologyType::MIL2525C:
// m_symbol.refValue().m_sidc = AdvancedSymbology::SidcCodec::encodeComplete(mapImpl->symbologyType(),"GUGPGPWP--"); // 0431 GUGPGPWP-- (Predicted Impact Point U) -> Point
m_symbol.refValue().sidc = AdvancedSymbology::SidcCodec::encodeComplete(mapImpl->symbologyType(), "GUGPGPWI--"); // 0293 GHGPGPWI-- (Impact Point H) -> Point
break;
case AdvancedSymbology::SymbologyType::APP6B:
//m_symbol.refValue().sidc = AdvancedSymbology::SidcCodec::encodeComplete(mapImpl->symbologyType(),"GUOPVMM---"); // APP6B: 2564 GUOPVMM--- -> Point
m_symbol.refValue().sidc = AdvancedSymbology::SidcCodec::encodeComplete(mapImpl->symbologyType(), "GUOPVI----"); // APP6B: 2560 GUOPVI---- -> Point
break;
case AdvancedSymbology::SymbologyType::APP6D:
m_symbol.refValue().sidc = AdvancedSymbology::SidcCodec::encodeComplete(mapImpl->symbologyType(), "10012500002108000000"); // SymbolSet = 21 270800 , 270900
break;
case AdvancedSymbology::SymbologyType::None:
// empty
break;
} // switch
} // if (mapImpl)
bool success = BaseClass::init(mapImpl, logicalLayerName, GraphicalObjectPathType::Polygon);
if (!success)
ERROR_LOG(m_logger) << LOGFUNCTION << " init failed";
TRACE_LOG(m_logger) << LOGFUNCTION << " END, success=" << success;
return success;
}
bool SingleFireImpl::onMapExtentChanged()
{
TRACE_LOG(m_logger) << LOGFUNCTION << " START";
bool successCenterImage = true;
if (m_centerImage)
{
bool visiScale = m_visibilityScaleRange.scaleHasVisibility(m_mapImpl->scale());
m_centerImage->setVisibility(visiScale && m_visibility && m_visibilityTechnical);
successCenterImage = m_centerImage->updateView();
}
bool success = BaseClass::onMapExtentChanged() && successCenterImage;
TRACE_LOG(m_logger) << LOGFUNCTION << " END, success=" << success;
return success;
}
QImage SingleFireImpl::renderDoubleImpactSymbol(const QColor &color, int size, bool filled)
{
QImage finalImage(2.25*size, size, QImage::Format_ARGB32);
finalImage.fill(Qt::transparent);
const QImage &singleImg = renderImpactSymbol(color, size, filled);
QRect target = singleImg.rect();
QPainter painter(&finalImage);
// left
painter.drawImage(target, singleImg, singleImg.rect());
// right
target.moveTo(finalImage.width() - singleImg.width(), 0);
painter.drawImage(target, singleImg, singleImg.rect());
painter.end();
return finalImage;
}
QImage SingleFireImpl::renderImpactSymbol(const QColor &color, int size, bool filled)
{
QImage image(size, size, QImage::Format_ARGB32);
image.fill(Qt::transparent);
QPainter painter(&image);
QPen pen(color);
int penWidth = size/10;
if (penWidth < 2)
penWidth = 2;
pen.setWidth(penWidth);
painter.setPen(pen);
const int sizeHalf = size / 2;
QPointF center(sizeHalf, sizeHalf);
// circle
if (filled)
painter.setBrush(color);
painter.drawEllipse(center, sizeHalf * 0.5, sizeHalf * 0.5);
// lines
QLine newLine(0, sizeHalf, size / 4.0, sizeHalf);
painter.drawLine(newLine);
QTransform trans;
trans.translate(sizeHalf, sizeHalf);
trans.rotate(45);
trans.translate(-sizeHalf, -sizeHalf);
// 8 are required, one is already draw, so 7:
for (int i=0; i<7; ++i)
{
newLine = trans.map(newLine);
painter.drawLine(newLine);
}
painter.end();
return image;
}
} // namespace SituationMap
+106
View File
@@ -0,0 +1,106 @@
/**
* @RDE_HEADER@
* Interface-Implementation of SingleFire
* $Id$
* $HeadURL$
* $Author$
*/
#pragma once
// Own
#include "basic_path_object_impl.h"
#include <MapObjects/single_fire.h> // Interface
#include <GraphicalObjects/graphical_object_picture_marker.h>
// Qt
//----------------------------------------------------------------------------
namespace SituationMap
{
/**
* @brief The SingleFireImpl class displays a single impact.
*
* A class instance consists of the following logical elements:
* - mainGraphicalObject (GraphicalObjectPictureMarker / Image, displaying the main techn. Appearance)
* - mainGraphicalObjectText (displaying the text/name)
* - tacticalAppearance (displaying the tact. Appearance)
*/
// inherent 'public', to get that implementation
// inherent 'public virtual' to get that interface
class SITUATIONMAPOBJECTS_EXPORT SingleFireImpl : public BasicPathObjectImpl, public virtual SingleFire
{
using BaseClass = BasicPathObjectImpl;
template <typename> friend class GenericObjectFactory;
protected:
explicit SingleFireImpl(const QString &debugInfo = QString());
virtual ~SingleFireImpl();
public:
SingleFireImpl(const SingleFireImpl &other) = delete;
SingleFireImpl &operator=(SingleFireImpl &other) = delete;
QString toString() const override;
// some set/get methods:
Point3D impactOrigin() const override;
void setImpactOrigin(const Point3D &impactOrigin) override;
ImpactType impactType() const override;
void setImpactType(ImpactType impactType = ImpactType::normalImpact) override;
Point3D origin() const override;
void setOrigin(const Point3D &origin) override;
float radius() const override;
void setRadius(float radius) override;
void setOriginatorToTargetLineSurface(const Point3D &start, const Point3D &end) override;
// Delegate to BaseClass:
AesEffectState aesState() const override;
void setAesState(AesEffectState aesState) override;
SymbolImage symbolImage() const override;
static QImage renderDoubleImpactSymbol(const QColor &color, int size, bool filled);
static QImage renderImpactSymbol(const QColor &color, int size, bool filled);
protected:
bool updateViewImpl() override;
bool updateViewImplPost() override
{
BaseClass::updateViewImplPost();
m_impactType.reset();
return true;
}
friend class MapImpl;
bool init(MapImpl *mapImpl, const QString &logicalLayerName) override;
bool onMapExtentChanged() override;
// internal/admin
// logical
private:
LOGGER_T m_logger; ///< Interface of the Logging-Facility
SimpleValue<ImpactType> m_impactType = ImpactType::normalImpact;
GraphicalObjectPictureMarker *m_centerImage = nullptr;
};
} // namespace SituationMap
@@ -0,0 +1,21 @@
/**
* Export definitions
* $Id$
* $HeadURL$
* $Author$
*/
#pragma once
#include <qglobal.h>
#ifndef SITUATIONMAPOBJECTS_EXPORT
# ifdef BUILD_STATIC_LIBRARIES
# define SITUATIONMAPOBJECTS_EXPORT
# else
# if defined(MAKE_SITUATIONMAPOBJECTS_LIB)
# define SITUATIONMAPOBJECTS_EXPORT Q_DECL_EXPORT
# else
# define SITUATIONMAPOBJECTS_EXPORT Q_DECL_IMPORT
# endif
# endif
#endif
+193
View File
@@ -0,0 +1,193 @@
/**
* @RDE_HEADER@
* Interface-Implementation of FunctionalArea
* $Id$
* $HeadURL$
* $Author$
*/
// Own
#include "sound_area_impl.h"
#include <MapImpl/map_impl.h>
#include <GraphicalObjects/graphical_object_path.h>
#include <GraphicalObjects/graphical_object_text.h>
#include <GraphicalObjects/graphical_object_picture_marker.h>
// ESRI
// Qt
#include <QPainter>
namespace SituationMap
{
//-----------------------------------------------------------------------------
// class SoundAreaImpl
//-----------------------------------------------------------------------------
SoundAreaImpl::SoundAreaImpl(const QString &debugInfo)
: SoundArea() // Interface
, BaseClass(debugInfo) // Implementation
, m_logger(getLogger("SoundAreaImpl"))
{
TRACE_LOG(m_logger) << LOGFUNCTION << " START";
m_markerOrigin.setMapObjectImpl(this);
TRACE_LOG(m_logger) << LOGFUNCTION << " END";
}
SoundAreaImpl::~SoundAreaImpl()
{
TRACE_LOG(m_logger) << LOGFUNCTION << " START";
delete m_pictureMarker;
TRACE_LOG(m_logger) << LOGFUNCTION << " END";
}
//void SoundAreaImpl::reRenderSymbol()
//{
// BaseClass::reRenderSymbol();
// if (m_pointSymbol)
// m_pointSymbol->reRenderSymbol();
//}
Point3D SoundAreaImpl::markerOrigin() const
{
return m_markerOrigin.origin();
}
void SoundAreaImpl::setMarkerOrigin(const Point3D &origin)
{
m_markerOrigin.setOrigin(origin);
}
const MarkerData &SoundAreaImpl::markerData() const
{
return m_markerData.value();
}
void SoundAreaImpl::setMarkerData(const MarkerData &markerData)
{
m_markerData = markerData;
}
QImage SoundAreaImpl::previewImageTypical() const
{
return m_markerData.value().m_proxyImage; // maybe mainImage if it will be provided (see geo_image_impl)
}
QImage SoundAreaImpl::previewImageSpecific() const
{
QImage imageFromForm = BaseClass::previewImageSpecific();
QImage markerImage = markerData().proxyImage();
// most likely bothj are available:
if (!imageFromForm.isNull() && !markerImage.isNull())
{
// merge marker image on top:
const QSize &outerSize = imageFromForm.size();
markerImage = markerImage.scaled(outerSize/1.5, Qt::KeepAspectRatioByExpanding, Qt::SmoothTransformation);
QPainter painter(&imageFromForm);
painter.setRenderHints(QPainter::Antialiasing|QPainter::SmoothPixmapTransform);
QRect r = markerImage.rect();
int offsetX = (outerSize.width() - r.width()) / 2;
int offsetY = (outerSize.height() - r.height()) / 2;
r.moveTo(offsetX, offsetY);
painter.drawImage(r, markerImage, markerImage.rect());
return imageFromForm;
} else if (imageFromForm.isNull())
return markerImage;
return imageFromForm;
}
bool SoundAreaImpl::updateViewImpl()
{
TRACE_LOG(m_logger) << LOGFUNCTION << " START"
<< " symbol=" << m_symbol.value().sidc
<< " visibility=" << m_visibility
<< " visiTechn=" << m_visibilityTechnical
<< " visiTact=" << m_visibilityTactical;
bool success = BaseClass::updateViewImpl();
if (!success)
ERROR_LOG(m_logger) << LOGFUNCTION << " updateViewImpl failed";
if (!updateViewImplMarkerData())
ERROR_LOG(m_logger) << LOGFUNCTION << " updateViewImplPointSymbolData failed";
TRACE_LOG(m_logger) << LOGFUNCTION << " END, success=" << success;
return success;
}
bool SoundAreaImpl::updateViewImplMarkerData()
{
TRACE_LOG(m_logger) << LOGFUNCTION << " START";
if (m_markerData.changed())
{
const MarkerData &markerData = m_markerData.value();
// empty?
if (markerData.isEmpty())
{
delete m_pictureMarker;
m_pictureMarker = nullptr;
return true;
}
// ok, data available:
if (!m_pictureMarker)
{
m_pictureMarker = new GraphicalObjectPictureMarker(m_mapImpl->getEsriGeoView(),
m_graphicsLayer,
m_debugInfo + QLatin1String("#Marker"),
m_uniqueMapId);
}
if (markerData.hasMarker())
m_pictureMarker->setMarkerSymbol(markerData.m_proxyMarker,
markerData.m_proxyMarkerSize,
markerData.m_proxyMarkerColor);
else if (markerData.hasProxyImage())
m_pictureMarker->setImage(markerData.m_proxyImage,
markerData.m_proxyImageDefaultSize);
} // if (m_markerData.changed())
m_pictureMarker->setOrigin(m_markerOrigin.originTranslated());
m_pictureMarker->setPickable(m_mainGraphicalObject->pickable());
m_pictureMarker->setSelected(m_mainGraphicalObject->selected());
m_pictureMarker->setDrawOrder(m_internalDrawOrder + 1);
// m_pictureMarker->setScale();
m_pictureMarker->setVisibility(m_visibility && m_visibilityTechnical);
bool success = m_pictureMarker->updateView();
if (!success)
ERROR_LOG(m_logger) << LOGFUNCTION << " updateViewImpl failed, m_debugInfo =" << m_debugInfo;
TRACE_LOG(m_logger) << LOGFUNCTION << " END, success=" << success;
return success;
}
bool SoundAreaImpl::init(MapImpl *mapImpl, const QString &logicalLayerName)
{
TRACE_LOG(m_logger) << LOGFUNCTION << " START";
bool success = BaseClass::init(mapImpl, logicalLayerName, GraphicalObjectPathType::Polygon);
setLineStyle(LineStyle(Qt::black, 2));
if (!success)
ERROR_LOG(m_logger) << LOGFUNCTION << " init failed";
TRACE_LOG(m_logger) << LOGFUNCTION << " END, success=" << success;
return success;
}
} // namespace SituationMap
+89
View File
@@ -0,0 +1,89 @@
/**
* @RDE_HEADER@
* Interface-Implementation of FunctionalArea
* $Id$
* $HeadURL$
* $Author$
*/
#pragma once
// Own
#include "abstract_multi_point_map_object_impl.h"
#include "basic_path_object_impl.h"
#include <MapObjects/sound_area.h> // Interface
// Qt
#include <QImage>
//----------------------------------------------------------------------------
namespace SituationMap
{
// forward:
/**
* @brief The SoundAreaImpl class displays a sound area and an image.
*
* A class instance consists of the following logical elements:
* - mainGraphicalObject (GraphicalObjectPath displaying the main techn. Appearance)
* - mainGraphicalObjectText (displaying the text/name)
*/
// inherent 'public', to get that implementation
// inherent 'public virtual' to get that interface
class SITUATIONMAPOBJECTS_EXPORT SoundAreaImpl : public BasicPathObjectImpl, public virtual SoundArea
{
using BaseClass = BasicPathObjectImpl;
template <typename> friend class GenericObjectFactory;
protected:
explicit SoundAreaImpl(const QString &debugInfo = QString());
virtual ~SoundAreaImpl();
public:
SoundAreaImpl(const SoundAreaImpl &other) = delete;
SoundAreaImpl &operator=(SoundAreaImpl &other) = delete;
// void reRenderSymbol() override;
/*! \name Marker / Point symbol*/
//@{
Point3D markerOrigin() const override;
void setMarkerOrigin(const Point3D &origin) override;
const MarkerData &markerData() const override;
void setMarkerData(const MarkerData &markerData) override;
//@}
QImage previewImageTypical() const override;
QImage previewImageSpecific() const override;
protected:
bool updateViewImpl() override;
bool updateViewImplMarkerData();
friend class MapImpl;
bool init(MapImpl *mapImpl, const QString &logicalLayerName) override;
// internal/admin
private:
// logical
OriginTranslated m_markerOrigin;
SimpleValue<MarkerData> m_markerData;
GraphicalObjectPictureMarker *m_pictureMarker{nullptr};
LOGGER_T m_logger; ///< Interface of the Logging-Facility
};
} // namespace SituationMap
+149
View File
@@ -0,0 +1,149 @@
/**
* @RDE_HEADER@
* Interface-Implementation of Text
* $Id$
* $HeadURL$
* $Author$
*/
// Own
#include "text_impl.h"
#include <MapImpl/map_impl.h>
#include <GraphicalObjects/graphical_object_path.h>
#include <GraphicalObjects/stub_graphical_object.h>
#include <GraphicalObjects/graphical_object_picture_marker.h>
#include <GraphicalObjects/graphical_object_text.h>
// ESRI
// Qt
#include <QString>
#include "position_marker.xpm"
namespace SituationMap
{
//-----------------------------------------------------------------------------
// constants
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
// Utils:
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
// class TextImpl
//-----------------------------------------------------------------------------
TextImpl::TextImpl(const QString &debugInfo)
: Text() // Interface
, BaseClass(debugInfo) // Implementation
, m_showAnchorMarker(false)
, m_anchorMarker(nullptr)
, m_logger(getLogger("TextImpl"))
{
TRACE_LOG(m_logger) << LOGFUNCTION << " START";
m_visibilityScaleRange.resetToMax();
TRACE_LOG(m_logger) << LOGFUNCTION << " END";
}
TextImpl::~TextImpl()
{
TRACE_LOG(m_logger) << LOGFUNCTION << " START";
delete m_anchorMarker;
TRACE_LOG(m_logger) << LOGFUNCTION << " END";
}
void TextImpl::setShowAnchorMarker(bool on)
{
if (on == m_showAnchorMarker)
return;
m_showAnchorMarker = on;
if (on)
{
static QImage markerSymbol;
if (markerSymbol.isNull())
markerSymbol = QImage(position_marker_xpm);
m_anchorMarker = new GraphicalObjectPictureMarker(m_mapImpl->getEsriGeoView(),
m_graphicsLayer,
QLatin1String("AnchorMarker"),
INVALID_MAP_ID);
m_anchorMarker->setImage(markerSymbol);
}
else
{
delete m_anchorMarker;
m_anchorMarker = nullptr;
}
} // TextImpl::setShowAnchorMarker
bool TextImpl::showAnchorMarker() const { return m_showAnchorMarker; }
bool TextImpl::updateViewImpl()
{
TRACE_LOG(m_logger) << LOGFUNCTION << " START"
<< " visibility=" << m_visibility;
// put translated origin to stub. Later GOText will takeover the (translated) origin.
if (m_mainGraphicalObject) m_mainGraphicalObject->setOrigin(originTranslated());
bool success = BaseClass::updateViewImpl();
if (m_anchorMarker)
{
m_anchorMarker -> setSelected(m_selected);
m_anchorMarker -> setDrawOrder(m_internalDrawOrder);
m_anchorMarker -> setOrigin(m_mainGraphicalObjectText->origin());
m_anchorMarker -> setVisibility(m_mainGraphicalObjectText->visibility());
m_anchorMarker -> updateView();
}
if (!success)
ERROR_LOG(m_logger) << LOGFUNCTION << " updateViewImpl failed";
TRACE_LOG(m_logger) << LOGFUNCTION << " END, success=" << success;
return success;
}
bool TextImpl::init(MapImpl *mapImpl, const QString &logicalLayerName)
{
TRACE_LOG(m_logger) << LOGFUNCTION << " START";
bool success = BaseClass::init(mapImpl, logicalLayerName);
if (success)
{
/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
* Use the StubGraphicalObject, which is doing nothing of the work, because
* the text will be rendered using m_mainGraphicalObjectText
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
m_mainGraphicalObject = new StubGraphicalObject();
}
else
ERROR_LOG(m_logger) << LOGFUNCTION << " init failed";
TRACE_LOG(m_logger) << LOGFUNCTION << " END, success=" << success;
return success;
}
} // namespace SituationMap
+76
View File
@@ -0,0 +1,76 @@
/**
* @RDE_HEADER@
* Interface-Implementation of Text
* $Id$
* $HeadURL$
* $Author$
*/
#pragma once
// Own
#include "abstract_single_point_map_object_impl.h"
#include "basic_path_object_impl.h"
#include <MapObjects/text.h> // Interface
// Qt
#include <QString>
//----------------------------------------------------------------------------
namespace SituationMap
{
class GraphicalObjectPictureMarker;
/**
* @brief The TextImpl class displays a text.
*
* A class instance consists of the following logical elements:
* - mainGraphicalObject (irrelevant)
* - mainGraphicalObjectText (displaying the text/name)
* - tacticalAppearance (irrelevant)
*/
// inherent 'public', to get that implementation
// inherent 'public virtual' to get that interface
class SITUATIONMAPOBJECTS_EXPORT TextImpl : public AbstractSinglePointMapObjectImpl, public virtual Text
{
using BaseClass = AbstractSinglePointMapObjectImpl;
template <typename> friend class GenericObjectFactory;
protected:
explicit TextImpl(const QString &debugInfo = QString());
virtual ~TextImpl();
public:
TextImpl(const TextImpl &other) = delete;
TextImpl &operator=(TextImpl &other) = delete;
// void setScale(float) override {}
void setShowAnchorMarker(bool on) override;
bool showAnchorMarker() const override;
protected:
bool updateViewImpl() override;
friend class MapImpl;
bool init(MapImpl *mapImpl, const QString &logicalLayerName) override;
// internal/admin
// logical
bool m_showAnchorMarker;
GraphicalObjectPictureMarker *m_anchorMarker;
private:
LOGGER_T m_logger; ///< Interface of the Logging-Facility
};
} // namespace SituationMap
@@ -0,0 +1,494 @@
/**
* @RDE_HEADER@
* Interface-Implementation of VirtualMine
* $Id$
* $HeadURL$
* $Author$
*/
// Own
#include "virtual_mine_impl.h"
#include <MapImpl/map_impl.h>
#include <GraphicalObjects/graphical_object_path.h>
#include <GraphicalObjects/graphical_object_text.h>
#include <GraphicalObjects/graphical_object_renderer_attributes.h>
#include <GraphicalObjects/graphical_object_scene_marker.h>
#include <Symbology/sidc_codec.h>
// ESRI
#include <arcgis/Graphic.h>
#include <arcgis/GraphicListModel.h>
#include <arcgis/GraphicsOverlay.h>
// Qt
#include <QList>
#include <QSharedPointer>
namespace SituationMap
{
//// to get access to 'init'
//class VMineLocalBasicPathObject final : public BasicPathObjectImpl
//{
//public:
// using BasicPathObjectImpl::BasicPathObjectImpl;
// using BasicPathObjectImpl::init;
// using BasicPathObjectImpl::setUniqueId;
//};
using VMineLocalBasicPathObject = LocalBasicPathObject;
class VirtualMineImpl::Private
{
public:
Private() = default;
~Private() = default;
// ESRI data:
// Esri::ArcGISRuntime::GraphicsOverlay *m_graphicsLayer = nullptr;
// Own data:
MapImpl *m_mapImpl = nullptr;
QString m_logicalLayer;
QString m_debugInfo; // will be appended by consecutive number
UniqueMapId m_uniqueMapId = INVALID_MAP_ID;
struct MarkerSymbolDataRenderer
{
// std::shared_ptr<Esri::ArcGISRuntime::Graphic> m_graphic3D;
QSharedPointer<GraphicalObjectRendererAttributes> m_goRendererAtt;
QVariantMap m_attribMap;
OriginTranslated m_origin;
} m_markerSymbolDataRenderer;
struct MarkerSymbolData
{
QSharedPointer<GraphicalObjectSceneMarker> m_goSceneMarker;
SceneSymbolData m_sceneSymbolData;
OriginTranslated m_origin;
} m_markerSymbolData;
struct ValueDataVM
{
QSharedPointer<BasicPathObjectImpl> basicPathObj;
VirtualMine::OptionalData optData;
};
QMap<int, ValueDataVM> m_cont; /// one polyline per subsidiary line
using MAP_IT_T = QMapIterator<int, ValueDataVM>;
// int m_drawOrder = 0;
bool hasPathObject(int key) const { return m_cont.contains(key); }
QList<int> keysInUse() const { return m_cont.keys(); }
void remove(int key) { m_cont.remove(key); }
void clear() { m_cont.clear(); }
ValueDataVM getPathObject(int key, const OptionalData &optData = OptionalData())
{
auto ret = m_cont.value(key); // copy
if (ret.basicPathObj.isNull())
{
QString debugInfo = QStringLiteral("%1#SubsidiaryLine(%2)").arg(m_debugInfo).arg(key);
VMineLocalBasicPathObject *temp = new VMineLocalBasicPathObject(debugInfo);
GraphicalObjectPathType pathType = GraphicalObjectPathType::Polyline;
if (optData.closed)
pathType = GraphicalObjectPathType::Polygon;
bool success = temp->init(m_mapImpl, m_logicalLayer, pathType);
temp->setUniqueId(m_uniqueMapId);
if (success)
ret.basicPathObj = QSharedPointer<BasicPathObjectImpl>(static_cast<BasicPathObjectImpl *>(temp));
else
temp->removeMySelf();
ret.optData.closed = optData.closed;
}
// transfer optional data (line|fill) to ret and then to container _if_ set:
if (optData.lineStyle)
ret.optData.lineStyle = optData.lineStyle;
if (optData.fillStyle)
ret.optData.fillStyle = optData.fillStyle;
m_cont.insert(key, ret);
return ret;
}
}; // class VirtualMineImpl::Private
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
// class VirtualMineImpl
//-----------------------------------------------------------------------------
VirtualMineImpl::VirtualMineImpl(const QString &debugInfo)
: VirtualMine() // Interface
, BaseClass(debugInfo) // Implementation
, d(new Private)
, m_logger(getLogger("VirtualMineImpl"))
{
TRACE_LOG(m_logger) << LOGFUNCTION << " START";
m_fillColorAlpha = 200;
TRACE_LOG(m_logger) << LOGFUNCTION << " END";
}
VirtualMineImpl::~VirtualMineImpl()
{
TRACE_LOG(m_logger) << LOGFUNCTION << " START";
d->m_markerSymbolDataRenderer.m_goRendererAtt.clear();
d->m_markerSymbolData.m_goSceneMarker.clear();
// // approach for V100.15 ; will maybe crash with older versions
// if (d->m_markerSymbolData.m_graphic3D && m_graphicsLayer && m_graphicsLayer->graphics())
// m_graphicsLayer->graphics()->removeOne(d->m_markerSymbolData.m_graphic3D.get());
// d->m_markerSymbolData.m_graphic3D.reset();
delete d;
TRACE_LOG(m_logger) << LOGFUNCTION << " END";
}
void VirtualMineImpl::setUniqueId(const UniqueMapId &uniqueId)
{
BaseClass::setUniqueId(uniqueId);
d->m_uniqueMapId = m_uniqueMapId;
}
PositionCont VirtualMineImpl::subsidiaryLine(int key) const
{
TRACE_LOG(m_logger) << LOGFUNCTION << " START";
if (d->hasPathObject(key))
return d->getPathObject(key).basicPathObj->positions();
else
return PositionCont();
}
void VirtualMineImpl::setSubsidiaryLine(int key, const PositionCont &positions, const OptionalData &optData)
{
TRACE_LOG(m_logger) << LOGFUNCTION << " START"
<< ", key=" << key
<< ", closed=" << optData.closed
<< ", positions.size=" << positions.size();
Private::ValueDataVM vd = d->getPathObject(key, optData);
QSharedPointer<BasicPathObjectImpl> pathObj = vd.basicPathObj;
if (pathObj)
pathObj->setPositions(positions);
TRACE_LOG(m_logger) << LOGFUNCTION << " END";
}
QList<int> VirtualMineImpl::subsidiaryKeysInUse()
{
TRACE_LOG(m_logger) << LOGFUNCTION << " START";
TRACE_LOG(m_logger) << LOGFUNCTION << " END";
return d->keysInUse();
}
void VirtualMineImpl::removeSubsidiaryLine(int key)
{
TRACE_LOG(m_logger) << LOGFUNCTION << " START";
TRACE_LOG(m_logger) << LOGFUNCTION << " END";
return d->remove(key);
}
void VirtualMineImpl::removeSubsidiaryLines()
{
TRACE_LOG(m_logger) << LOGFUNCTION << " START";
TRACE_LOG(m_logger) << LOGFUNCTION << " END";
return d->clear();
}
bool VirtualMineImpl::has3DMarkerRenderer() const
{
// TRACE_LOG(m_logger) << LOGFUNCTION << " START";
// TRACE_LOG(m_logger) << LOGFUNCTION << " END, isEmpty = " << d->m_markerSymbolData.m_origin.isEmpty();
return !d->m_markerSymbolDataRenderer.m_origin.isEmpty();
}
void VirtualMineImpl::set3DMarkerRenderer(const Point3D &markerOrigin, const QVariantMap &attribMap)
{
TRACE_LOG(m_logger) << LOGFUNCTION << " START";
d->m_markerSymbolDataRenderer.m_origin.setOrigin(markerOrigin);
d->m_markerSymbolDataRenderer.m_attribMap = attribMap;
TRACE_LOG(m_logger) << LOGFUNCTION << " END";
}
bool VirtualMineImpl::has3DMarkerSceneSymbol() const
{
// TRACE_LOG(m_logger) << LOGFUNCTION << " START";
// TRACE_LOG(m_logger) << LOGFUNCTION << " END";
return !d->m_markerSymbolData.m_origin.isEmpty();
}
void VirtualMineImpl::set3DMarkerSceneSymbol(const Point3D &markerOrigin, const SceneSymbolData &sceneSymbolData)
{
TRACE_LOG(m_logger) << LOGFUNCTION << " START";
d->m_markerSymbolData.m_origin.setOrigin(markerOrigin);
d->m_markerSymbolData.m_sceneSymbolData = sceneSymbolData;
TRACE_LOG(m_logger) << LOGFUNCTION << " END";
}
bool VirtualMineImpl::updateViewImpl()
{
TRACE_LOG(m_logger) << LOGFUNCTION << " START"
<< " m_debugInfo=" << m_debugInfo
<< " symbol=" << m_symbol.value().sidc
<< " visibility=" << m_visibility
<< " visiTechn=" << m_visibilityTechnical
<< " visiTact=" << m_visibilityTactical;
bool success = BaseClass::updateViewImpl();
if (!success)
{
ERROR_LOG(m_logger) << LOGFUNCTION << " updateViewImpl failed";
return false;
}
if (nullptr == m_mainGraphicalObject)
{
ERROR_LOG(m_logger) << LOGFUNCTION << " no m_mainGraphicalObject";
return false;
}
// subsidiary :
Private::MAP_IT_T mapIt(d->m_cont);
while (mapIt.hasNext())
{
mapIt.next();
const Private::ValueDataVM &vd = mapIt.value();
QSharedPointer<BasicPathObjectImpl> pathObj = vd.basicPathObj;
const OptionalData &optData = vd.optData;
if (pathObj)
{
// pathObj->setDebugInfo(m_mainGraphicalObject->debugInfo()); // will overwrite complete string -> skip
if (optData.lineStyle)
pathObj->setLineStyle((*optData.lineStyle.data()));
else
pathObj->setLineStyle(m_mainGraphicalObject->lineStyle());
// transfer fillStyle only if relevant:
if (pathObj->pathType() == GraphicalObjectPathType::Polygon)
{
if (optData.fillStyle)
pathObj->setFillStyle((*optData.fillStyle.data()));
else
pathObj->setFillStyle(m_mainGraphicalObject->fillStyle());
}
pathObj->setVisibility(m_visibility);
pathObj->setVisibility(ObjectAppearance::Technical, m_visibilityTechnical);
// Do not Transfer symbol. Only m_mainGraphicalObject uses ObjectAppearance::Tactical:
// pathObj->setSymbol(this->symbol());
pathObj->setVisibility(ObjectAppearance::Tactical, false);
pathObj->setPickable(m_mainGraphicalObject->pickable());
pathObj->setSelected(m_mainGraphicalObject->selected());
pathObj->setDrawOrder(m_internalDrawOrder);
success = pathObj->updateView();
if (!success)
{
int key = mapIt.key();
ERROR_LOG(m_logger) << LOGFUNCTION << " updateViewImpl failed, key=" << key
<< ", m_debugInfo=" << m_debugInfo;
}
}
} // while
// : subsidiary
// 3DMarkerSceneSymbol :
if (m_mapImpl->mode() == Mode::Mode_3D)
{
const bool successUpdateRender = updateViewImpl3DMarkerRenderer();
if (!successUpdateRender)
ERROR_LOG(m_logger) << LOGFUNCTION << " updateViewImpl3DMarkerRenderer failed" << ", m_debugInfo=" << m_debugInfo;
const bool successUpdateSceneSymbol = updateViewImpl3DMarkerSceneSymbol();
if (!successUpdateSceneSymbol)
ERROR_LOG(m_logger) << LOGFUNCTION << " updateViewImpl3DMarkerSceneSymbol failed" << ", m_debugInfo=" << m_debugInfo;
success = success && successUpdateRender && successUpdateSceneSymbol;
}
// : 3DMarkerSceneSymbol
TRACE_LOG(m_logger) << LOGFUNCTION << " END, success=" << success;
return success;
}
bool VirtualMineImpl::updateViewImpl3DMarkerRenderer()
{
TRACE_LOG(m_logger) << LOGFUNCTION << " START";
bool success = true;
// qCritical() << " attribMap " << attribMap;
if (m_mapImpl->mode() == Mode::Mode_3D)
{
if (d->m_markerSymbolDataRenderer.m_origin.isEmpty())
{
d->m_markerSymbolDataRenderer.m_goRendererAtt.clear();
} else {
if (!d->m_markerSymbolDataRenderer.m_goRendererAtt)
{
QString debugInfo = QStringLiteral("%1#goRendererAtt").arg(m_debugInfo);
d->m_markerSymbolDataRenderer.m_goRendererAtt = QSharedPointer<GraphicalObjectRendererAttributes>
(new GraphicalObjectRendererAttributes(m_mapImpl->getEsriGeoView()
, m_graphicsLayer
, debugInfo
, m_uniqueMapId)
);
}
d->m_markerSymbolDataRenderer.m_origin.setMapObjectImpl(this);
const Point3D &pos = d->m_markerSymbolDataRenderer.m_origin.originTranslated();
d->m_markerSymbolDataRenderer.m_goRendererAtt->setOrigin(pos);
d->m_markerSymbolDataRenderer.m_goRendererAtt->setAttributeMap(d->m_markerSymbolDataRenderer.m_attribMap);
d->m_markerSymbolDataRenderer.m_goRendererAtt->setVisibility(m_visibility);
d->m_markerSymbolDataRenderer.m_goRendererAtt->setPickable(m_mainGraphicalObject->pickable());
d->m_markerSymbolDataRenderer.m_goRendererAtt->setSelected(m_mainGraphicalObject->selected());
d->m_markerSymbolDataRenderer.m_goRendererAtt->setDrawOrder(m_internalDrawOrder);
// scale does not makes sense :-)
success = d->m_markerSymbolDataRenderer.m_goRendererAtt->updateView();
if (!success)
ERROR_LOG(m_logger) << LOGFUNCTION << " updateViewImpl failed, m_goRendererAtt"
<< ", m_debugInfo=" << m_debugInfo;
}
}
TRACE_LOG(m_logger) << LOGFUNCTION << " END, success=" << success;
return success;
}
bool VirtualMineImpl::updateViewImpl3DMarkerSceneSymbol()
{
TRACE_LOG(m_logger) << LOGFUNCTION << " START";
bool success = true;
// qCritical() << " attribMap " << attribMap;
if (m_mapImpl->mode() == Mode::Mode_3D)
{
if (d->m_markerSymbolData.m_origin.isEmpty())
{
d->m_markerSymbolData.m_goSceneMarker.clear();
} else {
if (!d->m_markerSymbolData.m_goSceneMarker)
{
SituationMap::SceneMarkerType type = SituationMap::SceneMarkerType::SPHERE;
if (d->m_markerSymbolData.m_sceneSymbolData.cone)
type = SituationMap::SceneMarkerType::CONE;
QString debugInfo = QStringLiteral("%1#goSceneMarker").arg(m_debugInfo);
d->m_markerSymbolData.m_goSceneMarker = QSharedPointer<GraphicalObjectSceneMarker>
(new GraphicalObjectSceneMarker(type,
m_mapImpl->getEsriGeoView()
, m_graphicsLayer
, debugInfo
, m_uniqueMapId)
);
}
d->m_markerSymbolData.m_origin.setMapObjectImpl(this);
const Point3D &pos = d->m_markerSymbolData.m_origin.originTranslated();
d->m_markerSymbolData.m_goSceneMarker->setOrigin(pos);
d->m_markerSymbolData.m_goSceneMarker->setDiameter(d->m_markerSymbolData.m_sceneSymbolData.radius*2.0);
d->m_markerSymbolData.m_goSceneMarker->setHeading(d->m_markerSymbolData.m_sceneSymbolData.heading);
d->m_markerSymbolData.m_goSceneMarker->setPitch(d->m_markerSymbolData.m_sceneSymbolData.pitch);
d->m_markerSymbolData.m_goSceneMarker->setRoll(d->m_markerSymbolData.m_sceneSymbolData.roll);
d->m_markerSymbolData.m_goSceneMarker->setVisibility(m_visibility);
d->m_markerSymbolData.m_goSceneMarker->setPickable(m_mainGraphicalObject->pickable());
d->m_markerSymbolData.m_goSceneMarker->setSelected(m_mainGraphicalObject->selected());
d->m_markerSymbolData.m_goSceneMarker->setDrawOrder(m_internalDrawOrder);
QColor col = d->m_markerSymbolData.m_sceneSymbolData.color;
col.setAlphaF(col.alphaF() / 2.0);
d->m_markerSymbolData.m_goSceneMarker->setFillStyle(FillStyle(col, FillPattern::Solid));
// scale does not makes sense :-)
success = d->m_markerSymbolData.m_goSceneMarker->updateView();
if (!success)
ERROR_LOG(m_logger) << LOGFUNCTION << " updateViewImpl failed, m_goSceneMarker"
<< ", m_debugInfo=" << m_debugInfo;
}
}
TRACE_LOG(m_logger) << LOGFUNCTION << " END, success=" << success;
return success;
}
bool VirtualMineImpl::init(MapImpl *mapImpl, const QString &logicalLayerName)
{
TRACE_LOG(m_logger) << LOGFUNCTION << " START";
if (mapImpl)
{
switch (mapImpl->symbologyType())
{
case AdvancedSymbology::SymbologyType::APP6D:
case AdvancedSymbology::SymbologyType::MIL2525D:
m_symbol.refValue().sidc = AdvancedSymbology::SidcCodec::encodeComplete(mapImpl->symbologyType(), "10012500002719000000"); // SymbolSet = 25 271900
break;
case AdvancedSymbology::SymbologyType::MIL2525C:
m_symbol.refValue().sidc = AdvancedSymbology::SidcCodec::encodeComplete(mapImpl->symbologyType(), "GUMPNR----"); // MIL2525D: 1388 GUMPNR---- -> Polygon (Radioactive Area U)
// m_symbol.refValue().sidc = AdvancedSymbology::SidcCodec::encodeComplete(mapImpl->symbologyType(),"GUMPNZ----"); // MIL2525D: 0359 GUMPNZ---- -> Point (Nuclear Detonations Ground Zero U)
break;
case AdvancedSymbology::SymbologyType::APP6B:
m_symbol.refValue().sidc = AdvancedSymbology::SidcCodec::encodeComplete(mapImpl->symbologyType(), "GUCPBWR---"); // APP6B: 3935 GUCPBWR--- -> Polygon
// m_symbol.refValue().sidc = AdvancedSymbology::SidcCodec::encodeComplete(mapImpl->symbologyType(),"GUCPBWP---"); // APP6B: 2871 GUCPBWP--- -> Point (Fallout Producing U)
break;
case AdvancedSymbology::SymbologyType::None:
// empty
break;
} // switch
} // if (mapImpl)
bool success = BaseClass::init(mapImpl, logicalLayerName, GraphicalObjectPathType::Polygon);
setLineStyle(LineStyle(Qt::yellow, 2));
setFillStyle(FillStyle(Qt::yellow, FillPattern::Null));
if (!success)
ERROR_LOG(m_logger) << LOGFUNCTION << " init failed";
// set some values to Private:
d->m_mapImpl = m_mapImpl;
d->m_logicalLayer = m_logicalLayerName;
d->m_debugInfo = m_debugInfo;
d->m_uniqueMapId = m_uniqueMapId;
TRACE_LOG(m_logger) << LOGFUNCTION << " END, success=" << success;
return success;
}
} // namespace SituationMap
+102
View File
@@ -0,0 +1,102 @@
/**
* @RDE_HEADER@
* Interface-Implementation of VirtualMine
* $Id$
* $HeadURL$
* $Author$
*/
#pragma once
// Own
#include "abstract_multi_point_map_object_impl.h"
#include "basic_path_object_impl.h"
#include <MapObjects/virtual_mine.h> // Interface
// Qt
#include <QString>
//----------------------------------------------------------------------------
namespace SituationMap
{
/**
* @brief The VirtualMineImpl class displays a nuclear area. The outline is displayed as well a subsidiary lines.
*
* A class instance consists of the following logical elements:
* - mainGraphicalObject (GraphicalObjectPath displaying the main techn. Appearance / outline)
* - mainGraphicalObjectText (displaying the text/name)
* - tacticalAppearance (displaying the tact. Appearance)
* - Container of BasicPathObjectImpl's to display the subsidiary lines.
*/
// inherent 'public', to get that implementation
// inherent 'public virtual' to get that interface
class SITUATIONMAPOBJECTS_EXPORT VirtualMineImpl : public BasicPathObjectImpl, public virtual VirtualMine
{
using BaseClass = BasicPathObjectImpl;
template <typename> friend class GenericObjectFactory;
protected:
explicit VirtualMineImpl(const QString &debugInfo = QString());
virtual ~VirtualMineImpl();
public:
VirtualMineImpl(const VirtualMineImpl &other) = delete;
VirtualMineImpl &operator=(VirtualMineImpl &other) = delete;
void setUniqueId(const UniqueMapId &uniqueId) override;
/*! \name Subsidiary polylines, identified by an arbitrary choose key.*/
//@{
PositionCont subsidiaryLine(int key) const override;
void setSubsidiaryLine(int key, const PositionCont &positions, const OptionalData &optData = OptionalData()) override;
QList<int> subsidiaryKeysInUse() override;
void removeSubsidiaryLine(int key) override;
void removeSubsidiaryLines() override;
//@}
/*! \name 3D marker / SimpleMarkerSceneSymbol (via renderer) */
//@{
bool has3DMarkerRenderer() const override;
void set3DMarkerRenderer(const Point3D &markerOrigin, const QVariantMap &attribMap) override;
//@}
bool has3DMarkerSceneSymbol() const override;
void set3DMarkerSceneSymbol(const Point3D &markerOrigin, const SceneSymbolData &sceneSymbolData) override;
protected:
bool updateViewImpl() override;
bool updateViewImpl3DMarkerRenderer();
bool updateViewImpl3DMarkerSceneSymbol();
friend class MapImpl;
bool init(MapImpl *mapImpl, const QString &logicalLayerName) override;
// internal/admin
// logical
private:
class Private;
/**
* The private d->pointer to not break BC when changing internals of this class
*/
Private *d = nullptr;
LOGGER_T m_logger; ///< Interface of the Logging-Facility
};
} // namespace SituationMap