Initial commit
This commit is contained in:
commit
b7d90b9afe
16245 files changed
+3396666
No files matched your search
+517
@@ -0,0 +1,517 @@
|
||||
/**
|
||||
* @RDE_HEADER@
|
||||
* Interface-Implementation of ObjectIndicator
|
||||
* $Id$
|
||||
* $HeadURL$
|
||||
* $Author$
|
||||
*/
|
||||
|
||||
// Own
|
||||
#include "object_indicator_impl.h"
|
||||
#include <MapImpl/map_impl.h>
|
||||
#include <Map/bounding_box.h>
|
||||
#include <Map/object_factory.h>
|
||||
#include <MapImpl/abstract_map_object_impl.h>
|
||||
#include <ElevationMap/elevation_map_manager.h>
|
||||
#include <MathUtils/simple_helper.h>
|
||||
|
||||
|
||||
// ESRI
|
||||
#include <arcgis/MapGraphicsView.h>
|
||||
#include <arcgis/SceneGraphicsView.h>
|
||||
|
||||
|
||||
// Qt
|
||||
#include <QGraphicsView>
|
||||
|
||||
|
||||
#include <cassert>
|
||||
|
||||
namespace SituationMap
|
||||
{
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// class ObjectIndicatorImpl
|
||||
//-----------------------------------------------------------------------------
|
||||
ObjectIndicatorImpl::ObjectIndicatorImpl()
|
||||
: BaseClass()
|
||||
, m_logger(getLogger("ObjectIndicatorImpl"))
|
||||
{
|
||||
TRACE_LOG(m_logger) << LOGFUNCTION << " START";
|
||||
|
||||
m_markerSize = 15; // size of filled circle at the origin (indicating the center of the map)
|
||||
m_lineWidth = 3; // lineWidth of (dashed) line from origin to target
|
||||
|
||||
// updateTimer:
|
||||
m_updateTimer = new QTimer(this);
|
||||
m_updateTimer->setSingleShot(true);
|
||||
m_updateTimer->setInterval(100);
|
||||
connect(m_updateTimer, &QTimer::timeout, this, &ObjectIndicatorImpl::updateImpl);
|
||||
|
||||
TRACE_LOG(m_logger) << LOGFUNCTION << " END";
|
||||
}
|
||||
|
||||
bool ObjectIndicatorImpl::init(MapImpl *mapImpl)
|
||||
{
|
||||
TRACE_LOG(m_logger) << LOGFUNCTION << " START";
|
||||
|
||||
m_mapImpl = mapImpl;
|
||||
|
||||
if (!m_mapImpl)
|
||||
{
|
||||
ERROR_LOG(m_logger) << LOGFUNCTION << " m_map_impl is nullptr, init failed";
|
||||
return false;
|
||||
}
|
||||
|
||||
// to ensure graceful shutdown: (remove QGraphicsItems BEFORE qGraphicsScene/qGraphicsView is destroyed:
|
||||
connect(m_mapImpl, &Map::beginDestroy, this, &ObjectIndicatorImpl::onMapDestroyed, Qt::UniqueConnection);
|
||||
|
||||
m_qGraphicsView = static_cast<QGraphicsView *>(m_mapImpl->getEsriQGraphicsView());
|
||||
if (m_qGraphicsView)
|
||||
m_qGraphicsScene = m_qGraphicsView->scene();
|
||||
|
||||
TRACE_LOG(m_logger) << LOGFUNCTION << " END";
|
||||
return true;
|
||||
}
|
||||
|
||||
ObjectIndicatorImpl::~ObjectIndicatorImpl()
|
||||
{
|
||||
TRACE_LOG(m_logger) << LOGFUNCTION << " START";
|
||||
remove();
|
||||
TRACE_LOG(m_logger) << LOGFUNCTION << " END";
|
||||
}
|
||||
|
||||
UniqueMapId ObjectIndicatorImpl::mapObjectToPointTo()
|
||||
{
|
||||
return m_uniqueIdToPointTo;
|
||||
}
|
||||
|
||||
void ObjectIndicatorImpl::setMapObjectToPointTo(const UniqueMapId &newUniqueId, bool setSelected, int lifetimeMsec)
|
||||
{
|
||||
TRACE_LOG(m_logger) << LOGFUNCTION << " START, newUniqueId = " << newUniqueId
|
||||
<< ", (old m_uniqueIdToPointTo = " << m_uniqueIdToPointTo
|
||||
<< ", lifetimeMsec=" << lifetimeMsec;
|
||||
|
||||
m_targetGeo2D = QPointF();
|
||||
|
||||
connect(m_mapImpl, &MapImpl::extentChangedDelayed,
|
||||
this, &ObjectIndicatorImpl::update, Qt::UniqueConnection);
|
||||
|
||||
if (m_uniqueIdToPointTo != newUniqueId)
|
||||
{
|
||||
addRemoveCallback(m_uniqueIdToPointTo, AddRemove::Remove);
|
||||
m_uniqueIdToPointTo = newUniqueId;
|
||||
addRemoveCallback(m_uniqueIdToPointTo, AddRemove::Add);
|
||||
}
|
||||
|
||||
update();
|
||||
|
||||
if (m_lifetimeTimer)
|
||||
m_lifetimeTimer->stop();
|
||||
|
||||
if (lifetimeMsec > 1)
|
||||
{
|
||||
if (!m_lifetimeTimer)
|
||||
{
|
||||
m_lifetimeTimer = new QTimer(this);
|
||||
m_lifetimeTimer->setSingleShot(true);
|
||||
connect(m_lifetimeTimer.data(), &QTimer::timeout, this, &ObjectIndicatorImpl::remove); // lifetime expired
|
||||
}
|
||||
m_lifetimeTimer->setInterval(lifetimeMsec);
|
||||
m_lifetimeTimer->start();
|
||||
}
|
||||
|
||||
m_setSelected = setSelected;
|
||||
if (m_setSelected)
|
||||
setMapObjectSelected(m_setSelected);
|
||||
|
||||
TRACE_LOG(m_logger) << LOGFUNCTION << " END, newUniqueId = " << newUniqueId;
|
||||
}
|
||||
|
||||
void ObjectIndicatorImpl::setPointToPointTo(const QPointF &targetGeo, int lifetimeMsec)
|
||||
{
|
||||
TRACE_LOG(m_logger) << LOGFUNCTION << " START, targetGeo = " << targetGeo
|
||||
<< ", lifetimeMsec=" << lifetimeMsec;
|
||||
|
||||
connect(m_mapImpl, &MapImpl::extentChangedDelayed,
|
||||
this, &ObjectIndicatorImpl::update, Qt::UniqueConnection);
|
||||
|
||||
clearCurrentSelection();
|
||||
|
||||
addRemoveCallback(m_uniqueIdToPointTo, AddRemove::Remove);
|
||||
m_uniqueIdToPointTo = INVALID_MAP_ID;
|
||||
m_targetGeo2D = targetGeo;
|
||||
|
||||
update();
|
||||
|
||||
if (m_lifetimeTimer)
|
||||
m_lifetimeTimer->stop();
|
||||
|
||||
if (lifetimeMsec > 1)
|
||||
{
|
||||
if (!m_lifetimeTimer)
|
||||
{
|
||||
m_lifetimeTimer = new QTimer(this);
|
||||
m_lifetimeTimer->setSingleShot(true);
|
||||
connect(m_lifetimeTimer.data(), &QTimer::timeout, this, &ObjectIndicatorImpl::remove); // lifetime expired
|
||||
}
|
||||
m_lifetimeTimer->setInterval(lifetimeMsec);
|
||||
m_lifetimeTimer->start();
|
||||
}
|
||||
}
|
||||
|
||||
void ObjectIndicatorImpl::clearCurrentSelection()
|
||||
{
|
||||
ObjectContainer &objCont = m_mapImpl->objectContainer();
|
||||
const QList<ObjectContainer::Object*> &allObj = objCont.getAllObjects();
|
||||
|
||||
for (ObjectContainer::Object* mapObj : allObj)
|
||||
{
|
||||
if (!mapObj)
|
||||
continue;
|
||||
if (!mapObj->selected())
|
||||
continue;
|
||||
mapObj->setSelected(false);
|
||||
mapObj->updateView();
|
||||
}
|
||||
}
|
||||
|
||||
bool ObjectIndicatorImpl::update()
|
||||
{
|
||||
if (!m_updateTimer)
|
||||
return false;
|
||||
m_updateTimer->start(); // start is restart
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ObjectIndicatorImpl::updateImpl()
|
||||
{
|
||||
DEBUG_LOG(m_logger) << LOGFUNCTION << " START"
|
||||
<< ", m_uniqueIdToPointTo = " << m_uniqueIdToPointTo;
|
||||
|
||||
if (!m_qGraphicsView)
|
||||
return false;
|
||||
if (!m_qGraphicsScene)
|
||||
return false;
|
||||
|
||||
if (!SituationMap::isUniqueMapIdValid(m_uniqueIdToPointTo) && m_targetGeo2D.isNull())
|
||||
return false;
|
||||
|
||||
|
||||
//
|
||||
// Line:
|
||||
//
|
||||
Point3D targetGeo;
|
||||
QColor color = m_defaultColor;
|
||||
|
||||
|
||||
// center:
|
||||
bool targetIsValid = false;
|
||||
if (!m_targetGeo2D.isNull())
|
||||
{
|
||||
DEBUG_LOG(m_logger) << LOGFUNCTION << " target: m_targetGeo2D= " << m_targetGeo2D;
|
||||
targetGeo = Point3D::fromQPointF(m_targetGeo2D);
|
||||
targetIsValid = true;
|
||||
} else {
|
||||
DEBUG_LOG(m_logger) << LOGFUNCTION << " target: m_uniqueIdToPointTo= " << m_uniqueIdToPointTo;
|
||||
if (!SituationMap::isUniqueMapIdValid(m_uniqueIdToPointTo))
|
||||
return false;
|
||||
targetIsValid = centerOfTarget(targetGeo, color);
|
||||
}
|
||||
|
||||
|
||||
QRectF rect = m_qGraphicsScene->sceneRect();
|
||||
DEBUG_LOG(m_logger) << LOGFUNCTION << " rect: " << rect;
|
||||
|
||||
QBrush brush(color, Qt::SolidPattern);
|
||||
QPen pen(brush, m_lineWidth, Qt::DashLine);
|
||||
|
||||
QPointF targetSceneCoordinate;
|
||||
if (targetIsValid)
|
||||
{
|
||||
if (m_mapImpl->getElevationMapManager())
|
||||
{
|
||||
const double ele = m_mapImpl->getElevationMapManager()->elevation(targetGeo.x(), targetGeo.y());
|
||||
targetGeo.rz() += ele; // targetGeo should contain an absolute z-value
|
||||
}
|
||||
QPointF targetWindowCoord = m_mapImpl->geoCoordinateToViewPortWindowPoint3D(targetGeo);
|
||||
targetSceneCoordinate = m_qGraphicsView->mapToScene(targetWindowCoord.toPoint());
|
||||
if (targetSceneCoordinate.isNull())
|
||||
{
|
||||
INFO_LOG(m_logger) << LOGFUNCTION << " targetSceneCoordinate invisible!!!?";
|
||||
targetSceneCoordinate = rect.center();
|
||||
}
|
||||
|
||||
QLineF lineData(rect.center(), targetSceneCoordinate);
|
||||
if (!m_qGraphicsLine)
|
||||
m_qGraphicsLine = m_qGraphicsScene->addLine(lineData, pen);
|
||||
m_qGraphicsLine->setLine(lineData);
|
||||
m_qGraphicsLine->setPen(pen);
|
||||
|
||||
DEBUG_LOG(m_logger) << LOGFUNCTION
|
||||
<< ", rect.center() " << rect.center()
|
||||
<< ", bCenterOfTarget " << targetIsValid
|
||||
<< ", targetGeo:" << targetGeo
|
||||
<< ", targetSceneCoordinate " << targetSceneCoordinate;
|
||||
}
|
||||
else
|
||||
{
|
||||
delete m_qGraphicsLine;
|
||||
m_qGraphicsLine = nullptr;
|
||||
targetSceneCoordinate = rect.center();
|
||||
}
|
||||
|
||||
//
|
||||
// ArrowTip:
|
||||
//
|
||||
m_arrowTip = QPixmap::fromImage(renderArrowHeadSymbol(color, 30, 10));
|
||||
|
||||
if (!m_qGraphicsArrowTip)
|
||||
{
|
||||
m_qGraphicsArrowTip = m_qGraphicsScene->addPixmap(m_arrowTip);
|
||||
m_qGraphicsArrowTip->setOffset(m_arrowTip.width() / -2.0, 0);
|
||||
}
|
||||
m_qGraphicsArrowTip->setPixmap(m_arrowTip);
|
||||
m_qGraphicsArrowTip->setPos(targetSceneCoordinate);
|
||||
|
||||
const double lineAngle = MathUtils::getAngleDegreeNorth(targetSceneCoordinate, rect.center());
|
||||
|
||||
const double angle = 360.0 - (lineAngle);
|
||||
DEBUG_LOG(m_logger) << LOGFUNCTION << ", lineAngle " << lineAngle
|
||||
<< ", angle " << angle;
|
||||
|
||||
// Sets the clockwise rotation angle, in degrees, around the Z axis.
|
||||
m_qGraphicsArrowTip->setRotation(angle);
|
||||
|
||||
//
|
||||
// centerMarker:
|
||||
//
|
||||
rect = QRect(rect.center().x() - m_markerSize * 0.5, rect.center().y() - m_markerSize * 0.5,
|
||||
m_markerSize, m_markerSize);
|
||||
|
||||
if (!m_qGraphicsCenterMarker)
|
||||
m_qGraphicsCenterMarker = m_qGraphicsScene->addEllipse(rect, pen, brush);
|
||||
m_qGraphicsCenterMarker->setRect(rect);
|
||||
m_qGraphicsCenterMarker->setPen(QPen(color, Qt::DashLine));
|
||||
m_qGraphicsCenterMarker->setBrush(brush);
|
||||
|
||||
TRACE_LOG(m_logger) << LOGFUNCTION << " END";
|
||||
return true;
|
||||
}
|
||||
|
||||
void ObjectIndicatorImpl::onMapDestroyed()
|
||||
{
|
||||
TRACE_LOG(m_logger) << LOGFUNCTION << " START";
|
||||
remove();
|
||||
TRACE_LOG(m_logger) << LOGFUNCTION << " END";
|
||||
}
|
||||
|
||||
AbstractMapObjectImpl *ObjectIndicatorImpl::getObject(const UniqueMapId &uniqueId)
|
||||
{
|
||||
TRACE_LOG(m_logger) << LOGFUNCTION << " START, uniqueId = " << uniqueId;
|
||||
|
||||
if (!SituationMap::isUniqueMapIdValid(uniqueId))
|
||||
{
|
||||
DEBUG_LOG(m_logger) << LOGFUNCTION << " uniqueId invalid: " << uniqueId;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
if (!m_mapImpl->objectFactory().contains(uniqueId))
|
||||
{
|
||||
DEBUG_LOG(m_logger) << LOGFUNCTION << " m_uniqueIdToPointTo not found: " << m_uniqueIdToPointTo;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
AbstractMapObjectImpl *impl = dynamic_cast<AbstractMapObjectImpl *>(m_mapImpl->objectFactory().idToMapObject(uniqueId));
|
||||
TRACE_LOG(m_logger) << LOGFUNCTION << " END, uniqueId = " << uniqueId;
|
||||
return impl;
|
||||
}
|
||||
|
||||
bool ObjectIndicatorImpl::addRemoveCallback(const UniqueMapId &uniqueId, AddRemove addRemove)
|
||||
{
|
||||
TRACE_LOG(m_logger) << LOGFUNCTION << " START, uniqueId = " << uniqueId
|
||||
<< " addRemove = " << (int)addRemove;
|
||||
|
||||
if (!SituationMap::isUniqueMapIdValid(uniqueId))
|
||||
{
|
||||
DEBUG_LOG(m_logger) << LOGFUNCTION << " uniqueId invalid: " << uniqueId;
|
||||
return false;
|
||||
}
|
||||
|
||||
AbstractMapObjectImpl *impl = getObject(uniqueId);
|
||||
|
||||
if (!impl)
|
||||
return false;
|
||||
|
||||
const QString &objToPointToDebugInfo = impl->debugInfo();
|
||||
DEBUG_LOG(m_logger) << LOGFUNCTION << " uniqueId is valid, uniqueId=" << uniqueId
|
||||
<< ", (objToPointToDebugInfo=" << objToPointToDebugInfo << ")";
|
||||
|
||||
if (addRemove == AddRemove::Add)
|
||||
impl->addChangedCallback(this);
|
||||
else
|
||||
impl->removeChangedCallback(this);
|
||||
|
||||
TRACE_LOG(m_logger) << LOGFUNCTION << " END, uniqueId = " << uniqueId
|
||||
<< ", addRemove = " << (int)addRemove;
|
||||
return true;
|
||||
}
|
||||
|
||||
void ObjectIndicatorImpl::remove()
|
||||
{
|
||||
TRACE_LOG(m_logger) << LOGFUNCTION << " START, m_uniqueIdToPointTo=" << m_uniqueIdToPointTo;
|
||||
disconnect(this);
|
||||
|
||||
if (m_updateTimer)
|
||||
m_updateTimer->stop();
|
||||
|
||||
addRemoveCallback(m_uniqueIdToPointTo, AddRemove::Remove);
|
||||
|
||||
// if we set the object selected, remove selection
|
||||
if (m_setSelected)
|
||||
setMapObjectSelected(false);
|
||||
|
||||
m_uniqueIdToPointTo = INVALID_MAP_ID;
|
||||
m_targetGeo2D = QPointF();
|
||||
delete m_qGraphicsCenterMarker;
|
||||
delete m_qGraphicsLine;
|
||||
delete m_qGraphicsArrowTip;
|
||||
|
||||
m_qGraphicsCenterMarker = nullptr;
|
||||
m_qGraphicsLine = nullptr;
|
||||
m_qGraphicsArrowTip = nullptr;
|
||||
|
||||
updateImpl();
|
||||
TRACE_LOG(m_logger) << LOGFUNCTION << " END, m_uniqueIdToPointTo=" << m_uniqueIdToPointTo;
|
||||
}
|
||||
|
||||
void ObjectIndicatorImpl::onOriginPositionChanged()
|
||||
{
|
||||
TRACE_LOG(m_logger) << LOGFUNCTION << " update...";
|
||||
update();
|
||||
}
|
||||
|
||||
bool ObjectIndicatorImpl::centerOfTarget(Point3D &objCenterPoint, QColor &objColor)
|
||||
{
|
||||
TRACE_LOG(m_logger) << LOGFUNCTION << " START";
|
||||
|
||||
//
|
||||
// point to desired obj:
|
||||
//
|
||||
RefPointer<AbstractMapObject> objToPointTo;
|
||||
if (!SituationMap::isUniqueMapIdValid(m_uniqueIdToPointTo))
|
||||
{
|
||||
DEBUG_LOG(m_logger) << LOGFUNCTION << " m_uniqueIdToPointTo invalid: " << m_uniqueIdToPointTo;
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!m_mapImpl->objectFactory().contains(m_uniqueIdToPointTo))
|
||||
{
|
||||
DEBUG_LOG(m_logger) << LOGFUNCTION << " m_uniqueIdToPointTo not found: " << m_uniqueIdToPointTo;
|
||||
return false;
|
||||
}
|
||||
|
||||
objToPointTo = m_mapImpl->objectFactory().get(m_uniqueIdToPointTo);
|
||||
|
||||
// retrive values from objToPointTo:
|
||||
|
||||
if (!objToPointTo.valid())
|
||||
{
|
||||
WARNING_LOG(m_logger) << LOGFUNCTION << " objToPointTo not found";
|
||||
return false;
|
||||
}
|
||||
|
||||
AbstractMapObjectImpl *impl = dynamic_cast<AbstractMapObjectImpl *>(objToPointTo.get());
|
||||
if (!impl)
|
||||
{
|
||||
WARNING_LOG(m_logger) << LOGFUNCTION << " dynamic_cast failed";
|
||||
return false;
|
||||
}
|
||||
|
||||
// get target position:
|
||||
BoundingBox bbox;
|
||||
objToPointTo->boundingBox(bbox);
|
||||
if (!bbox.isValid())
|
||||
WARNING_LOG(m_logger) << LOGFUNCTION << " boundingBox not valid: bbox = " << bbox;
|
||||
|
||||
const QString &objToPointToDebugInfo = objToPointTo->debugInfo();
|
||||
DEBUG_LOG(m_logger) << LOGFUNCTION
|
||||
<< ", objToPointTo is valid, uniqueIdToPointTo = " << m_uniqueIdToPointTo
|
||||
<< ", (objToPointToDebugInfo = " << objToPointToDebugInfo << ")"
|
||||
<< ", bbox= " << bbox;
|
||||
|
||||
|
||||
objCenterPoint = bbox.center();
|
||||
|
||||
// objColor:
|
||||
objColor = impl->majorColor();
|
||||
|
||||
TRACE_LOG(m_logger) << LOGFUNCTION << " END";
|
||||
return true;
|
||||
}
|
||||
|
||||
QImage ObjectIndicatorImpl::renderArrowHeadSymbol(const QColor &color, int length, int halfWidth)
|
||||
{
|
||||
int width = halfWidth * 2;
|
||||
QImage image(width, length, QImage::Format_ARGB32);
|
||||
image.fill(Qt::transparent);
|
||||
|
||||
QPainter painter(&image);
|
||||
painter.setRenderHints(QPainter::Antialiasing);
|
||||
|
||||
QPen pen(color);
|
||||
pen.setWidth(2);
|
||||
painter.setPen(pen);
|
||||
|
||||
painter.setBrush(QBrush(color, Qt::BrushStyle::SolidPattern));
|
||||
|
||||
// 2 ||
|
||||
// | |
|
||||
// 1 | | 3
|
||||
|
||||
QPolygon poly;
|
||||
poly.reserve(3);
|
||||
poly.append(QPoint(0, length));
|
||||
poly.append(QPoint(halfWidth, 0));
|
||||
poly.append(QPoint(width, length));
|
||||
|
||||
painter.drawPolygon(poly);
|
||||
|
||||
painter.end();
|
||||
|
||||
// image.save(QLatin1String("/tmp/Arrow.png"));
|
||||
return image;
|
||||
}
|
||||
|
||||
bool ObjectIndicatorImpl::setMapObjectSelected(bool selected)
|
||||
{
|
||||
// 'clear' current selection:
|
||||
clearCurrentSelection();
|
||||
|
||||
if (!selected)
|
||||
return true; // already done by clearCurrentSelection :-)
|
||||
|
||||
if (!SituationMap::isUniqueMapIdValid(m_uniqueIdToPointTo))
|
||||
return false;
|
||||
|
||||
RefPointer<AbstractMapObject> objToPointTo = m_mapImpl->objectFactory().get(m_uniqueIdToPointTo);
|
||||
// retrive values from objToPointTo:
|
||||
if (!objToPointTo.valid())
|
||||
{
|
||||
WARNING_LOG(m_logger) << LOGFUNCTION << " objToPointTo not found";
|
||||
return false;
|
||||
}
|
||||
AbstractMapObjectImpl *impl = dynamic_cast<AbstractMapObjectImpl *>(objToPointTo.get());
|
||||
if (!impl)
|
||||
{
|
||||
WARNING_LOG(m_logger) << LOGFUNCTION << " dynamic_cast failed";
|
||||
return false;
|
||||
}
|
||||
|
||||
if (impl->selected() == selected)
|
||||
return true;
|
||||
impl->setSelected(selected);
|
||||
return impl->updateView();
|
||||
}
|
||||
|
||||
} // namespace SituationMap
|
||||
Reference in new issue
Block a user