360 lines
12 KiB
C++
Executable File
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 */
|