/** ** ** @RDE_HEADER@ ** Implementation of base class for rubberband 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_ellipse_handle.h" #include #include #include #include #include #include namespace SituationMap { namespace RB { RubberbandEllipseHandle::RubberbandEllipseHandle(Esri::ArcGISRuntime::MapGraphicsView * mapView, QGraphicsScene *scene) : RubberbandHandle(mapView, scene) { zBufferPlane( ZBufferPlane::LineHandle ); updateGraphic(); } RubberbandEllipseHandle::~RubberbandEllipseHandle() { if (!_scene) return; if (_ellipseSymbol) { _scene->removeItem(_ellipseSymbol); delete _ellipseSymbol; } } void RubberbandEllipseHandle::adjustCoordinates() { _center.mapToScene(_mapView); updateGraphic(); emit adjusted(); } void RubberbandEllipseHandle::adjustWindow( const QRectF& ) { onDo_adjustCoordinates(); } qreal length(const QPointF &p) { return sqrt(p.x()*p.x()+p.y()*p.y()); } void RubberbandEllipseHandle::updateGraphic() { if (_scene) { if (!_ellipseSymbol) { _ellipseSymbol = new QGraphicsEllipseItem(); _scene->addItem(_ellipseSymbol); _ellipseSymbol->setFlags( QGraphicsItem::ItemIgnoresTransformations ); } _ellipseSymbol->setZValue(_zValue); // Style makeLineStyle( _dottedLine, _lineStyle ); if (_isSelected) { _lineStyle.setWidth( _lineStyle.width() + 1 ); _lineStyle.setColor( _selectionColor ); } _ellipseSymbol->setPen(_lineStyle); if (isSelected()) _ellipseSymbol->setBrush( QBrush(_selectionColor) ); else _ellipseSymbol->setBrush( QBrush(_fillColor) ); _ellipseSymbol->setVisible(_isVisible); // geometry: { _center.mapToScene(_mapView); QPointF mapCenter( _center._mapCoordinate.x(), _center._mapCoordinate.y() ); qreal mapRotatePhi = _mapView->mapRotation() * MathConst::pi / 180.0; qreal sinMap = sin(mapRotatePhi); qreal cosMap = cos(mapRotatePhi); qreal sinPhi = _sinRect * cosMap + _cosRect * sinMap; qreal cosPhi = _cosRect * cosMap - _sinRect * sinMap; RubberbandCoordinate x0y0(_mapView, convert( mapCenter+QPointF(-_radiusX,-_radiusY), _mapView->map()->spatialReference()) ); RubberbandCoordinate x1y0(_mapView, convert( mapCenter+QPointF( _radiusX,-_radiusY), _mapView->map()->spatialReference()) ); RubberbandCoordinate x0y1(_mapView, convert( mapCenter+QPointF(-_radiusX, _radiusY), _mapView->map()->spatialReference()) ); const qreal width = length(x1y0._sceneCoordinate-x0y0._sceneCoordinate); const qreal height = length(x0y1._sceneCoordinate-x0y0._sceneCoordinate); // honor sector?? if (_sectorStart != _sectorEnd) { auto getAngle = [](qreal sinPhi, qreal cosPhi) -> int { qreal phi = acos( cosPhi ); if (sinPhi < 0) phi = MathConst::pi_two - phi; return int( (phi * 180.0 / MathConst::pi) * 16); }; // getAngle int startAngle = getAngle(_sectorStart.y(), _sectorStart.x()); int endAngle = getAngle( _sectorEnd.y(), _sectorEnd.x()); int spanAngle = (endAngle > startAngle) ? endAngle-startAngle : 5760-startAngle+endAngle; QColor fillColor = transparentFillColor(); _ellipseSymbol->setRect(-width*0.5, -height*0.5, width, height); _ellipseSymbol->setPen(_lineStyle ); _ellipseSymbol->setBrush( (fillColor.alpha() > 0) ? QBrush(fillColor) : QBrush() ); _ellipseSymbol->setTransform( QTransform( cosPhi, -sinPhi, sinPhi, cosPhi, _center._sceneCoordinate.x(), _center._sceneCoordinate.y() )); _ellipseSymbol->setStartAngle(startAngle ); _ellipseSymbol->setSpanAngle(spanAngle); _ellipseSymbol->setVisible(true); } _ellipseSymbol->setRect(-width*0.5, -height*0.5, width, height); _ellipseSymbol->setTransform( QTransform( cosPhi, -sinPhi, sinPhi, cosPhi, _center._sceneCoordinate.x(), _center._sceneCoordinate.y()) ); } } } QPointF RubberbandEllipseHandle::getRadius() { return {_radiusX, _radiusY}; } void RubberbandEllipseHandle::setRect(const RubberbandCoordinate ¢er, qreal radiusX, qreal radiusY, qreal sin, qreal cos, const QPointF §orStart, const QPointF §orEnd) { // p1,p2 = corner points of unrotated ellipse in scene coordinates _center = center; _radiusX = radiusX; _radiusY = radiusY; _sinRect = sin; _cosRect = cos; _sectorStart = sectorStart; _sectorEnd = sectorEnd; updateGraphic(); } bool RubberbandEllipseHandle::isPositionInside(const QPointF &scenePosition) const { if (_ellipseSymbol) { if (_ellipseSymbol->contains( scenePosition )) { return true; } // else // { // // Ok, Qt's methodes doesn't work safely // // if it fails do some own calculations // QPointF V0 = _coordinates[0]._sceneCoordinate; // QPointF V1 = _coordinates[1]._sceneCoordinate; // QPointF R = V1-V0; // QPointF P = scenePosition-V0; // qreal lenR = R.x() * R.x() + R.y() * R.y(); // qreal lenP = P.x() * P.x() + P.y() * P.y(); // if ((lenR == 0) || (lenP > lenR)) return false; // scene Position is to far away // // now check the direction // lenR = sqrt(lenR); // lenP = sqrt(lenP); // R /= lenR; // P /= lenP; // qreal cosPhi = QPointF::dotProduct(R,P); // if (cosPhi < 0) return false; // qreal epsilon = sqrt(1.0-cosPhi*cosPhi) * lenR; // return (epsilon < qreal(_pickingRatio)); // } } return false; } } }