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

315 lines
11 KiB
C++
Executable File

/**
**
** @RDE_HEADER@
** Implementation of base class for rubberband frame handles
** $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 .........:
**
** 27.03.2015, JT : First edition for use with Qt5
**
** -----------------------------------------------------------------------------------------------
*/
#include "rubberband_frame_handle.h"
#include <MathUtils/math_const.h>
#include <arcgis/Map.h>
#include <arcgis/MapGraphicsView.h>
#include <QtWidgets/QGraphicsScene>
namespace SituationMap { namespace RB
{
static QGraphicsPolygonItem * createFrameGraphic( QGraphicsScene * mapScene, qreal zBufferValue )
{
if (mapScene != nullptr)
{
QGraphicsPolygonItem * frameSymbol = new QGraphicsPolygonItem();
frameSymbol -> setZValue( zBufferValue );
frameSymbol -> setFlags( QGraphicsItem::ItemIgnoresTransformations );
mapScene -> addItem( frameSymbol );
return frameSymbol;
}
return nullptr;
} /* createFrameGraphic */
class FramePoint : public QPointF
{
public:
Q_DECL_CONSTEXPR FramePoint(const QPointF &p) : QPointF(p) {}
Q_DECL_CONSTEXPR FramePoint(qreal x, qreal y) : QPointF(x, y) {}
FramePoint rotate(const QPointF &center, qreal sinA, qreal cosA) const
{
qreal cx = x() - center.x();
qreal cy = y() - center.y();
qreal px = cx*cosA - cy*sinA + center.x();
qreal py = cy*cosA + cx*sinA + center.y();
return FramePoint(px, py);
} // rotate( const QPointF & center, qreal sin qreal cosA )
FramePoint rotate(const RubberbandHandle::RubberbandCoordinate & center, qreal sinA, qreal cosA) const
{
return rotate(QPointF(center._mapCoordinate.x(), center._mapCoordinate.y()), sinA, cosA);
} /* rotate */
FramePoint rotate(qreal sinA, qreal cosA) const
{
return rotate(QPointF(), sinA, cosA);
} // rotate( const QPointF & center, qreal sin qreal cosA )
}; /* FramePoint */
RubberbandFrameHandle::RubberbandFrameHandle( Esri::ArcGISRuntime::MapGraphicsView * mapView
, QGraphicsScene * scene
, qreal sceneMargin )
: RubberbandHandle(mapView,scene)
, _frameSymbol(nullptr)
, _frameSceneMargin(sceneMargin)
, _frameRotationSin(0)
, _frameRotationCos(1)
, _frameWidth(0)
, _frameHeight(0)
, _frameCenterCoordinate()
, _mapRotateSin(0)
, _mapRotateCos(1)
, _drawDisabled(false)
, _frameLineHandleList()
{
qreal mapRotatePhi = _mapView->mapRotation() * MathConst::pi / 180.0;
_mapRotateSin = sin(mapRotatePhi);
_mapRotateCos = cos(mapRotatePhi);
zBufferPlane( ZBufferPlane::FrameHandle );
_frameSymbol = createFrameGraphic( _scene, _zBufferValue );
if (_drawDisabled) _frameSymbol->hide();
updateGraphic();
} /* RubberbandFrameHandle::RubberbandFrameHandle */
RubberbandFrameHandle::~RubberbandFrameHandle()
{
if (_scene)
{
if (_frameSymbol)
{
_scene->removeItem(_frameSymbol);
delete _frameSymbol;
}
}
_frameSymbol = nullptr;
} /* RubberbandFrameHandle::~RubberbandFrameHandle */
void RubberbandFrameHandle::buildFrameVertexCoordinates()
{
auto length = [](qreal x, qreal y) -> qreal { return sqrt(x*x+y*y); };
QPointF center( _frameCenterCoordinate._mapCoordinate.x(), _frameCenterCoordinate._mapCoordinate.y());
RubberbandCoordinate marginP( _mapView, _frameCenterCoordinate._sceneCoordinate+QPointF(_frameSceneMargin,0) );
qreal margin = length( marginP._mapCoordinate.x()-center.x(), marginP._mapCoordinate.y()-center.y() );
QPointF vertex[4];
qreal frameWidth2 = _frameWidth * 0.5;
qreal frameHeight2 = _frameHeight * 0.5;
vertex[0] = QPointF( center.x() - frameWidth2 - margin, center.y() - frameHeight2 - margin );
vertex[1] = QPointF( center.x() + frameWidth2 + margin, center.y() - frameHeight2 - margin );
vertex[2] = QPointF( center.x() + frameWidth2 + margin, center.y() + frameHeight2 + margin );
vertex[3] = QPointF( center.x() - frameWidth2 - margin, center.y() + frameHeight2 + margin );
for (int i = 0; i < 4; ++i)
{
const FramePoint & v = FramePoint(vertex[i]).rotate(_frameCenterCoordinate, -_frameRotationSin, _frameRotationCos );
_frameVertexCoordinate[i] = RubberbandCoordinate(_mapView, convert(v, _mapView->map()->spatialReference()));
}
// Now we have the vertex coordinates in map coordinate system
} /* RubberbandFrameHandle::buildFrameVertexCoordinates */
void RubberbandFrameHandle::adjustCoordinates()
{
qreal mapRotatePhi = _mapView->mapRotation() * MathConst::pi / 180.0;
_mapRotateSin = sin(mapRotatePhi);
_mapRotateCos = cos(mapRotatePhi);
_frameCenterCoordinate.mapToScene(_mapView);
buildFrameVertexCoordinates();
updateFramePolygonItem();
emit adjusted();
} /* RubberbandFrameHandle::adjustCoordinates */
void RubberbandFrameHandle::adjustWindow( const QRectF& )
{
onDo_adjustCoordinates();
} /* RubberbandFrameHandle::adjustWindow */
void RubberbandFrameHandle::updateFrameShape( const QVector<RubberbandCoordinate> & vertexList, qreal sinA, qreal cosA )
{
DEBUG_LOG(_logger) << LOGFUNCTION << "( const QVector<RubberbandCoordinate> & vertexList, qreal sinA, qreal cosA )";
qreal sinPhi = sinA * _mapRotateCos - cosA * _mapRotateSin; // Addition-Theorem get rotation of the frame without map rotation
qreal cosPhi = cosA * _mapRotateCos + sinA * _mapRotateSin;
qreal minX = std::numeric_limits<qreal>::infinity();
qreal maxX = -std::numeric_limits<qreal>::infinity();
qreal minY = std::numeric_limits<qreal>::infinity();
qreal maxY = -std::numeric_limits<qreal>::infinity();
for (const RubberbandCoordinate & vertex : vertexList)
{
// eliminate rotation from vertex scene coordinate
FramePoint xy = FramePoint(vertex._sceneCoordinate.x(),vertex._sceneCoordinate.y()).rotate( -sinPhi, cosPhi );
qreal x = xy.x();
qreal y = xy.y();
if (minX > x) minX = x;
if (minY > y) minY = y;
if (maxX < x) maxX = x;
if (maxY < y) maxY = y;
}
_frameRotationSin = sinA;
_frameRotationCos = cosA;
// calculate rotated coordinates (map rotation) of (minX,minY), (maxX,maxY) and frame scene center
FramePoint frameSceneV0 = FramePoint( minX , minY ).rotate( sinPhi, cosPhi );
FramePoint frameSceneVW = FramePoint( maxX , minY ).rotate( sinPhi, cosPhi );
FramePoint frameSceneVH = FramePoint( minX , maxY ).rotate( sinPhi, cosPhi );
FramePoint frameSceneCenter = FramePoint( (minX+maxX)*0.5, (minY+maxY)*0.5 ).rotate( sinPhi, cosPhi );
_frameCenterCoordinate.updateSceneCoordinate( _mapView, frameSceneCenter );
// Calculate map coordinates of bounding rectangle
RubberbandCoordinate frameV0( _mapView, QPointF(frameSceneV0.x(),frameSceneV0.y()) );
RubberbandCoordinate frameVW( _mapView, QPointF(frameSceneVW.x(),frameSceneVW.y()) );
RubberbandCoordinate frameVH( _mapView, QPointF(frameSceneVH.x(),frameSceneVH.y()) );
auto length = []( qreal x1, qreal y1, qreal x2, qreal y2 ) -> qreal
{
qreal dx = x2-x1;
qreal dy = y2-y1;
return sqrt(dx*dx+dy*dy);
};
// get frame width and height in map coordinates
_frameWidth = length( frameV0._mapCoordinate.x(), frameV0._mapCoordinate.y(), frameVW._mapCoordinate.x(), frameVW._mapCoordinate.y() );
_frameHeight = length( frameV0._mapCoordinate.x(), frameV0._mapCoordinate.y(), frameVH._mapCoordinate.x(), frameVH._mapCoordinate.y() );
buildFrameVertexCoordinates();
updateFramePolygonItem();
} /* RubberbandFrameHandle::updateFrameShape */
void RubberbandFrameHandle::updateFrameShape()
{
DEBUG_LOG(_logger) << LOGFUNCTION;
buildFrameVertexCoordinates();
updateFramePolygonItem();
} /* RubberbandFrameHandle::updateFrameShape */
void RubberbandFrameHandle::updateFramePolygonItem()
{
QPolygonF framePolygon;
framePolygon.reserve( 4 );
for (auto vertex : _frameVertexCoordinate)
{
framePolygon.append(vertex.mapToScene(_mapView));
}
framePolygon.append(_frameVertexCoordinate[0]._sceneCoordinate);
_frameSymbol->setPolygon(framePolygon);
} /* RubberbandFrameHandle::updateFramePolygonItem */
void RubberbandFrameHandle::updateGraphic()
{
if (_frameSymbol)
{
_frameSymbol -> setPen( QPen(QColor("black"),1,Qt::PenStyle::DashDotLine) );
_frameSymbol -> setVisible( _isVisible );
if (isSelected())
_frameSymbol -> setBrush( QBrush(_selectionColor) );
else
_frameSymbol -> setBrush( QBrush(_fillColor) );
}
} /* RubberbandFrameHandle::updateGraphic */
void RubberbandFrameHandle::updateCoordinate(const QPointF & scenePosition)
{
_frameCenterCoordinate.updateSceneCoordinate( _mapView, scenePosition );
updateFrameShape();
} /* RubberbandFrameHandle::updateCoordinate */
void RubberbandFrameHandle::moveCoordinate(const QPointF & sceneDelta)
{
_frameCenterCoordinate.updateSceneCoordinate( _mapView, _frameCenterCoordinate._sceneCoordinate+sceneDelta );
updateFrameShape();
} /* RubberbandFrameHandle::moveCoordinate */
RubberbandHandle::RubberbandCoordinate RubberbandFrameHandle::getCoordinate() const { return _frameCenterCoordinate; }
bool RubberbandFrameHandle::isPositionInside( const QPointF & scenePosition ) const
{
if (_frameSymbol)
{
return _frameSymbol->contains( scenePosition );
}
return false;
} /* RubberbandFrameHandle::isPositionInside */
} } /* namespace SituationMap::RB */