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

360 lines
12 KiB
C++
Executable File

/**
** @RDE_HEADER@
** Implementation of rubberband class to define multi point feature geoemtry with arrow
** $Id$
** $HeadURL$
** $Author$
**
** -----------------------------------------------------------------------------------------------
**
** Hardware-Environment: Intel-PC
** Software-Environment: Windows 7, Qt 5.4. ArcGIS 10.2.5
**
** Language ........: C++ 11
**
** -----------------------------------------------------------------------------------------------
**
** Author ...........: Jörg Turla, SPD G, Tel. 3132
**
** -----------------------------------------------------------------------------------------------
**
** Notes .........:
**
** 21.08.2015, JT : First edition for use with Qt5
**
** -----------------------------------------------------------------------------------------------
*/
#include "rubberband_arrow.h"
#include "rubberband_frame_handle.h"
#include "rubberband_line_handle.h"
#include "rubberband_point_handle.h"
#include "rubberband_drawable.h"
#include "drawable_painter_path.h"
#include "rubberband_internal.h"
#include "rubberband_base_internal.h"
namespace SituationMap { namespace RB
{
struct RubberbandArrow::InternalData
{
SituationMap::RefPointer<RubberbandPointHandle> _arrowHandle;
SituationMap::RefPointer<DrawablePainterPath> _arrowItem;
}; /* struct RubberbandArrow::InternalData */
RubberbandArrow::RubberbandArrow( SituationMap::Map * map, QObject * parent )
: RubberbandMultiPointFeature(map,parent)
, _internal(new InternalData)
, _arrowSceneHalfWidth(0)
, _arrowSceneLength(0)
{
_isClosed = false;
} /* RubberbandArrow::RubberbandArrow */
RubberbandArrow::~RubberbandArrow()
{
delete _internal;
_internal = nullptr;
} /* RubberbandArrow::~RubberbandArrow */
unsigned int RubberbandArrow::arrowHalfWidth() const { return _arrowSceneHalfWidth; }
unsigned int RubberbandArrow::arrowLength() const { return _arrowSceneLength; }
void RubberbandArrow::setCoordinateVector(const QVector<QPointF> & coordinateVec, CoordinateSystem cs )
{
setCoordinateVectorArrow( coordinateVec, 0.0, 0.0, cs );
} /* RubberbandArrow::coordinateVector */
void RubberbandArrow::setCoordinateVectorArrow(const QVector<QPointF> & coordinateVec, unsigned int arrowHalfWidth, unsigned int arrowLength, CoordinateSystem cs )
{
if (coordinateVec.size() < 2) return;
RubberbandMultiPointFeature::setCoordinateVector( coordinateVec, cs );
const QPointF & aux = pixel2ScenePosition(arrowHalfWidth,arrowLength);
_arrowSceneHalfWidth = (unsigned int) aux.x();
_arrowSceneLength = (unsigned int) aux.y();
enableModificationState();
constructArrowHandle();
_baseInternal->_applyIsPossible = true;
activateButtons();
} /* RubberbandArrow::setCoordinateVectorArrow */
QPointF RubberbandArrow::getArrowHandleScenePosition()
{
if (!_arrowSceneLength) _arrowSceneLength = 40;
if (!_arrowSceneHalfWidth) _arrowSceneHalfWidth = 20;
QPointF p0 = static_cast<RubberbandPointHandle*>(Rubberband::_internal->_handleList.end()[-2].get())->getCoordinate()._sceneCoordinate;
QPointF p1 = static_cast<RubberbandPointHandle*>(Rubberband::_internal->_handleList.end()[-1].get())->getCoordinate()._sceneCoordinate;
QPointF rv( p0.x()-p1.x(), p0.y()-p1.y() );
rv /= sqrt(rv.x()*rv.x()+rv.y()*rv.y());
return QPointF( p1.x() + rv.x()*_arrowSceneLength - rv.y()*_arrowSceneHalfWidth ,
p1.y() + rv.y()*_arrowSceneLength + rv.x()*_arrowSceneHalfWidth );
} /* RubberbandArrow::getArrowHandleScenePosition */
QPointF RubberbandArrow::getArrowHandlePosition()
{
const QPointF & handlePos = getArrowHandleScenePosition();
RubberbandDrawable::RubberbandCoordinate mapHandlePos(Rubberband::_internal->_mapView, handlePos);
return QPointF( mapHandlePos._mapCoordinate.x(), mapHandlePos._mapCoordinate.y() );
} /* RubberbandArrow::getArrowhHandlePosition */
void RubberbandArrow::constructArrowHandle()
{
if (Rubberband::_internal->_handleList.size() < 2) return;
const QPointF & p = getArrowHandlePosition();
_internal->_arrowHandle = new RubberbandPointHandle( Rubberband::_internal->_mapView, Rubberband::_internal->_mapScene, p );
// ensure thate the arrow the arrow size in pixel remain the same size
connect( _internal->_arrowHandle.get(), &RubberbandHandle::adjusted, this, [this]() {
this->_internal->_arrowHandle->updateCoordinate( this->getArrowHandleScenePosition() );
this->updateArrowPath();
} );
update();
} /* RubberbandArrow::constructArrowhHandle */
void RubberbandArrow::constructArrow( const QPointF & p )
{
qreal p0X = static_cast<RubberbandPointHandle*>(Rubberband::_internal->_handleList.end()[-2].get())->getCoordinate()._sceneCoordinate.x();
qreal p0Y = static_cast<RubberbandPointHandle*>(Rubberband::_internal->_handleList.end()[-2].get())->getCoordinate()._sceneCoordinate.y();
qreal p1X = static_cast<RubberbandPointHandle*>(Rubberband::_internal->_handleList.end()[-1].get())->getCoordinate()._sceneCoordinate.x();
qreal p1Y = static_cast<RubberbandPointHandle*>(Rubberband::_internal->_handleList.end()[-1].get())->getCoordinate()._sceneCoordinate.y();
QPointF rv10( p0X-p1X , p0Y-p1Y );
QPointF rv1p( p.x()-p1X, p.y()-p1Y );
rv10 /= sqrt(rv10.x()*rv10.x()+rv10.y()*rv10.y());
qreal scalarProduct = QPointF::dotProduct(rv1p, rv10);
if (scalarProduct > 0.0)
{
_internal->_arrowHandle->getCoordinate().updateSceneCoordinate( Rubberband::_internal->_mapView, p );
_arrowSceneLength = (unsigned int) scalarProduct;
_arrowSceneHalfWidth = (unsigned int) sqrt( rv1p.x()*rv1p.x()+rv1p.y()*rv1p.y() - scalarProduct*scalarProduct );
}
} /* RubberbandArrow::constructArrow */
void RubberbandArrow::updateHandleScenePosition()
{
if (!_internal->_arrowHandle) return;
QPointF pos = getArrowHandleScenePosition();
_internal->_arrowHandle->updateCoordinate( pos );
} /* RubberbandArrow::updateHandleScenePosition */
void RubberbandArrow::updateArrowPath()
{
if (!_internal->_arrowHandle) return;
if (Rubberband::_internal->_handleList.size() < 2) return;
const QPointF & p0 = static_cast<RubberbandPointHandle*>(Rubberband::_internal->_handleList.end()[-2].get())->getCoordinate()._sceneCoordinate;
const QPointF & p1 = static_cast<RubberbandPointHandle*>(Rubberband::_internal->_handleList.end()[-1].get())->getCoordinate()._sceneCoordinate;
const QPointF & p = _internal->_arrowHandle->getCoordinate()._sceneCoordinate;
QPointF rv( p0.x()-p1.x(), p0.y()-p1.y() );
rv /= sqrt(rv.x()*rv.x()+rv.y()*rv.y());
if (!_internal->_arrowItem)
{
_internal->_arrowItem = new DrawablePainterPath( Rubberband::_internal->_mapView );
_internal->_arrowItem -> enableClosedLine( true );
_internal->_arrowItem -> fillSolid( true );
_internal->_arrowItem -> zBufferPlane( RubberbandDrawable::ZBufferPlane::ArrowSymbol );
}
QVector<QPointF> arrowPath;
arrowPath.append( p1 );
arrowPath.append( p );
arrowPath.append( QPointF( p1.x() + rv.x()*_arrowSceneLength + rv.y()*_arrowSceneHalfWidth
, p1.y() + rv.y()*_arrowSceneLength - rv.x()*_arrowSceneHalfWidth ) );
_internal->_arrowItem -> setPath( arrowPath );
RubberbandFrameHandle * frameHandle = getFrameHandle();
if (frameHandle)
{
QVector<RubberbandHandle::RubberbandCoordinate> vertexSet;
for (auto handle : qAsConst(Rubberband::_internal->_handleList))
{
RubberbandPointHandle * pointHandlePtr = dynamic_cast<RubberbandPointHandle*>(handle.get());
vertexSet.append(pointHandlePtr->getCoordinate() );
}
vertexSet.append( _internal->_arrowHandle->getCoordinate() );
vertexSet.append( RubberbandDrawable::RubberbandCoordinate(Rubberband::_internal->_mapView,p) );
frameHandle->updateFrameShape( vertexSet );
}
} /* RubberbandArrow::updateArrowPath */
bool RubberbandArrow::selectAction( AbstractEventDispatcher * causer, int x, int y )
{
Q_UNUSED(causer);
if (!rubberbandIsAlive()) return false;
bool eventHandled = false;
QPointF scenePos(pixel2ScenePosition(x,y));
if (_baseInternal->buttonProxyActive(scenePos)) return false;
_baseInternal->_lastClickPosition = scenePos;
if (isEnabledConstructionState()) return RubberbandMultiPointFeature::selectAction(causer,x,y);
if (_internal->_arrowHandle->isPositionInside(scenePos))
{
_internal->_arrowHandle->setSelection();
eventHandled = true;
}
else eventHandled = selectHandles( x, y, scenePos );
if (eventHandled)
{
update();
deactivateButtons();
}
return eventHandled;
} /* RubberbandArrow::selectAction */
bool RubberbandArrow::setCoordinateAction(AbstractEventDispatcher * causer, int x, int y)
{
Q_UNUSED(causer);
if (!rubberbandIsAlive()) return false;
bool eventHandled = false;
QPointF scenePos(pixel2ScenePosition(x,y));
Rubberband::_internal->_lastClickPosition = scenePos;
if (isEnabledConstructionState()) return RubberbandMultiPointFeature::setCoordinateAction(causer, x, y);
if (_internal->_arrowHandle->isSelected())
{
_internal->_arrowHandle->setSelection(false);
constructArrow(scenePos);
eventHandled = true;
}
else return RubberbandMultiPointFeature::setCoordinateAction(causer, x, y);
if (eventHandled) update();
updateButtonPosition();
activateButtons();
return eventHandled;
} /* RubberbandArrow::setCoordinateAction */
bool RubberbandArrow::movePickedAction(AbstractEventDispatcher * causer, int x, int y )
{
if (!rubberbandIsAlive()) return false;
if ((_internal->_arrowHandle) && (_internal->_arrowHandle->isSelected()))
{
QPointF scenePos(pixel2ScenePosition(x,y));
constructArrow( scenePos );
update();
return false;
}
return RubberbandMultiPointFeature::movePickedAction(causer,x,y);
} /* RubberbandArrow::movePickedAction */
bool RubberbandArrow::moveAction(AbstractEventDispatcher * causer, int x, int y)
{
QPointF scenePos(pixel2ScenePosition(x,y));
if (_internal->_arrowHandle)
{
if (_internal->_arrowHandle->isPositionInside(scenePos))
{
_internal->_arrowHandle->setSelection(true);
return false;
}
_internal->_arrowHandle->setSelection(false);
}
return RubberbandMultiPointFeature::moveAction(causer,x,y);
} /* RubberbandArrow::moveAction */
bool RubberbandArrow::completeStateAction(AbstractEventDispatcher * causer, int x, int y)
{
if ((rubberbandIsAlive()) && (Rubberband::_internal->_mapView) && (Rubberband::_internal->_mapScene))
{
if (isEnabledConstructionState())
{
if ((unsigned int)Rubberband::_internal->_handleList.size() >= _minimumPointCount)
{
constructArrowHandle();
}
update();
}
}
return RubberbandMultiPointFeature::completeStateAction(causer,x,y);;
} /* RubberbandArrow::completeStateAction */
void RubberbandArrow::update()
{
_isClosed = false;
RubberbandMultiPointFeature::update();
if (_internal->_arrowHandle)
{
_internal->_arrowHandle -> setDrawColor(_handleDrawColor );
_internal->_arrowHandle -> setFillColor(_handleFillColor );
_internal->_arrowHandle -> setSelectionColor(_handleSelectionColor );
_internal->_arrowHandle -> setPickingRatio( _pickingRatio );
updateHandleScenePosition();
updateArrowPath();
}
} /* RubberbandArrow::update */
} } /* namespace SituationMap::RB */