1198 lines
51 KiB
C++
Executable File
1198 lines
51 KiB
C++
Executable File
/**
|
|
* @RDE_HEADER@
|
|
* PlanModel - Renderer
|
|
* $Id$
|
|
* $HeadURL$
|
|
* $Author$
|
|
*/
|
|
|
|
|
|
#include "geometry_model_renderer_esri.h"
|
|
|
|
#include <Common/id_handler.h>
|
|
|
|
#include <QtCore/QFile>
|
|
#include <QtCore/QTime>
|
|
#include <QtCore/QTimer>
|
|
|
|
#include <QtGui/QFontDatabase>
|
|
|
|
#include <GeometryModel/geometry_node_visitor.h>
|
|
|
|
#include <Symbology/sidc_codec.h>
|
|
#include <SymbologyXML/xml_symbol_codec.h>
|
|
|
|
#include <Map/map.h>
|
|
#include <Map/object_factory.h>
|
|
#include <Map/sidc_symbol.h>
|
|
#include <Map/situation_map_types.h>
|
|
#include <Map/coord_translation_functor.h>
|
|
#include <Map/party_id_to_color_functor.h>
|
|
|
|
#include <MapObjects/text.h>
|
|
#include <MapObjects/polygon.h>
|
|
#include <MapObjects/polyline.h>
|
|
#include <MapObjects/participant.h>
|
|
|
|
#include <MathUtils/curve.h>
|
|
#include <MathUtils/path_rasterer.h>
|
|
|
|
namespace SituationMap
|
|
{
|
|
|
|
GeometryModelRendererEsri::GeometryModelRendererEsri(Map *map, const QString &layerName, GeometryModel &geometryModel, QObject *parent)
|
|
: GeometryModelRenderer(map, layerName, geometryModel, parent)
|
|
, m_editorMode(false)
|
|
, m_delayedRenderTimer(new QTimer(this))
|
|
, m_delayedRenderIds()
|
|
{
|
|
m_delayedRenderTimer->setInterval(10);
|
|
m_delayedRenderTimer->setSingleShot(true);
|
|
|
|
connect(m_delayedRenderTimer, &QTimer::timeout, this, &GeometryModelRendererEsri::onDelayedRenderNodes);
|
|
|
|
connect(&geometryModel, &GeometryModel::nodeCleanup , this, &GeometryModelRendererEsri::onCleanupMapObjects);
|
|
connect(&geometryModel, &GeometryModel::userDataCleanup, this, &GeometryModelRendererEsri::onRemoveMapObject);
|
|
connect(&geometryModel, &GeometryModel::changed , this, &GeometryModelRendererEsri::onUpdate);
|
|
|
|
} // GeometryModelRendererEsri::GeometryModelRendererEsri
|
|
|
|
|
|
bool GeometryModelRendererEsri::editorMode() const { return m_editorMode; }
|
|
void GeometryModelRendererEsri::setEditorMode(bool on) { m_editorMode = on; }
|
|
|
|
|
|
class CleanUpMapObjectsVisitor : public GeometryNodeVisitor
|
|
{
|
|
SituationMap::Map *m_map;
|
|
|
|
public:
|
|
|
|
CleanUpMapObjectsVisitor(SituationMap::Map *map, SituationMap::GeometryModel *geoModel) : GeometryNodeVisitor(geoModel), m_map(map) { ; }
|
|
virtual ~CleanUpMapObjectsVisitor() = default;
|
|
|
|
bool apply(SituationMap::GeometryModel *geoModel, const SituationMap::GeometryModel::Node &node, SituationMap::GeometryModel::PrimitiveType primitiveType) override
|
|
{
|
|
switch (primitiveType)
|
|
{
|
|
case GeometryModel::PrimitiveType::RootNode:
|
|
case GeometryModel::PrimitiveType::Node:
|
|
break;
|
|
|
|
default:
|
|
{
|
|
if (geoModel->hasUserData(node))
|
|
{
|
|
bool ok = false;
|
|
int uid = geoModel->getUserData(node, &ok);
|
|
|
|
if (ok)
|
|
{
|
|
SituationMap::AbstractMapObject *mapObj = m_map->objectFactory().idToMapObject(uid);
|
|
if (mapObj)
|
|
mapObj->removeMySelf();
|
|
}
|
|
}
|
|
} break;
|
|
}
|
|
return true;
|
|
} // bool apply(SituationMap::GeometryModel * geoModel, const SituationMap::GeometryModel::Node & node, SituationMap::GeometryModel::PrimitiveType primitiveType )
|
|
|
|
}; // CleanUpMapObjectsVisitor
|
|
|
|
|
|
void GeometryModelRendererEsri::onCleanupMapObjects(const SituationMap::GeometryModel::Node &node)
|
|
{
|
|
if (m_map)
|
|
{
|
|
GeometryModel::Node p = node;
|
|
if (!p.isValid())
|
|
{
|
|
p = m_geometryModel.getRootNode();
|
|
}
|
|
CleanUpMapObjectsVisitor visitor(m_map, &m_geometryModel);
|
|
|
|
visitor.traverse(p);
|
|
}
|
|
} // GeometryModelRendererEsri::onCleanupMapObjects
|
|
|
|
|
|
void GeometryModelRendererEsri::onRemoveMapObject(int uid)
|
|
{
|
|
if (m_map)
|
|
{
|
|
SituationMap::AbstractMapObject *mapObj = m_map->objectFactory().idToMapObject(uid);
|
|
|
|
// crash see comment in abstract_map_object_impl.cpp 2016/01/08 JT
|
|
// SituationMap::RefPointer<SituationMap::AbstractMapObject> mapObj( m_map->objectFactory().idToMapObject( uid ) );
|
|
|
|
if (mapObj != nullptr)
|
|
{
|
|
mapObj->removeMySelf();
|
|
}
|
|
}
|
|
} // GeometryModelRendererEsri::onRemoveMapObject
|
|
|
|
|
|
void GeometryModelRendererEsri::onUpdate(const SituationMap::GeometryModel::Node &node, SituationMap::GeometryModel::Attribute /*att*/, bool /*coordsChanged*/)
|
|
{
|
|
if (m_geometryModel.hasUserData(node))
|
|
{
|
|
SituationMap::AbstractMapObject *mapObj = nullptr;
|
|
bool ok = false;
|
|
int uid = m_geometryModel.getUserData(node, &ok);
|
|
|
|
if (ok)
|
|
mapObj = m_map->objectFactory().idToMapObject(uid);
|
|
|
|
if (mapObj)
|
|
{
|
|
// render node later
|
|
if (!m_delayedRenderIds.contains(uid))
|
|
m_delayedRenderIds += uid;
|
|
m_delayedRenderTimer->start();
|
|
|
|
return;
|
|
}
|
|
}
|
|
renderNode(node);
|
|
} // GeometryModelRendererEsri::onUpdate(const SituationMap::GeometryModel::Node & node, SituationMap::GeometryModel::Attribute att, bool coordsChanged)
|
|
|
|
|
|
void GeometryModelRendererEsri::onDelayedRenderNodes()
|
|
{
|
|
for (auto uid : qAsConst(m_delayedRenderIds))
|
|
{
|
|
SituationMap::AbstractMapObject *mapObj = m_map->objectFactory().idToMapObject(uid);
|
|
renderNode(getAssociatedNode(mapObj));
|
|
}
|
|
m_delayedRenderIds.clear();
|
|
} // GeometryModelRendererEsri::onDelayedRenderNodes()
|
|
|
|
|
|
bool GeometryModelRendererEsri::render(QPixmap &drawable)
|
|
{
|
|
Q_UNUSED(drawable);
|
|
return false;
|
|
} // GeometryModelRendererEsri::render( QPixmap & drawable )
|
|
|
|
|
|
bool GeometryModelRendererEsri::render() { return renderNode(m_geometryModel.getRootNode()); }
|
|
|
|
|
|
bool GeometryModelRendererEsri::renderNode(const GeometryModel::Node &node)
|
|
{
|
|
bool ok = false;
|
|
if (!node.isValid())
|
|
{
|
|
const GeometryModel::Node &root = m_geometryModel.getRootNode();
|
|
ok = drawNodesRecursive(root);
|
|
}
|
|
else
|
|
ok = drawNodesRecursive(node);
|
|
|
|
return ok;
|
|
} // GeometryModelRendererEsri::renderNode( Map * map, const GeometryModel::Node & node, const QString & layername )
|
|
|
|
|
|
template <class MapObjectClass> uint GeometryModelRendererEsri::setLineStyle(const GeometryModel::Node &p, MapObjectClass *objPtr) const
|
|
|
|
{
|
|
SituationMap::LineStyle &&objLineStyle = objPtr->lineStyle();
|
|
|
|
const QColor &lineColor = m_geometryModel.getAttribute(p, GeometryModel::Attribute::Color).value<QColor>();
|
|
uint lineWidth = m_geometryModel.getAttribute(p, GeometryModel::Attribute::LineWidth).toUInt();
|
|
GeometryModel::LineStyle lineStyle = GeometryModel::LineStyle((m_geometryModel.getAttribute(p, GeometryModel::Attribute::LineStyle).toInt()));
|
|
|
|
objLineStyle.setLineColor(lineColor);
|
|
objLineStyle.setLineWidth((lineWidth > 0) ? lineWidth : 1);
|
|
|
|
switch (lineStyle)
|
|
{
|
|
case GeometryModel::LineStyle::Dashed : objLineStyle.setLinePattern(LinePattern::Dash); break;
|
|
case GeometryModel::LineStyle::DashedDotted : objLineStyle.setLinePattern(LinePattern::DashDot); break;
|
|
case GeometryModel::LineStyle::Dotted : objLineStyle.setLinePattern(LinePattern::Dot); break;
|
|
case GeometryModel::LineStyle::LineSolid : objLineStyle.setLinePattern(LinePattern::Solid); break;
|
|
default : objLineStyle.setLinePattern(LinePattern::Solid); break;
|
|
}
|
|
|
|
objPtr->setLineStyle(objLineStyle);
|
|
|
|
return lineWidth;
|
|
} // template <class MapObjectClass> uint GeometryModelRendererEsri::setLineStyle( const GeometryModel::Node & p, MapObjectClass * objPtr ) const
|
|
|
|
|
|
template <class MapObjectClass> void GeometryModelRendererEsri::setFillStyle(const GeometryModel::Node &p, MapObjectClass *objPtr) const
|
|
{
|
|
SituationMap::FillStyle &&objFillStyle = objPtr->fillStyle();
|
|
GeometryModel::FillPattern fillPattern = GeometryModel::FillPattern((m_geometryModel.getAttribute(p, GeometryModel::Attribute::FillPattern).toInt()));
|
|
const QColor &fillColor = m_geometryModel.getAttribute(p, GeometryModel::Attribute::FillColor).value<QColor>();
|
|
|
|
objFillStyle.setFillColor(fillColor);
|
|
switch (fillPattern)
|
|
{
|
|
case GeometryModel::FillPattern::Diag1 : objFillStyle.setFillPattern(FillPattern::BackwardDiagonal); break;
|
|
case GeometryModel::FillPattern::Diag2 : objFillStyle.setFillPattern(FillPattern::ForwardDiagonal); break;
|
|
case GeometryModel::FillPattern::Hor1 : objFillStyle.setFillPattern(FillPattern::BackwardDiagonal); break;
|
|
case GeometryModel::FillPattern::Hor2 : objFillStyle.setFillPattern(FillPattern::Horizontal); break;
|
|
case GeometryModel::FillPattern::Solid : objFillStyle.setFillPattern(FillPattern::Solid); break;
|
|
case GeometryModel::FillPattern::Ver1 :
|
|
case GeometryModel::FillPattern::Ver2 : objFillStyle.setFillPattern(FillPattern::Vertical); break;
|
|
case GeometryModel::FillPattern::Dots :
|
|
default : objFillStyle.setFillPattern(FillPattern::Null); break;
|
|
}
|
|
|
|
objPtr->setFillStyle(objFillStyle);
|
|
} // template <class MapObjectClass> void GeometryModelRendererEsri::setFillStyle( const GeometryModel::Node & p, MapObjectClass * objPtr ) const
|
|
|
|
|
|
class RenderMapObjectsVisitor : public GeometryNodeVisitor
|
|
{
|
|
GeometryModelRendererEsri *m_gmr;
|
|
|
|
public:
|
|
|
|
RenderMapObjectsVisitor(GeometryModelRendererEsri *gmr, SituationMap::GeometryModel *geoModel) : GeometryNodeVisitor(geoModel), m_gmr(gmr) { ; }
|
|
virtual ~RenderMapObjectsVisitor() = default;
|
|
|
|
bool apply(SituationMap::GeometryModel *geoModel, const SituationMap::GeometryModel::Node &node, SituationMap::GeometryModel::PrimitiveType primitiveType) override
|
|
{
|
|
SituationMap::AbstractMapObject *mapObj = nullptr;
|
|
|
|
if (geoModel->hasUserData(node))
|
|
{
|
|
bool ok = false;
|
|
int uid = geoModel->getUserData(node, &ok);
|
|
|
|
if (ok) mapObj = m_gmr->m_map->objectFactory().idToMapObject(uid);
|
|
}
|
|
|
|
switch (primitiveType)
|
|
{
|
|
case GeometryModel::PrimitiveType::ParticipantSymbol : m_gmr->drawParticipantSymbol( node, m_gmr->m_layerName, mapObj); break;
|
|
case GeometryModel::PrimitiveType::DictionarySymbol : m_gmr->drawDictionarySymbol ( node, m_gmr->m_layerName, mapObj); break;
|
|
case GeometryModel::PrimitiveType::Ellipse : m_gmr->drawEllipse ( node, m_gmr->m_layerName, mapObj); break;
|
|
case GeometryModel::PrimitiveType::Line : m_gmr->drawLine ( node, m_gmr->m_layerName, mapObj); break;
|
|
case GeometryModel::PrimitiveType::Polyline : m_gmr->drawPolyline ( node, m_gmr->m_layerName, mapObj); break;
|
|
case GeometryModel::PrimitiveType::Rectangle : m_gmr->drawRectangle ( node, m_gmr->m_layerName, mapObj); break;
|
|
case GeometryModel::PrimitiveType::Spline : m_gmr->drawSpline ( node, m_gmr->m_layerName, mapObj); break;
|
|
case GeometryModel::PrimitiveType::Symbol : m_gmr->drawSymbol ( node, m_gmr->m_layerName, mapObj); break;
|
|
case GeometryModel::PrimitiveType::Text : m_gmr->drawText ( node, m_gmr->m_layerName, mapObj); break;
|
|
|
|
case GeometryModel::PrimitiveType::RootNode : break;
|
|
case GeometryModel::PrimitiveType::Node : break;
|
|
case GeometryModel::PrimitiveType::Unknown : break;
|
|
default : break;
|
|
}
|
|
return true;
|
|
} // bool apply(SituationMap::GeometryModel * geoModel, const SituationMap::GeometryModel::Node & node, SituationMap::GeometryModel::PrimitiveType primitiveType )
|
|
|
|
}; // RenderMapObjectsVisitor
|
|
|
|
|
|
bool GeometryModelRendererEsri::drawNodesRecursive(const GeometryModel::Node &p)
|
|
{
|
|
if (!p.isValid()) return false;
|
|
|
|
TRACE_LOG(m_logger) << LOGFUNCTION << " START";
|
|
|
|
++m_stats.m_drawElementsRecursiveCount;
|
|
|
|
RenderMapObjectsVisitor visitor(this, &m_geometryModel);
|
|
visitor.traverse(p);
|
|
|
|
TRACE_LOG(m_logger) << LOGFUNCTION << " END";
|
|
|
|
return true;
|
|
} // void GeometryModelRendererEsri::drawNodesRecursive
|
|
|
|
|
|
UniqueMapId GeometryModelRendererEsri::getIdFromNode(const GeometryModel::Node &node) const
|
|
{
|
|
SituationMap::UniqueMapId mapId = SituationMap::INVALID_MAP_ID;
|
|
|
|
if (m_geometryModel.hasUserData(node))
|
|
{
|
|
bool ok;
|
|
int userData = m_geometryModel.getUserData(node, &ok);
|
|
if (!ok)
|
|
DEBUG_LOG(m_logger) << LOGFUNCTION << " getUserData failed";
|
|
else mapId = userData;
|
|
}
|
|
return mapId;
|
|
|
|
} // UniqueMapId GeometryModelRendererEsri::getIdFromNode() const
|
|
|
|
|
|
GeometryModel::Node GeometryModelRendererEsri::getAssociatedNode(const AbstractMapObject *mapObject)
|
|
{
|
|
if (mapObject == nullptr) return GeometryModel::Node();
|
|
SituationMap::UniqueMapId mapId = mapObject->uniqueMapId();
|
|
|
|
if (mapId == SituationMap::INVALID_MAP_ID) return GeometryModel::Node();
|
|
|
|
return m_geometryModel.findPrimitive(mapId);
|
|
} // getAssociatedNode( const AbstractMapObject * mapObject )
|
|
|
|
|
|
bool GeometryModelRendererEsri::getNodesPickable() const { return m_nodesPickable; }
|
|
|
|
|
|
void GeometryModelRendererEsri::setNodesPickable(bool nodesPickable) { m_nodesPickable = nodesPickable; }
|
|
|
|
|
|
void GeometryModelRendererEsri::drawParticipantSymbol(const GeometryModel::Node &p, const QString &layer, SituationMap::AbstractMapObject *mapObj)
|
|
{
|
|
QList<QPointF> points = m_geometryModel.getPrimitivePoints(p);
|
|
SituationMap::UniqueMapId mapId = getIdFromNode(p);
|
|
|
|
if (points.size() == 0)
|
|
{
|
|
DEBUG_LOG(m_logger) << LOGFUNCTION << "Primitive Dictionary Symbol don't have any coordinates!"
|
|
<< " (" << mapId << ")";
|
|
return;
|
|
}
|
|
|
|
|
|
bool ok;
|
|
|
|
const QString & sidc = m_geometryModel.getAttribute(p, GeometryModel::Attribute::SIDC).toString();
|
|
const QString & sidcAttributes = m_geometryModel.getAttribute(p, GeometryModel::Attribute::SIDC_Attributes).toString();
|
|
|
|
int symbolForceId = m_geometryModel.getAttribute(p, GeometryModel::Attribute::ForceId).toInt(&ok); if (!ok) symbolForceId = -1;
|
|
int symbolInjuryId = m_geometryModel.getAttribute(p, GeometryModel::Attribute::DamageForceId).toInt(&ok); if (!ok) symbolInjuryId = -1;
|
|
int symbolInjury = m_geometryModel.getAttribute(p, GeometryModel::Attribute::Injury).toInt(&ok); if (!ok) symbolInjury = static_cast<int>(AdvancedSymbology::Injury::NoInjury);
|
|
|
|
const QVector<int> &partyIds = m_map->partyIdToColorFunctor().partyIds();
|
|
|
|
if (!partyIds.contains(symbolForceId)) symbolForceId = -1;
|
|
if (!partyIds.contains(symbolInjuryId)) symbolInjuryId = -1;
|
|
|
|
SituationMap::ObjectFactory & objFac = m_map->objectFactory();
|
|
SituationMap::Participant * objPtr = dynamic_cast<SituationMap::Participant *>(mapObj);
|
|
|
|
|
|
if (objPtr == nullptr)
|
|
{
|
|
if (mapObj)
|
|
mapObj -> removeMySelf();
|
|
objPtr = objFac.create<SituationMap::Participant> (layer, QStringLiteral("Plan-ParticipantSymbol:sidc=%1").arg(sidc)).get();
|
|
|
|
if (objPtr == nullptr)
|
|
{
|
|
ERROR_LOG(m_logger) << LOGFUNCTION << " objFac.create failed";
|
|
return;
|
|
}
|
|
}
|
|
|
|
++m_stats.m_drawDictionarySymbolCount;
|
|
m_stats.m_timer.restart();
|
|
|
|
SituationMap::SymbolData symbolData;
|
|
|
|
symbolData.sidc = sidc;
|
|
|
|
objPtr->setVisibility(true);
|
|
objPtr->setPickable(m_nodesPickable);
|
|
objPtr->setOrigin(SituationMap::Point3D::fromQPointF(points.first()));
|
|
objPtr->setSymbol(symbolData);
|
|
objPtr->setPartyId(symbolForceId);
|
|
objPtr->setInjury(static_cast<AdvancedSymbology::Injury>(symbolInjury), symbolInjuryId );
|
|
|
|
|
|
objPtr->setTextModifier( SituationMap::Participant::TextModifier::W_DateTimeGroup , m_geometryModel.getAttribute(p, GeometryModel::Attribute::Text_W).toString());
|
|
objPtr->setTextModifier( SituationMap::Participant::TextModifier::T_UniqueDesignation , m_geometryModel.getAttribute(p, GeometryModel::Attribute::Text_T).toString());
|
|
objPtr->setTextModifier( SituationMap::Participant::TextModifier::M_HigherFormation , m_geometryModel.getAttribute(p, GeometryModel::Attribute::Text_M).toString());
|
|
objPtr->setTextModifier( SituationMap::Participant::TextModifier::EF_ReinforcedReduced , m_geometryModel.getAttribute(p, GeometryModel::Attribute::Text_EF).toString());
|
|
objPtr->setTextModifier( SituationMap::Participant::TextModifier::XY_AltitudeLocation , m_geometryModel.getAttribute(p, GeometryModel::Attribute::Text_XY).toString());
|
|
objPtr->setTextModifier( SituationMap::Participant::TextModifier::V_Type , m_geometryModel.getAttribute(p, GeometryModel::Attribute::Text_V).toString());
|
|
objPtr->setTextModifier( SituationMap::Participant::TextModifier::Z_Speed , m_geometryModel.getAttribute(p, GeometryModel::Attribute::Text_Z).toString());
|
|
objPtr->setTextModifier( SituationMap::Participant::TextModifier::G_StaffComments , m_geometryModel.getAttribute(p, GeometryModel::Attribute::Text_G).toString());
|
|
objPtr->setTextModifier( SituationMap::Participant::TextModifier::H_AdditionalInformation , m_geometryModel.getAttribute(p, GeometryModel::Attribute::Text_H).toString());
|
|
objPtr->setTextModifier( SituationMap::Participant::TextModifier::JKLNP , m_geometryModel.getAttribute(p, GeometryModel::Attribute::Text_KLNPJ).toString());
|
|
|
|
QMap<QString, QVariant> attrMap;
|
|
|
|
m_geometryModel.parseSymbolAttributeString(sidcAttributes, attrMap);
|
|
|
|
const auto tm = Participant::textModifiers();
|
|
for (auto textModifier : tm)
|
|
objPtr->setTextModifierVisibility(textModifier, true);
|
|
|
|
|
|
bool success = objPtr->updateView();
|
|
|
|
if (!success) ERROR_LOG(m_logger) << LOGFUNCTION << " failed";
|
|
|
|
DEBUG_LOG(m_logger) << LOGFUNCTION << " uniqueMapId=" << objPtr->uniqueMapId();
|
|
|
|
// Store id in primitive
|
|
m_geometryModel.setUserData(p, objPtr->uniqueMapId());
|
|
|
|
int ms = m_stats.m_timer.elapsed();
|
|
m_stats.m_msDictionarySymbol += ms;
|
|
m_stats.m_msDictionarySymbolMin = std::min(ms, m_stats.m_msDictionarySymbolMin);
|
|
m_stats.m_msDictionarySymbolMax = std::max(ms, m_stats.m_msDictionarySymbolMax);
|
|
|
|
} // void GeometryModelRendererEsri::drawParticipantSymbol(const GeometryModel::Node &p, const QString &layer, SituationMap::AbstractMapObject *mapObj)
|
|
|
|
|
|
void GeometryModelRendererEsri::drawDictionarySymbol(const GeometryModel::Node &p, const QString &layer, SituationMap::AbstractMapObject *mapObj)
|
|
{
|
|
QList<QPointF> points = m_geometryModel.getPrimitivePoints(p);
|
|
SituationMap::UniqueMapId mapId = getIdFromNode(p);
|
|
|
|
if (points.size() == 0)
|
|
{
|
|
DEBUG_LOG(m_logger) << LOGFUNCTION << "Primitive Dictionary Symbol don't have any coordinates!"
|
|
<< " (" << mapId << ")";
|
|
return;
|
|
}
|
|
|
|
const QString & sidc = m_geometryModel.getAttribute(p, GeometryModel::Attribute::SIDC).toString();
|
|
const QString & sidcAttributes = m_geometryModel.getAttribute(p, GeometryModel::Attribute::SIDC_Attributes).toString();
|
|
SituationMap::ObjectFactory & objFac = m_map->objectFactory();
|
|
SituationMap::SidcSymbol * objPtr = dynamic_cast<SituationMap::SidcSymbol *>(mapObj);
|
|
|
|
|
|
if (objPtr == nullptr)
|
|
{
|
|
if (mapObj) mapObj -> removeMySelf();
|
|
|
|
objPtr = objFac.create<SituationMap::SidcSymbol> (layer, QStringLiteral("Plan-TacticalSymbol:sidc=%1").arg(sidc)).get();
|
|
|
|
if (objPtr == nullptr)
|
|
{
|
|
ERROR_LOG(m_logger) << LOGFUNCTION << " objFac.create failed";
|
|
return;
|
|
}
|
|
}
|
|
|
|
++m_stats.m_drawDictionarySymbolCount;
|
|
m_stats.m_timer.restart();
|
|
|
|
DEBUG_LOG(m_logger) << LOGFUNCTION << "TacticalAppearanceAttrList: " << sidcAttributes;
|
|
|
|
QMap<QString, QVariant> attrMap;
|
|
|
|
m_geometryModel.parseSymbolAttributeString(sidcAttributes, attrMap);
|
|
|
|
objPtr->setVisibility(true);
|
|
objPtr->setPickable(m_nodesPickable);
|
|
objPtr->defineSymbol(sidc, SituationMap::convert2D3D(points), attrMap );
|
|
|
|
bool success = objPtr->updateView();
|
|
|
|
if (!success) ERROR_LOG(m_logger) << LOGFUNCTION << " failed";
|
|
|
|
DEBUG_LOG(m_logger) << LOGFUNCTION << " uniqueMapId=" << objPtr->uniqueMapId();
|
|
|
|
// Store id in primitive
|
|
m_geometryModel.setUserData(p, objPtr->uniqueMapId());
|
|
|
|
int ms = m_stats.m_timer.elapsed();
|
|
m_stats.m_msDictionarySymbol += ms;
|
|
m_stats.m_msDictionarySymbolMin = std::min(ms, m_stats.m_msDictionarySymbolMin);
|
|
m_stats.m_msDictionarySymbolMax = std::max(ms, m_stats.m_msDictionarySymbolMax);
|
|
|
|
} // GeometryModelRendererEsri::drawDictionarySymbol
|
|
|
|
|
|
void GeometryModelRendererEsri::drawEllipse(const GeometryModel::Node &p, const QString &layer, SituationMap::AbstractMapObject *mapObj)
|
|
{
|
|
SituationMap::CoordTranslationFunctor *ctf = m_map->coordTranslationFunctor();
|
|
|
|
if (nullptr == ctf)
|
|
{
|
|
DEBUG_LOG(m_logger) << LOGFUNCTION << "Map don't have defined any map projection! Can't render ellipse ...";
|
|
return;
|
|
}
|
|
|
|
QList<QPointF> points = m_geometryModel.getPrimitivePoints(p);
|
|
|
|
if (points.size() != 4)
|
|
{
|
|
DEBUG_LOG(m_logger) << LOGFUNCTION << "Primitive Ellipse has wrong count of geo coordinates!";
|
|
return;
|
|
}
|
|
|
|
++m_stats.m_drawEllipseCount;
|
|
m_stats.m_timer.restart();
|
|
|
|
double radiusX = m_geometryModel.getAttribute(p, GeometryModel::Attribute::Width).toDouble() * 0.5;
|
|
double radiusY = m_geometryModel.getAttribute(p, GeometryModel::Attribute::Height).toDouble() * 0.5;
|
|
double phi = m_geometryModel.getAttribute(p, GeometryModel::Attribute::Rotate).toDouble() * (M_PI / 180.0);
|
|
double start = m_geometryModel.getAttribute(p, GeometryModel::Attribute::Start).toDouble();
|
|
double extent = m_geometryModel.getAttribute(p, GeometryModel::Attribute::Extent).toDouble();
|
|
|
|
bool fullCircle = (fabs(extent) > 359.5);
|
|
|
|
if (fullCircle)
|
|
{
|
|
start = 0.0;
|
|
extent = 360.0;
|
|
}
|
|
|
|
start *= (M_PI / 180.0);
|
|
extent *= (M_PI / 180.0);
|
|
|
|
QPointF centerPoint(points.first());
|
|
for (int i = 1; i < 4; ++i) centerPoint += points.at(i);
|
|
centerPoint /= 4;
|
|
centerPoint = ctf->geographicToMap(centerPoint);
|
|
|
|
points.clear();
|
|
|
|
qreal referenceLon = 9999;
|
|
if (ctf->mapIsGeographic())
|
|
{
|
|
referenceLon = centerPoint.x();
|
|
points << centerPoint;
|
|
ctf->geographicToUtm( referenceLon, points);
|
|
centerPoint = points.first();
|
|
points.clear();
|
|
}
|
|
|
|
SituationMap::MathUtils::Ellipse ellipseCurve(centerPoint, radiusX, radiusY, phi, start, start + extent);
|
|
std::unique_ptr<SituationMap::MathUtils::PathRasterer> pathRasterer(ellipseCurve.createPathRaster());
|
|
|
|
pathRasterer->epsilon(0.25 * m_map->pixelSizeMeter());
|
|
pathRasterer->maxVertexCount(1000);
|
|
|
|
pathRasterer->rasterize(ellipseCurve.minimumCurveParameter(), ellipseCurve.maximumCurveParameter(), points);
|
|
|
|
if (!fullCircle)
|
|
{
|
|
GeometryModel::FillStyle fillStyle = (GeometryModel::FillStyle)(m_geometryModel.getAttribute(p, GeometryModel::Attribute::FillStyle).toInt());
|
|
|
|
switch (fillStyle)
|
|
{
|
|
case GeometryModel::FillStyle::Pieslice: points.append(centerPoint); break;
|
|
case GeometryModel::FillStyle::Chord: break;
|
|
case GeometryModel::FillStyle::Open: break;
|
|
}
|
|
}
|
|
|
|
if (ctf->mapIsGeographic())
|
|
{
|
|
ctf->utmToGeographic(referenceLon, points);
|
|
}
|
|
|
|
drawPolyline(p, layer, points, mapObj, false);
|
|
|
|
int ms = m_stats.m_timer.elapsed();
|
|
m_stats.m_msEllipse += ms;
|
|
m_stats.m_msEllipseMin = std::min(ms, m_stats.m_msEllipseMin);
|
|
m_stats.m_msEllipseMax = std::max(ms, m_stats.m_msEllipseMax);
|
|
|
|
} // void GeometryModelRendererEsri::drawEllipse
|
|
|
|
|
|
void GeometryModelRendererEsri::drawLine(const GeometryModel::Node &p, const QString &layer, SituationMap::AbstractMapObject *mapObj)
|
|
{
|
|
++m_stats.m_drawLineCount;
|
|
m_stats.m_timer.restart();
|
|
drawPolyline(p, layer, mapObj);
|
|
int ms = m_stats.m_timer.elapsed();
|
|
m_stats.m_msLine += ms;
|
|
m_stats.m_msLineMin = std::min(ms, m_stats.m_msLineMin);
|
|
m_stats.m_msLineMax = std::max(ms, m_stats.m_msLineMax);
|
|
} // void GeometryModelRendererEsri::drawLine
|
|
|
|
|
|
void GeometryModelRendererEsri::drawPolyline(const GeometryModel::Node &p, const QString &layer, SituationMap::AbstractMapObject *mapObj)
|
|
{
|
|
TRACE_LOG(m_logger) << LOGFUNCTION << " START";
|
|
|
|
++m_stats.m_drawPolylineCount;
|
|
m_stats.m_timer.restart();
|
|
|
|
drawPolyline(p, layer, m_geometryModel.getPrimitivePoints(p), mapObj);
|
|
|
|
int ms = m_stats.m_timer.elapsed();
|
|
m_stats.m_msPolyline += ms;
|
|
m_stats.m_msPolylineMin = std::min(ms, m_stats.m_msPolylineMin);
|
|
m_stats.m_msPolylineMax = std::max(ms, m_stats.m_msPolylineMax);
|
|
|
|
TRACE_LOG(m_logger) << LOGFUNCTION << " END";
|
|
|
|
} /* GeometryModelRendererEsri::drawPolyline */
|
|
|
|
|
|
void GeometryModelRendererEsri::drawPolyline( const GeometryModel::Node & p
|
|
, const QString & layer
|
|
, const QList<QPointF> & points
|
|
, SituationMap::AbstractMapObject * mapObj
|
|
, bool geoCoordinates )
|
|
{
|
|
bool isRectangle = (m_geometryModel.getType(p) == GeometryModel::PrimitiveType::Rectangle);
|
|
bool isEllipse = (m_geometryModel.getType(p) == GeometryModel::PrimitiveType::Ellipse);
|
|
bool isFilled = (points.size() > 2) && m_geometryModel.getAttribute(p, GeometryModel::Attribute::Fill).toBool();
|
|
bool isClosed = ((isEllipse) || (isRectangle) || ((points.size() > 2) && m_geometryModel.getAttribute(p, GeometryModel::Attribute::Close).toBool()));
|
|
|
|
|
|
if ((points.size() > 2) || (isRectangle) || (isEllipse))
|
|
{
|
|
GeometryModel::FillPattern fillPattern = GeometryModel::FillPattern((m_geometryModel.getAttribute(p, GeometryModel::Attribute::FillPattern).toInt()));
|
|
|
|
if (isEllipse)
|
|
{
|
|
double extent = m_geometryModel.getAttribute(p, GeometryModel::Attribute::Extent).toDouble();
|
|
|
|
if (fabs(extent) <= 359.5)
|
|
{
|
|
GeometryModel::FillStyle fillStyle = GeometryModel::FillStyle((m_geometryModel.getAttribute(p, GeometryModel::Attribute::FillStyle).toInt()));
|
|
switch (fillStyle)
|
|
{
|
|
case GeometryModel::FillStyle::Chord : isClosed = true; break;
|
|
case GeometryModel::FillStyle::Pieslice : isClosed = true; break;
|
|
case GeometryModel::FillStyle::Open : isClosed = false; break;
|
|
}
|
|
}
|
|
else isClosed = true;
|
|
}
|
|
|
|
if (fillPattern == GeometryModel::FillPattern::None) isFilled = false;
|
|
}
|
|
|
|
SituationMap::RefPointer<SituationMap::AbstractMultiPointMapObject> objPtr(mapObj);
|
|
SituationMap::ObjectFactory &objFac = m_map->objectFactory();
|
|
bool createMapObj = false;
|
|
bool selectMapObj = false;
|
|
SituationMap::UniqueMapId removedUidMapObj = SituationMap::INVALID_MAP_ID;
|
|
|
|
if (mapObj)
|
|
{
|
|
objPtr = (SituationMap::AbstractMultiPointMapObject *) dynamic_cast<SituationMap::Polyline *>(mapObj);
|
|
if (objPtr.valid())
|
|
{
|
|
if (isClosed)
|
|
{
|
|
createMapObj = true;
|
|
selectMapObj = objPtr->selected();
|
|
removedUidMapObj = objPtr->uniqueMapId();
|
|
|
|
objPtr->removeMySelf();
|
|
objPtr = nullptr;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
objPtr = (SituationMap::AbstractMultiPointMapObject *) dynamic_cast<SituationMap::Polygon *>(mapObj);
|
|
if (objPtr.valid())
|
|
{
|
|
if (!isClosed)
|
|
{
|
|
createMapObj = true;
|
|
selectMapObj = objPtr->selected();
|
|
removedUidMapObj = objPtr->uniqueMapId();
|
|
|
|
objPtr->removeMySelf();
|
|
objPtr = nullptr;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
createMapObj = true;
|
|
selectMapObj = objPtr->selected();
|
|
removedUidMapObj = objPtr->uniqueMapId();
|
|
|
|
mapObj->removeMySelf();
|
|
}
|
|
}
|
|
}
|
|
else createMapObj = true;
|
|
|
|
if (createMapObj)
|
|
{
|
|
// re use the uid if the map object was removed before ...
|
|
if (isClosed) objPtr = (SituationMap::AbstractMultiPointMapObject *) objFac.create<SituationMap::Polygon> ( removedUidMapObj, layer, QLatin1String("PlanElement")).get();
|
|
else objPtr = (SituationMap::AbstractMultiPointMapObject *) objFac.create<SituationMap::Polyline>( removedUidMapObj, layer, QLatin1String("PlanElement")).get();
|
|
|
|
if (!objPtr.valid())
|
|
{
|
|
ERROR_LOG(m_logger) << LOGFUNCTION << " SituationMap::ObjectFactory.create() failed";
|
|
return;
|
|
}
|
|
|
|
objPtr->setSelected(selectMapObj);
|
|
objPtr->setScaleEnable(false); // disable scaling (setScale, most of the time done by user)
|
|
}
|
|
|
|
objPtr->setPickable(m_nodesPickable);
|
|
|
|
uint lineWidth = setLineStyle(p, objPtr.get());
|
|
|
|
Q_UNUSED(lineWidth);
|
|
|
|
if (!isFilled)
|
|
{
|
|
SituationMap::FillStyle &&objFillStyle = objPtr->fillStyle();
|
|
objFillStyle.setFillPattern(SituationMap::FillPattern::Null);
|
|
objPtr->setFillStyle(objFillStyle);
|
|
}
|
|
else setFillStyle(p, objPtr.get());
|
|
|
|
if ((!isClosed) && (!isEllipse))
|
|
{
|
|
SituationMap::Polyline *lineObj = dynamic_cast<SituationMap::Polyline *>(objPtr.get());
|
|
|
|
if (lineObj)
|
|
{
|
|
// adding arrows if defined
|
|
|
|
lineObj -> setArrowHeadStart(false);
|
|
lineObj -> setArrowHeadEnd(false);
|
|
|
|
GeometryModel::Arrows arrows = (GeometryModel::Arrows) m_geometryModel.getAttribute(p, GeometryModel::Attribute::Arrows).toInt();
|
|
|
|
switch (arrows)
|
|
{
|
|
case GeometryModel::Arrows::Both : lineObj -> setArrowHeadEnd(true);
|
|
Q_FALLTHROUGH();
|
|
case GeometryModel::Arrows::Start : lineObj -> setArrowHeadStart(true); break;
|
|
case GeometryModel::Arrows::End : lineObj -> setArrowHeadEnd(true); break;
|
|
case GeometryModel::Arrows::NoArrows :
|
|
default : arrows = GeometryModel::Arrows::NoArrows; break;
|
|
}
|
|
|
|
if (arrows != GeometryModel::Arrows::NoArrows)
|
|
{
|
|
#ifdef NEVER
|
|
double scale = (lineWidth < 2) ? 1.0 : double(lineWidth) * 0.5;
|
|
|
|
double arrowWidth = scale * (m_geometryModel.getAttribute(p, GeometryModel::Attribute::ArrowWidth).toDouble());
|
|
double arrowHeight = scale * (m_geometryModel.getAttribute(p, GeometryModel::Attribute::ArrowHeight).toDouble());
|
|
double arrowClampHeight = scale * (m_geometryModel.getAttribute(p, GeometryModel::Attribute::ArrowClampHeight).toDouble());
|
|
|
|
Q_UNUSED(arrowWidth);
|
|
Q_UNUSED(arrowHeight);
|
|
Q_UNUSED(arrowClampHeight);
|
|
#endif
|
|
}
|
|
}
|
|
}
|
|
|
|
(geoCoordinates) ? objPtr->setPositions(SituationMap::convert2D3D(points)) : objPtr->setPositionsTranslated(SituationMap::convert2D3D(points));
|
|
|
|
bool success = objPtr->updateView();
|
|
|
|
if (!success) ERROR_LOG(m_logger) << LOGFUNCTION << " failed";
|
|
|
|
DEBUG_LOG(m_logger) << LOGFUNCTION << " uniqueMapId=" << objPtr->uniqueMapId();
|
|
|
|
// Store id in primitive
|
|
m_geometryModel.setUserData(p, objPtr->uniqueMapId());
|
|
|
|
} // void GeometryModelRendererEsri::drawPolyline
|
|
|
|
|
|
void GeometryModelRendererEsri::drawRectangle(const GeometryModel::Node &p, const QString &layer, SituationMap::AbstractMapObject *mapObj)
|
|
{
|
|
QList<QPointF> points = m_geometryModel.getPrimitivePoints(p);
|
|
if (points.size() != 4)
|
|
{
|
|
DEBUG_LOG(m_logger) << LOGFUNCTION << "Primitive Rectangle has wrong count of points!";
|
|
return;
|
|
}
|
|
++m_stats.m_drawRectangleCount;
|
|
m_stats.m_timer.restart();
|
|
|
|
GeometryModelRendererEsri::drawPolyline(p, layer, points, mapObj);
|
|
|
|
int ms = m_stats.m_timer.elapsed();
|
|
m_stats.m_msRectangle += ms;
|
|
m_stats.m_msRectangleMin = std::min(ms, m_stats.m_msRectangleMin);
|
|
m_stats.m_msRectangleMax = std::max(ms, m_stats.m_msRectangleMax);
|
|
} // void GeometryModelRendererEsri::drawRectangle
|
|
|
|
|
|
void GeometryModelRendererEsri::drawSpline(const GeometryModel::Node &p, const QString &layer, SituationMap::AbstractMapObject *mapObj)
|
|
{
|
|
SituationMap::CoordTranslationFunctor *ctf = m_map->coordTranslationFunctor();
|
|
|
|
if (nullptr == ctf)
|
|
{
|
|
ERROR_LOG(m_logger) << LOGFUNCTION << "Map doesn't have defined any map projection! Can't render spline ...";
|
|
#if LTS_DEBUG
|
|
abort();
|
|
#else
|
|
return;
|
|
#endif // LTS_DEBUG
|
|
}
|
|
|
|
++m_stats.m_drawSplineCount;
|
|
m_stats.m_timer.restart();
|
|
|
|
SituationMap::MathUtils::SmoothLine splineCurve;
|
|
std::unique_ptr<SituationMap::MathUtils::PathRasterer> pathRasterer(splineCurve.createPathRaster());
|
|
bool isClosed(m_geometryModel.getAttribute(p, GeometryModel::Attribute::Close).toBool());
|
|
|
|
const auto & pointsMap = m_geometryModel.getPrimitivePoints(p);
|
|
|
|
if (pointsMap.size() < 2)
|
|
{
|
|
DEBUG_LOG(m_logger) << LOGFUNCTION << "Too little count of occordiantes. Can't render spline ...";
|
|
return;
|
|
}
|
|
|
|
QList<QPointF> points;
|
|
points.reserve(pointsMap.size());
|
|
|
|
for (int i = 0; i < pointsMap.size(); ++i)
|
|
{
|
|
points.push_back(ctf->geographicToMap(pointsMap.at(i)));
|
|
}
|
|
|
|
qreal referenceLon = 9999;
|
|
if (ctf->mapIsGeographic())
|
|
{
|
|
// In case of geographic coordinate system do rasterization in UTM coordinate system to avoid
|
|
// trouble with termination threshold.
|
|
referenceLon = points.first().x();
|
|
ctf->geographicToUtm( referenceLon, points );
|
|
}
|
|
|
|
splineCurve.vertexVector(points.toVector(), isClosed);
|
|
|
|
pathRasterer -> epsilon(0.25 * m_map->pixelSizeMeter());
|
|
pathRasterer -> maxVertexCount(1000);
|
|
|
|
QList<QPointF> rasterizedPoints;
|
|
pathRasterer -> rasterize(splineCurve.minimumCurveParameter(), splineCurve.maximumCurveParameter(), rasterizedPoints);
|
|
|
|
if (ctf->mapIsGeographic())
|
|
ctf->utmToGeographic( referenceLon, rasterizedPoints );
|
|
|
|
if (rasterizedPoints.size() <= 2)
|
|
{
|
|
NOTICE_LOG(m_logger) << LOGFUNCTION
|
|
<< "< pointsMap.size() " << pointsMap.size()
|
|
<< "< points.size() " << points.size()
|
|
<< "< splineCurve.minimumCurveParameter() " << splineCurve.minimumCurveParameter()
|
|
<< "< splineCurve.maximumCurveParameter() " << splineCurve.maximumCurveParameter()
|
|
<< "< rasterizedPoints.size() === " << rasterizedPoints.size()
|
|
<< "< m_map->pixelSizeMeter()=" << m_map->pixelSizeMeter();
|
|
}
|
|
drawPolyline(p, layer, rasterizedPoints, mapObj, false);
|
|
|
|
int ms = m_stats.m_timer.elapsed();
|
|
m_stats.m_msSpline += ms;
|
|
m_stats.m_msSplineMin = std::min(ms, m_stats.m_msSplineMin);
|
|
m_stats.m_msSplineMax = std::max(ms, m_stats.m_msSplineMax);
|
|
|
|
} // void GeometryModelRendererEsri::drawSpline
|
|
|
|
|
|
|
|
void GeometryModelRendererEsri::drawSymbol(const GeometryModel::Node &p, const QString &layer, SituationMap::AbstractMapObject *mapObj)
|
|
{
|
|
if (nullptr == m_map->coordTranslationFunctor())
|
|
{
|
|
ERROR_LOG(m_logger) << LOGFUNCTION << "Map doesn't have defined any map projection! Can't render symbol ...";
|
|
return;
|
|
}
|
|
|
|
const QVector<int> &partyIds = m_map->partyIdToColorFunctor().partyIds();
|
|
if (partyIds.size() < 1)
|
|
{
|
|
ERROR_LOG(m_logger) << LOGFUNCTION << " Party colors are not defined. Can't render symbol ...";
|
|
return;
|
|
}
|
|
|
|
++m_stats.m_drawSymbolCount;
|
|
|
|
const auto & pointsMap = m_geometryModel.getPrimitivePoints(p);
|
|
|
|
if (pointsMap.size() == 0)
|
|
{
|
|
ERROR_LOG(m_logger) << LOGFUNCTION << " Primitive Symbol has no points!";
|
|
return;
|
|
}
|
|
|
|
const QPointF & point = pointsMap.at(0);
|
|
|
|
SituationMap::RefPointer<SituationMap::Participant> objPtr;
|
|
SituationMap::ObjectFactory &objFac = m_map->objectFactory();
|
|
bool createMapObj = false;
|
|
|
|
if (mapObj)
|
|
{
|
|
objPtr = (SituationMap::Participant *) dynamic_cast<SituationMap::Participant *>(mapObj);
|
|
if (!objPtr.valid())
|
|
{
|
|
createMapObj = true;
|
|
mapObj->removeMySelf();
|
|
}
|
|
}
|
|
else createMapObj = true;
|
|
|
|
if (createMapObj)
|
|
{
|
|
objPtr = (SituationMap::Participant *) objFac.create<SituationMap::Participant> (layer, QLatin1String("PlanElement")).get();
|
|
|
|
if (!objPtr.valid())
|
|
{
|
|
ERROR_LOG(m_logger) << LOGFUNCTION << " SituationMap::ObjectFactory.create() failed";
|
|
return;
|
|
}
|
|
objPtr->setScaleEnable(false); // disable scaling (setScale, most of the time done by user)
|
|
}
|
|
|
|
bool ok;
|
|
|
|
SituationMap::GeometryModel::t_vbg_et vbg = SituationMap::GeometryModel::t_vbg_et(m_geometryModel.getAttribute(p,SituationMap::GeometryModel::Attribute::att_vbg_et).toInt());
|
|
SymbologyXML::SymbolTypes::t_state state = SymbologyXML::SymbolTypes::t_state( m_geometryModel.getAttribute(p,SituationMap::GeometryModel::Attribute::SymbolState).toInt() );
|
|
SymbologyXML::SymbolTypes::t_uncertainty uncertainty = SymbologyXML::SymbolTypes::t_uncertainty( m_geometryModel.getAttribute(p,SituationMap::GeometryModel::Attribute::SymbolUncertainty).toInt() );
|
|
SymbologyXML::SymbolTypes::t_affil affil = SymbologyXML::SymbolTypes::t_affil(m_geometryModel.getAttribute(p,SituationMap::GeometryModel::Attribute::Affiliation).toInt());
|
|
SymbologyXML::SymbolTypes::t_mob mob = SymbologyXML::SymbolTypes::t_mob(m_geometryModel.getAttribute(p,SituationMap::GeometryModel::Attribute::Mobility).toInt());
|
|
// bool abcProtect = m_geometryModel.getAttribute(p,SituationMap::GeometryModel::Attribute::AbcProtection).toBool();
|
|
|
|
SymbolData symData;
|
|
|
|
int symbolID = m_geometryModel.getAttribute(p, GeometryModel::Attribute::SymbolId).toInt();
|
|
if (symbolID < 0)
|
|
{
|
|
ERROR_LOG(m_logger) << LOGFUNCTION << "Primitive Symbol has undefinded symbol!";
|
|
return;
|
|
}
|
|
|
|
symData.sidc = AdvancedSymbology::SidcCodec::encodeCivilXmlSymbolId(uint(symbolID),state,uncertainty,affil,mob);
|
|
|
|
/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
int symbolOffsetX = m_geometryModel.getAttribute(p,SituationMap::GeometryModel::Attribute::SymbolOffsetX).toInt(&ok); if (!ok) symbolOffsetX = 0;
|
|
int symbolOffsetY = m_geometryModel.getAttribute(p,SituationMap::GeometryModel::Attribute::SymbolOffsetY).toInt(&ok); if (!ok) symbolOffsetY = 0;
|
|
int symbolDirection = m_geometryModel.getAttribute(p,SituationMap::GeometryModel::Attribute::SymbolDirection).toInt(&ok); if (!ok) symbolDirection = 0;
|
|
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
|
|
float symbolScale = m_geometryModel.getAttribute(p,SituationMap::GeometryModel::Attribute::SymbolExplicitScale).toFloat(&ok); if (!ok) symbolScale = 1.0f;
|
|
int symbolForceId = m_geometryModel.getAttribute(p, GeometryModel::Attribute::ForceId).toInt(&ok); if (!ok) symbolForceId = -1;
|
|
int symbolInjuryId = m_geometryModel.getAttribute(p, GeometryModel::Attribute::DamageForceId).toInt(&ok); if (!ok) symbolInjuryId = -1;
|
|
|
|
if (!partyIds.contains(symbolForceId)) symbolForceId = partyIds.first();
|
|
if (!partyIds.contains(symbolInjuryId)) symbolInjuryId = partyIds.first();
|
|
|
|
symData.size = (symbolScale > 0) ? symbolScale : 1.0;
|
|
|
|
objPtr->setOrigin( Point3D(point.x(),point.y(),0.0) );
|
|
objPtr->setPickable(m_nodesPickable);
|
|
|
|
objPtr->setSymbol(symData);
|
|
objPtr->setPartyId( symbolForceId );
|
|
|
|
AdvancedSymbology::Injury injury = AdvancedSymbology::Injury::NoInjury;
|
|
|
|
switch (vbg)
|
|
{
|
|
case SituationMap::GeometryModel::t_vbg_et::ANNAEHENDER_TREFFER :
|
|
case SituationMap::GeometryModel::t_vbg_et::TREFFER_OHNE_WIRKUNG :
|
|
case SituationMap::GeometryModel::t_vbg_et::EINSATZBEREIT : injury = AdvancedSymbology::Injury::NoInjury; break;
|
|
|
|
case SituationMap::GeometryModel::t_vbg_et::AUSFALL_WAFFENANLAGE :
|
|
case SituationMap::GeometryModel::t_vbg_et::AUSFALL_WAFFENANLAGE_SICHTB : injury = AdvancedSymbology::Injury::WeaponKill; break;
|
|
|
|
case SituationMap::GeometryModel::t_vbg_et::BEWEGUNGSUNFAEHIG :
|
|
case SituationMap::GeometryModel::t_vbg_et::BEWEGUNGSUNFAEHIG_SICHTB : injury = AdvancedSymbology::Injury::MobilityKill; break;
|
|
|
|
case SituationMap::GeometryModel::t_vbg_et::LEICHTER_TREFFER :
|
|
case SituationMap::GeometryModel::t_vbg_et::MITTLERER_TREFFER :
|
|
case SituationMap::GeometryModel::t_vbg_et::SCHWERER_TREFFER : injury = AdvancedSymbology::Injury::Hit; break;
|
|
case SituationMap::GeometryModel::t_vbg_et::TOTALAUSFALL : injury = AdvancedSymbology::Injury::TotalKill; break;
|
|
case SituationMap::GeometryModel::t_vbg_et::ZEITLICHER_AUSFALL : injury = AdvancedSymbology::Injury::TotalKill; break;
|
|
}
|
|
|
|
objPtr->setInjury( injury , symbolInjuryId );
|
|
|
|
objPtr->setTextModifier( SituationMap::Participant::TextModifier::W_DateTimeGroup , m_geometryModel.getAttribute(p, GeometryModel::Attribute::Text_W).toString());
|
|
objPtr->setTextModifier( SituationMap::Participant::TextModifier::T_UniqueDesignation , m_geometryModel.getAttribute(p, GeometryModel::Attribute::Text_T).toString());
|
|
objPtr->setTextModifier( SituationMap::Participant::TextModifier::M_HigherFormation , m_geometryModel.getAttribute(p, GeometryModel::Attribute::Text_M).toString());
|
|
objPtr->setTextModifier( SituationMap::Participant::TextModifier::EF_ReinforcedReduced , m_geometryModel.getAttribute(p, GeometryModel::Attribute::Text_EF).toString());
|
|
|
|
objPtr->setTextModifier( SituationMap::Participant::TextModifier::XY_AltitudeLocation , m_geometryModel.getAttribute(p, GeometryModel::Attribute::Text_XY).toString());
|
|
objPtr->setTextModifier( SituationMap::Participant::TextModifier::V_Type , m_geometryModel.getAttribute(p, GeometryModel::Attribute::Text_V).toString());
|
|
objPtr->setTextModifier( SituationMap::Participant::TextModifier::Z_Speed , m_geometryModel.getAttribute(p, GeometryModel::Attribute::Text_Z).toString());
|
|
objPtr->setTextModifier( SituationMap::Participant::TextModifier::G_StaffComments , m_geometryModel.getAttribute(p, GeometryModel::Attribute::Text_G).toString());
|
|
objPtr->setTextModifier( SituationMap::Participant::TextModifier::H_AdditionalInformation, m_geometryModel.getAttribute(p, GeometryModel::Attribute::Text_H).toString());
|
|
objPtr->setTextModifier( SituationMap::Participant::TextModifier::JKLNP , m_geometryModel.getAttribute(p, GeometryModel::Attribute::Text_KLNPJ).toString());
|
|
|
|
|
|
/*
|
|
AdditionalSymbolType additionalSymbol;
|
|
|
|
AdditionalSymbolType::NbcProtection, ///< Line at top left.
|
|
AdditionalSymbolType::Manipulation, ///< Black and white dashed lines at bottom (1st of three)
|
|
AdditionalSymbolType::NoPosition, ///< Red line at bottom (2nd of three)
|
|
AdditionalSymbolType::BiteError ///< Yellow line at bottom. (3rd of three)
|
|
|
|
objPtr->setAdditionalSymbol(additionalSymbol);
|
|
*/
|
|
|
|
bool success = objPtr->updateView();
|
|
|
|
if (!success) ERROR_LOG(m_logger) << LOGFUNCTION << " failed";
|
|
|
|
DEBUG_LOG(m_logger) << LOGFUNCTION << " uniqueMapId=" << objPtr->uniqueMapId();
|
|
|
|
// Store id in primitive
|
|
m_geometryModel.setUserData(p, objPtr->uniqueMapId());
|
|
|
|
int ms = m_stats.m_timer.elapsed();
|
|
m_stats.m_msSymbol += ms;
|
|
m_stats.m_msSymbolMin = std::min(ms, m_stats.m_msDictionarySymbolMin);
|
|
m_stats.m_msSymbolMax = std::max(ms, m_stats.m_msDictionarySymbolMax);
|
|
|
|
} // void GeometryModelRendererEsri::drawSymbol
|
|
|
|
|
|
void GeometryModelRendererEsri::drawText(const GeometryModel::Node &p, const QString &layer, SituationMap::AbstractMapObject * /*mapObj*/)
|
|
{
|
|
QList<QPointF> points = m_geometryModel.getPrimitivePoints(p);
|
|
|
|
if (points.size() != 1)
|
|
{
|
|
DEBUG_LOG(m_logger) << LOGFUNCTION << "Primitive TextBox doesn't have origin!";
|
|
return;
|
|
}
|
|
|
|
SituationMap::UniqueMapId mapId = getIdFromNode(p);
|
|
SituationMap::ObjectFactory &objFac = m_map->objectFactory();
|
|
SituationMap::RefPointer<SituationMap::Text> objPtr;
|
|
|
|
if (SituationMap::isUniqueMapIdValid(mapId))
|
|
objPtr = objFac.get<SituationMap::Text>(mapId).get();
|
|
|
|
if (!objPtr.valid())
|
|
{
|
|
objPtr = objFac.create<SituationMap::Text> (layer, QLatin1String("PlanElement")).get();
|
|
|
|
if (!objPtr.valid())
|
|
{
|
|
ERROR_LOG(m_logger) << LOGFUNCTION << " objFac.create failed";
|
|
return;
|
|
}
|
|
objPtr->setScaleEnable(false); // disable scaling (setScale, most of the time done by user)
|
|
}
|
|
|
|
++m_stats.m_drawTextCount;
|
|
m_stats.m_timer.restart();
|
|
|
|
double phi = m_geometryModel.getAttribute(p, GeometryModel::Attribute::Rotate).toDouble(); // *(M_PI/180.0);
|
|
const QString & text = m_geometryModel.getTextData(p);
|
|
double fontSize = m_geometryModel.getAttribute(p, GeometryModel::Attribute::FontSize).toDouble();
|
|
const QColor & textColor = m_geometryModel.getAttribute(p, GeometryModel::Attribute::Color).value<QColor>();
|
|
const QColor & lineColor = m_geometryModel.getAttribute(p, GeometryModel::Attribute::LineColor).value<QColor>();
|
|
QColor fillColor = m_geometryModel.getAttribute(p, GeometryModel::Attribute::FillColor).value<QColor>();
|
|
int lineWidth = m_geometryModel.getAttribute(p, GeometryModel::Attribute::LineWidth).toInt();
|
|
bool fill = m_geometryModel.getAttribute(p, GeometryModel::Attribute::Fill).toBool();
|
|
bool bold = m_geometryModel.getAttribute(p, GeometryModel::Attribute::FontBold).toBool();
|
|
bool italic = m_geometryModel.getAttribute(p, GeometryModel::Attribute::FontItalic).toBool();
|
|
bool useBox = m_geometryModel.getAttribute(p, GeometryModel::Attribute::Box).toBool();
|
|
GeometryModel::Font pmFont = (GeometryModel::Font)(m_geometryModel.getAttribute(p, GeometryModel::Attribute::Font).toInt());
|
|
const GeometryModel::Node & td = p.firstChildNode(QLatin1String("text_data"));
|
|
GeometryModel::HorizontalAlign pmAlign = (GeometryModel::HorizontalAlign)(m_geometryModel.getAttribute(td, GeometryModel::Attribute::Alignment).toInt());
|
|
GeometryModel::HorizontalAlign anchorH = (GeometryModel::HorizontalAlign)(m_geometryModel.getAttribute(p, GeometryModel::Attribute::AnchorHorizontal).toInt());
|
|
GeometryModel::VerticalAlign anchorV = (GeometryModel::VerticalAlign)(m_geometryModel.getAttribute(p, GeometryModel::Attribute::AnchorVertical).toInt());
|
|
int marginH = m_geometryModel.getAttribute(p, GeometryModel::Attribute::MarginHorizontal).toInt();
|
|
int marginV = m_geometryModel.getAttribute(p, GeometryModel::Attribute::MarginVertical).toInt();
|
|
|
|
if (fontSize <= 0) fontSize = 14.0;
|
|
|
|
Q_UNUSED(useBox);
|
|
Q_UNUSED(marginH);
|
|
Q_UNUSED(marginV);
|
|
|
|
QString fontName;
|
|
|
|
switch (pmFont)
|
|
{
|
|
case GeometryModel::Font::SansSerif : fontName = QLatin1String("Arial"); break;
|
|
case GeometryModel::Font::Serif : fontName = QLatin1String("Times New Roman"); break;
|
|
case GeometryModel::Font::Fixed : fontName = QLatin1String("Courier New"); break;
|
|
case GeometryModel::Font::Decorative :
|
|
{
|
|
QStringList fontFamilies = QFontDatabase().families();
|
|
|
|
fontName.clear();
|
|
for (const QLatin1String &fontFamilyName : { QLatin1String("Freestyle Script"), QLatin1String("MV Boli"), QLatin1String("URW Chancery L")})
|
|
{
|
|
if (fontFamilies.contains(fontFamilyName))
|
|
{
|
|
fontName = fontFamilyName;
|
|
break;
|
|
}
|
|
}
|
|
} break;
|
|
default : fontName = QLatin1String("Wingdings"); break;
|
|
}
|
|
|
|
SituationMap::HorizontalAlignment fontAlignm = SituationMap::HorizontalAlignment::Left;
|
|
SituationMap::HorizontalAlignment hAlignm = SituationMap::HorizontalAlignment::Center;
|
|
SituationMap::VerticalAlignment vAlignm = SituationMap::VerticalAlignment::Middle;
|
|
|
|
switch (pmAlign)
|
|
{
|
|
case GeometryModel::HorizontalAlign::Left : fontAlignm = SituationMap::HorizontalAlignment::Left; break;
|
|
case GeometryModel::HorizontalAlign::HCenter : fontAlignm = SituationMap::HorizontalAlignment::Center; break;
|
|
case GeometryModel::HorizontalAlign::Right : fontAlignm = SituationMap::HorizontalAlignment::Right; break;
|
|
}
|
|
|
|
Q_UNUSED(fontAlignm);
|
|
|
|
switch (anchorV)
|
|
{
|
|
case GeometryModel::VerticalAlign::Bottom : vAlignm = SituationMap::VerticalAlignment::Bottom; break;
|
|
case GeometryModel::VerticalAlign::VCenter : vAlignm = SituationMap::VerticalAlignment::Middle; break;
|
|
case GeometryModel::VerticalAlign::Top : vAlignm = SituationMap::VerticalAlignment::Top; break;
|
|
}
|
|
|
|
switch (anchorH)
|
|
{
|
|
case GeometryModel::HorizontalAlign::Left : hAlignm = SituationMap::HorizontalAlignment::Left; break;
|
|
case GeometryModel::HorizontalAlign::HCenter : hAlignm = SituationMap::HorizontalAlignment::Center; break;
|
|
case GeometryModel::HorizontalAlign::Right : hAlignm = SituationMap::HorizontalAlignment::Right; break;
|
|
}
|
|
|
|
// uint lineWidth = setLineStyle( p, objPtr.get() );
|
|
|
|
setFillStyle(p, objPtr.get());
|
|
|
|
SituationMap::TextStyle &textStyle = objPtr->rTextStyle();
|
|
|
|
if (!fill) fillColor.setAlpha(0);
|
|
|
|
textStyle.setTextColor(textColor);
|
|
textStyle.setTextOutlineColor(lineColor);
|
|
textStyle.setBackgroundColor(fillColor);
|
|
textStyle.setTextOutlineWidth(lineWidth-1);
|
|
// textStyle.setTextOutlineWidth(0.0f);
|
|
|
|
textStyle.setFontFamily(fontName);
|
|
textStyle.setSize(fontSize);
|
|
textStyle.setAngle(phi);
|
|
textStyle.setBold(bold);
|
|
textStyle.setItalic(italic);
|
|
textStyle.setHorizontalAlignment(hAlignm);
|
|
textStyle.setVerticalAlignment(vAlignm);
|
|
|
|
|
|
objPtr -> setIdentifier(text.isEmpty() ? QLatin1String("????????") : text);
|
|
objPtr -> setPickable(m_nodesPickable);
|
|
objPtr -> setOrigin(SituationMap::Point3D::fromQPointF(points.first()));
|
|
objPtr -> setShowAnchorMarker(m_editorMode);
|
|
|
|
bool success = objPtr->updateView();
|
|
|
|
if (!success) ERROR_LOG(m_logger) << LOGFUNCTION << " failed";
|
|
|
|
// Store id in primitive
|
|
m_geometryModel.setUserData(p, objPtr->uniqueMapId());
|
|
|
|
int ms = m_stats.m_timer.elapsed();
|
|
m_stats.m_msText += ms;
|
|
m_stats.m_msTextMin = std::min(ms, m_stats.m_msTextMin);
|
|
m_stats.m_msTextMax = std::max(ms, m_stats.m_msTextMax);
|
|
|
|
} // void GeometryModelRendererEsri::drawText
|
|
|
|
} // namepace SituationMap
|
|
|