Initial commit
This commit is contained in:
commit
b7d90b9afe
16245 files changed
+3396666
No files matched your search
+34
@@ -0,0 +1,34 @@
|
||||
// @RDE_HEADER@
|
||||
// Notizen zu den Rubberbands
|
||||
// $Id$
|
||||
// $HeadURL$
|
||||
// $Author$
|
||||
// Created by Norbert Thoden, SLSE, 2023-08-26
|
||||
|
||||
Notizen zu den Rubberbands
|
||||
|
||||
- Sie wurden von Jörg Turla erstellt
|
||||
|
||||
- 2023: Erweiterung durch Steve Kemayou and Norbert Thoden
|
||||
|
||||
Norbert Thoden, 08/2023 :
|
||||
- Habe ein neues RB erstellt: RubberbandMultiEllipseFeature
|
||||
- Vorlage war RubberbandMultiPointFeature (Polyline)
|
||||
Weiterer Stützpunte habe nicht mehr die Linie verlängtert, sondern neue Ellipse/Kreise eingefügt.
|
||||
|
||||
- API & Name wurden überwiegend für Ellipse konzipiert, getestet wurde aber im Wesentlichen mit Kreis (constrainQuadratic=true9
|
||||
|
||||
Probleme/ToDo sind u.a:
|
||||
- Screenresolution führt dazu, das bei eng gefassten Constraints (z.B. radius =5m, min/Max ebenfalls bei 5m)
|
||||
die checkMinMaxRadiusConstraint nicht bestehen und als Fehler betrachtet werden... :-(
|
||||
|
||||
- Setzen der Predefines Values (setCenterAndRadii) unterstützt noch keine Constraints
|
||||
|
||||
|
||||
Empfehlung für neues RB
|
||||
- Bedeutung erlernen von: selectAction, moveAction, movePickedAction und ihrer returnValues.
|
||||
- Hilfsfile für rotations methoden etc. um ständiges kopieren (von Lmabdas!?) zu vermeiden.
|
||||
- ...
|
||||
|
||||
: Norbert Thoden, 08/2023:
|
||||
|
||||
+149
@@ -0,0 +1,149 @@
|
||||
/* XPM */
|
||||
static const char * abort_xpm[] = {
|
||||
"24 24 122 2",
|
||||
" c None",
|
||||
". c #E98774",
|
||||
"+ c #F6866F",
|
||||
"@ c #FB6C50",
|
||||
"# c #F28773",
|
||||
"$ c #F8856E",
|
||||
"% c #EF8672",
|
||||
"& c #F5846E",
|
||||
"* c #F96346",
|
||||
"= c #F96042",
|
||||
"- c #F96649",
|
||||
"; c #F28670",
|
||||
"> c #8E5246",
|
||||
", c #F7836C",
|
||||
"' c #F96245",
|
||||
") c #F9674B",
|
||||
"! c #F18570",
|
||||
"~ c #F3836D",
|
||||
"{ c #F76245",
|
||||
"] c #F75F41",
|
||||
"^ c #F76447",
|
||||
"/ c #F2846E",
|
||||
"( c #945549",
|
||||
"_ c #F7806A",
|
||||
": c #F76143",
|
||||
"< c #F76548",
|
||||
"[ c #F0856F",
|
||||
"} c #E47B66",
|
||||
"| c #F56043",
|
||||
"1 c #F55D3F",
|
||||
"2 c #F56144",
|
||||
"3 c #9A574A",
|
||||
"4 c #F57E67",
|
||||
"5 c #F55E41",
|
||||
"6 c #F56245",
|
||||
"7 c #D1725F",
|
||||
"8 c #E55539",
|
||||
"9 c #F35A3C",
|
||||
"0 c #F35D40",
|
||||
"a c #F27F68",
|
||||
"b c #9F5A4C",
|
||||
"c c #F47B63",
|
||||
"d c #F35B3E",
|
||||
"e c #D44E34",
|
||||
"f c #E35337",
|
||||
"g c #F1583A",
|
||||
"h c #F15B3D",
|
||||
"i c #F17D66",
|
||||
"j c #F37860",
|
||||
"k c #F1593B",
|
||||
"l c #D14C32",
|
||||
"m c #DF5034",
|
||||
"n c #EE5638",
|
||||
"o c #EE583A",
|
||||
"p c #EE5739",
|
||||
"q c #CC4A30",
|
||||
"r c #DC4D31",
|
||||
"s c #EC5335",
|
||||
"t c #CA472D",
|
||||
"u c #D94B2F",
|
||||
"v c #E95133",
|
||||
"w c #C7452C",
|
||||
"x c #DF4B2E",
|
||||
"y c #E74E30",
|
||||
"z c #CE462B",
|
||||
"A c #A45949",
|
||||
"B c #E55235",
|
||||
"C c #E44C2E",
|
||||
"D c #E35A3F",
|
||||
"E c #975244",
|
||||
"F c #E76950",
|
||||
"G c #E2492B",
|
||||
"H c #E24B2D",
|
||||
"I c #E47059",
|
||||
"J c #83473C",
|
||||
"K c #E36A52",
|
||||
"L c #DF4628",
|
||||
"M c #E04A2C",
|
||||
"N c #E06F59",
|
||||
"O c #E16C55",
|
||||
"P c #DC4528",
|
||||
"Q c #DC4426",
|
||||
"R c #DD482B",
|
||||
"S c #DC6F59",
|
||||
"T c #DD6C56",
|
||||
"U c #DA4326",
|
||||
"V c #DA4123",
|
||||
"W c #D74022",
|
||||
"X c #D84123",
|
||||
"Y c #DB472A",
|
||||
"Z c #D96E59",
|
||||
"` c #DA6A55",
|
||||
" . c #D94325",
|
||||
".. c #D83F21",
|
||||
"+. c #D13D20",
|
||||
"@. c #D63F21",
|
||||
"#. c #DA472B",
|
||||
"$. c #D46C58",
|
||||
"%. c #D26A55",
|
||||
"&. c #D64326",
|
||||
"*. c #D53D1F",
|
||||
"=. c #CF3B1E",
|
||||
"-. c #D33C1F",
|
||||
";. c #D7482B",
|
||||
">. c #C36552",
|
||||
",. c #D03A1D",
|
||||
"'. c #D33B1D",
|
||||
"). c #CB391C",
|
||||
"!. c #D13A1D",
|
||||
"~. c #CA381C",
|
||||
"{. c #CD381A",
|
||||
"]. c #D2391B",
|
||||
"^. c #CB371A",
|
||||
"/. c #D0381B",
|
||||
"(. c #C7361A",
|
||||
"_. c #CA3518",
|
||||
":. c #D03719",
|
||||
"<. c #C93518",
|
||||
"[. c #CD3619",
|
||||
"}. c #C43417",
|
||||
"|. c #BF3216",
|
||||
"1. c #BD3116",
|
||||
" ",
|
||||
" . . ",
|
||||
" + @ # $ @ % ",
|
||||
" & * = - ; > , ' = ) ! ",
|
||||
" ~ { ] ] ] ^ / ( _ : ] ] ] < [ ",
|
||||
" } | 1 1 1 1 1 2 ~ 3 4 5 1 1 1 1 1 6 7 ",
|
||||
" 8 9 9 9 9 9 9 0 a b c d 9 9 9 9 9 9 e ",
|
||||
" f g g g g g g h i j k g g g g g g l ",
|
||||
" m n n n n n n o p n n n n n n q ",
|
||||
" r s s s s s s s s s s s s t ",
|
||||
" u v v v v v v v v v v w ",
|
||||
" x y y y y y y y y z ",
|
||||
" A B C C C C C C C C D ",
|
||||
" E F G G G G G G G G G H I ",
|
||||
" J K L L L L L L L L L L L M N ",
|
||||
" O P Q Q Q Q Q Q Q Q Q Q Q Q R S ",
|
||||
" T U V V V V V V W X V V V V V V Y Z ",
|
||||
" ` .............+. @.............#.$. ",
|
||||
" %.&.*.*.*.*.*.*.=. -.*.*.*.*.*.*.;.>. ",
|
||||
" ,.'.'.'.'.'.). !.'.'.'.'.'.~. ",
|
||||
" {.].].].^. /.].].].(. ",
|
||||
" _.:.<. [.:.}. ",
|
||||
" |. 1. ",
|
||||
" "};
|
||||
@@ -0,0 +1,291 @@
|
||||
/**
|
||||
**
|
||||
** @RDE_HEADER@
|
||||
** Abstract Event Dispatcher for Qt5
|
||||
** $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 .........:
|
||||
**
|
||||
** 28.04.2003, JT : First edition for use with Qt4 in START Feature Editor fee
|
||||
** 25.03.2015, JT : Refactoring for use with Qt5
|
||||
**
|
||||
** -----------------------------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
#include "abstract_event_dispatcher.h"
|
||||
#include "gestures.h"
|
||||
|
||||
#include <math.h>
|
||||
|
||||
#include <QtWidgets/QWidget>
|
||||
#include <QtCore/QCoreApplication>
|
||||
|
||||
|
||||
namespace SituationMap { namespace RB
|
||||
{
|
||||
|
||||
static QHash<QWidget*, QList<AbstractEventDispatcher*>> &runningDispatcher()
|
||||
{
|
||||
static QHash<QWidget*, QList<AbstractEventDispatcher*>> hashTable;
|
||||
return hashTable;
|
||||
} // runningDispatcher()
|
||||
|
||||
|
||||
QGestureRecognizer * AbstractEventDispatcher::_applyGestureDetection = nullptr;
|
||||
unsigned int AbstractEventDispatcher::_applyGestureID = 0;
|
||||
|
||||
|
||||
AbstractEventDispatcher::AbstractEventDispatcher( QWidget * getEventsFrom )
|
||||
: QObject(getEventsFrom)
|
||||
, _getEventsFrom(getEventsFrom)
|
||||
, _logger(getLogger("EventDispatcher"))
|
||||
, _cursorIsInWidget(false)
|
||||
, _synthesisTouchFromMouseEvents(false)
|
||||
, _deleteRequested(false)
|
||||
, _hasGrab(false)
|
||||
, _finishFlag(false)
|
||||
, _activeEvent(false)
|
||||
, _dispatcherCursor()
|
||||
, _whatsThisBackup()
|
||||
, _eventActions(nullptr)
|
||||
{
|
||||
DEBUG_LOG(_logger) << LOGFUNCTION << " " << this;
|
||||
initDispatcher();
|
||||
} /* AbstractEventDispatcher::AbstractEventDispatcher */
|
||||
|
||||
|
||||
AbstractEventDispatcher::AbstractEventDispatcher( QWidget * getEventsFrom, EventActionInterface * eventActions )
|
||||
: QObject(getEventsFrom)
|
||||
, _getEventsFrom(getEventsFrom)
|
||||
, _logger(getLogger("EventDispatcher"))
|
||||
, _cursorIsInWidget(false)
|
||||
, _synthesisTouchFromMouseEvents(false)
|
||||
, _deleteRequested(false)
|
||||
, _hasGrab(false)
|
||||
, _finishFlag(false)
|
||||
, _activeEvent(false)
|
||||
, _dispatcherCursor()
|
||||
, _whatsThisBackup()
|
||||
, _eventActions(eventActions)
|
||||
|
||||
{
|
||||
DEBUG_LOG(_logger) << LOGFUNCTION << " " << this;
|
||||
initDispatcher();
|
||||
} /* AbstractEventDispatcher::AbstractEventDispatcher */
|
||||
|
||||
|
||||
void AbstractEventDispatcher::initDispatcher()
|
||||
{
|
||||
_restoreCursor = _getEventsFrom->testAttribute(Qt::WA_SetCursor);
|
||||
|
||||
if (_restoreCursor)
|
||||
{
|
||||
_cursorToRestore = getCursorFromWidget();
|
||||
|
||||
DEBUG_LOG(_logger) << LOGFUNCTION << " this=" << this << " get cursorToRestore";
|
||||
}
|
||||
_restoreMouseTracking = _getEventsFrom->hasMouseTracking();
|
||||
|
||||
// {
|
||||
// bool activeEvent = _activeEvent;
|
||||
// _activeEvent = true; // don't process events while init has not been finished
|
||||
// QCoreApplication::process Events(); // remove events from event queue; in which circumstances this is necessary?
|
||||
// _activeEvent = activeEvent;
|
||||
// }
|
||||
|
||||
_getEventsFrom->setMouseTracking(true);
|
||||
_getEventsFrom->raise();
|
||||
_getEventsFrom->installEventFilter(this);
|
||||
|
||||
_synthesisTouchFromMouseEvents = QCoreApplication::testAttribute( Qt::AA_SynthesizeTouchForUnhandledMouseEvents );
|
||||
QCoreApplication::setAttribute( Qt::AA_SynthesizeTouchForUnhandledMouseEvents, false );
|
||||
QCoreApplication::setAttribute( Qt::AA_SynthesizeMouseForUnhandledTouchEvents, true );
|
||||
|
||||
static const Qt::GestureType gestures[] = { Qt::GestureType::TapGesture
|
||||
, Qt::GestureType::TapAndHoldGesture
|
||||
, Qt::GestureType::PanGesture
|
||||
, Qt::GestureType::PinchGesture
|
||||
, Qt::GestureType::SwipeGesture };
|
||||
|
||||
for (auto gestureType : gestures) _getEventsFrom->grabGesture(gestureType);
|
||||
|
||||
if (_applyGestureDetection == nullptr)
|
||||
{
|
||||
_applyGestureDetection = new ApplyGestureRecognizer();
|
||||
_applyGestureID = QGestureRecognizer::registerRecognizer( _applyGestureDetection );
|
||||
}
|
||||
|
||||
_getEventsFrom->grabGesture( (Qt::GestureType)_applyGestureID );
|
||||
_getEventsFrom->setAttribute( Qt::WA_AcceptTouchEvents, true );
|
||||
|
||||
runningDispatcher()[_getEventsFrom].append(this);
|
||||
} /* AbstractEventDispatcher::initDispatcher */
|
||||
|
||||
|
||||
AbstractEventDispatcher::~AbstractEventDispatcher()
|
||||
{
|
||||
DEBUG_LOG(_logger) << LOGFUNCTION << " " << this;
|
||||
|
||||
_finishFlag = true;
|
||||
|
||||
if (_getEventsFrom)
|
||||
{
|
||||
_getEventsFrom->removeEventFilter(this);
|
||||
_getEventsFrom->setMouseTracking( _restoreMouseTracking );
|
||||
|
||||
ungrab();
|
||||
|
||||
if (!_whatsThisBackup.isNull())
|
||||
{
|
||||
_getEventsFrom->setWhatsThis(_whatsThisBackup);
|
||||
}
|
||||
runningDispatcher()[_getEventsFrom].removeAll(this);
|
||||
}
|
||||
|
||||
QCoreApplication::setAttribute( Qt::AA_SynthesizeTouchForUnhandledMouseEvents, _synthesisTouchFromMouseEvents );
|
||||
|
||||
} /* AbstractEventDispatcher::~AbstractEventDispatcher */
|
||||
|
||||
|
||||
unsigned int AbstractEventDispatcher::numberOfEventDispatcher() const
|
||||
{
|
||||
return static_cast<unsigned int>( runningDispatcher()[_getEventsFrom].size() );
|
||||
} /* AbstractEventDispatcher::numberOfEventDispatcher */
|
||||
|
||||
|
||||
void AbstractEventDispatcher::onDo_delete()
|
||||
{
|
||||
if (_deleteRequested) return;
|
||||
_deleteRequested = true;
|
||||
QObject::deleteLater();
|
||||
} /* AbstractEventDispatcher::onDo_delete */
|
||||
|
||||
|
||||
void AbstractEventDispatcher::KickTheBucket()
|
||||
{
|
||||
if (_getEventsFrom == nullptr) return;
|
||||
|
||||
_finishFlag = true;
|
||||
|
||||
unlinkEventDispatcher();
|
||||
|
||||
_getEventsFrom->removeEventFilter(this);
|
||||
_getEventsFrom->setMouseTracking( _restoreMouseTracking );
|
||||
|
||||
ungrab();
|
||||
|
||||
if (!_whatsThisBackup.isNull())
|
||||
{
|
||||
_getEventsFrom->setWhatsThis(_whatsThisBackup);
|
||||
}
|
||||
|
||||
runningDispatcher()[_getEventsFrom].removeAll(this);
|
||||
_getEventsFrom = nullptr;
|
||||
|
||||
emit signalKickTheBucket();
|
||||
|
||||
// QCoreApplication::sendPostedEvents();
|
||||
// QCoreApplication::process Events(); // dispatch window system events
|
||||
|
||||
onDo_delete();
|
||||
|
||||
} /* AbstractEventDispatcher::KickTheBucket */
|
||||
|
||||
|
||||
void AbstractEventDispatcher::onDo_kickTheBucket() { KickTheBucket(); }
|
||||
|
||||
|
||||
void AbstractEventDispatcher::setWhatsThis(const QString & whatsThis)
|
||||
{
|
||||
if (_whatsThisBackup.isNull())
|
||||
{
|
||||
_whatsThisBackup = _getEventsFrom->whatsThis();
|
||||
}
|
||||
_getEventsFrom->setWhatsThis(whatsThis);
|
||||
} /* AbstractEventDispatcher::setWhatsThis */
|
||||
|
||||
|
||||
|
||||
void AbstractEventDispatcher::grab()
|
||||
{
|
||||
if (_hasGrab) return;
|
||||
_hasGrab = true;
|
||||
DEBUG_LOG(_logger) << LOGFUNCTION << " this=" << this << " set dispatcherCursor = " << (int)_dispatcherCursor.shape();
|
||||
setCursorToWidget( _dispatcherCursor );
|
||||
_getEventsFrom -> setFocus();
|
||||
} /* AbstractEventDispatcher::Grab */
|
||||
|
||||
|
||||
void AbstractEventDispatcher::ungrab()
|
||||
{
|
||||
if (!_hasGrab) return;
|
||||
|
||||
_hasGrab = false;
|
||||
if (_restoreCursor)
|
||||
{
|
||||
DEBUG_LOG(_logger) << LOGFUNCTION << " this=" << this << " set cursorToRestore = " << (int)_cursorToRestore.shape();
|
||||
setCursorToWidget( _cursorToRestore );
|
||||
}
|
||||
else _getEventsFrom -> unsetCursor();
|
||||
|
||||
_getEventsFrom -> clearFocus();
|
||||
|
||||
} /* AbstractEventDispatcher::Ungrab */
|
||||
|
||||
|
||||
bool AbstractEventDispatcher::eventFilter( QObject * widget, QEvent * e )
|
||||
{
|
||||
if (widget != ((QObject*)_getEventsFrom)) return false;
|
||||
|
||||
if (_logger.isDebugEnabled())
|
||||
{
|
||||
switch (e->type())
|
||||
{
|
||||
case QEvent::CursorChange:
|
||||
{
|
||||
QCursor cursor = _getEventsFrom->cursor();
|
||||
DEBUG_LOG(_logger) << LOGFUNCTION << " Cursor has changed, this = " << this << " cursor = " << cursor.shape();
|
||||
} break;
|
||||
|
||||
case QEvent::Enter :
|
||||
{
|
||||
_cursorIsInWidget = true;
|
||||
QCursor cursor = _getEventsFrom->cursor();
|
||||
DEBUG_LOG(_logger) << LOGFUNCTION << " Enter event, this = " << this << " cursor = " << cursor.shape();
|
||||
} break;
|
||||
|
||||
case QEvent::Leave :
|
||||
{
|
||||
_cursorIsInWidget = false;
|
||||
QCursor cursor = _getEventsFrom->cursor();
|
||||
DEBUG_LOG(_logger) << LOGFUNCTION << " Leave event, this = " << " cursor = " << cursor.shape();
|
||||
} break;
|
||||
|
||||
default: break;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
} /* AbstractEventDispatcher::eventFilter */
|
||||
|
||||
|
||||
void AbstractEventDispatcher::setCursorToWidget( const QCursor & cursor ) { _getEventsFrom -> setCursor( cursor ); }
|
||||
|
||||
QCursor AbstractEventDispatcher::getCursorFromWidget() const { return _getEventsFrom->cursor(); }
|
||||
|
||||
|
||||
} } /* namespace SituationMap::RB */
|
||||
@@ -0,0 +1,234 @@
|
||||
/**
|
||||
**
|
||||
** @RDE_HEADER@
|
||||
** Abstract Event Dispatcher for Qt5
|
||||
** $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 .........:
|
||||
**
|
||||
** 28.04.2003, JT : First edition for use with Qt4 in START Feature Editor fee
|
||||
** 25.03.2015, JT : Refactoring for use with Qt5
|
||||
**
|
||||
** -----------------------------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <functional>
|
||||
|
||||
#include <QtCore/QObject>
|
||||
#include <QtCore/QString>
|
||||
#include <QtGui/QCursor>
|
||||
|
||||
#include <Common/situation_map_logging.h>
|
||||
|
||||
class QEvent;
|
||||
class QWidget;
|
||||
class QGestureRecognizer;
|
||||
|
||||
|
||||
namespace SituationMap { namespace RB
|
||||
{
|
||||
|
||||
/**
|
||||
@class AbstractEventDispatcher abstract_event_dispatcher.h
|
||||
@brief Base class of Qt event filter implementations to handle user interactions of map window
|
||||
|
||||
An EventDispatcher installs an event filter on a QWidget to receive all events that are send to
|
||||
the widget. Depending on the type of event and the state of the event dispatcher the event will
|
||||
be processed by the dispatcher and stopped or forwarded to the QWidget. In case of processing
|
||||
the event methodes of the EventActionInterface are called to controll a rubberband.
|
||||
|
||||
@see EventDelegater, EventDispatcher, EventMouseNavigator
|
||||
*/
|
||||
class AbstractEventDispatcher : public QObject
|
||||
{
|
||||
friend class EventDelegater;
|
||||
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
|
||||
/**
|
||||
@brief Logical interface between EventDispatcher and Rubberband
|
||||
Defines interface functions the EventDispatcher will call to control a rubberband. The rubberband class
|
||||
is derived from EventActionInterface and overrides the interface functions to implement them. The mapping
|
||||
user interaction to interface action is defined the derived classes of AbstractEventDispatcher.
|
||||
*/
|
||||
class EventActionInterface
|
||||
{
|
||||
public:
|
||||
|
||||
EventActionInterface() = default;
|
||||
virtual ~EventActionInterface() = default;
|
||||
|
||||
virtual void unlinkEventDispatcher ( AbstractEventDispatcher * causer ) = 0;
|
||||
virtual void resetAction ( AbstractEventDispatcher * causer, int x, int y ) { Q_UNUSED(causer); Q_UNUSED(x); Q_UNUSED(y); }
|
||||
virtual bool selectAction ( AbstractEventDispatcher * causer, int x, int y ) { Q_UNUSED(causer); Q_UNUSED(x); Q_UNUSED(y); return false; }
|
||||
virtual bool multiSelectActionPress ( AbstractEventDispatcher * causer, int x, int y ) { Q_UNUSED(causer); Q_UNUSED(x); Q_UNUSED(y); return false; }
|
||||
virtual bool multiSelectActionRelease( AbstractEventDispatcher * causer, int x, int y ) { Q_UNUSED(causer); Q_UNUSED(x); Q_UNUSED(y); return false; }
|
||||
virtual bool setCoordinateAction ( AbstractEventDispatcher * causer, int x, int y ) { Q_UNUSED(causer); Q_UNUSED(x); Q_UNUSED(y); return false; }
|
||||
virtual bool moveAction ( AbstractEventDispatcher * causer, int x, int y ) { Q_UNUSED(causer); Q_UNUSED(x); Q_UNUSED(y); return false; }
|
||||
virtual bool movePickedAction ( AbstractEventDispatcher * causer, int x, int y ) { Q_UNUSED(causer); Q_UNUSED(x); Q_UNUSED(y); return false; }
|
||||
virtual bool contextMenuAction ( AbstractEventDispatcher * causer, int x, int y ) { Q_UNUSED(causer); Q_UNUSED(x); Q_UNUSED(y); return false; }
|
||||
virtual bool completeStateAction ( AbstractEventDispatcher * causer, int x, int y ) { Q_UNUSED(causer); Q_UNUSED(x); Q_UNUSED(y); return false; }
|
||||
virtual bool deleteAction ( AbstractEventDispatcher * causer, int x, int y ) { Q_UNUSED(causer); Q_UNUSED(x); Q_UNUSED(y); return false; }
|
||||
virtual bool undoAction ( AbstractEventDispatcher * causer, int x, int y ) { Q_UNUSED(causer); Q_UNUSED(x); Q_UNUSED(y); return false; }
|
||||
virtual bool applyAndEndAction ( AbstractEventDispatcher * causer, int x, int y ) { Q_UNUSED(causer); Q_UNUSED(x); Q_UNUSED(y); return false; }
|
||||
virtual bool abortAction ( AbstractEventDispatcher * causer, int x, int y ) { Q_UNUSED(causer); Q_UNUSED(x); Q_UNUSED(y); return false; }
|
||||
virtual bool buttonPositionAction ( AbstractEventDispatcher * causer, int x, int y ) { Q_UNUSED(causer); Q_UNUSED(x); Q_UNUSED(y); return false; }
|
||||
|
||||
virtual void userActionFinished() = 0;
|
||||
|
||||
}; /* EventActionInterface */
|
||||
|
||||
/**
|
||||
@name Construction & Destruction
|
||||
@{
|
||||
*/
|
||||
explicit AbstractEventDispatcher( QWidget * getEventsFrom );
|
||||
explicit AbstractEventDispatcher( QWidget * getEventsFrom, EventActionInterface* );
|
||||
|
||||
virtual ~AbstractEventDispatcher();
|
||||
|
||||
AbstractEventDispatcher(const AbstractEventDispatcher &) = delete;
|
||||
AbstractEventDispatcher & operator = (const AbstractEventDispatcher &) = delete;
|
||||
/** @} */
|
||||
|
||||
/**
|
||||
Conceal deleteLater slot. Use onDo_delete() instead to avoid "QCoreApplication::postEvent: Unexpected null receiver" warning.
|
||||
*/
|
||||
void deleteLater() = delete;
|
||||
|
||||
/**
|
||||
Provides the number of EventDispatcher installed to the QWidget of this EventDispatcher
|
||||
*/
|
||||
unsigned int numberOfEventDispatcher() const;
|
||||
|
||||
inline void setEventActions(EventActionInterface * eventActions) { _eventActions = eventActions; }
|
||||
|
||||
inline bool hasGrab() const { return _hasGrab; }
|
||||
|
||||
inline void setCursor(const QCursor & cursor) { _dispatcherCursor = cursor; }
|
||||
|
||||
void setWhatsThis(const QString & whatsThis);
|
||||
|
||||
void grab();
|
||||
void ungrab();
|
||||
|
||||
|
||||
public slots:
|
||||
|
||||
/**
|
||||
@brief Slot calling internal \c KickTheBucket methode
|
||||
|
||||
Calls internal methode \c KickTheBucket. Be careful using this function. Should only be used
|
||||
from implementations of \c EventActionInterface methodes or \c EventDelegater class.
|
||||
*/
|
||||
void onDo_kickTheBucket();
|
||||
|
||||
/**
|
||||
@brief Slot calling \c deleteLater function of QObject
|
||||
|
||||
Never use \c delete directly for EventDispatcher class. Instead of use \c onDo_delete() function.
|
||||
*/
|
||||
void onDo_delete();
|
||||
|
||||
protected:
|
||||
|
||||
QWidget * _getEventsFrom;
|
||||
LOGGER_T _logger;
|
||||
bool _cursorIsInWidget;
|
||||
|
||||
inline bool hasFinished() { return _finishFlag; }
|
||||
inline bool hasActiveEvent() { return _activeEvent; }
|
||||
|
||||
inline void setActiveEvent(bool val) { _activeEvent = val; }
|
||||
|
||||
/**
|
||||
@brief Destroying EventDispatcher as result of an incoming event.
|
||||
|
||||
As result of an incomming event (e.g. Keypress ESC) the EventDispatcher will stop, emiting signal \c signalKickTheBucket()
|
||||
and calls methode \c EventActionInterface::unlinkEventDispatcher() before setup \c deleteLater() call to destroy it self.
|
||||
*/
|
||||
virtual void KickTheBucket();
|
||||
|
||||
|
||||
inline void unlinkEventDispatcher()
|
||||
{
|
||||
if (_eventActions)
|
||||
{
|
||||
_eventActions -> unlinkEventDispatcher( this );
|
||||
_eventActions = nullptr;
|
||||
}
|
||||
} /* unlinkEventDispatcher */
|
||||
|
||||
|
||||
inline bool callEventAction( bool( EventActionInterface::*actionMethodePtr)( AbstractEventDispatcher*,int,int), int x, int y )
|
||||
{
|
||||
if (_eventActions == nullptr) return false;
|
||||
return (_eventActions->*actionMethodePtr)( this, x, y );
|
||||
} /* callEventAction */
|
||||
|
||||
|
||||
/**
|
||||
Event filter function to override to implement event handling. To workaround a cursor handling bug in QGraphicsView it is
|
||||
necessary to call the eventFilter function of this base class, which will monitor enter and leave events.
|
||||
*/
|
||||
virtual bool eventFilter( QObject * widget, QEvent * e );
|
||||
|
||||
inline EventActionInterface * getEventActions() { return _eventActions; }
|
||||
|
||||
void setCursorToWidget( const QCursor & cursor );
|
||||
QCursor getCursorFromWidget() const;
|
||||
|
||||
bool _synthesisTouchFromMouseEvents;
|
||||
|
||||
static unsigned int _applyGestureID;
|
||||
|
||||
private:
|
||||
|
||||
void initDispatcher();
|
||||
|
||||
bool _deleteRequested;
|
||||
|
||||
bool _hasGrab;
|
||||
bool _finishFlag;
|
||||
|
||||
bool _restoreCursor;
|
||||
bool _restoreMouseTracking;
|
||||
QCursor _cursorToRestore;
|
||||
|
||||
bool _activeEvent;
|
||||
|
||||
QCursor _dispatcherCursor;
|
||||
QString _whatsThisBackup;
|
||||
|
||||
EventActionInterface * _eventActions;
|
||||
|
||||
|
||||
|
||||
static QGestureRecognizer * _applyGestureDetection;
|
||||
|
||||
signals:
|
||||
|
||||
void signalKickTheBucket();
|
||||
|
||||
}; /* EventDispatcher */
|
||||
|
||||
} } /* namespace SituationMap::RB */
|
||||
+110
@@ -0,0 +1,110 @@
|
||||
/* XPM */
|
||||
static const char * apply_xpm[] = {
|
||||
"24 24 83 1",
|
||||
" c None",
|
||||
". c #7FBD7C",
|
||||
"+ c #8BCF88",
|
||||
"@ c #84C582",
|
||||
"# c #588456",
|
||||
"$ c #63BE5F",
|
||||
"% c #57B953",
|
||||
"& c #73BF70",
|
||||
"* c #56B752",
|
||||
"= c #499B45",
|
||||
"- c #699F66",
|
||||
"; c #59B755",
|
||||
"> c #54B550",
|
||||
", c #52B14E",
|
||||
"' c #6ABC67",
|
||||
") c #52B34E",
|
||||
"! c #377334",
|
||||
"~ c #6FAF6C",
|
||||
"{ c #50B24C",
|
||||
"] c #4FB14B",
|
||||
"^ c #48A144",
|
||||
"/ c #4C734A",
|
||||
"( c #5DB559",
|
||||
"_ c #4DAE49",
|
||||
": c #4CAD48",
|
||||
"< c #6BB569",
|
||||
"[ c #4AAC46",
|
||||
"} c #377F35",
|
||||
"| c #5E915C",
|
||||
"1 c #50AD4C",
|
||||
"2 c #48A944",
|
||||
"3 c #44A040",
|
||||
"4 c #61B05E",
|
||||
"5 c #45A641",
|
||||
"6 c #527F50",
|
||||
"7 c #7BBF78",
|
||||
"8 c #78BA75",
|
||||
"9 c #639C60",
|
||||
"0 c #46A542",
|
||||
"a c #42A33E",
|
||||
"b c #368633",
|
||||
"c c #389035",
|
||||
"d c #3FA13B",
|
||||
"e c #43A33F",
|
||||
"f c #619B5E",
|
||||
"g c #56AC53",
|
||||
"h c #3D9D39",
|
||||
"i c #3B9C37",
|
||||
"j c #3C9E38",
|
||||
"k c #54A951",
|
||||
"l c #64A761",
|
||||
"m c #3D9E39",
|
||||
"n c #2A6B26",
|
||||
"o c #3A9B35",
|
||||
"p c #3B9B36",
|
||||
"q c #62A55F",
|
||||
"r c #4B7749",
|
||||
"s c #48A243",
|
||||
"t c #33892F",
|
||||
"u c #328B2F",
|
||||
"v c #379833",
|
||||
"w c #459F41",
|
||||
"x c #4F7E4D",
|
||||
"y c #5CA659",
|
||||
"z c #369632",
|
||||
"A c #349530",
|
||||
"B c #349630",
|
||||
"C c #59A955",
|
||||
"D c #3A9936",
|
||||
"E c #276C25",
|
||||
"F c #256C22",
|
||||
"G c #32932E",
|
||||
"H c #2F892B",
|
||||
"I c #2C8728",
|
||||
"J c #2F912B",
|
||||
"K c #2F902B",
|
||||
"L c #2D8E29",
|
||||
"M c #2D8F29",
|
||||
"N c #257322",
|
||||
"O c #226E1F",
|
||||
"P c #2B8D27",
|
||||
"Q c #298826",
|
||||
"R c #288424",
|
||||
" ",
|
||||
" ",
|
||||
" .+++@ ",
|
||||
" #$%%% ",
|
||||
" &***= ",
|
||||
" -;>>, ",
|
||||
" ')))! ",
|
||||
" ~{]]^ ",
|
||||
" /(__: ",
|
||||
" <[[[} ",
|
||||
" |1223 ",
|
||||
" 4555 ",
|
||||
" 67778 90aab ",
|
||||
" cddef gddh ",
|
||||
" ijjk lmjj ",
|
||||
" noopq rsoot ",
|
||||
" uvvwxyvvz ",
|
||||
" ABBCDBBE ",
|
||||
" FGGGGGH ",
|
||||
" IJJJK ",
|
||||
" LMMN ",
|
||||
" OPQ ",
|
||||
" R ",
|
||||
" "};
|
||||
+200
@@ -0,0 +1,200 @@
|
||||
/* XPM */
|
||||
static const char * constrainsMarker_xpm[] = {
|
||||
"24 24 173 2",
|
||||
" c None",
|
||||
". c #AE6557",
|
||||
"+ c #DF826F",
|
||||
"@ c #F18C78",
|
||||
"# c #FE947F",
|
||||
"$ c #FD937E",
|
||||
"% c #EC8976",
|
||||
"& c #E08270",
|
||||
"* c #A35F51",
|
||||
"= c #C17060",
|
||||
"- c #F88C77",
|
||||
"; c #FD7F67",
|
||||
"> c #FC7257",
|
||||
", c #FC6A4E",
|
||||
"' c #FC6345",
|
||||
") c #FC6446",
|
||||
"! c #FC6C50",
|
||||
"~ c #FD8269",
|
||||
"{ c #B86A5B",
|
||||
"] c #EA8672",
|
||||
"^ c #FC7A61",
|
||||
"/ c #FB6548",
|
||||
"( c #FB6244",
|
||||
"_ c #F45F42",
|
||||
": c #E85B3F",
|
||||
"< c #EF5D41",
|
||||
"[ c #FC7C64",
|
||||
"} c #EA8673",
|
||||
"| c #EF846F",
|
||||
"1 c #F9694D",
|
||||
"2 c #F96042",
|
||||
"3 c #F55E41",
|
||||
"4 c #BB4832",
|
||||
"5 c #C04A33",
|
||||
"6 c #F65F41",
|
||||
"7 c #EE8571",
|
||||
"8 c #E9816C",
|
||||
"9 c #F76548",
|
||||
"0 c #F75E40",
|
||||
"a c #F66143",
|
||||
"b c #E6573C",
|
||||
"c c #F76649",
|
||||
"d c #E67F6B",
|
||||
"e c #B86959",
|
||||
"f c #F56549",
|
||||
"g c #F45C3E",
|
||||
"h c #E8583B",
|
||||
"i c #F45D3F",
|
||||
"j c #F27D66",
|
||||
"k c #E25539",
|
||||
"l c #F5674B",
|
||||
"m c #F0725A",
|
||||
"n c #F2593B",
|
||||
"o c #EE583A",
|
||||
"p c #B8442D",
|
||||
"q c #F25C3F",
|
||||
"r c #EA7C67",
|
||||
"s c #EE7259",
|
||||
"t c #A95E4F",
|
||||
"u c #EF593B",
|
||||
"v c #EF5638",
|
||||
"w c #B4432D",
|
||||
"x c #CF4B30",
|
||||
"y c #F05D41",
|
||||
"z c #DF7A66",
|
||||
"A c #B9452E",
|
||||
"B c #EF593C",
|
||||
"C c #A75C4E",
|
||||
"D c #D36650",
|
||||
"E c #EC5436",
|
||||
"F c #DA4E32",
|
||||
"G c #ED6044",
|
||||
"H c #CE7361",
|
||||
"I c #D16550",
|
||||
"J c #E35E44",
|
||||
"K c #EA5133",
|
||||
"L c #DF4D31",
|
||||
"M c #E24E31",
|
||||
"N c #EC6449",
|
||||
"O c #B36354",
|
||||
"P c #DF5D43",
|
||||
"Q c #E75436",
|
||||
"R c #E74E30",
|
||||
"S c #D04D34",
|
||||
"T c #E44D2F",
|
||||
"U c #EB6A51",
|
||||
"V c #8D4E42",
|
||||
"W c #D54D32",
|
||||
"X c #E45539",
|
||||
"Y c #E34C2E",
|
||||
"Z c #E44B2D",
|
||||
"` c #CE5138",
|
||||
" . c #E76F57",
|
||||
".. c #D45036",
|
||||
"+. c #E14E30",
|
||||
"@. c #D94729",
|
||||
"#. c #E1492A",
|
||||
"$. c #D85339",
|
||||
"%. c #A0341E",
|
||||
"&. c #E14B2D",
|
||||
"*. c #E0725B",
|
||||
"=. c #DB5236",
|
||||
"-. c #D8492C",
|
||||
";. c #C24329",
|
||||
">. c #DE4628",
|
||||
",. c #E04F32",
|
||||
"'. c #BB3B22",
|
||||
"). c #DF4C2F",
|
||||
"!. c #D56F5B",
|
||||
"~. c #C2432A",
|
||||
"{. c #963B28",
|
||||
"]. c #DC4325",
|
||||
"^. c #B25C4B",
|
||||
"/. c #C93D22",
|
||||
"(. c #DE4F33",
|
||||
"_. c #C86A57",
|
||||
":. c #B95D4A",
|
||||
"<. c #913927",
|
||||
"[. c #D53F21",
|
||||
"}. c #D94022",
|
||||
"|. c #DC5B42",
|
||||
"1. c #CF3D21",
|
||||
"2. c #DD5338",
|
||||
"3. c #B25F4F",
|
||||
"4. c #DB583F",
|
||||
"5. c #9D311B",
|
||||
"6. c #D73E20",
|
||||
"7. c #D84123",
|
||||
"8. c #D16A55",
|
||||
"9. c #D33D1F",
|
||||
"0. c #DD5A40",
|
||||
"a. c #D86B55",
|
||||
"b. c #D74023",
|
||||
"c. c #9A2F1B",
|
||||
"d. c #C3371C",
|
||||
"e. c #D43C1E",
|
||||
"f. c #D7472B",
|
||||
"g. c #D06C58",
|
||||
"h. c #D33C1E",
|
||||
"i. c #D64326",
|
||||
"j. c #C4381C",
|
||||
"k. c #C7361A",
|
||||
"l. c #D2391B",
|
||||
"m. c #D54529",
|
||||
"n. c #DB6B56",
|
||||
"o. c #B35E4D",
|
||||
"p. c #B85441",
|
||||
"q. c #D0391C",
|
||||
"r. c #CA371A",
|
||||
"s. c #C13418",
|
||||
"t. c #D0381A",
|
||||
"u. c #D13A1D",
|
||||
"v. c #D65339",
|
||||
"w. c #DC6A53",
|
||||
"x. c #D7715D",
|
||||
"y. c #CF6C59",
|
||||
"z. c #DC735E",
|
||||
"A. c #DC6953",
|
||||
"B. c #D64F35",
|
||||
"C. c #BD3318",
|
||||
"D. c #972812",
|
||||
"E. c #CC3518",
|
||||
"F. c #CF3618",
|
||||
"G. c #D03C1E",
|
||||
"H. c #D24226",
|
||||
"I. c #D0381B",
|
||||
"J. c #CA3517",
|
||||
"K. c #912611",
|
||||
"L. c #B12E14",
|
||||
"M. c #BE3115",
|
||||
"N. c #CA3417",
|
||||
"O. c #CC3517",
|
||||
"P. c #AF2D14",
|
||||
" ",
|
||||
" . + @ # $ % & * ",
|
||||
" = - ; > , ' ) ! > ~ - { ",
|
||||
" ] ^ / ( ( _ : : < ( ( / [ } ",
|
||||
" | 1 2 3 4 5 6 2 1 7 ",
|
||||
" 8 9 0 0 a b 0 c d ",
|
||||
" e f g h g i j k g l e ",
|
||||
" m n o p n q r o n s ",
|
||||
" t u v w x v y z A v B C ",
|
||||
" D E E F E G H E E I ",
|
||||
" J K L M K N O M K P ",
|
||||
" Q R S T R U V W R X ",
|
||||
" Y Z ` Z Z . ..Z +. ",
|
||||
" @.#.$. %.#.&.*. =.#.-. ",
|
||||
" ;.>.,. '.>.).!. ).>.~. ",
|
||||
" {.].].^. /.].(._. :.].].<. ",
|
||||
" [.}.|. 1.}.2.3. 4.}.[. ",
|
||||
" 5.6.7.8. 9.6.0.a.b.6.c. ",
|
||||
" d.e.f.g. h.e.i.e.j. ",
|
||||
" k.l.m.n.o. p.q.l.l.r. ",
|
||||
" s.t.u.v.w.x.y.y.z.A.B.u.t.C. ",
|
||||
" D.E.F.F.G.H.H.I.F.F.J.K. ",
|
||||
" L.M.N.O.M.P. ",
|
||||
" "};
|
||||
+127
@@ -0,0 +1,127 @@
|
||||
|
||||
/**
|
||||
**
|
||||
** @RDE_HEADER@
|
||||
** Definition of ellipse drawable
|
||||
** $Id$
|
||||
** $HeadURL$
|
||||
** $Author$
|
||||
*/
|
||||
|
||||
#include "drawable_ellipse.h"
|
||||
|
||||
#include <MathUtils/math_const.h>
|
||||
#include <QtWidgets/QGraphicsEllipseItem>
|
||||
|
||||
|
||||
namespace SituationMap { namespace RB
|
||||
{
|
||||
|
||||
DrawableEllipse::DrawableEllipse(Esri::ArcGISRuntime::MapGraphicsView * map) : DrawableEllipse(map,map->scene()) {;}
|
||||
|
||||
|
||||
DrawableEllipse::DrawableEllipse(Esri::ArcGISRuntime::MapGraphicsView * map, QGraphicsScene * scene)
|
||||
: RubberbandDrawable(map, scene)
|
||||
, _elliItem(nullptr)
|
||||
, _center()
|
||||
, _radiusX(0)
|
||||
, _radiusY(0)
|
||||
, _elliStyle()
|
||||
, _sinRect(0)
|
||||
, _cosRect(1)
|
||||
, _sectorStart()
|
||||
, _sectorEnd()
|
||||
{
|
||||
_elliItem = new QGraphicsEllipseItem();
|
||||
_scene -> addItem( _elliItem );
|
||||
makeLineStyle( false, _elliStyle );
|
||||
_elliItem -> setPen( _elliStyle );
|
||||
|
||||
_sectItem = new QGraphicsEllipseItem();
|
||||
_scene -> addItem( _sectItem );
|
||||
makeLineStyle( false, _elliStyle );
|
||||
_sectItem -> setPen( _elliStyle );
|
||||
} /* DrawableLine::DrawableLine */
|
||||
|
||||
|
||||
DrawableEllipse::~DrawableEllipse()
|
||||
{
|
||||
if (_scene)
|
||||
{
|
||||
if (_elliItem) _scene->removeItem(_elliItem);
|
||||
if (_sectItem) _scene->removeItem(_sectItem);
|
||||
delete _elliItem;
|
||||
delete _sectItem;
|
||||
}
|
||||
_elliItem = nullptr;
|
||||
_sectItem = nullptr;
|
||||
} /* DrawableEllipse::~DrawableEllipse */
|
||||
|
||||
|
||||
void DrawableEllipse::updateGraphic()
|
||||
{
|
||||
auto length = []( const QPointF & p ) -> qreal { return sqrt(p.x()*p.x()+p.y()*p.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;
|
||||
|
||||
_center.mapToScene(_mapView);
|
||||
|
||||
QPointF mapCenter( _center._mapCoordinate.x(), _center._mapCoordinate.y() );
|
||||
|
||||
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()) );
|
||||
|
||||
qreal width = length(x1y0._sceneCoordinate-x0y0._sceneCoordinate);
|
||||
qreal height = length(x0y1._sceneCoordinate-x0y0._sceneCoordinate);
|
||||
|
||||
makeLineStyle( false, _elliStyle );
|
||||
|
||||
QColor fillColor = transparentFillColor();
|
||||
//fillColor.setAlpha(0);
|
||||
|
||||
QPen pen(_drawColor);
|
||||
pen.setWidth(_lineWidth);
|
||||
|
||||
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;
|
||||
|
||||
_sectItem -> setRect( -width*0.5, -height*0.5, width, height );
|
||||
_sectItem -> setPen( pen );
|
||||
_sectItem -> setBrush( (fillColor.alpha() > 0) ? QBrush(fillColor) : QBrush() );
|
||||
_sectItem -> setTransform( QTransform( cosPhi, -sinPhi, sinPhi, cosPhi, _center._sceneCoordinate.x(), _center._sceneCoordinate.y() ));
|
||||
_sectItem -> setStartAngle( startAngle );
|
||||
_sectItem -> setSpanAngle( spanAngle );
|
||||
_sectItem -> setVisible( true );
|
||||
|
||||
fillColor.setAlphaF(fillColor.alphaF() * 0.5 );
|
||||
}
|
||||
else _sectItem -> setVisible( false );
|
||||
|
||||
_elliItem -> setRect( -width*0.5, -height*0.5, width, height );
|
||||
_elliItem -> setPen(pen);
|
||||
_elliItem -> setBrush( (fillColor.alpha() > 0) ? QBrush(fillColor) : QBrush() );
|
||||
_elliItem -> setTransform( QTransform( cosPhi, -sinPhi, sinPhi, cosPhi, _center._sceneCoordinate.x(), _center._sceneCoordinate.y() ));
|
||||
|
||||
} /* DrawableEllipse::updateGraphic */
|
||||
|
||||
void DrawableEllipse::adjustCoordinates() { updateGraphic(); }
|
||||
void DrawableEllipse::adjustWindow( const QRectF& ) { updateGraphic(); }
|
||||
|
||||
} } /* namespace SituationMap::RB */
|
||||
+72
@@ -0,0 +1,72 @@
|
||||
/**
|
||||
**
|
||||
** @RDE_HEADER@
|
||||
** Definition of ellipse drawable
|
||||
** $Id$
|
||||
** $HeadURL$
|
||||
** $Author$
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
|
||||
#include "rubberband_drawable.h"
|
||||
|
||||
#include <arcgis/Map.h>
|
||||
|
||||
|
||||
namespace SituationMap { namespace RB
|
||||
{
|
||||
class DrawableEllipse : public RubberbandDrawable
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
|
||||
explicit DrawableEllipse( Esri::ArcGISRuntime::MapGraphicsView * );
|
||||
explicit DrawableEllipse( Esri::ArcGISRuntime::MapGraphicsView *, QGraphicsScene * );
|
||||
~DrawableEllipse();
|
||||
|
||||
DrawableEllipse(const RubberbandDrawable &) = delete;
|
||||
DrawableEllipse & operator = (const RubberbandDrawable &) = delete;
|
||||
|
||||
|
||||
inline void setRect(const QPointF & center, qreal radiusX, qreal radiusY, qreal sin, qreal cos, const QPointF & sectorStart = QPointF(), const QPointF & sectorEnd = QPointF() )
|
||||
{
|
||||
// p1,p2 = corner points of unrotated ellipse in scene coordinates
|
||||
_center = RubberbandCoordinate( _mapView, convert(center, _mapView->map()->spatialReference()) );
|
||||
_radiusX = radiusX;
|
||||
_radiusY = radiusY;
|
||||
|
||||
_sinRect = sin;
|
||||
_cosRect = cos;
|
||||
|
||||
_sectorStart = sectorStart;
|
||||
_sectorEnd = sectorEnd;
|
||||
updateGraphic();
|
||||
}
|
||||
|
||||
qreal radiusX() { return _radiusX; }
|
||||
qreal radiusY() { return _radiusY; }
|
||||
|
||||
protected:
|
||||
|
||||
QGraphicsEllipseItem * _elliItem;
|
||||
QGraphicsEllipseItem * _sectItem;
|
||||
RubberbandDrawable::RubberbandCoordinate _center;
|
||||
qreal _radiusX;
|
||||
qreal _radiusY;
|
||||
QPen _elliStyle;
|
||||
qreal _sinRect;
|
||||
qreal _cosRect;
|
||||
QPointF _sectorStart;
|
||||
QPointF _sectorEnd;
|
||||
|
||||
void updateGraphic() override;
|
||||
|
||||
|
||||
void adjustCoordinates() override;
|
||||
void adjustWindow( const QRectF& ) override;
|
||||
|
||||
}; /* DrawableEllipse */
|
||||
|
||||
} } /* namespace SituationMap::RB */
|
||||
+109
@@ -0,0 +1,109 @@
|
||||
|
||||
/**
|
||||
**
|
||||
** @RDE_HEADER@
|
||||
** Implementation of line drawables
|
||||
** $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 .........:
|
||||
**
|
||||
** 06.08.2015, JT : First edition for use with Qt5
|
||||
**
|
||||
** -----------------------------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
#include "drawable_line.h"
|
||||
|
||||
#include <QtWidgets/QGraphicsLineItem>
|
||||
|
||||
|
||||
namespace SituationMap { namespace RB
|
||||
{
|
||||
|
||||
DrawableLine::DrawableLine(Esri::ArcGISRuntime::MapGraphicsView * map)
|
||||
: RubberbandDrawable(map)
|
||||
, _lineItem(nullptr)
|
||||
, _lineStyle()
|
||||
, _dottedLine(false)
|
||||
{
|
||||
_lineItem = new QGraphicsLineItem();
|
||||
_scene -> addItem( _lineItem );
|
||||
|
||||
makeLineStyle( _dottedLine, _lineStyle );
|
||||
_lineItem -> setPen( _lineStyle );
|
||||
|
||||
} /* DrawableLine::DrawableLine */
|
||||
|
||||
|
||||
DrawableLine::DrawableLine(Esri::ArcGISRuntime::MapGraphicsView * map, QGraphicsScene * scene)
|
||||
: RubberbandDrawable(map, scene)
|
||||
, _lineItem(nullptr)
|
||||
, _lineStyle()
|
||||
, _dottedLine(false)
|
||||
{
|
||||
_lineItem = new QGraphicsLineItem();
|
||||
_scene -> addItem( _lineItem );
|
||||
makeLineStyle( _dottedLine, _lineStyle );
|
||||
_lineItem -> setPen( _lineStyle );
|
||||
|
||||
} /* DrawableLine::DrawableLine */
|
||||
|
||||
DrawableLine::~DrawableLine()
|
||||
{
|
||||
if (_scene)
|
||||
{
|
||||
if (_lineItem)
|
||||
{
|
||||
_scene->removeItem(_lineItem);
|
||||
delete _lineItem;
|
||||
}
|
||||
}
|
||||
_lineItem = nullptr;
|
||||
} /* DrawableLine::~DrawableLine */
|
||||
|
||||
|
||||
void DrawableLine::setLine( const RubberbandDrawable::RubberbandCoordinate & p1, const RubberbandDrawable::RubberbandCoordinate & p2 )
|
||||
{
|
||||
_lineCoordinates[0] = p1;
|
||||
_lineCoordinates[1] = p2;
|
||||
updateGraphic();
|
||||
} /* DrawableLine::setPath */
|
||||
|
||||
|
||||
void DrawableLine::updateGraphic()
|
||||
{
|
||||
_lineCoordinates[0].mapToScene(_mapView);
|
||||
_lineCoordinates[1].mapToScene(_mapView);
|
||||
|
||||
qreal x1 = _lineCoordinates[0]._sceneCoordinate.x();
|
||||
qreal y1 = _lineCoordinates[0]._sceneCoordinate.y();
|
||||
qreal x2 = _lineCoordinates[1]._sceneCoordinate.x();
|
||||
qreal y2 = _lineCoordinates[1]._sceneCoordinate.y();
|
||||
|
||||
makeLineStyle( _dottedLine, _lineStyle );
|
||||
|
||||
_lineItem -> setLine( x1,y1,x2,y2 );
|
||||
_lineItem -> setPen( _lineStyle );
|
||||
_lineItem -> setVisible( _isVisible );
|
||||
|
||||
} /* DrawableLine::updateGraphic */
|
||||
|
||||
void DrawableLine::adjustCoordinates() { updateGraphic(); }
|
||||
void DrawableLine::adjustWindow( const QRectF& ) { updateGraphic(); }
|
||||
|
||||
} } /* namespace SituationMap::RB */
|
||||
+68
@@ -0,0 +1,68 @@
|
||||
/**
|
||||
**
|
||||
** @RDE_HEADER@
|
||||
** Definition of line drawable
|
||||
** $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
|
||||
**
|
||||
** -----------------------------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
|
||||
#include "rubberband_drawable.h"
|
||||
|
||||
|
||||
namespace SituationMap { namespace RB
|
||||
{
|
||||
|
||||
class DrawableLine : public RubberbandDrawable
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
|
||||
explicit DrawableLine( Esri::ArcGISRuntime::MapGraphicsView * );
|
||||
explicit DrawableLine( Esri::ArcGISRuntime::MapGraphicsView *, QGraphicsScene * );
|
||||
~DrawableLine();
|
||||
|
||||
DrawableLine(const RubberbandDrawable &) = delete;
|
||||
DrawableLine & operator = (const RubberbandDrawable &) = delete;
|
||||
|
||||
void setLine( const RubberbandDrawable::RubberbandCoordinate & p1, const RubberbandDrawable::RubberbandCoordinate & p2 );
|
||||
|
||||
inline void dottedLine(bool on = true) { _dottedLine = on; }
|
||||
|
||||
protected:
|
||||
|
||||
QGraphicsLineItem * _lineItem;
|
||||
RubberbandDrawable::RubberbandCoordinate _lineCoordinates[2];
|
||||
QPen _lineStyle;
|
||||
bool _dottedLine;
|
||||
|
||||
void updateGraphic() override;
|
||||
|
||||
void adjustCoordinates() override;
|
||||
void adjustWindow( const QRectF& ) override;
|
||||
|
||||
}; /* DrawableLine */
|
||||
|
||||
} } /* namespace SituationMap::RB */
|
||||
@@ -0,0 +1,152 @@
|
||||
|
||||
/**
|
||||
**
|
||||
** @RDE_HEADER@
|
||||
** Implementation of path drawables
|
||||
** $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.07.2015, JT : First edition for use with Qt5
|
||||
**
|
||||
** -----------------------------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
#include "drawable_painter_path.h"
|
||||
|
||||
#include <QGraphicsPathItem>
|
||||
#include <QPainterPath>
|
||||
|
||||
|
||||
namespace SituationMap { namespace RB
|
||||
{
|
||||
|
||||
DrawablePainterPath::DrawablePainterPath(Esri::ArcGISRuntime::MapGraphicsView * map)
|
||||
: RubberbandDrawable(map)
|
||||
, _painterPathItem(nullptr)
|
||||
, _pathCoordinates()
|
||||
, _lineStyle()
|
||||
, _dottedPath(false)
|
||||
, _closedLine(false)
|
||||
, _fillSolid(false)
|
||||
{
|
||||
_painterPathItem = _scene->addPath( QPainterPath() );
|
||||
_painterPathItem -> setFlags( QGraphicsItem::ItemIgnoresTransformations );
|
||||
makeLineStyle( _dottedPath, _lineStyle );
|
||||
_painterPathItem -> setPen ( (_drawColor.alpha()) ? QPen(_drawColor) : QPen() );
|
||||
_fillColor.setAlpha(0);
|
||||
_painterPathItem -> setBrush( (_fillColor.alpha()) ? QBrush(_fillColor) : QBrush() );
|
||||
} /* DrawablePainterPath::DrawablePainterPath */
|
||||
|
||||
|
||||
DrawablePainterPath::DrawablePainterPath(Esri::ArcGISRuntime::MapGraphicsView * map, QGraphicsScene * scene)
|
||||
: RubberbandDrawable(map, scene)
|
||||
, _painterPathItem(nullptr)
|
||||
, _pathCoordinates()
|
||||
, _lineStyle()
|
||||
, _dottedPath(false)
|
||||
, _closedLine(false)
|
||||
, _fillSolid(false)
|
||||
{
|
||||
_painterPathItem = _scene->addPath( QPainterPath() );
|
||||
_painterPathItem -> setFlags( QGraphicsItem::ItemIgnoresTransformations );
|
||||
makeLineStyle( _dottedPath, _lineStyle );
|
||||
_painterPathItem -> setPen ( (_drawColor.alpha()) ? _lineStyle : QPen() );
|
||||
_fillColor.setAlpha(0);
|
||||
_painterPathItem -> setBrush( (_fillColor.alpha()) ? QBrush(_fillColor) : QBrush() );
|
||||
} /* DrawablePainterPath::DrawablePainterPath */
|
||||
|
||||
|
||||
DrawablePainterPath::~DrawablePainterPath()
|
||||
{
|
||||
if (_scene)
|
||||
{
|
||||
if (_painterPathItem)
|
||||
{
|
||||
_scene->removeItem(_painterPathItem);
|
||||
delete _painterPathItem;
|
||||
}
|
||||
_painterPathItem = nullptr;
|
||||
}
|
||||
} /* DrawablePainterPath::~DrawablePainterPath */
|
||||
|
||||
|
||||
void DrawablePainterPath::setPath( const QVector<RubberbandDrawable::RubberbandCoordinate> & path )
|
||||
{
|
||||
_pathCoordinates = path;
|
||||
updateGraphic();
|
||||
} /* DrawablePainterPath::setPath */
|
||||
|
||||
|
||||
void DrawablePainterPath::setPath( const QVector<QPointF> & scenePath )
|
||||
{
|
||||
_pathCoordinates.clear();
|
||||
_pathCoordinates.reserve( scenePath.size() );
|
||||
|
||||
for ( auto p : scenePath )
|
||||
{
|
||||
_pathCoordinates.append( RubberbandDrawable::RubberbandCoordinate(_mapView,p) );
|
||||
}
|
||||
updateGraphic();
|
||||
|
||||
} /* DrawablePainterPath::setPath */
|
||||
|
||||
|
||||
void DrawablePainterPath::updateGraphic()
|
||||
{
|
||||
DEBUG_LOG(_logger) << LOGFUNCTION;
|
||||
|
||||
if ((_closedLine) && (_pathCoordinates.size() < 3))
|
||||
{
|
||||
_painterPathItem -> setVisible( false );
|
||||
return;
|
||||
}
|
||||
|
||||
QPainterPath painterPath;
|
||||
|
||||
QVector<RubberbandDrawable::RubberbandCoordinate>::iterator it = _pathCoordinates.begin();
|
||||
|
||||
if (it != _pathCoordinates.end())
|
||||
{
|
||||
painterPath.moveTo( it->mapToScene(_mapView) );
|
||||
DEBUG_LOG(_logger) << LOGFUNCTION << " map-x = " << it->_mapCoordinate.x() << " map-y = " << it->_mapCoordinate.y();
|
||||
while (true)
|
||||
{
|
||||
++it;
|
||||
if (it == _pathCoordinates.end()) break;
|
||||
painterPath.lineTo( it->mapToScene(_mapView) );
|
||||
DEBUG_LOG(_logger) << LOGFUNCTION << " map-x = " << it->_mapCoordinate.x() << " map-y = " << it->_mapCoordinate.y();
|
||||
}
|
||||
if (_closedLine) painterPath.closeSubpath();
|
||||
}
|
||||
|
||||
const QColor &fillColor = transparentFillColor();
|
||||
makeLineStyle( _dottedPath, _lineStyle );
|
||||
|
||||
_painterPathItem -> setVisible( _isVisible );
|
||||
_painterPathItem -> setPen ( (_drawColor.alpha() > 0) ? _lineStyle : QPen() );
|
||||
_painterPathItem -> setBrush( ( fillColor.alpha() > 0) ? QBrush(fillColor) : QBrush() );
|
||||
_painterPathItem -> setZValue( _zBufferValue );
|
||||
_painterPathItem -> setPath( painterPath );
|
||||
|
||||
} /* DrawablePainterPath::updateGraphic */
|
||||
|
||||
void DrawablePainterPath::adjustCoordinates() { updateGraphic(); }
|
||||
void DrawablePainterPath::adjustWindow( const QRectF& ) { updateGraphic(); }
|
||||
|
||||
} } /* namespace SituationMap::RB */
|
||||
@@ -0,0 +1,75 @@
|
||||
/**
|
||||
**
|
||||
** @RDE_HEADER@
|
||||
** Definition of base class for rubberband drawing objects
|
||||
** $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
|
||||
**
|
||||
** -----------------------------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
|
||||
#include "rubberband_drawable.h"
|
||||
|
||||
|
||||
namespace SituationMap { namespace RB
|
||||
{
|
||||
|
||||
class DrawablePainterPath : public RubberbandDrawable
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
|
||||
explicit DrawablePainterPath( Esri::ArcGISRuntime::MapGraphicsView * );
|
||||
explicit DrawablePainterPath( Esri::ArcGISRuntime::MapGraphicsView *, QGraphicsScene * );
|
||||
~DrawablePainterPath();
|
||||
|
||||
DrawablePainterPath(const RubberbandDrawable &) = delete;
|
||||
DrawablePainterPath & operator = (const RubberbandDrawable &) = delete;
|
||||
|
||||
void setPath( const QVector<QPointF> & scenePath );
|
||||
|
||||
void setPath( const QVector<RubberbandDrawable::RubberbandCoordinate> & path );
|
||||
|
||||
inline void enableClosedLine(bool on = true) { _closedLine = on; }
|
||||
|
||||
inline void dottedPath(bool on = true) { _dottedPath = on; }
|
||||
inline void fillSolid(bool on = true) { _fillSolid = on; }
|
||||
|
||||
protected:
|
||||
|
||||
QGraphicsPathItem * _painterPathItem;
|
||||
QVector<RubberbandDrawable::RubberbandCoordinate> _pathCoordinates;
|
||||
QPen _lineStyle;
|
||||
bool _dottedPath;
|
||||
bool _closedLine;
|
||||
bool _fillSolid;
|
||||
|
||||
void updateGraphic() override;
|
||||
|
||||
void adjustCoordinates() override;
|
||||
void adjustWindow( const QRectF& ) override;
|
||||
|
||||
}; /* DrawablePainterPath */
|
||||
|
||||
} } /* namespace SituationMap::RB */
|
||||
@@ -0,0 +1,127 @@
|
||||
|
||||
/**
|
||||
**
|
||||
** @RDE_HEADER@
|
||||
** Implementation of line drawables
|
||||
** $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 .........:
|
||||
**
|
||||
** 06.08.2015, JT : First edition for use with Qt5
|
||||
**
|
||||
** -----------------------------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
#include "drawable_smooth_path.h"
|
||||
|
||||
#include <QPainterPath>
|
||||
#include <QGraphicsPathItem>
|
||||
|
||||
#include <MathUtils/curve.h>
|
||||
#include <MathUtils/path_rasterer.h>
|
||||
|
||||
|
||||
namespace SituationMap { namespace RB
|
||||
{
|
||||
|
||||
DrawableSmoothPath::DrawableSmoothPath(Esri::ArcGISRuntime::MapGraphicsView * map)
|
||||
: DrawablePainterPath(map)
|
||||
, _smoothLine( new SituationMap::MathUtils::SmoothLine() )
|
||||
{
|
||||
_pathRasterer = _smoothLine->createPathRaster();
|
||||
} /* DrawableSmoothPath::DrawableLine */
|
||||
|
||||
|
||||
DrawableSmoothPath::DrawableSmoothPath(Esri::ArcGISRuntime::MapGraphicsView * map, QGraphicsScene * scene)
|
||||
: DrawablePainterPath(map, scene)
|
||||
, _smoothLine( new SituationMap::MathUtils::SmoothLine() )
|
||||
{
|
||||
_pathRasterer = _smoothLine->createPathRaster();
|
||||
} /* DrawableSmoothLine::DrawableLine */
|
||||
|
||||
|
||||
DrawableSmoothPath::~DrawableSmoothPath()
|
||||
{
|
||||
delete _pathRasterer;
|
||||
delete _smoothLine;
|
||||
_pathRasterer = nullptr;
|
||||
_smoothLine = nullptr;
|
||||
} /* DrawableSmoothPath::~DrawableSmoothPath */
|
||||
|
||||
|
||||
void DrawableSmoothPath::setPath( const QVector<RubberbandDrawable::RubberbandCoordinate> & vertexVector )
|
||||
{
|
||||
_pathCoordinates = vertexVector;
|
||||
updateGraphic();
|
||||
} /* DrawableSmoothPath::setPath */
|
||||
|
||||
|
||||
void DrawableSmoothPath::updateGraphic()
|
||||
{
|
||||
if (_pathCoordinates.size() > 2)
|
||||
{
|
||||
makeLineStyle( _dottedPath, _lineStyle );
|
||||
|
||||
_painterPathItem -> setPen( _lineStyle );
|
||||
_painterPathItem -> setVisible( _isVisible );
|
||||
|
||||
if (_closedLine)
|
||||
{
|
||||
const QColor &fillColor = transparentFillColor();
|
||||
_painterPathItem -> setBrush( (fillColor.alpha() > 0) ? QBrush(fillColor) : QBrush() );
|
||||
}
|
||||
else _painterPathItem -> setBrush( QBrush() );
|
||||
|
||||
QVector<QPointF> vertexVector;
|
||||
vertexVector.reserve( _pathCoordinates.size() );
|
||||
|
||||
for (auto vertex : qAsConst(_pathCoordinates))
|
||||
{
|
||||
vertex.mapToScene(_mapView);
|
||||
vertexVector.append( vertex._sceneCoordinate );
|
||||
}
|
||||
|
||||
_smoothLine -> vertexVector( vertexVector, _closedLine );
|
||||
_pathRasterer -> epsilon( 2 );
|
||||
_pathRasterer -> maxVertexCount( 1000 );
|
||||
_pathRasterer -> rasterize( _smoothLine->minimumCurveParameter(), _smoothLine->maximumCurveParameter(), vertexVector );
|
||||
|
||||
QPainterPath path;
|
||||
|
||||
if (vertexVector.size() > 1)
|
||||
{
|
||||
QVector<QPointF>::const_iterator vit = vertexVector.constBegin();
|
||||
|
||||
path.moveTo( *vit );
|
||||
for (++vit; vit != vertexVector.end(); ++vit)
|
||||
{
|
||||
path.lineTo( *vit );
|
||||
}
|
||||
if (_closedLine) path.lineTo( QPointF(path.elementAt(0)) );
|
||||
}
|
||||
_painterPathItem->setPath(path);
|
||||
}
|
||||
else _painterPathItem ->setVisible(false);
|
||||
|
||||
} /* DrawableSmoothPath::updateGraphic */
|
||||
|
||||
|
||||
void DrawableSmoothPath::adjustCoordinates() { updateGraphic(); }
|
||||
void DrawableSmoothPath::adjustWindow( const QRectF& ) { updateGraphic(); }
|
||||
|
||||
} } /* namespace SituationMap::RB */
|
||||
@@ -0,0 +1,77 @@
|
||||
/**
|
||||
**
|
||||
** @RDE_HEADER@
|
||||
** Definition of line drawable
|
||||
** $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
|
||||
**
|
||||
** -----------------------------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
|
||||
#include "drawable_painter_path.h"
|
||||
|
||||
|
||||
namespace SituationMap {
|
||||
|
||||
|
||||
namespace MathUtils
|
||||
{
|
||||
class SmoothLine;
|
||||
class PathRasterer;
|
||||
}
|
||||
|
||||
|
||||
namespace RB
|
||||
{
|
||||
|
||||
|
||||
class DrawableSmoothPath : public DrawablePainterPath
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
|
||||
explicit DrawableSmoothPath( Esri::ArcGISRuntime::MapGraphicsView * );
|
||||
explicit DrawableSmoothPath( Esri::ArcGISRuntime::MapGraphicsView *, QGraphicsScene * );
|
||||
~DrawableSmoothPath();
|
||||
|
||||
DrawableSmoothPath(const DrawableSmoothPath &) = delete;
|
||||
DrawableSmoothPath & operator = (const DrawableSmoothPath &) = delete;
|
||||
|
||||
void setPath( const QVector<RubberbandDrawable::RubberbandCoordinate> & vertexVector );
|
||||
|
||||
protected:
|
||||
|
||||
|
||||
SituationMap::MathUtils::SmoothLine * _smoothLine;
|
||||
SituationMap::MathUtils::PathRasterer * _pathRasterer;
|
||||
|
||||
void updateGraphic() override;
|
||||
|
||||
void adjustCoordinates() override;
|
||||
void adjustWindow( const QRectF& ) override;
|
||||
|
||||
}; /* DrawableSmoothPath */
|
||||
|
||||
} /* namespace RB */
|
||||
} /* namespace SituationMap */
|
||||
+72
@@ -0,0 +1,72 @@
|
||||
/**
|
||||
**
|
||||
** @RDE_HEADER@
|
||||
** Event Dispatcher for Qt5 to delegate mouse and keyboard event to another event dispatcher
|
||||
** $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 .........:
|
||||
**
|
||||
** 15.04.2015, JT : First edition
|
||||
**
|
||||
** -----------------------------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
#include "event_delegater.h"
|
||||
|
||||
namespace SituationMap { namespace RB
|
||||
{
|
||||
|
||||
EventDelegater::EventDelegater(QWidget * getEventsFrom, AbstractEventDispatcher * delegateEventTo)
|
||||
: AbstractEventDispatcher(getEventsFrom), _delegateEventTo(delegateEventTo)
|
||||
{
|
||||
connect( delegateEventTo, &AbstractEventDispatcher::signalKickTheBucket,
|
||||
this , &AbstractEventDispatcher::onDo_kickTheBucket );
|
||||
|
||||
connect( this , &AbstractEventDispatcher::signalKickTheBucket,
|
||||
delegateEventTo, &AbstractEventDispatcher::onDo_kickTheBucket );
|
||||
|
||||
_restoreMouseTracking = delegateEventTo->_restoreMouseTracking;
|
||||
_whatsThisBackup = delegateEventTo->_whatsThisBackup;
|
||||
|
||||
} /* EventDispatcher::EventDispatcher */
|
||||
|
||||
|
||||
bool EventDelegater::eventFilter(QObject * watched, QEvent * e)
|
||||
{
|
||||
if (hasFinished()) return true; // don't accept new events if dispatcher is going to finish
|
||||
if (hasActiveEvent()) return true; // don't accept new events before last event has been handled completly
|
||||
|
||||
if (_delegateEventTo != nullptr)
|
||||
{
|
||||
return _delegateEventTo->eventFilter( watched, e );
|
||||
}
|
||||
return false;
|
||||
} /* EventDispatcher::eventFilter */
|
||||
|
||||
|
||||
void EventDelegater::KickTheBucket()
|
||||
{
|
||||
if (_delegateEventTo != nullptr)
|
||||
{
|
||||
_delegateEventTo->unlinkEventDispatcher();
|
||||
}
|
||||
AbstractEventDispatcher::KickTheBucket();
|
||||
} /* EventDelegater::KickTheBucket */
|
||||
|
||||
|
||||
} } /* namespace SituationMap::RB */
|
||||
+72
@@ -0,0 +1,72 @@
|
||||
/**
|
||||
**
|
||||
** @RDE_HEADER@
|
||||
** Event Dispatcher for Qt5 to delegate mouse and keyboard event to another event dispatcher
|
||||
** $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 .........:
|
||||
**
|
||||
** 15.04.2015, JT : first edition
|
||||
**
|
||||
** -----------------------------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <QtCore/QPointer>
|
||||
|
||||
#include "abstract_event_dispatcher.h"
|
||||
|
||||
|
||||
namespace SituationMap { namespace RB
|
||||
{
|
||||
|
||||
/**
|
||||
@class EventDelegater event_delegater.h
|
||||
@brief Event filter that delegates events to another event filter
|
||||
|
||||
Some Qt-Widgets have a special viewport widget. In this case keyboard and mouse events
|
||||
are sended to different widgets. To concentrate the event handling in one event filter
|
||||
for both types of events, it is necessary to forward events from event filter to another
|
||||
one.
|
||||
|
||||
@see AbstractEventDispatcher, EventDispatcher, EventMouseNavigator
|
||||
*/
|
||||
class EventDelegater final : public AbstractEventDispatcher
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
|
||||
EventDelegater( QWidget * getEventsFrom, AbstractEventDispatcher * delegateEventTo );
|
||||
|
||||
~EventDelegater() = default;
|
||||
|
||||
EventDelegater(const EventDelegater &) = delete;
|
||||
EventDelegater & operator = (const EventDelegater &) = delete;
|
||||
|
||||
protected:
|
||||
|
||||
QPointer<AbstractEventDispatcher> _delegateEventTo;
|
||||
|
||||
bool eventFilter(QObject*, QEvent*) override;
|
||||
|
||||
void KickTheBucket() override;
|
||||
}; /* EventDelegater */
|
||||
|
||||
|
||||
} } /* namespace SituationMap::RB */
|
||||
+626
@@ -0,0 +1,626 @@
|
||||
/**
|
||||
**
|
||||
** @RDE_HEADER@
|
||||
** Event Dispatcher for Qt5 to handle mouse and keyboard event
|
||||
** $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 .........:
|
||||
**
|
||||
** 28.04.2003, JT : First edition for use with Qt4 in START Feature Editor fee
|
||||
** 25.03.2015, JT : Refactoring for use with Qt5
|
||||
**
|
||||
** -----------------------------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
#include "event_dispatcher.h"
|
||||
|
||||
#include "gestures.h"
|
||||
|
||||
#include <QtGui/QKeyEvent>
|
||||
|
||||
#include <QtGui/QMouseEvent>
|
||||
#include <QtGui/QWheelEvent>
|
||||
|
||||
#include <QtWidgets/QGesture>
|
||||
#include <QtWidgets/QWidget>
|
||||
#include <QMetaMethod>
|
||||
|
||||
namespace SituationMap { namespace RB
|
||||
{
|
||||
|
||||
EventDispatcher::EventDispatcher(QWidget * getEventsFrom)
|
||||
: AbstractEventDispatcher(getEventsFrom)
|
||||
, _snapEnabled(false)
|
||||
, _snapRatio(5)
|
||||
, _drawRatio(false)
|
||||
, _doubleClickHandled(false)
|
||||
, _leftPressHandled(false)
|
||||
{
|
||||
} /* EventDispatcher::EventDispatcher */
|
||||
|
||||
|
||||
EventDispatcher::EventDispatcher(QWidget * getEventsFrom, EventActionInterface * eventActions )
|
||||
: AbstractEventDispatcher(getEventsFrom, eventActions)
|
||||
, _snapEnabled(false)
|
||||
, _snapRatio(5)
|
||||
, _drawRatio(false)
|
||||
, _doubleClickHandled(false)
|
||||
, _leftPressHandled(false)
|
||||
{
|
||||
} /* EventDispatcher::EventDispatcher */
|
||||
|
||||
|
||||
bool EventDispatcher::eventFilterKey( int key, Qt::KeyboardModifiers mod )
|
||||
{
|
||||
QPoint moveDelta;
|
||||
int multiply ( (mod.testFlag(Qt::KeyboardModifier::ShiftModifier)) ? 10 : 1);
|
||||
bool controlKey( (mod.testFlag(Qt::KeyboardModifier::ControlModifier)) );
|
||||
|
||||
switch (key)
|
||||
{
|
||||
case Qt::Key_Delete : return onDoDelete(); break;
|
||||
case Qt::Key_Z : if (controlKey) return onDoUndo(); break;
|
||||
case Qt::Key_Escape : return onDoEscape(); break;
|
||||
case Qt::Key_Return : return onDoEnd(); break;
|
||||
case Qt::Key_Left : moveDelta = QPoint(-1, 0)*multiply; break;
|
||||
case Qt::Key_Right : moveDelta = QPoint( 1, 0)*multiply; break;
|
||||
case Qt::Key_Up : moveDelta = QPoint( 0,-1)*multiply; break;
|
||||
case Qt::Key_Down : moveDelta = QPoint( 0, 1)*multiply; break;
|
||||
default : return false;
|
||||
} /* switch */
|
||||
|
||||
if (_getEventsFrom != nullptr)
|
||||
{
|
||||
QPoint cursorPos = _getEventsFrom->mapFromGlobal( QCursor::pos() );
|
||||
onPress( cursorPos.x(), cursorPos.y(), mod );
|
||||
cursorPos += moveDelta;
|
||||
onMove ( cursorPos.x(), cursorPos.y(), Qt::MouseButton::LeftButton, mod );
|
||||
onClick( cursorPos.x(), cursorPos.y(), mod );
|
||||
|
||||
QCursor::setPos( _getEventsFrom->mapToGlobal(cursorPos) );
|
||||
}
|
||||
return true;
|
||||
} /* EventDispatcher::eventFilterKey */
|
||||
|
||||
|
||||
bool EventDispatcher::eventFilterGesture( QGestureEvent * gestureEvent )
|
||||
{
|
||||
bool handled = false;
|
||||
|
||||
if (gestureEvent)
|
||||
{
|
||||
const QList<QGesture*> & gestureList = gestureEvent->gestures();
|
||||
for (auto gesture : gestureList)
|
||||
{
|
||||
Qt::GestureType gestureType = gesture->gestureType();
|
||||
Qt::GestureState gestureState = gesture->state();
|
||||
|
||||
QTapGesture * tapGesture = nullptr;
|
||||
QTapAndHoldGesture * tapAndHoldGesture = nullptr;
|
||||
QPanGesture * panGesture = nullptr;
|
||||
QPinchGesture * pinchGesture = nullptr;
|
||||
QSwipeGesture * swipeGesture = nullptr;
|
||||
ApplyGesture * applyGesture = nullptr;
|
||||
QString typeName;
|
||||
QString stateName;
|
||||
|
||||
switch (gestureType)
|
||||
{
|
||||
case Qt::TapGesture : tapGesture = static_cast<QTapGesture *>(gesture); typeName = QLatin1String("TapGesture"); break;
|
||||
case Qt::TapAndHoldGesture : tapAndHoldGesture = static_cast<QTapAndHoldGesture*>(gesture); typeName = QLatin1String("TapAndHoldGesture"); break;
|
||||
case Qt::PanGesture : panGesture = static_cast<QPanGesture *>(gesture); typeName = QLatin1String("PanGesture"); break;
|
||||
case Qt::PinchGesture : pinchGesture = static_cast<QPinchGesture *>(gesture); typeName = QLatin1String("PinchGesture"); break;
|
||||
case Qt::SwipeGesture : swipeGesture = static_cast<QSwipeGesture *>(gesture); typeName = QLatin1String("SwipeGesture"); break;
|
||||
default:
|
||||
{
|
||||
if (gestureType == _applyGestureID)
|
||||
{
|
||||
applyGesture = static_cast<ApplyGesture*>(gesture);
|
||||
typeName = QLatin1String("ApplyGesture");
|
||||
}
|
||||
} break;
|
||||
}
|
||||
switch (gestureState)
|
||||
{
|
||||
case Qt::NoGesture : stateName = QLatin1String("NoGesture"); break;
|
||||
case Qt::GestureStarted : stateName = QLatin1String("GestureStarted"); break;
|
||||
case Qt::GestureUpdated : stateName = QLatin1String("GestureUpdated"); break;
|
||||
case Qt::GestureFinished : stateName = QLatin1String("GestureFinished"); break;
|
||||
case Qt::GestureCanceled : stateName = QLatin1String("GestureCanceled"); break;
|
||||
}
|
||||
|
||||
DEBUG_LOG(_logger) << LOGFUNCTION << " Gesture type=" << typeName << " Gesture state=" << stateName;
|
||||
|
||||
if (panGesture)
|
||||
{
|
||||
const QPoint & offset = panGesture->offset().toPoint();
|
||||
const QPoint & hotSpot = _getEventsFrom->mapFromGlobal( panGesture->hotSpot().toPoint() );
|
||||
|
||||
switch (gestureState)
|
||||
{
|
||||
case Qt::GestureStarted:
|
||||
{
|
||||
handled = onPress( hotSpot.x(), hotSpot.y(), nullptr );
|
||||
if (handled) gestureEvent -> accept( panGesture );
|
||||
} break;
|
||||
|
||||
case Qt::GestureUpdated:
|
||||
handled = onMove ( hotSpot.x() + offset.x(), hotSpot.y() + offset.y(), Qt::MouseButton::LeftButton, nullptr );
|
||||
break;
|
||||
case Qt::GestureFinished:
|
||||
// handled = onMove ( hotSpot.x() + offset.x(), hotSpot.y() + offset.y(), Qt::MouseButton::LeftButton, 0 );
|
||||
handled = onClick( hotSpot.x() + offset.x(), hotSpot.y() + offset.y(), nullptr );
|
||||
break;
|
||||
case Qt::GestureCanceled:
|
||||
getEventActions()->resetAction( this, 0, 0 );
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if (applyGesture)
|
||||
{
|
||||
switch (gestureState)
|
||||
{
|
||||
case Qt::GestureStarted : gestureEvent -> accept( applyGesture ); break;
|
||||
case Qt::GestureFinished :
|
||||
{
|
||||
getEventActions()->resetAction( this, qRound(applyGesture->position().x()), qRound(applyGesture->position().y()) );
|
||||
handled = onDoubleClick( qRound(applyGesture->position().x()), qRound(applyGesture->position().y()), nullptr );
|
||||
if (handled)
|
||||
{
|
||||
gestureEvent -> accept( applyGesture );
|
||||
return true;
|
||||
}
|
||||
} break;
|
||||
default : break;
|
||||
}
|
||||
}
|
||||
|
||||
// currently not used
|
||||
Q_UNUSED(handled);
|
||||
Q_UNUSED(tapGesture);
|
||||
Q_UNUSED(tapAndHoldGesture);
|
||||
Q_UNUSED(pinchGesture);
|
||||
Q_UNUSED(swipeGesture);
|
||||
}
|
||||
}
|
||||
return handled;
|
||||
} /* EventDispatcher::eventFilerGesture */
|
||||
|
||||
|
||||
bool EventDispatcher::eventFilterWheel( QWheelEvent * e )
|
||||
{
|
||||
const int WHEEL_DELTA = 120; // natural mouse driver constant
|
||||
|
||||
if (e->modifiers().testFlag(Qt::KeyboardModifier::ControlModifier) &&
|
||||
e->buttons().testFlag(Qt::MidButton))
|
||||
{
|
||||
int newValue = (int)_snapRatio + (e->angleDelta() / WHEEL_DELTA).manhattanLength();
|
||||
_snapRatio = (newValue < 5) ? 5 : newValue;
|
||||
return onMove( e->x(), e->y(), e->buttons(), e->modifiers() );
|
||||
}
|
||||
return false;
|
||||
} /* EventDispatcher::eventFilterWheel */
|
||||
|
||||
|
||||
bool EventDispatcher::eventFilter( QObject * watched, QEvent * e )
|
||||
{
|
||||
// Maybe ???
|
||||
// qCritical() << " _getEventsFrom = " << _getEventsFrom
|
||||
// << " watched = " << watched
|
||||
// << " e->type() = " << e->type();
|
||||
// if (watched != _getEventsFrom)
|
||||
// return AbstractEventDispatcher::eventFilter(watched,e);
|
||||
|
||||
|
||||
Q_UNUSED(watched);
|
||||
|
||||
QString debugString(QLatin1String("unhandled event"));
|
||||
|
||||
if (hasFinished()) return true; // don't accept new events if dispatcher is going to finish
|
||||
if (hasActiveEvent()) return true; // don't accept new events before last event has been handled completly
|
||||
|
||||
if (e)
|
||||
{
|
||||
bool handled( false );
|
||||
|
||||
setActiveEvent( true );
|
||||
|
||||
switch( e->type() )
|
||||
{
|
||||
case QEvent::Enter :
|
||||
{
|
||||
debugString = QLatin1String("enter event");
|
||||
_getEventsFrom -> setFocus();
|
||||
_doubleClickHandled = false;
|
||||
_leftPressHandled = false;
|
||||
} break;
|
||||
|
||||
case QEvent::Leave : _doubleClickHandled = _leftPressHandled = false; break;
|
||||
|
||||
case QEvent::GraphicsSceneMousePress : break;
|
||||
case QEvent::MouseButtonPress :
|
||||
{
|
||||
debugString = QLatin1String("mouse button press event");
|
||||
|
||||
_doubleClickHandled = false;
|
||||
|
||||
QMouseEvent *mouseEvent = static_cast<QMouseEvent*>(e);
|
||||
if (Qt::RightButton == mouseEvent->button())
|
||||
{
|
||||
handled = onMenuPress( mouseEvent->x()
|
||||
, mouseEvent->y()
|
||||
, mouseEvent->modifiers() );
|
||||
}
|
||||
if (Qt::LeftButton == mouseEvent->button())
|
||||
{
|
||||
if (!(mouseEvent->modifiers().testFlag(Qt::KeyboardModifier::ControlModifier)))
|
||||
{
|
||||
handled = onPress( mouseEvent->x()
|
||||
, mouseEvent->y()
|
||||
, mouseEvent->modifiers() );
|
||||
if (handled) _leftPressHandled = true;
|
||||
}
|
||||
}
|
||||
if (Qt::MidButton == mouseEvent->button())
|
||||
{
|
||||
handled = mouseEvent->modifiers().testFlag(Qt::KeyboardModifier::ControlModifier);
|
||||
}
|
||||
} break;
|
||||
|
||||
case QEvent::TouchBegin:
|
||||
{
|
||||
debugString = QLatin1String("mouse button press event TOUCH");
|
||||
|
||||
_doubleClickHandled = false;
|
||||
|
||||
QTouchEvent *mouseEvent = static_cast<QTouchEvent*>(e);
|
||||
|
||||
if (mouseEvent->touchPoints().size() > 0)
|
||||
{
|
||||
const QTouchEvent::TouchPoint tp = mouseEvent->touchPoints().at(0);
|
||||
|
||||
handled = onPress( tp.pos().x()
|
||||
, tp.pos().y()
|
||||
, mouseEvent->modifiers() );
|
||||
if (handled) _leftPressHandled = true;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
case QEvent::GraphicsSceneMouseDoubleClick : break;
|
||||
case QEvent::MouseButtonDblClick :
|
||||
{
|
||||
debugString = QLatin1String("mouse double click event");
|
||||
QMouseEvent *mouseEvent = static_cast<QMouseEvent*>(e);
|
||||
if (Qt::LeftButton == mouseEvent->button())
|
||||
{
|
||||
if (!(mouseEvent->modifiers().testFlag(Qt::KeyboardModifier::ControlModifier)))
|
||||
{
|
||||
onDoubleClick( mouseEvent->x()
|
||||
, mouseEvent->y()
|
||||
, mouseEvent->modifiers() );
|
||||
|
||||
_doubleClickHandled = handled = true;
|
||||
}
|
||||
}
|
||||
} break;
|
||||
|
||||
case QEvent::GraphicsSceneMouseRelease : break;
|
||||
case QEvent::MouseButtonRelease :
|
||||
{
|
||||
if (!_doubleClickHandled)
|
||||
{
|
||||
debugString = QLatin1String("mouse button release event");
|
||||
QMouseEvent *mouseEvent = static_cast<QMouseEvent*>(e);
|
||||
if (Qt::RightButton == mouseEvent->button())
|
||||
{
|
||||
handled = onMenuClick( mouseEvent->x()
|
||||
, mouseEvent->y()
|
||||
, mouseEvent->modifiers() );
|
||||
}
|
||||
if (Qt::LeftButton == mouseEvent->button())
|
||||
{
|
||||
if (!(mouseEvent->modifiers().testFlag(Qt::KeyboardModifier::ControlModifier)))
|
||||
{
|
||||
// The mouse button press event must had be handled before. If not skip button release ...
|
||||
if (_leftPressHandled)
|
||||
{
|
||||
_leftPressHandled = false;
|
||||
handled = onClick( mouseEvent->x()
|
||||
, mouseEvent->y()
|
||||
, mouseEvent->modifiers() );
|
||||
}
|
||||
else callEventAction( &EventActionInterface::buttonPositionAction, mouseEvent->x(), mouseEvent->y() );
|
||||
}
|
||||
}
|
||||
if (Qt::MidButton == mouseEvent->button())
|
||||
{
|
||||
handled = mouseEvent->modifiers().testFlag(Qt::KeyboardModifier::ControlModifier);
|
||||
}
|
||||
}
|
||||
else _doubleClickHandled = false;
|
||||
|
||||
} break;
|
||||
|
||||
case QEvent::TouchEnd:
|
||||
{
|
||||
|
||||
debugString = QLatin1String("mouse button release event TOUCH");
|
||||
QTouchEvent *mouseEvent = static_cast<QTouchEvent*>(e);
|
||||
|
||||
// The mouse button press event must had be handled before. If not skip button release ...
|
||||
if (mouseEvent->touchPoints().size() > 0)
|
||||
{
|
||||
const QTouchEvent::TouchPoint tp = mouseEvent->touchPoints().at(0);
|
||||
if (_leftPressHandled)
|
||||
{
|
||||
_leftPressHandled = false;
|
||||
handled = onClick( tp.pos().x()
|
||||
, tp.pos().y()
|
||||
, mouseEvent->modifiers() );
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
callEventAction( &EventActionInterface::buttonPositionAction, tp.pos().x(), tp.pos().y() );
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case QEvent::GraphicsSceneMouseMove : break;
|
||||
case QEvent::MouseMove :
|
||||
{
|
||||
debugString = QLatin1String("mouse move event");
|
||||
|
||||
_doubleClickHandled = false;
|
||||
|
||||
QMouseEvent *mouseEvent = static_cast<QMouseEvent*>(e);
|
||||
|
||||
if (mouseEvent->buttons() != Qt::MidButton)
|
||||
{
|
||||
if (!(mouseEvent->modifiers().testFlag(Qt::KeyboardModifier::ControlModifier)))
|
||||
{
|
||||
if (_drawRatio)
|
||||
{
|
||||
if (!(mouseEvent->modifiers().testFlag(Qt::KeyboardModifier::AltModifier)))
|
||||
{
|
||||
_drawRatio = false;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (mouseEvent->modifiers().testFlag(Qt::KeyboardModifier::AltModifier))
|
||||
{
|
||||
_drawRatio = true;
|
||||
}
|
||||
}
|
||||
|
||||
handled = onMove( mouseEvent->x()
|
||||
, mouseEvent->y()
|
||||
, mouseEvent->buttons()
|
||||
, mouseEvent->modifiers());
|
||||
|
||||
// REGG-5230 - PlanEditor: Position beim Erstellen und Modifizieren
|
||||
// von Elementen wird nicht aktualisiert
|
||||
// Next handler is EventMouseNavigator. ::eventFilter() will handle
|
||||
// QEvent::MouseMove and emit mouseMovedEvent to update PositionStr.
|
||||
// If handled == true, the next handler is NOT called.
|
||||
// So emit here alternatively.
|
||||
if (handled)
|
||||
emit mouseMovedEvent(mouseEvent->pos().x(), mouseEvent->pos().y());
|
||||
}
|
||||
}
|
||||
} break;
|
||||
|
||||
case QEvent::TouchUpdate:
|
||||
{
|
||||
debugString = QLatin1String("mouse move event Touch");
|
||||
|
||||
_doubleClickHandled = false;
|
||||
|
||||
QTouchEvent* mouseEvent = static_cast<QTouchEvent*>(e);
|
||||
if (mouseEvent->touchPoints().size() > 0)
|
||||
{
|
||||
const QTouchEvent::TouchPoint tp = mouseEvent->touchPoints().at(0);
|
||||
|
||||
handled = onMove( tp.pos().x()
|
||||
, tp.pos().y()
|
||||
, Qt::LeftButton
|
||||
, mouseEvent->modifiers());
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
case QEvent::KeyPress :
|
||||
{
|
||||
QKeyEvent *keyEvent = static_cast<QKeyEvent*>(e);
|
||||
|
||||
debugString = QStringLiteral("key press event (%1)").arg(keyEvent->key());
|
||||
|
||||
handled = eventFilterKey( keyEvent->key(),keyEvent->modifiers() );
|
||||
if ((keyEvent->modifiers().testFlag(Qt::KeyboardModifier::ControlModifier)) || (keyEvent->key() == Qt::Key_Control))
|
||||
{
|
||||
setSnapEnabled( true );
|
||||
_drawRatio = true;
|
||||
handled = true;
|
||||
}
|
||||
} break;
|
||||
|
||||
case QEvent::KeyRelease :
|
||||
{
|
||||
debugString = QLatin1String("key release event");
|
||||
if (_drawRatio)
|
||||
{
|
||||
_drawRatio = false;
|
||||
setSnapEnabled( true );
|
||||
}
|
||||
// handled = true;
|
||||
} break;
|
||||
|
||||
|
||||
case QEvent::Wheel :
|
||||
{
|
||||
debugString = QLatin1String("mouse wheel event");
|
||||
QWheelEvent *wheelEvent = static_cast<QWheelEvent*>(e);
|
||||
if (wheelEvent->modifiers() & (Qt::KeyboardModifier::ShiftModifier | Qt::KeyboardModifier::ControlModifier))
|
||||
{
|
||||
handled = eventFilterWheel( wheelEvent );
|
||||
}
|
||||
} break;
|
||||
|
||||
case QEvent::Gesture:
|
||||
{
|
||||
handled = eventFilterGesture( static_cast<QGestureEvent*>(e) );
|
||||
} break;
|
||||
|
||||
default: break;
|
||||
|
||||
} /* switch */
|
||||
|
||||
if (!hasFinished()) setActiveEvent( false );
|
||||
|
||||
if (handled) e->accept();
|
||||
|
||||
TRACE_LOG(_logger) << LOGFUNCTION << " Event " << debugString << " handled = " << handled;
|
||||
|
||||
if (handled) return true;
|
||||
}
|
||||
return AbstractEventDispatcher::eventFilter(watched,e);
|
||||
} /* EventDispatcher::eventFilter */
|
||||
|
||||
|
||||
bool EventDispatcher::onMove(int x, int y, Qt::MouseButtons buttons, Qt::KeyboardModifiers mod)
|
||||
{
|
||||
Q_UNUSED(mod);
|
||||
if (buttons.testFlag(Qt::MouseButton::LeftButton)) return callEventAction( &EventActionInterface::movePickedAction, x, y );
|
||||
return callEventAction( &EventActionInterface::moveAction, x, y );
|
||||
} /* EventDispatcher::onMove */
|
||||
|
||||
|
||||
bool EventDispatcher::onPress(int x, int y, Qt::KeyboardModifiers mod)
|
||||
{
|
||||
if (mod == Qt::NoModifier)
|
||||
return callEventAction( &EventActionInterface::selectAction, x, y );
|
||||
if (mod.testFlag(Qt::KeyboardModifier::ShiftModifier))
|
||||
return callEventAction( &EventActionInterface::multiSelectActionPress, x, y );
|
||||
return false;
|
||||
} /* EventDispatcher::onPress */
|
||||
|
||||
|
||||
bool EventDispatcher::onClick(int x, int y, Qt::KeyboardModifiers mod)
|
||||
{
|
||||
Q_UNUSED(x);
|
||||
Q_UNUSED(y);
|
||||
|
||||
if (mod == Qt::NoModifier)
|
||||
{
|
||||
bool ret = callEventAction( &EventActionInterface::setCoordinateAction, x, y );
|
||||
if (ret)
|
||||
{
|
||||
EventActionInterface * eaIf = getEventActions();
|
||||
if (eaIf) eaIf->userActionFinished();
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
if (mod.testFlag( Qt::KeyboardModifier::ShiftModifier ))
|
||||
return callEventAction( &EventActionInterface::multiSelectActionRelease, x, y );
|
||||
|
||||
return false;
|
||||
} /* EventDispatcher::onClick */
|
||||
|
||||
|
||||
bool EventDispatcher::onMenuPress(int x, int y, Qt::KeyboardModifiers mod)
|
||||
{
|
||||
Q_UNUSED(x);
|
||||
Q_UNUSED(y);
|
||||
Q_UNUSED(mod);
|
||||
|
||||
return false;
|
||||
} /* EventDispatcher::onMenuPress */
|
||||
|
||||
|
||||
bool EventDispatcher::onMenuClick(int x, int y, Qt::KeyboardModifiers mod)
|
||||
{
|
||||
Q_UNUSED(mod);
|
||||
return callEventAction( &EventActionInterface::contextMenuAction, x, y );
|
||||
} /* EventDispatcher::onMenuClick */
|
||||
|
||||
|
||||
bool EventDispatcher::onDoubleClick(int x, int y, Qt::KeyboardModifiers )
|
||||
{
|
||||
callEventAction( &EventActionInterface::completeStateAction, x, y );
|
||||
return true;
|
||||
} /* EventDispatcher::onDoubleClick */
|
||||
|
||||
|
||||
bool EventDispatcher::onDoDelete()
|
||||
{
|
||||
if (_getEventsFrom != nullptr)
|
||||
{
|
||||
QPoint cursorPos = _getEventsFrom->mapFromGlobal( QCursor::pos() );
|
||||
callEventAction( &EventActionInterface::selectAction, cursorPos.x(), cursorPos.y() );
|
||||
bool ret = callEventAction( &EventActionInterface::deleteAction, cursorPos.x(), cursorPos.y() );
|
||||
if (ret)
|
||||
{
|
||||
EventActionInterface * eaIf = getEventActions();
|
||||
if (eaIf) eaIf->userActionFinished();
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
return false;
|
||||
} /* EventDispatcher::onDoDelete */
|
||||
|
||||
|
||||
bool EventDispatcher::onDoUndo()
|
||||
{
|
||||
bool ret = callEventAction( &EventActionInterface::undoAction, 0, 0 );
|
||||
if (ret)
|
||||
{
|
||||
EventActionInterface * eaIf = getEventActions();
|
||||
if (eaIf) eaIf->userActionFinished();
|
||||
}
|
||||
return ret;
|
||||
} /* EventDispatcher::onDoUndo */
|
||||
|
||||
|
||||
bool EventDispatcher::onDoEscape()
|
||||
{
|
||||
EventActionInterface * eventActions = getEventActions();
|
||||
KickTheBucket();
|
||||
if (eventActions) eventActions->abortAction( this, 0, 0 );
|
||||
return true;
|
||||
} /* EventDispatcher::onDoEscape */
|
||||
|
||||
bool EventDispatcher::onDoEnd()
|
||||
{
|
||||
EventActionInterface * eventActions = getEventActions();
|
||||
KickTheBucket();
|
||||
if (eventActions) eventActions->applyAndEndAction( this, 0, 0 );
|
||||
return true;
|
||||
} /* EventDispatcher::onDoEnd */
|
||||
|
||||
|
||||
} } /* namespace SituationMap::RB */
|
||||
+140
@@ -0,0 +1,140 @@
|
||||
/**
|
||||
**
|
||||
** @RDE_HEADER@
|
||||
** Event Dispatcher for Qt5 to handle mouse and keyboard event
|
||||
** $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 .........:
|
||||
**
|
||||
** 28.04.2003, JT : First edition for use with Qt4 in START Feature Editor fee
|
||||
** 25.03.2015, JT : Refactoring for use with Qt5
|
||||
**
|
||||
** -----------------------------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
|
||||
#include "abstract_event_dispatcher.h"
|
||||
|
||||
class QGestureEvent;
|
||||
class QWheelEvent;
|
||||
|
||||
namespace SituationMap { namespace RB
|
||||
{
|
||||
|
||||
/**
|
||||
@class EventDispatcher event_dispatcher.h
|
||||
@brief Event filter that handles events when a rubberband it active.
|
||||
|
||||
Implements class \c AbstractEventDispatcher to manage event handling for rubberbands. Following events are handled:
|
||||
|
||||
| Input-Event | Interface Function | Description |
|
||||
| :--------------------------------------------- | : ----------------- | : ------------------------------------------------------------------------------------------------------ |
|
||||
| Mouse move without any modifier | moveAction | Move Cursor or preview |
|
||||
| Mouse move with pressed left button | movePickedAction | Move selected items. If movePickedAction == false redirect to \c EventMouseNavigator for panning of map. |
|
||||
| Mouse move with pressed middle button | | Redirect to \c EventMouseNavigator for panning of map |
|
||||
| Mouse wheel | | Redirect to \c EventMouseNavigator for zooming of map |
|
||||
| Left mouse button press | selectAction | Do selection of single item or panning of map. |
|
||||
| Left mouse button press with pressed SHIFT key | multiSelectAction | Do selection of multiple items. |
|
||||
| Left mouse button release | setCoordinateAction | Set final coordinate to selected items and deselects item. |
|
||||
| Double click left mouse button | completeStateAction | Finish input. |
|
||||
| Right mouse button release | contextMenuAction | Show context menu. |
|
||||
| Key release CTRL-Z | undoMenuAction | Undo last left mouse button click if possible. |
|
||||
| Key release Delete | deleteMenuAction | Delete selected item. |
|
||||
| Key release ESC | abortAction | Abort rubberband without saving data. The rubberband emits the abort signal. |
|
||||
| Key release RETURN | applyAndEndAction | Finish rubberband. The rubberband emits the apply signal. |
|
||||
| Key release UP | moveAction | Moves 1 pixel up. |
|
||||
| Key release DOWN | moveAction | Moves 1 pixel down. |
|
||||
| Key release LEFT | moveAction | Moves 1 pixel left. |
|
||||
| Key release RIGHT | moveAction | Moves 1 pixel right. |
|
||||
| Key release UP with SHIFT key pressed | moveAction | Moves 10 pixel up. |
|
||||
| Key release DOWN with SHIFT key pressed | moveAction | Moves 10 pixel down. |
|
||||
| Key release LEFT with SHIFT key pressed | moveAction | Moves 10 pixel left. |
|
||||
| Key release RIGHT with SHIFT key pressed | moveAction | Moves 10 pixel right. |
|
||||
|
||||
@see AbstractEventDispatcher, EventDelegater, EventMouseNavigator,
|
||||
Rubberband, RubberbandPointFeature, RubberbandPointCluster,
|
||||
RubberbandMultiPointFeature, RubberbandCorridor, RubberbandRectangle, RubberbandEllipse,
|
||||
EventMouseNavigator
|
||||
*/
|
||||
|
||||
class EventDispatcher final : public AbstractEventDispatcher
|
||||
{
|
||||
friend class RubberbandBase;
|
||||
|
||||
Q_OBJECT
|
||||
public:
|
||||
|
||||
/**
|
||||
@name Construction & Destruction
|
||||
@{
|
||||
*/
|
||||
explicit EventDispatcher( QWidget * getEventsFrom );
|
||||
explicit EventDispatcher( QWidget * getEventsFrom, EventActionInterface* );
|
||||
|
||||
~EventDispatcher() = default;
|
||||
|
||||
EventDispatcher(const EventDispatcher &) = delete;
|
||||
EventDispatcher & operator = (const EventDispatcher &) = delete;
|
||||
/** @} */
|
||||
|
||||
inline void setSnapEnabled(bool) {}
|
||||
inline bool SnapEnabled() { return _snapEnabled; }
|
||||
|
||||
signals:
|
||||
/**
|
||||
Signal will be emitted if a mouse move is done (and if event is handled)
|
||||
*/
|
||||
void mouseMovedEvent(int windowPosX, int windowPosY);
|
||||
|
||||
|
||||
protected:
|
||||
|
||||
bool eventFilter(QObject*, QEvent*) override;
|
||||
|
||||
bool eventFilterKey( int key, Qt::KeyboardModifiers mod );
|
||||
bool eventFilterGesture( QGestureEvent * gestureEvent );
|
||||
bool eventFilterWheel( QWheelEvent * );
|
||||
|
||||
private:
|
||||
|
||||
bool onMove (int x, int y, Qt::MouseButtons buttons, Qt::KeyboardModifiers mod); //!< Handle a mouse move event.
|
||||
|
||||
bool onPress ( int x, int y, Qt::KeyboardModifiers mod); //!< Handle left mouse button press event.
|
||||
bool onClick ( int x, int y, Qt::KeyboardModifiers mod); //!< Handle left mouse button release event.
|
||||
bool onMenuPress ( int x, int y, Qt::KeyboardModifiers mod); //!< Handle right mouse button press event.
|
||||
bool onMenuClick ( int x, int y, Qt::KeyboardModifiers mod); //!< Handle right mouse button release event.
|
||||
bool onDoubleClick( int x, int y, Qt::KeyboardModifiers mod); //!< Handle left mouse button double click event.
|
||||
|
||||
bool onDoDelete(); //!< Handle del key press event.
|
||||
|
||||
bool onDoUndo(); //!< Handle ctrl-c key press event.
|
||||
bool onDoEscape(); //!< Handle esc key press event.
|
||||
bool onDoEnd(); //!< Handle enter key press event.
|
||||
|
||||
bool _snapEnabled;
|
||||
uint _snapRatio;
|
||||
bool _drawRatio;
|
||||
bool _doubleClickHandled;
|
||||
bool _leftPressHandled;
|
||||
|
||||
}; /* EventDispatcher */
|
||||
|
||||
|
||||
} } /* namespace SituationMap::RB */
|
||||
@@ -0,0 +1,643 @@
|
||||
/**
|
||||
**
|
||||
** @RDE_HEADER@
|
||||
** Event Dispatcher for Qt5 to delegate mouse and keyboard event to another event dispatcher
|
||||
** $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 .........:
|
||||
**
|
||||
** 15.04.2015, JT : First edition
|
||||
**
|
||||
** -----------------------------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
#include "event_mouse_navigator.h"
|
||||
#include "rubberband.h"
|
||||
|
||||
#include <QtCore/QMetaMethod>
|
||||
#include <QtCore/QtMath>
|
||||
|
||||
#include <QtGui/QMouseEvent>
|
||||
#include <QtGui/QWheelEvent>
|
||||
|
||||
#include <QtWidgets/QGesture>
|
||||
#include <QtWidgets/QWidget>
|
||||
|
||||
#include <MapImpl/map_impl.h>
|
||||
#include <Map/situation_map_utils.h>
|
||||
|
||||
#include <arcgis/Map.h>
|
||||
#include <arcgis/Layer.h>
|
||||
#include <arcgis/FeatureLayer.h>
|
||||
#include <arcgis/GraphicsOverlay.h>
|
||||
#include <arcgis/Graphic.h>
|
||||
#include <arcgis/MapGraphicsView.h>
|
||||
#include <arcgis/SceneGraphicsView.h>
|
||||
|
||||
|
||||
namespace SituationMap { namespace RB
|
||||
{
|
||||
|
||||
int EventMouseNavigator::_pickTolerance = 5;
|
||||
qreal EventMouseNavigator::_zoomFactorBase = 1.002;
|
||||
|
||||
EventMouseNavigator::EventMouseNavigator(QWidget * getEventsFrom, SituationMap::MapImpl *sitMap )
|
||||
: AbstractEventDispatcher(getEventsFrom)
|
||||
, _sitMap(sitMap)
|
||||
, _cursorChanged(false)
|
||||
, _viewPortPos(QPointF(-1, -1))
|
||||
, _selectionMode(SelectionMode::NoSelection)
|
||||
, _pendingRequest(RequestType::None)
|
||||
, _mousePanningActive(false)
|
||||
, _mousePanningActiveForCenterMapMidButton(false)
|
||||
#ifdef SITUATIONMAP_OWN_WHEEL_HANDLING
|
||||
, _mouseZoomTaskWatcher()
|
||||
#endif
|
||||
, _pressedMouseButton(Qt::NoButton)
|
||||
{
|
||||
// prepare identify:
|
||||
switch (_sitMap->mode())
|
||||
{
|
||||
case Mode::Mode_2D:
|
||||
connect( _sitMap->getEsriMapGraphicsView()
|
||||
, &Esri::ArcGISRuntime::MapGraphicsView::identifyGraphicsOverlaysCompleted
|
||||
, this
|
||||
, &EventMouseNavigator::onGetPickingResult );
|
||||
break;
|
||||
case Mode::Mode_3D:
|
||||
connect( _sitMap->getEsriSceneGraphicsView()
|
||||
, &Esri::ArcGISRuntime::SceneGraphicsView::identifyGraphicsOverlaysCompleted
|
||||
, this
|
||||
, &EventMouseNavigator::onGetPickingResult );
|
||||
break;
|
||||
default:
|
||||
// empty
|
||||
break;
|
||||
}
|
||||
} // EventMouseNavigator::EventMouseNavigator
|
||||
|
||||
|
||||
bool EventMouseNavigator::eventFilter(QObject * watched, QEvent * e)
|
||||
{
|
||||
Q_UNUSED(watched);
|
||||
|
||||
QString debugString(QLatin1String("unhandled event"));
|
||||
|
||||
if (hasFinished()) return true; // don't accept new events if dispatcher is going to finish
|
||||
if (hasActiveEvent()) return true; // don't accept new events before last event has been handled completly
|
||||
|
||||
if (e)
|
||||
{
|
||||
bool handled( false );
|
||||
|
||||
setActiveEvent( true );
|
||||
|
||||
switch( e->type() )
|
||||
{
|
||||
case QEvent::Enter :
|
||||
{
|
||||
_pressedMouseButton = Qt::NoButton;
|
||||
emit enterEvent();
|
||||
} break;
|
||||
|
||||
case QEvent::Leave :
|
||||
{
|
||||
emit leaveEvent();
|
||||
_pressedMouseButton = Qt::NoButton;
|
||||
} break;
|
||||
|
||||
case QEvent::MouseButtonPress :
|
||||
{
|
||||
handled = false;
|
||||
debugString = QLatin1String("mouse button press event");
|
||||
|
||||
QMouseEvent * mouseEvent = static_cast<QMouseEvent*>(e);
|
||||
|
||||
_pressedMouseButton = mouseEvent->button();
|
||||
|
||||
_mousePanningActive = false;
|
||||
_mouseMoveRefPos = mouseEvent->pos(); // for panning
|
||||
|
||||
_restoreMouseCursor = getCursorFromWidget();
|
||||
|
||||
if (Qt::MidButton == mouseEvent->button())
|
||||
{
|
||||
handled = true;
|
||||
|
||||
_mousePanningActive = true;
|
||||
_mousePanningActiveForCenterMapMidButton = false;
|
||||
// setCursorToWidget( QCursor(Qt::CursorShape::ClosedHandCursor) );
|
||||
}
|
||||
} break;
|
||||
case QEvent::TouchBegin :
|
||||
{
|
||||
handled = false;
|
||||
debugString = QLatin1String("Touch button press event");
|
||||
|
||||
QTouchEvent * mouseEvent = static_cast<QTouchEvent*>(e);
|
||||
|
||||
_pressedMouseButton = Qt::MouseButton::LeftButton;
|
||||
|
||||
_mousePanningActive = false;
|
||||
if (mouseEvent->touchPoints().size() > 0)
|
||||
{
|
||||
const QTouchEvent::TouchPoint tp = mouseEvent->touchPoints().at(0);
|
||||
|
||||
_mouseMoveRefPos = tp.pos().toPoint(); // for panning
|
||||
_restoreMouseCursor = getCursorFromWidget();
|
||||
}
|
||||
} break;
|
||||
|
||||
case QEvent::MouseButtonRelease :
|
||||
{
|
||||
debugString = QLatin1String("mouse button release event");
|
||||
|
||||
QMouseEvent * mouseEvent = static_cast<QMouseEvent*>(e);
|
||||
|
||||
|
||||
if (Qt::LeftButton == mouseEvent->button())
|
||||
{
|
||||
if (_cursorChanged)
|
||||
{
|
||||
setCursorToWidget(_restoreMouseCursor);
|
||||
_cursorChanged = false;
|
||||
}
|
||||
|
||||
/*
|
||||
* The ESRI::MapView is doing panning on mouse move when left mouse button is pressed.
|
||||
* To prevent selection in this case check mouse move distance.
|
||||
*/
|
||||
if (Qt::LeftButton == _pressedMouseButton && ((mouseEvent->pos() - _mouseMoveRefPos).manhattanLength() < 3) )
|
||||
{
|
||||
if (Rubberband::activeRubberbands(_sitMap).isEmpty())
|
||||
{
|
||||
handled = false; // pass event to esri map to click buttons
|
||||
selectionRequested(mouseEvent->localPos());
|
||||
// do not handled = true; because some buttons in GraphicsView needs to get the event later.
|
||||
}
|
||||
}
|
||||
else
|
||||
handled = true; // may be a double click catched at higher event filter
|
||||
}
|
||||
|
||||
if (Qt::RightButton == mouseEvent->button())
|
||||
{
|
||||
handled = true;
|
||||
pickRequested( mouseEvent->localPos() );
|
||||
}
|
||||
|
||||
if ((Qt::MidButton == mouseEvent->button()))
|
||||
{
|
||||
if (!_mousePanningActiveForCenterMapMidButton)
|
||||
{
|
||||
// press MidButton and Release MidButton without panning in the meantime:
|
||||
// center map to current mouse position:
|
||||
|
||||
// set viewpoint : (perform this only in 2D - MapGraphicsView <-> MapSceneView)
|
||||
// (3D had different screenToLocation...)
|
||||
Esri::ArcGISRuntime::MapGraphicsView *esriMapGraphicsView = _sitMap->getEsriMapGraphicsView();
|
||||
if (esriMapGraphicsView)
|
||||
{
|
||||
const QPoint &mousePos = mouseEvent->pos();
|
||||
const Esri::ArcGISRuntime::Point & mapCoordEsri = esriMapGraphicsView->screenToLocation(mousePos.x(), mousePos.y());
|
||||
const Esri::ArcGISRuntime::Viewpoint & curVp = esriMapGraphicsView->currentViewpoint(Esri::ArcGISRuntime::ViewpointType::CenterAndScale);
|
||||
const Esri::ArcGISRuntime::Viewpoint newVp(mapCoordEsri, curVp.targetScale());
|
||||
|
||||
esriMapGraphicsView->setViewpointAndWait(newVp); // sync / andWAIT
|
||||
|
||||
_getEventsFrom -> update();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ((_mousePanningActive) || (Qt::MidButton == mouseEvent->button()))
|
||||
{
|
||||
handled = (Qt::MidButton == mouseEvent->button());
|
||||
setCursorToWidget( _restoreMouseCursor );
|
||||
}
|
||||
_mousePanningActive = false;
|
||||
|
||||
} break;
|
||||
|
||||
case QEvent::TouchEnd :
|
||||
{
|
||||
debugString = QLatin1String("Touch button release event");
|
||||
|
||||
QTouchEvent * mouseEvent = static_cast<QTouchEvent*>(e);
|
||||
if (mouseEvent->touchPoints().size() > 0)
|
||||
{
|
||||
const QTouchEvent::TouchPoint tp = mouseEvent->touchPoints().at(0);
|
||||
|
||||
if (_cursorChanged)
|
||||
{
|
||||
setCursorToWidget(_restoreMouseCursor);
|
||||
_cursorChanged = false;
|
||||
}
|
||||
|
||||
/*
|
||||
* The ESRI::MapView is doing panning on mouse move when left mouse button is pressed.
|
||||
* To prevent selection in this case check mouse move distance.
|
||||
*/
|
||||
if (Qt::LeftButton == _pressedMouseButton && ((tp.pos() - _mouseMoveRefPos).manhattanLength() < 3) )
|
||||
{
|
||||
if (Rubberband::activeRubberbands(_sitMap).isEmpty())
|
||||
{
|
||||
handled = false; // pass event to esri map to click buttons
|
||||
selectionRequested(tp.pos());
|
||||
// do not handled = true; because some buttons in GraphicsView needs to get the event later.
|
||||
}
|
||||
}
|
||||
else
|
||||
handled = true; // may be a double click catched at higher event filter
|
||||
|
||||
}
|
||||
_mousePanningActive = false;
|
||||
|
||||
} break;
|
||||
|
||||
case QEvent::MouseMove :
|
||||
{
|
||||
handled = false;
|
||||
debugString = QLatin1String("mouse button move event");
|
||||
QMouseEvent *mouseEvent = static_cast<QMouseEvent*>(e);
|
||||
|
||||
if (isSignalConnected(QMetaMethod::fromSignal(&EventMouseNavigator::mouseMovedEvent)))
|
||||
{
|
||||
emit mouseMovedEvent(mouseEvent->pos().x(), mouseEvent->pos().y());
|
||||
}
|
||||
|
||||
if (_mousePanningActive)
|
||||
{
|
||||
handled = true;
|
||||
|
||||
if (mouseEvent->buttons().testFlag(Qt::MidButton))
|
||||
{
|
||||
_mousePanningActiveForCenterMapMidButton = true;
|
||||
|
||||
// move viewpoint : (perform this only in 2D - MapGraphicsView <-> MapSceneView)
|
||||
// (3D had different screenToLocation...)
|
||||
Esri::ArcGISRuntime::MapGraphicsView *esriMapGraphicsView = _sitMap->getEsriMapGraphicsView();
|
||||
if (esriMapGraphicsView)
|
||||
{
|
||||
QPointF deltaMove = mouseEvent->pos()-_mouseMoveRefPos;
|
||||
QPointF winCenter = QPointF( qreal(_getEventsFrom->width())*0.5, qreal(_getEventsFrom->height())*0.5 );
|
||||
QPointF newCenter = winCenter-deltaMove;
|
||||
|
||||
_mouseMoveRefPos = mouseEvent->pos();
|
||||
|
||||
const Esri::ArcGISRuntime::Point & mapCoordEsri = esriMapGraphicsView->screenToLocation(newCenter.x(), newCenter.y());
|
||||
const Esri::ArcGISRuntime::Viewpoint & curVp = esriMapGraphicsView->currentViewpoint(Esri::ArcGISRuntime::ViewpointType::CenterAndScale);
|
||||
const Esri::ArcGISRuntime::Viewpoint newVp(mapCoordEsri, curVp.targetScale());
|
||||
|
||||
esriMapGraphicsView->setViewpointAndWait(newVp); // sync / andWAIT
|
||||
|
||||
_getEventsFrom -> update();
|
||||
|
||||
DEBUG_LOG(_logger) << LOGFUNCTION << " Panning to " << mapCoordEsri.x() << " - " << mapCoordEsri.y()
|
||||
<< " newCenter pos=" << newCenter
|
||||
<< " mouse pos=" << mouseEvent->pos()
|
||||
<< " delta pos=" << deltaMove;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
setCursorToWidget( _restoreMouseCursor );
|
||||
_mousePanningActive = false;
|
||||
}
|
||||
// : move viewpoint
|
||||
}
|
||||
} break;
|
||||
case QEvent::TouchUpdate :
|
||||
{
|
||||
handled = false;
|
||||
debugString = QLatin1String("touch button move event");
|
||||
QTouchEvent *mouseEvent = static_cast<QTouchEvent*>(e);
|
||||
|
||||
if (mouseEvent->touchPoints().size() > 0)
|
||||
{
|
||||
const QTouchEvent::TouchPoint tp = mouseEvent->touchPoints().at(0);
|
||||
|
||||
if (isSignalConnected(QMetaMethod::fromSignal(&EventMouseNavigator::mouseMovedEvent)))
|
||||
{
|
||||
emit mouseMovedEvent(tp.pos().x(), tp.pos().y());
|
||||
}
|
||||
|
||||
if (_mousePanningActive)
|
||||
{
|
||||
handled = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
setCursorToWidget( _restoreMouseCursor );
|
||||
_mousePanningActive = false;
|
||||
}
|
||||
|
||||
}
|
||||
} break;
|
||||
|
||||
#ifdef SITUATIONMAP_OWN_WHEEL_HANDLING
|
||||
case QEvent::Wheel :
|
||||
{
|
||||
debugString = QLatin1String("mouse wheel event");
|
||||
handled = true;
|
||||
if ((!_mouseZoomTaskWatcher.isValid()) || (_mouseZoomTaskWatcher.isDone()))
|
||||
{
|
||||
|
||||
QWheelEvent * wheelEvent = static_cast<QWheelEvent*>(e);
|
||||
qreal delta = wheelEvent->angleDelta().manhattanLength();
|
||||
bool zoomIn = (wheelEvent->angleDelta().x() < 0) || (wheelEvent->angleDelta().y() < 0);
|
||||
qreal zoomFactor = qreal( qRound( qPow( _zoomFactorBase, (zoomIn) ? delta : -delta ) * 10 )) / 10.0;
|
||||
QPointF winCenter = QPointF( qreal(_getEventsFrom->width())*0.5, qreal(_getEventsFrom->height())*0.5 );
|
||||
|
||||
const QPoint & cursorPosWidget = _getEventsFrom->mapFromGlobal( QCursor::pos() ); // e doesn't have a position get position from cursor here
|
||||
|
||||
Esri::ArcGISRuntime::MapView * esriMapView = _sitMap->getEsriMapGraphicsView();
|
||||
const Esri::ArcGISRuntime::Point & mapCenter = esriMapView -> screenToLocation(winCenter.x(), winCenter.y());
|
||||
const Esri::ArcGISRuntime::Point & cursorPosMap = esriMapView -> screenToLocation(cursorPosWidget.x(), cursorPosWidget.y());
|
||||
double mapScale = esriMapView -> mapScale() * zoomFactor;
|
||||
|
||||
double mapX = (-cursorPosMap.x()+mapCenter.x())*zoomFactor + cursorPosMap.x();
|
||||
double mapY = (-cursorPosMap.y()+mapCenter.y())*zoomFactor + cursorPosMap.y();
|
||||
|
||||
_mouseZoomTaskWatcher = esriMapView->setViewpointCenter( Esri::ArcGISRuntime::Point(mapX,mapY,esriMapView->map()->spatialReference()), mapScale );
|
||||
if (isSignalConnected( QMetaMethod::fromSignal(&EventMouseNavigator::mouseWheelEvent) ))
|
||||
{
|
||||
emit mouseWheelEvent(zoomFactor, QPointF(cursorPosMap.x(), cursorPosMap.y()) );
|
||||
}
|
||||
|
||||
}
|
||||
} break;
|
||||
#endif
|
||||
|
||||
case QEvent::Gesture:
|
||||
{
|
||||
QGestureEvent * gestureEvent = static_cast<QGestureEvent*>(e);
|
||||
|
||||
if (gestureEvent)
|
||||
{
|
||||
const QList<QGesture*> & gestureList = gestureEvent->gestures();
|
||||
for (auto gesture : gestureList)
|
||||
{
|
||||
Qt::GestureType gestureType = gesture->gestureType();
|
||||
Qt::GestureState gestureState = gesture->state();
|
||||
|
||||
// QTapGesture * tapGesture = nullptr;
|
||||
// QTapAndHoldGesture * tapAndHoldGesture = nullptr;
|
||||
QPanGesture * panGesture = nullptr;
|
||||
QPinchGesture * pinchGesture = nullptr;
|
||||
// QSwipeGesture * swipeGesture = nullptr;
|
||||
QString typeName;
|
||||
QString stateName;
|
||||
|
||||
switch (gestureType)
|
||||
{
|
||||
// case Qt::TapGesture : tapGesture = (QTapGesture *)gesture; typeName = QLatin1String("TapGesture"); break;
|
||||
// case Qt::TapAndHoldGesture : tapAndHoldGesture = (QTapAndHoldGesture*)gesture; typeName = QLatin1String("TapAndHoldGesture"); break;
|
||||
case Qt::PanGesture : panGesture = (QPanGesture *)gesture; typeName = QLatin1String("PanGesture"); break;
|
||||
case Qt::PinchGesture : pinchGesture = (QPinchGesture *)gesture; typeName = QLatin1String("PinchGesture"); break;
|
||||
// case Qt::SwipeGesture : swipeGesture = (QSwipeGesture *)gesture; typeName = QLatin1String("SwipeGesture"); break;
|
||||
|
||||
default: break;
|
||||
}
|
||||
switch (gestureState)
|
||||
{
|
||||
case Qt::NoGesture : stateName = QLatin1String("NoGesture"); break;
|
||||
case Qt::GestureStarted : stateName = QLatin1String("GestureStarted"); break;
|
||||
case Qt::GestureUpdated : stateName = QLatin1String("GestureUpdated"); break;
|
||||
case Qt::GestureFinished : stateName = QLatin1String("GestureFinished"); break;
|
||||
case Qt::GestureCanceled : stateName = QLatin1String("GestureCanceled"); break;
|
||||
}
|
||||
DEBUG_LOG(_logger) << LOGFUNCTION << " Gesture type=" << typeName << " Gesture state=" << stateName;
|
||||
|
||||
// tapGesture = nullptr;
|
||||
panGesture = nullptr; // ToDo: check: Why this?
|
||||
|
||||
if (panGesture)
|
||||
{
|
||||
QPointF deltaMove = panGesture->delta();
|
||||
QPoint winCenter = QPoint( _getEventsFrom->width() / 2, _getEventsFrom->height() / 2 );
|
||||
QPoint newCenter = winCenter-QPoint((int)deltaMove.x(),(int)deltaMove.y());
|
||||
|
||||
const Esri::ArcGISRuntime::Point mapCoordEsri =
|
||||
_sitMap->getEsriMapGraphicsView()->screenToLocation(newCenter.x(), newCenter.y());
|
||||
Esri::ArcGISRuntime::Viewpoint curVp = _sitMap->getEsriMapGraphicsView()->currentViewpoint(Esri::ArcGISRuntime::ViewpointType::CenterAndScale);
|
||||
Esri::ArcGISRuntime::Viewpoint newVp(mapCoordEsri, curVp.targetScale());
|
||||
_sitMap->getEsriMapGraphicsView()->setViewpointAndWait(newVp);
|
||||
|
||||
_getEventsFrom -> update();
|
||||
|
||||
if (gestureState == Qt::GestureStarted) gestureEvent -> setAccepted(panGesture, true);
|
||||
|
||||
}
|
||||
|
||||
if (pinchGesture)
|
||||
{
|
||||
///// QPinchGesture::ChangeFlags changeFlags = pinchGesture->changeFlags();
|
||||
|
||||
|
||||
///// if (changeFlags & QPinchGesture::RotationAngleChanged)
|
||||
///// {
|
||||
///// qreal deltaPhi = pinchGesture->rotationAngle() - pinchGesture->lastRotationAngle();
|
||||
|
||||
///// _esriMap -> setRotation( _esriMap->rotation()-deltaPhi );
|
||||
///// }
|
||||
///// if (changeFlags & QPinchGesture::ScaleFactorChanged) _esriMap -> zoom( 1.0/pinchGesture->scaleFactor() );
|
||||
|
||||
_getEventsFrom -> update();
|
||||
|
||||
if (gestureState == Qt::GestureStarted) gestureEvent -> setAccepted(pinchGesture, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
} break;
|
||||
|
||||
default: break;
|
||||
|
||||
} // switch
|
||||
|
||||
if (!hasFinished()) setActiveEvent( false );
|
||||
|
||||
if (handled) e->accept();
|
||||
DEBUG_LOG(_logger) << LOGFUNCTION
|
||||
<< " Event '" << debugString << "'"
|
||||
<< " event->type() '" << e->type() << "'"
|
||||
<< " handled = " << handled
|
||||
<< " mouse panning is active = " << _mousePanningActive;
|
||||
|
||||
//
|
||||
// 'if (handled) return true;' lead to bad behaviour at 3D: globe is often connected to mouse, without any button pressed...
|
||||
//
|
||||
// if (handled) return true;
|
||||
|
||||
}
|
||||
return AbstractEventDispatcher::eventFilter(watched,e);
|
||||
|
||||
} // EventMouseNavigator::eventFilter
|
||||
|
||||
|
||||
bool EventMouseNavigator::checkRunningPickingTask()
|
||||
{
|
||||
if ((!_pickingTask.isCanceled()) && (_pendingRequest != RequestType::None))
|
||||
{
|
||||
_pickingTask.cancel();
|
||||
_pendingRequest = RequestType::None;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
} // void EventMouseNavigator::checkRunningPickingTask()
|
||||
|
||||
|
||||
void EventMouseNavigator::selectionRequested( const QPointF & pos )
|
||||
{
|
||||
// do the work only in case of slot connections are installed
|
||||
if (! isSignalConnected( QMetaMethod::fromSignal(&EventMouseNavigator::selectionRequest) ))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (checkRunningPickingTask())
|
||||
{
|
||||
qWarning() << LOGFUNCTION << " request is still pending!";
|
||||
}
|
||||
|
||||
_pendingRequest = RequestType::Selection;
|
||||
_viewPortPos = pos;
|
||||
|
||||
requestPicking(pos);
|
||||
|
||||
} // EventMouseNavigator::selectionRequested
|
||||
|
||||
|
||||
void EventMouseNavigator::pickRequested( const QPointF &pos )
|
||||
{
|
||||
// do the work only in case of slot connections are installed
|
||||
if (! isSignalConnected( QMetaMethod::fromSignal(&EventMouseNavigator::contextMenuRequest) ))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (checkRunningPickingTask())
|
||||
{
|
||||
qWarning() << LOGFUNCTION << " request is still pending!";
|
||||
}
|
||||
|
||||
_pendingRequest = RequestType::Picking;
|
||||
_viewPortPos = pos;
|
||||
|
||||
requestPicking(pos);
|
||||
|
||||
} // EventMouseNavigator::pickRequested
|
||||
|
||||
|
||||
void EventMouseNavigator::requestPicking(const QPointF &pos)
|
||||
{
|
||||
_pickingTask.cancel(); // cancel old task
|
||||
|
||||
// store new task
|
||||
bool returnPopUpsOnly = false;
|
||||
int maximumResultsPerOverlay = std::numeric_limits<int>::max(); // huge number;
|
||||
_pickingTask = _sitMap->getEsriGeoView()->identifyGraphicsOverlays(pos.x(), pos.y(), _pickTolerance,
|
||||
returnPopUpsOnly, maximumResultsPerOverlay);
|
||||
//qWarning() << " XXXXXXX" << LOGFUNCTION;
|
||||
|
||||
// check new task
|
||||
if (!_pickingTask.isValid())
|
||||
{
|
||||
_pendingRequest = RequestType::None;
|
||||
qWarning() << LOGFUNCTION << " _identfyGraphicsOverlayTask invalid";
|
||||
}
|
||||
|
||||
} // EventMouseNavigator::requestPicking
|
||||
|
||||
|
||||
void EventMouseNavigator::onGetPickingResult(const QUuid &taskId, const QList<Esri::ArcGISRuntime::IdentifyGraphicsOverlayResult*> &identifyResults)
|
||||
{
|
||||
// qWarning() << " YYYYYYY" << LOGFUNCTION;
|
||||
|
||||
if (_pickingTask.taskId() != taskId)
|
||||
{
|
||||
qDebug() << " taskId does not match";
|
||||
return;
|
||||
}
|
||||
|
||||
const QList<SituationMap::UniqueMapId> & selectedIdList = mapToUniqueMapId(identifyResults);
|
||||
|
||||
// qWarning() << " _pendingRequest="<< (int)_pendingRequest << " count= " << _selectedIdList.count();
|
||||
|
||||
switch (_pendingRequest)
|
||||
{
|
||||
case RequestType::Picking:
|
||||
emit contextMenuRequest(selectedIdList, _viewPortPos);
|
||||
break;
|
||||
case RequestType::Selection:
|
||||
emit selectionRequest(selectedIdList, _viewPortPos);
|
||||
break;
|
||||
case RequestType::None:
|
||||
//emtpy
|
||||
break;
|
||||
} // switch
|
||||
|
||||
// reset some 'flags' to enable a new request:
|
||||
_pendingRequest = RequestType::None;
|
||||
_viewPortPos = QPointF(-1, -1);
|
||||
} // EventMouseNavigator::onGetPickingResult
|
||||
|
||||
|
||||
QList<UniqueMapId> EventMouseNavigator::mapToUniqueMapId(const QList<Esri::ArcGISRuntime::IdentifyGraphicsOverlayResult *> &identifyResults)
|
||||
{
|
||||
QList<SituationMap::UniqueMapId> idList;
|
||||
|
||||
for (auto iResult : identifyResults)
|
||||
{
|
||||
// qWarning() << " process result of layer: " << iResult->graphicsOverlay();
|
||||
|
||||
const QList<Esri::ArcGISRuntime::Graphic*> &gResults = iResult->graphics();
|
||||
for (auto pickedGraphic : gResults)
|
||||
{
|
||||
// qWarning() << " process pickedGraphic: " << pickedGraphic;
|
||||
if (pickedGraphic->attributes())
|
||||
{
|
||||
// qWarning() << " process pickedGraphic cont: " << pickedGraphic->attributes()->containsAttribute(QLatin1String(SituationMap::UniqueMapIdAttribute));
|
||||
// qWarning() << " process pickedGraphic cont: " << pickedGraphic->attributes()->containsAttribute(QLatin1String(SituationMap::IsPickableAttribute));
|
||||
|
||||
bool ok;
|
||||
SituationMap::UniqueMapId uniqueMapId = pickedGraphic->attributes()->attributeValue(QLatin1String(SituationMap::UniqueMapIdAttribute)).toUInt(&ok);
|
||||
|
||||
if (ok)
|
||||
{
|
||||
// qWarning() << " process pickedGraphic uid: " << uniqueMapId;
|
||||
if (!idList.contains(uniqueMapId))
|
||||
{
|
||||
idList += uniqueMapId;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
ERROR_LOG(_logger) << " process pickedGraphic " << pickedGraphic
|
||||
<< " uid: '" << pickedGraphic->attributes()->attributeValue(QLatin1String(SituationMap::UniqueMapIdAttribute)).toString()
|
||||
<< "' (has uid attribute is " << pickedGraphic->attributes()->containsAttribute(QLatin1String(SituationMap::UniqueMapIdAttribute)) << ")";
|
||||
}
|
||||
}
|
||||
} // foreach inner
|
||||
} // foreach outter
|
||||
|
||||
return idList;
|
||||
} // EventMouseNavigator::mapToUniqueMapId
|
||||
|
||||
|
||||
} } /* namespace SituationMap::RB */
|
||||
+225
@@ -0,0 +1,225 @@
|
||||
/**
|
||||
**
|
||||
** @RDE_HEADER@
|
||||
** Event Dispatcher for Qt5 to handle mouse events navigate on map
|
||||
** $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 .........:
|
||||
**
|
||||
** 24.04.2015, JT : first edition
|
||||
**
|
||||
** -----------------------------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
// Own
|
||||
#include <Map/situation_map_types.h>
|
||||
#include "abstract_event_dispatcher.h"
|
||||
|
||||
|
||||
//Esri
|
||||
#include <arcgis/TaskWatcher.h>
|
||||
|
||||
|
||||
// Qt
|
||||
#include <QtCore/QList>
|
||||
|
||||
|
||||
// #define SITUATIONMAP_OWN_WHEEL_HANDLING
|
||||
|
||||
|
||||
|
||||
// Forward:
|
||||
namespace Esri {
|
||||
namespace ArcGISRuntime {
|
||||
class Map;
|
||||
class IdentifyGraphicsOverlayResult;
|
||||
} }
|
||||
|
||||
namespace SituationMap {
|
||||
class MapImpl;
|
||||
}
|
||||
|
||||
|
||||
namespace SituationMap { namespace RB
|
||||
{
|
||||
|
||||
/**
|
||||
@class EventMouseNavigator event_mouse_navigator.h
|
||||
@brief Event filter that handles mouse events for general map operation like selecting object, zooming and paning the map window
|
||||
|
||||
Implements class \c AbstractEventDispatcher to manage event handling for general map operation like selecting object, zooming and
|
||||
panning the map window. Monitoring the mouse position can be realized by connecting the \c mouseMovedEvent signal. If the user has
|
||||
clicked to map objects the signal \c selectionRequest is emitted.
|
||||
|
||||
Following events are handled:
|
||||
|
||||
| Input-Event | Interface Function | Description |
|
||||
| :--------------------------------------------- | : ----------------- | : --------------------------------------------------------------------------- |
|
||||
| Mouse enter | | To show/hide some widgets |
|
||||
| Mouse leave | | To show/hide some widgets |
|
||||
| Mouse move without any modifier | | Move Cursor. |
|
||||
| Mouse move with pressed left button | | Panning of map if more then 3 pixels moved. |
|
||||
| Mouse move with pressed middle button | | Panning of map. |
|
||||
| Mouse wheel | | Redirect to \c Esri map for zooming. |
|
||||
| Left mouse button release | | Emits signal \c selectionRequest with list of map objects at cursor position. |
|
||||
|
||||
@see AbstractEventDispatcher, EventDelegater, EventDispatcher
|
||||
*/
|
||||
|
||||
class EventMouseNavigator : public AbstractEventDispatcher
|
||||
{
|
||||
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
|
||||
/**
|
||||
@name Construction & Destruction
|
||||
@{
|
||||
*/
|
||||
EventMouseNavigator(const EventMouseNavigator &) = delete;
|
||||
EventMouseNavigator & operator = (const EventMouseNavigator &) = delete;
|
||||
|
||||
EventMouseNavigator( QWidget * getEventsFrom, SituationMap::MapImpl *sitMap );
|
||||
|
||||
virtual ~EventMouseNavigator() = default;
|
||||
/** @} */
|
||||
|
||||
inline static void setPickTolerance( int value = 5 ) { _pickTolerance = value; }
|
||||
|
||||
inline static int pickTolerance() { return _pickTolerance; }
|
||||
|
||||
inline static void setZoomFactorBase(qreal value = 1.002) { if ((value > 1) && (value <= 1.1))_zoomFactorBase = value; }
|
||||
|
||||
inline static qreal zoomFactorBase() { return _zoomFactorBase; }
|
||||
|
||||
signals:
|
||||
/**
|
||||
Will be emitted if the mouse enters the widget.
|
||||
*/
|
||||
void enterEvent();
|
||||
|
||||
/**
|
||||
Will be emitted if the mouse leaves the widget.
|
||||
*/
|
||||
void leaveEvent();
|
||||
|
||||
|
||||
/**
|
||||
Will be emitted if the user clicks to map objects with the left mouse button.
|
||||
*/
|
||||
void selectionRequest( const QList< SituationMap::UniqueMapId > & idList, const QPointF &viewPortPos );
|
||||
|
||||
/**
|
||||
Will be emitted if the user clicks to the map with the rigth mouse button.
|
||||
*/
|
||||
void contextMenuRequest( const QList< SituationMap::UniqueMapId > & idList, const QPointF &viewPortPos );
|
||||
|
||||
/**
|
||||
Signal will be emitted if a mouse move is done.
|
||||
*/
|
||||
void mouseMovedEvent( int x, int y );
|
||||
|
||||
#ifdef SITUATIONMAP_OWN_WHEEL_HANDLING
|
||||
/**
|
||||
Signal will be emitted if the mouse wheel has been rotated
|
||||
*/
|
||||
void mouseWheelEvent(qreal factor, const QPointF &cursorPositionMap);
|
||||
#endif
|
||||
|
||||
protected slots:
|
||||
|
||||
void onGetPickingResult(const QUuid &taskId, const QList<Esri::ArcGISRuntime::IdentifyGraphicsOverlayResult *> &identifyResults );
|
||||
|
||||
protected:
|
||||
|
||||
|
||||
QList<UniqueMapId> mapToUniqueMapId( const QList<Esri::ArcGISRuntime::IdentifyGraphicsOverlayResult*> & identifyResults);
|
||||
|
||||
bool eventFilter(QObject*, QEvent*) override;
|
||||
|
||||
|
||||
enum class RequestType
|
||||
{
|
||||
None,
|
||||
Selection,
|
||||
Picking
|
||||
}; // RequestType
|
||||
|
||||
|
||||
enum SelectionMode
|
||||
{
|
||||
NoSelection = 0x00,
|
||||
SingleSelection = 0x01,
|
||||
MultiSelection = 0x02,
|
||||
FrameSelection = 0x04
|
||||
}; // SelectionMode
|
||||
|
||||
Q_DECLARE_FLAGS(SelectionModes,SelectionMode)
|
||||
|
||||
SituationMap::MapImpl *_sitMap;
|
||||
|
||||
QPoint _mouseMoveRefPos;
|
||||
QCursor _restoreMouseCursor;
|
||||
bool _cursorChanged;
|
||||
|
||||
static int _pickTolerance;
|
||||
|
||||
QPointF _viewPortPos;
|
||||
SelectionModes _selectionMode;
|
||||
RequestType _pendingRequest;
|
||||
bool _mousePanningActive;
|
||||
bool _mousePanningActiveForCenterMapMidButton;
|
||||
|
||||
#ifdef SITUATIONMAP_OWN_WHEEL_HANDLING
|
||||
Esri::ArcGISRuntime::TaskWatcher _mouseZoomTaskWatcher;
|
||||
#endif
|
||||
|
||||
Qt::MouseButton _pressedMouseButton;
|
||||
|
||||
static qreal _zoomFactorBase; // Base value to calculate zoom factor values from QWheelEvent
|
||||
|
||||
Esri::ArcGISRuntime::TaskWatcher _pickingTask;
|
||||
|
||||
/**
|
||||
test for already running picking task.
|
||||
*/
|
||||
bool checkRunningPickingTask();
|
||||
|
||||
/**
|
||||
Find out which map objects are at given mouse position and emits the signal selectionRequest
|
||||
*/
|
||||
void selectionRequested(const QPointF & );
|
||||
|
||||
/**
|
||||
Find out which map objects are at given mouse position and emits the signal contextMenuRequest
|
||||
*/
|
||||
void pickRequested( const QPointF & );
|
||||
|
||||
/**
|
||||
Helper function to get all map objects at a given position of all GraphicsOverlays
|
||||
@param pos position in window coordinates
|
||||
*/
|
||||
void requestPicking(const QPointF &pos);
|
||||
|
||||
}; /* EventMouseNavigator */
|
||||
|
||||
|
||||
} } /* namespace SituationMap::RB */
|
||||
+106
@@ -0,0 +1,106 @@
|
||||
/**
|
||||
* @RDE_HEADER@
|
||||
* Declaration/Definition
|
||||
* $Id$
|
||||
* $HeadURL$
|
||||
* $Author$
|
||||
*/
|
||||
|
||||
|
||||
#include "gestures.h"
|
||||
|
||||
#include <QtCore/QDebug>
|
||||
#include <QtCore/QEvent>
|
||||
|
||||
#include <QtWidgets/QWidget>
|
||||
|
||||
namespace SituationMap { namespace RB {
|
||||
|
||||
// TabGestureRecognizer
|
||||
|
||||
ApplyGestureRecognizer::ApplyGestureRecognizer() : QGestureRecognizer()
|
||||
{
|
||||
}
|
||||
|
||||
ApplyGestureRecognizer::~ApplyGestureRecognizer()
|
||||
{}
|
||||
|
||||
|
||||
QGesture * ApplyGestureRecognizer::create( QObject * target )
|
||||
{
|
||||
// qDebug() << "ApplyGesture create";
|
||||
|
||||
if (target && target->isWidgetType())
|
||||
{
|
||||
((QWidget*)target)->setAttribute(Qt::WA_AcceptTouchEvents);
|
||||
}
|
||||
return new ApplyGesture();
|
||||
} // TabGestureRecognizer::create
|
||||
|
||||
|
||||
QGestureRecognizer::Result ApplyGestureRecognizer::recognize( QGesture * stateGesture, QObject* , QEvent * event)
|
||||
{
|
||||
ApplyGesture * q = static_cast<ApplyGesture*>(stateGesture);
|
||||
|
||||
QGestureRecognizer::Result result = QGestureRecognizer::CancelGesture;
|
||||
|
||||
switch (event->type())
|
||||
{
|
||||
case QEvent::TouchBegin:
|
||||
{
|
||||
const QTouchEvent * ev = static_cast<const QTouchEvent*>(event);
|
||||
// qDebug() << "ApplyGesture begin";
|
||||
q->_position = ev->touchPoints().at(0).pos();
|
||||
q->setHotSpot(ev->touchPoints().at(0).screenPos());
|
||||
q->_tripleTouch = (ev->touchPoints().size() == 3);
|
||||
if (ev->touchPoints().size() == 1 )
|
||||
result = QGestureRecognizer::Ignore;
|
||||
else
|
||||
result = QGestureRecognizer::TriggerGesture;
|
||||
} break;
|
||||
|
||||
case QEvent::TouchUpdate:
|
||||
case QEvent::TouchEnd:
|
||||
{
|
||||
const QTouchEvent * ev = static_cast<const QTouchEvent*>(event);
|
||||
if (q->state() != Qt::NoGesture && ev->touchPoints().size() >= 1 && ev->touchPoints().size() <= 3)
|
||||
{
|
||||
if (ev->touchPoints().size() == 3) q->_tripleTouch = true;
|
||||
// qDebug() << "ApplyGesture update _tripleTouch=" << q->_tripleTouch;
|
||||
QTouchEvent::TouchPoint p = ev->touchPoints().at(0);
|
||||
QPoint delta = p.pos().toPoint() - p.startPos().toPoint();
|
||||
enum { TapRadius = 40 };
|
||||
if (delta.manhattanLength() <= TapRadius)
|
||||
{
|
||||
if (event->type() == QEvent::TouchEnd)
|
||||
{
|
||||
result = (q->_tripleTouch) ? QGestureRecognizer::FinishGesture : QGestureRecognizer::CancelGesture;
|
||||
}
|
||||
else result = QGestureRecognizer::TriggerGesture;
|
||||
}
|
||||
}
|
||||
} break;
|
||||
|
||||
case QEvent::MouseButtonPress:
|
||||
case QEvent::MouseMove:
|
||||
case QEvent::MouseButtonRelease:
|
||||
result = QGestureRecognizer::Ignore;
|
||||
break;
|
||||
default:
|
||||
result = QGestureRecognizer::Ignore;
|
||||
break;
|
||||
}
|
||||
|
||||
return result;
|
||||
} // TabGestureRecognizer::recognize( QGesture * stateGesture, QObject * watched, QEvent * event)
|
||||
|
||||
|
||||
void ApplyGestureRecognizer::reset( QGesture * stateGesture )
|
||||
{
|
||||
ApplyGesture * q = static_cast<ApplyGesture*>(stateGesture);
|
||||
q->_tripleTouch = false;
|
||||
} // TabGestureRecognizer::reset( QGesture * stateGesture )
|
||||
|
||||
|
||||
|
||||
}} // namspaces
|
||||
+72
@@ -0,0 +1,72 @@
|
||||
/**
|
||||
**
|
||||
** @RDE_HEADER@
|
||||
** Gesture recognition
|
||||
** $Id$
|
||||
** $HeadURL$
|
||||
** $Author$
|
||||
**
|
||||
** -----------------------------------------------------------------------------------------------
|
||||
**
|
||||
** Hardware-Environment: Intel-PC
|
||||
** Software-Environment: Windows 7, Qt 5.4. ArcGIS 10.2.5
|
||||
**
|
||||
** Language ........: C++ 11
|
||||
**
|
||||
** -----------------------------------------------------------------------------------------------
|
||||
**
|
||||
** Author ...........: Joerg Turla, SPD G, Tel. 3132
|
||||
**
|
||||
** -----------------------------------------------------------------------------------------------
|
||||
**
|
||||
** Notes .........:
|
||||
**
|
||||
** 09.12.2015, JT : First edition for use with Qt5
|
||||
**
|
||||
** -----------------------------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <QtCore/QObject>
|
||||
#include <QtWidgets/QGesture>
|
||||
#include <QtWidgets/QGestureRecognizer>
|
||||
|
||||
|
||||
namespace SituationMap { namespace RB
|
||||
{
|
||||
class ApplyGestureRecognizer : public QGestureRecognizer
|
||||
{
|
||||
public:
|
||||
ApplyGestureRecognizer();
|
||||
virtual ~ApplyGestureRecognizer();
|
||||
|
||||
QGesture * create( QObject * target ) override;
|
||||
QGestureRecognizer::Result recognize( QGesture * stateGesture, QObject * watched, QEvent * event) override;
|
||||
void reset( QGesture * stateGesture ) override;
|
||||
|
||||
}; // ApplyGestureRecognizer
|
||||
|
||||
|
||||
class ApplyGesture : public QGesture
|
||||
{
|
||||
Q_OBJECT
|
||||
friend class ApplyGestureRecognizer;
|
||||
|
||||
public:
|
||||
|
||||
ApplyGesture() = default;
|
||||
~ApplyGesture() = default;
|
||||
|
||||
ApplyGesture( const ApplyGesture & ) = delete;
|
||||
ApplyGesture & operator = ( const ApplyGesture & ) = delete;
|
||||
|
||||
QPointF position() const { return _position; }
|
||||
|
||||
private:
|
||||
|
||||
QPointF _position;
|
||||
bool _tripleTouch;
|
||||
}; // ApplyGesture
|
||||
|
||||
}} // namespaces
|
||||
+52
@@ -0,0 +1,52 @@
|
||||
/* XPM */
|
||||
static const char * polygon_xpm[] = {
|
||||
"24 24 25 1",
|
||||
" c None",
|
||||
". c #59BA55",
|
||||
"+ c #57B953",
|
||||
"@ c #56B852",
|
||||
"# c #55B651",
|
||||
"$ c #53B44F",
|
||||
"% c #51B24D",
|
||||
"& c #4FB04B",
|
||||
"* c #4DAE49",
|
||||
"= c #4AAC46",
|
||||
"- c #48A944",
|
||||
"; c #46A742",
|
||||
"> c #43A53F",
|
||||
", c #41A23D",
|
||||
"' c #3E9F3A",
|
||||
") c #3C9D38",
|
||||
"! c #399B35",
|
||||
"~ c #379833",
|
||||
"{ c #349630",
|
||||
"] c #32942E",
|
||||
"^ c #30922C",
|
||||
"/ c #2E902A",
|
||||
"( c #2D8E28",
|
||||
"_ c #2B8C27",
|
||||
": c #2A8B26",
|
||||
" . ",
|
||||
" ++ ",
|
||||
" @ @ @ ",
|
||||
" # # ### ",
|
||||
" $$ $ $$$ $$ ",
|
||||
" % %% %%% % ",
|
||||
" && & &&& & ",
|
||||
" * *** * ",
|
||||
" == = ",
|
||||
" - - ",
|
||||
" ; ;",
|
||||
" > >",
|
||||
" , ,,",
|
||||
"'' '' ",
|
||||
") )) ",
|
||||
"! !! ",
|
||||
"~~ ~~ ",
|
||||
" {{{ {{ ",
|
||||
" ]]] ]] ",
|
||||
" ^^ ^^ ",
|
||||
" // // ",
|
||||
" (( (( ",
|
||||
" __ __ ",
|
||||
" :::: "};
|
||||
+309
@@ -0,0 +1,309 @@
|
||||
|
||||
/**
|
||||
**
|
||||
** @RDE_HEADER@
|
||||
** Implementation of base class for 2D rubberbands
|
||||
** $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.h"
|
||||
#include "rubberband_drawable.h"
|
||||
#include "rubberband_handle.h"
|
||||
#include "rubberband_handle_proxy.h"
|
||||
#include "rubberband_point_handle.h"
|
||||
#include "rubberband_internal.h"
|
||||
#include "rubberband_base_internal.h"
|
||||
|
||||
#include "rubberband_factory.h"
|
||||
|
||||
#include <arcgis/MapGraphicsView.h>
|
||||
|
||||
// Qt
|
||||
#include <QtCore/QMetaMethod>
|
||||
#include <QtWidgets/QGraphicsPixmapItem>
|
||||
|
||||
|
||||
namespace SituationMap { namespace RB
|
||||
{
|
||||
|
||||
|
||||
Rubberband::Rubberband( SituationMap::Map * map, QObject * parent, bool isActive )
|
||||
: RubberbandBase(map,parent,isActive)
|
||||
, _internal( new Rubberband::InternalData(map) )
|
||||
, _state( RubberbandState::ConstructionState )
|
||||
, _previewSidc()
|
||||
, _previewCursorOffset(32,32)
|
||||
, _previewSize(32)
|
||||
{
|
||||
_fillColor.setAlpha(100);
|
||||
|
||||
connect( &_previewSymbolResultWatcher
|
||||
, &AdvancedSymbology::SymbolResultWatcher::resultReady
|
||||
, this
|
||||
, &Rubberband::onPreviewSymbolResultReady );
|
||||
|
||||
} /* Rubberband::Rubberband */
|
||||
|
||||
|
||||
Rubberband::~Rubberband()
|
||||
{
|
||||
delete _internal;
|
||||
_internal = nullptr;
|
||||
} /* Rubberband::~Rubberband */
|
||||
|
||||
|
||||
void Rubberband::connectPreviewPixmap( const QPixmap & symbolPixmap )
|
||||
{
|
||||
if (nullptr == _internal->_connectedPreviewPixmap)
|
||||
{
|
||||
_internal->_connectedPreviewPixmap = new QGraphicsPixmapItem( symbolPixmap );
|
||||
_internal->_connectedPreviewPixmap -> setOffset(-qreal(symbolPixmap.width())/2,-qreal(symbolPixmap.height())/2);
|
||||
|
||||
_internal->_mapScene -> addItem( _internal->_connectedPreviewPixmap );
|
||||
}
|
||||
} /* RubberbandPointFeature::connectPreviewPixmap */
|
||||
|
||||
unsigned int Rubberband::coordinateCount() const { return static_cast<unsigned int>(_internal->_handleList.size()); }
|
||||
|
||||
|
||||
void Rubberband::resetAction(AbstractEventDispatcher*, int, int)
|
||||
{
|
||||
disenableSelectedState();
|
||||
disenableMultiSelectedState();
|
||||
update();
|
||||
} /* Rubberband::resetAction */
|
||||
|
||||
|
||||
|
||||
bool Rubberband::selectAction( AbstractEventDispatcher*, int x, int y )
|
||||
{
|
||||
if (rubberbandIsAlive())
|
||||
{
|
||||
QPointF scenePos = pixel2ScenePosition(x,y);
|
||||
|
||||
if (_baseInternal->buttonProxyActive(scenePos)) return false;
|
||||
_baseInternal->_lastClickPosition = scenePos;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
} /* Rubberband::selectAction */
|
||||
|
||||
|
||||
bool Rubberband::multiSelectActionPress( AbstractEventDispatcher * causer, int x, int y )
|
||||
{
|
||||
if (rubberbandIsAlive())
|
||||
{
|
||||
if (isEnabledModificationState())
|
||||
{
|
||||
_baseInternal->_lastClickPosition = pixel2ScenePosition(x,y);
|
||||
enableMultiSelectedState();
|
||||
}
|
||||
return selectAction( causer, x, y);
|
||||
}
|
||||
return false;
|
||||
} /* RubberbandPointFeature::multiSelectActionPress */
|
||||
|
||||
|
||||
bool Rubberband::multiSelectActionRelease( AbstractEventDispatcher * causer, int x, int y )
|
||||
{
|
||||
if (rubberbandIsAlive())
|
||||
{
|
||||
if (isEnabledModificationState())
|
||||
{
|
||||
updateButtonPosition();
|
||||
activateButtons();
|
||||
}
|
||||
else return setCoordinateAction(causer,x,y);
|
||||
}
|
||||
return false;
|
||||
} /* RubberbandPointFeature::multiSelectActionRelease */
|
||||
|
||||
|
||||
void Rubberband::adjustConnectedPreviewPixmap( int x, int y )
|
||||
{
|
||||
if (_internal->_connectedPreviewPixmap)
|
||||
{
|
||||
_internal->_connectedPreviewPixmap -> setPos(pixel2ScenePosition( x+_previewCursorOffset.x(), y+_previewCursorOffset.y() ));
|
||||
}
|
||||
} /* Rubberband::adjustConnectedPreviewPixmap */
|
||||
|
||||
|
||||
bool Rubberband::moveAction( AbstractEventDispatcher*, int x, int y )
|
||||
{
|
||||
adjustConnectedPreviewPixmap(x,y);
|
||||
return rubberbandIsAlive();
|
||||
|
||||
} /* moveAction */
|
||||
|
||||
|
||||
bool Rubberband::setCoordinateAction( AbstractEventDispatcher*, int x, int y )
|
||||
{
|
||||
if (rubberbandIsAlive())
|
||||
{
|
||||
QPointF scenePos = pixel2ScenePosition(x,y);
|
||||
if (_baseInternal->buttonProxyActive(scenePos)) return false;
|
||||
_internal->_lastClickPosition = scenePos;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
} /* Rubberband::setCoordinateAction */
|
||||
|
||||
|
||||
bool Rubberband::movePickedAction ( AbstractEventDispatcher*, int x, int y ) { adjustConnectedPreviewPixmap(x,y); return false; }
|
||||
bool Rubberband::contextMenuAction ( AbstractEventDispatcher*, int x, int y ) { Q_UNUSED(x); Q_UNUSED(y); return rubberbandIsAlive(); }
|
||||
bool Rubberband::completeStateAction ( AbstractEventDispatcher*, int x, int y ) { Q_UNUSED(x); Q_UNUSED(y); return rubberbandIsAlive(); }
|
||||
bool Rubberband::deleteAction ( AbstractEventDispatcher*, int x, int y ) { Q_UNUSED(x); Q_UNUSED(y); return rubberbandIsAlive(); }
|
||||
bool Rubberband::undoAction ( AbstractEventDispatcher*, int x, int y ) { Q_UNUSED(x); Q_UNUSED(y); return rubberbandIsAlive(); }
|
||||
|
||||
|
||||
RubberbandHandle * Rubberband::pickHandle( int x, int y ) const
|
||||
{
|
||||
if (_internal->_mapView != nullptr)
|
||||
{
|
||||
QPointF scenePosition = pixel2ScenePosition(x,y);
|
||||
for (auto handle : qAsConst(_internal->_handleList))
|
||||
{
|
||||
if (handle->isPositionInside(scenePosition))
|
||||
return handle.get();
|
||||
}
|
||||
}
|
||||
return nullptr;
|
||||
} /* Rubberband::pickHandle */
|
||||
|
||||
|
||||
void Rubberband::deSelectHandles()
|
||||
{
|
||||
for (auto handle : qAsConst(_internal->_handleList))
|
||||
{
|
||||
RubberbandHandle * handlePtr = handle.get();
|
||||
if (handlePtr)
|
||||
{
|
||||
handlePtr->setSelection(false);
|
||||
}
|
||||
}
|
||||
} /* Rubberband::deSelectHandles */
|
||||
|
||||
|
||||
QRectF Rubberband::sceneBbox() const
|
||||
{
|
||||
DEBUG_LOG(_internal->_logger) << LOGFUNCTION;
|
||||
|
||||
QPointF topLeft( std::numeric_limits<double>::max(), std::numeric_limits<double>::max() );
|
||||
QPointF bottomRight( std::numeric_limits<double>::min(), std::numeric_limits<double>::min() );
|
||||
|
||||
for (auto handle : qAsConst(_internal->_handleList))
|
||||
{
|
||||
RubberbandPointHandle * pointHandlePtr = dynamic_cast<RubberbandPointHandle*>(handle.get());
|
||||
|
||||
if (pointHandlePtr)
|
||||
{
|
||||
const QPointF & p = pointHandlePtr->getCoordinate()._sceneCoordinate;
|
||||
if (topLeft.x() > p.x()) topLeft.setX(p.x());
|
||||
if (topLeft.y() > p.y()) topLeft.setY(p.y());
|
||||
if (bottomRight.x() < p.x()) bottomRight.setX(p.x());
|
||||
if (bottomRight.y() < p.y()) bottomRight.setY(p.y());
|
||||
}
|
||||
}
|
||||
|
||||
return QRectF( topLeft, bottomRight );
|
||||
|
||||
} /* Rubberband::sceneBbox */
|
||||
|
||||
|
||||
void Rubberband::update()
|
||||
{
|
||||
// Check Quartz
|
||||
// if (isSignalConnected(QMetaMethod::fromSignal(&Rubberband::updatePreview)))
|
||||
// {
|
||||
// emit updatePreview( this );
|
||||
// }
|
||||
// if (_internal->_map->symbolDictionary().contains(_previewSidc))
|
||||
// {
|
||||
// const QImage& symbolImage = _internal->_map->symbolDictionary().symbolImageBySidc( _previewSidc, _previewSize );
|
||||
// connectPreviewPixmap( QPixmap::fromImage(symbolImage) );
|
||||
// }
|
||||
|
||||
if ((!_previewSidc.isEmpty()) && (nullptr == _internal->_connectedPreviewPixmap) && (!_previewSymbolResultWatcher.resultIsValid()))
|
||||
{
|
||||
_previewSymbolResultWatcher.setSymbolResult(_baseInternal->_map->symbolDictionary().findBaseSymbol(_previewSidc));
|
||||
}
|
||||
|
||||
for (auto handle : qAsConst(_internal->_handleList))
|
||||
{
|
||||
handle -> setDrawColor(_handleDrawColor);
|
||||
handle -> setFillColor(_handleFillColor);
|
||||
handle -> setSelectionColor(_handleSelectionColor);
|
||||
handle -> setPickingRatio( _pickingRatio );
|
||||
}
|
||||
|
||||
updateButtonPosition();
|
||||
|
||||
if (_internal->_constructionObjectDraw != nullptr)
|
||||
{
|
||||
// _constructionObjectDraw -> setColors
|
||||
}
|
||||
|
||||
externalUpdate();
|
||||
|
||||
} /* Rubberband::update */
|
||||
|
||||
|
||||
void Rubberband::onPreviewSymbolResultReady()
|
||||
{
|
||||
QSharedPointer<AdvancedSymbology::SymbolResult> symResult = _previewSymbolResultWatcher.symbolResult();
|
||||
|
||||
if (!symResult) return; // should NEVER happen! (Which object should have triggered the signal???)
|
||||
|
||||
const QPixmap & symbolPixmap = QPixmap::fromImage(symResult->symbolImage().image()).scaled(_previewSize,_previewSize,Qt::KeepAspectRatio);
|
||||
|
||||
if (symbolPixmap.isNull())
|
||||
{
|
||||
DEBUG_LOG(_internal->_logger) << LOGFUNCTION << "Preview symbol image is empty.";
|
||||
}
|
||||
connectPreviewPixmap( symbolPixmap );
|
||||
} /* Rubberband::onPreviewSymbolResultReady */
|
||||
|
||||
|
||||
#include "./constrainsMarker.xpm"
|
||||
|
||||
void Rubberband::markFailedConstrains( const QPointF & scenePos, bool on )
|
||||
{
|
||||
if (on)
|
||||
{
|
||||
QPixmap markerPixmap(constrainsMarker_xpm);
|
||||
|
||||
if (nullptr == _internal->_constrainFailedMarker)
|
||||
{
|
||||
_internal->_constrainFailedMarker = new QGraphicsPixmapItem( markerPixmap );
|
||||
_internal->_mapScene -> addItem( _internal->_constrainFailedMarker );
|
||||
}
|
||||
_internal->_constrainFailedMarker -> setOffset(-qreal(markerPixmap.width())/2,-qreal(markerPixmap.height())/2);
|
||||
_internal->_constrainFailedMarker -> setPos(scenePos-QPointF(_previewCursorOffset));
|
||||
_internal->_constrainFailedMarker->setVisible(true);
|
||||
}
|
||||
else if (_internal->_constrainFailedMarker) _internal->_constrainFailedMarker->setVisible(false);
|
||||
} /* Rubberband::markFailedConstrains */
|
||||
|
||||
|
||||
} } /* namespace SituationMap::RB */
|
||||
+319
@@ -0,0 +1,319 @@
|
||||
/**
|
||||
**
|
||||
** @RDE_HEADER@
|
||||
** Definition of base class for 2D rubberbands
|
||||
** $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
|
||||
**
|
||||
** -----------------------------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
|
||||
#include "rubberband_base.h"
|
||||
|
||||
#include <Map/map.h>
|
||||
#include <Common/ref_pointer.h>
|
||||
|
||||
#include <QtCore/QFlags>
|
||||
#include <QtCore/QPointer>
|
||||
|
||||
#include <memory>
|
||||
|
||||
|
||||
namespace Esri {
|
||||
namespace ArcGISRuntime {
|
||||
class MapGraphicsView;
|
||||
class Point;
|
||||
} }
|
||||
|
||||
|
||||
|
||||
namespace SituationMap
|
||||
{
|
||||
|
||||
/**
|
||||
Namespace for all rubberband stuff (is part of namespace SituationMap)
|
||||
*/
|
||||
namespace RB
|
||||
{
|
||||
class RubberbandDrawable;
|
||||
class RubberbandHandle;
|
||||
|
||||
/**
|
||||
@class Rubberband rubberband.h
|
||||
@brief Base class of all 2D rubberbands
|
||||
|
||||
Rubberbands are used to create or modifiy 2D geometries like lines, circles, polygons etc. by processing
|
||||
Qt input events like keyboard and mouse events. To create a rubberband the RubberbandFactory has to be used.
|
||||
At end of rubberband processing the signal \c abort or\c apply are emitted. To delete the rubberband the
|
||||
function deleteMySelf must be called. To use the delete operator is dangerous because at end of signal
|
||||
processing some program code may be performed.
|
||||
|
||||
Example to how to use rubberband:
|
||||
|
||||
@code
|
||||
|
||||
SituationMap::Map & map = ...
|
||||
|
||||
const RubberbandFactory & rubberbandFactory = map.rubberbandFactory();
|
||||
|
||||
RubberbandPointFeature * rubberband = rubberbandFactory.create<RubberbandPointFeature>();
|
||||
if (rubberband != nullptr)
|
||||
{
|
||||
QObject::connect( rubberband, &SiMapRubBnd::Rubberband::apply, [=](SiMapRubBnd::Rubberband * rubberband )
|
||||
{
|
||||
// rubberband has finished input
|
||||
if (rubberband)
|
||||
{
|
||||
const QVector<QPointF> & vertexList = rubberband->coordinateVector();
|
||||
|
||||
// do something with vertexList
|
||||
|
||||
rubberband->deleteMySelf(); // notice don't call here delete rubberband directly !!!
|
||||
}
|
||||
} );
|
||||
|
||||
QObject::connect( rubberband, &SiMapRubBnd::Rubberband::abort, this, [=](SiMapRubBnd::Rubberband * rubberband )
|
||||
{
|
||||
// Rubberband has been aborted by user
|
||||
if (rubberband)
|
||||
{
|
||||
rubberband->deleteMySelf(); // notice don't call here delete rubberband directly !!!
|
||||
}
|
||||
} );
|
||||
}
|
||||
|
||||
@endcode
|
||||
|
||||
Following keyboard commands are available in active rubberbands:
|
||||
|
||||
| Key | Modifier | Funktion |
|
||||
| :----: |:-------: | :--------------------------------------------------------------------------- |
|
||||
| Esc | | Rubberband abbrechen |
|
||||
| Return | | Rubberband abschließen und Eingabe übernehmen wenn möglich, sonst Abbruch |
|
||||
| Left | | Selektierten Handle (Punkt,Frame) um 1 Pixel nach links schieben |
|
||||
| Right | | Selektierten Handle (Punkt,Frame) um 1 Pixel nach rechts schieben |
|
||||
| Up | | Selektierten Handle (Punkt,Frame) um 1 Pixel nach oben schieben |
|
||||
| Down | | Selektierten Handle (Punkt,Frame) um 1 Pixel nach unten schieben |
|
||||
| Left | Shift | Selektierten Handle (Punkt,Frame) um 10 Pixel nach links schieben |
|
||||
| Right | Shift | Selektierten Handle (Punkt,Frame) um 10 Pixel nach rechts schieben |
|
||||
| Up | Shift | Selektierten Handle (Punkt,Frame) um 10 Pixel nach oben schieben |
|
||||
| Down | Shift | Selektierten Handle (Punkt,Frame) um 10 Pixel nach unten schieben |
|
||||
|
||||
@see EventDispatcher
|
||||
@see RubberbandBase, Rubberband, RubberbandPointFeature, RubberbandPointCluster, RubberbandMultiPointFeature, RubberbandRectangle, RubberbandEllipse, RubberbandCorridor, RubberbandArrow
|
||||
*/
|
||||
|
||||
class SITUATIONMAP_EXPORT Rubberband : public RubberbandBase
|
||||
{
|
||||
/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
* Because class EventDispatcher::EventActionInterface is a pure virtual interface function the classic way of declaration would be
|
||||
*
|
||||
* SITUATIONMAP_EXPORT Rubberband : public QObject, public virtual EventDispatcher::EventActionInterface
|
||||
*
|
||||
* But with Visual Studio 2013 virtual inheritance combined with constructor delegation doesn't work and may crash the program. In
|
||||
* this case the virtual inheritance of EventActionInterface isn't need because in the derived classes multiple inheritance will
|
||||
* not be used.
|
||||
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
|
||||
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
|
||||
/**
|
||||
@defgroup States Internal state of the rubberband
|
||||
@{
|
||||
*/
|
||||
|
||||
enum RubberbandState : unsigned int
|
||||
{
|
||||
ConstructionState = 1 << 0, ///< Construction state is active when a geomtrie is been build new
|
||||
ModificationState = 1 << 1, ///< Modification state is active when a existing geometrie is been modified
|
||||
SelectedState = 1 << 2, ///< Selection state is active, one ore more handles are selected
|
||||
MultiSelectedState = 1 << 3, ///< multiple handles can be selected
|
||||
ConstructionWidthState = 1 << 4 ///< Initial define of a width e.b. for corridors
|
||||
}; /* RubberbandSate */
|
||||
|
||||
Q_DECLARE_FLAGS(RubberbandStates,RubberbandState)
|
||||
|
||||
/** @} */
|
||||
|
||||
/**
|
||||
@name Construction & Destruction
|
||||
@{
|
||||
*/
|
||||
|
||||
private:
|
||||
|
||||
friend class RubberbandFreeHand;
|
||||
friend class RubberbandPointFeature;
|
||||
friend class RubberbandMultiPointFeature;
|
||||
friend class RubberbandMultiEllipseFeature;
|
||||
friend class RubberbandRectangle;
|
||||
friend class RubberbandStateSelect;
|
||||
friend class RubberbandTransformMove;
|
||||
friend class RubberbandTransformRotate;
|
||||
friend class RubberbandTransformScale;
|
||||
|
||||
/**
|
||||
Constructs a Rubberband for a situation map. Use \c RubberbandFactor to create a rubberband.
|
||||
In case of the user actions the autoDelete mechanism can be used to delete the rubberband. Sometimes
|
||||
the application wants to finish a running rubberband. This can be done by calling \c deleteMySelf. The
|
||||
rubberband will be destroyed also automatically if the parent QObject or the map (see
|
||||
SituationMap::Map::beginDestroy signal) will be destroyed.
|
||||
|
||||
@param map Pointer to SituationMap::Map
|
||||
@param parent Pointer to QObject to use as parent.
|
||||
@isActive If set to false the Rubberband is not active and have to be actived to start the input.
|
||||
@see RubberbandFactory
|
||||
*/
|
||||
explicit Rubberband( SituationMap::Map * map, QObject * parent, bool isActive = true );
|
||||
|
||||
public:
|
||||
Q_DISABLE_COPY(Rubberband)
|
||||
|
||||
virtual ~Rubberband();
|
||||
|
||||
/** @} */
|
||||
|
||||
/**
|
||||
@addtogroup States Methodes to query and modify rubberband states
|
||||
@{
|
||||
*/
|
||||
inline bool isEnabledConstructionState() const { return _state.testFlag(RubberbandState::ConstructionState); }
|
||||
inline bool isEnabledModificationState() const { return _state.testFlag(RubberbandState::ModificationState); }
|
||||
inline bool isEnabledSelectedState() const { return _state.testFlag(RubberbandState::SelectedState); }
|
||||
inline bool isEnabledMultiSelectedState() const { return _state.testFlag(RubberbandState::MultiSelectedState); }
|
||||
|
||||
inline void enableConstructionState() { disenableModificationState(); }
|
||||
inline void enableModificationState() { disenableConstructionState(); }
|
||||
inline void enableSelectedState() { _state |= RubberbandState::SelectedState; }
|
||||
inline void enableMultiSelectedState() { _state |= RubberbandState::MultiSelectedState; }
|
||||
|
||||
inline void disenableConstructionState() { _state &= ~QFlags<RubberbandState>(RubberbandState::ConstructionState); _state |= RubberbandState::ModificationState; }
|
||||
inline void disenableModificationState() { _state &= ~QFlags<RubberbandState>(RubberbandState::ModificationState); _state |= RubberbandState::ConstructionState; }
|
||||
inline void disenableSelectedState() { _state &= ~QFlags<RubberbandState>(RubberbandState::SelectedState); }
|
||||
inline void disenableMultiSelectedState() { _state &= ~QFlags<RubberbandState>(RubberbandState::MultiSelectedState); }
|
||||
//@}
|
||||
|
||||
/**
|
||||
@name EventHandlerInterface Methodes of AbstractEventDispatcher::EventActionInterface
|
||||
The interface between EventDispatcher and Rubberband are defined in class AbstractEventDispatcher.
|
||||
To Implement the interface these methodes have to be override again in the derived classes of the Rubberband class. */
|
||||
/**
|
||||
@{
|
||||
*/
|
||||
bool selectAction ( AbstractEventDispatcher * causer, int x, int y ) override;
|
||||
bool multiSelectActionPress ( AbstractEventDispatcher * causer, int x, int y ) override;
|
||||
bool multiSelectActionRelease( AbstractEventDispatcher * causer, int x, int y ) override;
|
||||
bool setCoordinateAction ( AbstractEventDispatcher * causer, int x, int y ) override;
|
||||
bool moveAction ( AbstractEventDispatcher * causer, int x, int y ) override;
|
||||
bool movePickedAction ( AbstractEventDispatcher * causer, int x, int y ) override;
|
||||
void resetAction ( AbstractEventDispatcher * causer, int x, int y ) override;
|
||||
bool contextMenuAction ( AbstractEventDispatcher * causer, int x, int y ) override;
|
||||
bool completeStateAction ( AbstractEventDispatcher * causer, int x, int y ) override;
|
||||
bool deleteAction ( AbstractEventDispatcher * causer, int x, int y ) override;
|
||||
bool undoAction ( AbstractEventDispatcher * causer, int x, int y ) override;
|
||||
|
||||
|
||||
/** @} */
|
||||
|
||||
/**
|
||||
@name Preview Setting Methodes to define visual behaviour of rubberband preview
|
||||
@{
|
||||
*/
|
||||
inline void setPreviewSidc (const QString & sidc ) { _previewSidc = sidc; update(); } ///< Defines tactical symbol for preview
|
||||
inline void setPreviewOffset (const QPoint & off ) { _previewCursorOffset = off; update(); } ///< set offset to cursor position for preview pixmap
|
||||
inline void setPreviewSize (unsigned int size ) { _previewSize = size; update(); } ///< set size of preview pixmap
|
||||
|
||||
inline QString getPreviewSidc() const { return _previewSidc; } ///< get code of tactical preview symbol
|
||||
inline const QPoint getPreviewOffset() const { return _previewCursorOffset; } ///< get offset to cursor position for preview pixmap
|
||||
inline unsigned int getPreviewSize() const { return _previewSize; } ///< get size of preview pixmap
|
||||
/** @} */
|
||||
|
||||
|
||||
/**
|
||||
Returns Sidc code of preview symbol (if defined)
|
||||
*/
|
||||
inline QString previewSidc() const { return _previewSidc; }
|
||||
|
||||
/**
|
||||
Sets a QPixmap to use for drawing symbol preview image
|
||||
@param symbolImage a nice QPixmap
|
||||
*/
|
||||
void connectPreviewPixmap( const QPixmap & symbolPixmap );
|
||||
|
||||
/**
|
||||
Returns count of coordinates
|
||||
*/
|
||||
virtual unsigned int coordinateCount() const override;
|
||||
|
||||
protected:
|
||||
|
||||
void deSelectHandles();
|
||||
|
||||
|
||||
void update() override;
|
||||
|
||||
/**
|
||||
Returns the rubberband handle at screen position (x,y) or nullptr if there isn't any handle at this
|
||||
position.
|
||||
*/
|
||||
RubberbandHandle * pickHandle( int x, int y ) const;
|
||||
|
||||
/**
|
||||
Moves preview image to QGraphicView position (x,y) in window coordinates.
|
||||
*/
|
||||
void adjustConnectedPreviewPixmap( int x, int y );
|
||||
|
||||
|
||||
/**
|
||||
Shows a icon near the cursor to mark failing constrains.
|
||||
*/
|
||||
void markFailedConstrains( const QPointF & scenePos, bool on );
|
||||
|
||||
/*
|
||||
Forward declaration of internal container class for member variables. The derived classes of Rubberband
|
||||
often have also a declaration of InternalData for there own internal members.
|
||||
*/
|
||||
struct InternalData;
|
||||
|
||||
InternalData * _internal;
|
||||
|
||||
RubberbandStates _state;
|
||||
|
||||
QString _previewSidc;
|
||||
QPoint _previewCursorOffset;
|
||||
unsigned int _previewSize;
|
||||
|
||||
AdvancedSymbology::SymbolResultWatcher _previewSymbolResultWatcher;
|
||||
|
||||
QRectF sceneBbox() const override;
|
||||
|
||||
protected slots:
|
||||
|
||||
void onPreviewSymbolResultReady();
|
||||
|
||||
}; /* Rubberband */
|
||||
|
||||
} } /* namespace SituationMap::RB */
|
||||
+116
@@ -0,0 +1,116 @@
|
||||
/**
|
||||
**
|
||||
** @RDE_HEADER@
|
||||
** Implementation of base class for 3d rubberbands
|
||||
** $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_3d.h"
|
||||
|
||||
#include <Map/map.h>
|
||||
|
||||
#include <QtGui/QPainter>
|
||||
|
||||
namespace SituationMap
|
||||
{
|
||||
|
||||
|
||||
namespace RB
|
||||
{
|
||||
|
||||
Rubberband3D::Rubberband3D( SituationMap::Map * map, QObject * parent, bool isActive )
|
||||
: RubberbandBase(map,parent,isActive), _markerPixmap(nullptr), _markerSelectionPixmap(nullptr)
|
||||
{
|
||||
} // Rubberband3D::Rubberband3D( SituationMap::Map * map, QObject * parent, bool isActive )
|
||||
|
||||
|
||||
Rubberband3D::~Rubberband3D()
|
||||
{
|
||||
delete _markerPixmap;
|
||||
delete _markerSelectionPixmap;
|
||||
} // Rubberband3D::~Rubberband3D()
|
||||
|
||||
|
||||
void Rubberband3D::resetAction( AbstractEventDispatcher*,int,int ) {;}
|
||||
bool Rubberband3D::selectAction( AbstractEventDispatcher*,int,int ) { return false; }
|
||||
bool Rubberband3D::multiSelectActionPress ( AbstractEventDispatcher*,int,int ) { return false; }
|
||||
bool Rubberband3D::multiSelectActionRelease( AbstractEventDispatcher*,int,int ) { return false; }
|
||||
bool Rubberband3D::setCoordinateAction( AbstractEventDispatcher*,int,int ) { return false; }
|
||||
bool Rubberband3D::moveAction( AbstractEventDispatcher*,int,int ) { return false; }
|
||||
bool Rubberband3D::movePickedAction( AbstractEventDispatcher*,int,int ) { return false; }
|
||||
bool Rubberband3D::contextMenuAction( AbstractEventDispatcher*,int,int ) { return false; }
|
||||
bool Rubberband3D::completeStateAction( AbstractEventDispatcher*,int,int ) { return false; }
|
||||
bool Rubberband3D::deleteAction( AbstractEventDispatcher*,int,int ) { return false; }
|
||||
bool Rubberband3D::undoAction( AbstractEventDispatcher*,int,int ) { return false; }
|
||||
|
||||
|
||||
QRectF Rubberband3D::sceneBbox() const { return QRectF(); }
|
||||
|
||||
|
||||
#include "sphere_pattern.xpm"
|
||||
|
||||
QImage Rubberband3D::markerSelectionImage()
|
||||
{
|
||||
if (nullptr == _markerSelectionPixmap)
|
||||
{
|
||||
_markerSelectionPixmap = new QPixmap( sphere_pattern_xpm );
|
||||
|
||||
QPainter painter(_markerSelectionPixmap);
|
||||
QBrush brush;
|
||||
|
||||
brush.setStyle(Qt::BrushStyle::SolidPattern);
|
||||
brush.setColor(_handleSelectionColor);
|
||||
|
||||
painter.setCompositionMode(QPainter::CompositionMode::CompositionMode_Multiply);
|
||||
painter.setPen(_handleDrawColor);
|
||||
painter.setBrush(brush);
|
||||
painter.drawEllipse( 0, 0, _markerSelectionPixmap->width(), _markerSelectionPixmap->height() );
|
||||
}
|
||||
return _markerSelectionPixmap->toImage();
|
||||
} // QImage Rubberband3D::markerSelectionImage()
|
||||
|
||||
|
||||
QImage Rubberband3D::markerImage()
|
||||
{
|
||||
if (nullptr == _markerPixmap)
|
||||
{
|
||||
_markerPixmap = new QPixmap( sphere_pattern_xpm );
|
||||
|
||||
QPainter painter(_markerPixmap);
|
||||
QBrush brush;
|
||||
|
||||
brush.setStyle(Qt::BrushStyle::SolidPattern);
|
||||
brush.setColor(_handleFillColor);
|
||||
|
||||
painter.setCompositionMode(QPainter::CompositionMode::CompositionMode_Multiply);
|
||||
painter.setPen(_handleDrawColor);
|
||||
painter.setBrush(brush);
|
||||
painter.drawEllipse( 0, 0, _markerPixmap->width(), _markerPixmap->height() );
|
||||
}
|
||||
return _markerPixmap->toImage();
|
||||
} // QImage Rubberband3D::markerImage()
|
||||
|
||||
|
||||
} } /* namespace SituationMap::RB */
|
||||
+214
@@ -0,0 +1,214 @@
|
||||
/**
|
||||
**
|
||||
** @RDE_HEADER@
|
||||
** Definition of base class for 3d rubberbands
|
||||
** $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
|
||||
**
|
||||
** -----------------------------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
|
||||
#include "rubberband_base.h"
|
||||
|
||||
#include <Map/map.h>
|
||||
#include <Common/ref_pointer.h>
|
||||
|
||||
|
||||
class QObject;
|
||||
namespace Esri {
|
||||
namespace ArcGISRuntime {
|
||||
class MapGraphicsView;
|
||||
class Point;
|
||||
} }
|
||||
|
||||
|
||||
|
||||
namespace SituationMap
|
||||
{
|
||||
|
||||
/**
|
||||
Namespace for all rubberband stuff (is part of namespace SituationMap)
|
||||
*/
|
||||
namespace RB
|
||||
{
|
||||
class RubberbandDrawable;
|
||||
class RubberbandHandle;
|
||||
|
||||
/**
|
||||
@class Rubberband3D rubberband_3d.h
|
||||
@brief Base class of all 3D rubberbands
|
||||
|
||||
Rubberbands are used to create or modifiy geometries like single points or lines in 3D views by processing
|
||||
Qt input events like keyboard and mouse events. To create a rubberband the RubberbandFactory has to be used.
|
||||
At end of rubberband processing the signal \c abort or\c apply are emitted. To delete the rubberband the
|
||||
function deleteMySelf must be called. To use the delete operator is dangerous because at end of signal
|
||||
processing some program code may be performed.
|
||||
|
||||
Example to how to use rubberband:
|
||||
|
||||
@code
|
||||
|
||||
SituationMap::Map & map = ...
|
||||
|
||||
const RubberbandFactory & rubberbandFactory = map.rubberbandFactory();
|
||||
|
||||
RubberbandPointFeature * rubberband = rubberbandFactory.create<RubberbandPointFeature3D>(); // the map has to be in 3D mode
|
||||
if (rubberband != nullptr)
|
||||
{
|
||||
QObject::connect( rubberband, &SiMapRubBnd::Rubberband::apply, [=](SiMapRubBnd::Rubberband * rubberband )
|
||||
{
|
||||
// rubberband has finished input
|
||||
if (rubberband)
|
||||
{
|
||||
const QVector<QPointF> & vertexList = rubberband->coordinateVector();
|
||||
|
||||
// do something with vertexList
|
||||
|
||||
rubberband->deleteMySelf(); // notice don't call here delete rubberband directly !!!
|
||||
}
|
||||
} );
|
||||
|
||||
QObject::connect( rubberband, &SiMapRubBnd::Rubberband::abort, this, [=](SiMapRubBnd::Rubberband * rubberband )
|
||||
{
|
||||
// Rubberband has been aborted by user
|
||||
if (rubberband)
|
||||
{
|
||||
rubberband->deleteMySelf(); // notice don't call here delete rubberband directly !!!
|
||||
}
|
||||
} );
|
||||
}
|
||||
|
||||
@endcode
|
||||
|
||||
Following keyboard commands are available in active rubberbands:
|
||||
|
||||
| Key | Modifier | Funktion |
|
||||
| :----: |:-------: | :--------------------------------------------------------------------------- |
|
||||
| Esc | | Rubberband abbrechen |
|
||||
| Return | | Rubberband abschließen und Eingabe übernehmen wenn möglich, sonst Abbruch |
|
||||
| Left | | Selektierten Handle (Punkt,Frame) um 1 Pixel nach links schieben |
|
||||
| Right | | Selektierten Handle (Punkt,Frame) um 1 Pixel nach rechts schieben |
|
||||
| Up | | Selektierten Handle (Punkt,Frame) um 1 Pixel nach oben schieben |
|
||||
| Down | | Selektierten Handle (Punkt,Frame) um 1 Pixel nach unten schieben |
|
||||
| Left | Shift | Selektierten Handle (Punkt,Frame) um 10 Pixel nach links schieben |
|
||||
| Right | Shift | Selektierten Handle (Punkt,Frame) um 10 Pixel nach rechts schieben |
|
||||
| Up | Shift | Selektierten Handle (Punkt,Frame) um 10 Pixel nach oben schieben |
|
||||
| Down | Shift | Selektierten Handle (Punkt,Frame) um 10 Pixel nach unten schieben |
|
||||
|
||||
@see EventDispatcher
|
||||
@see RubberbandBase, Rubberband, RubberbandPointFeature3D, RubberbandMultiPointFeature3D
|
||||
*/
|
||||
|
||||
class SITUATIONMAP_EXPORT Rubberband3D : public RubberbandBase
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
|
||||
/**
|
||||
@name Construction & Destruction
|
||||
@{
|
||||
*/
|
||||
|
||||
private:
|
||||
|
||||
friend class RubberbandPointFeature3D;
|
||||
friend class RubberbandMultiPointFeature3D;
|
||||
|
||||
|
||||
/**
|
||||
Constructs a Rubberband for a situation map. Use \c RubberbandFactor to create a rubberband.
|
||||
In case of the user actions the autoDelete mechanism can be used to delete the rubberband. Sometimes
|
||||
the application wants to finish a running rubberband. This can be done by calling \c deleteMySelf. The
|
||||
rubberband will be destroyed also automatically if the parent QObject or the map (see
|
||||
SituationMap::Map::beginDestroy signal) will be destroyed.
|
||||
|
||||
@param map Pointer to SituationMap::Map
|
||||
@param parent Pointer to QObject to use as parent.
|
||||
@isActive If set to false the Rubberband is not active and have to be actived to start the input.
|
||||
@see RubberbandFactory
|
||||
*/
|
||||
explicit Rubberband3D( SituationMap::Map * map, QObject * parent, bool isActive = true );
|
||||
|
||||
public:
|
||||
|
||||
~Rubberband3D();
|
||||
|
||||
/** @} */
|
||||
|
||||
/**
|
||||
@name EventHandlerInterface Methodes of AbstractEventDispatcher::EventActionInterface
|
||||
The interface between EventDispatcher and Rubberband are defined in class AbstractEventDispatcher.
|
||||
To Implement the interface these methodes have to be override again in the derived classes of the Rubberband class. */
|
||||
/**
|
||||
@{
|
||||
*/
|
||||
|
||||
bool selectAction ( AbstractEventDispatcher * causer, int x, int y ) override;
|
||||
bool multiSelectActionPress ( AbstractEventDispatcher * causer, int x, int y ) override;
|
||||
bool multiSelectActionRelease( AbstractEventDispatcher * causer, int x, int y ) override;
|
||||
bool setCoordinateAction ( AbstractEventDispatcher * causer, int x, int y ) override;
|
||||
bool moveAction ( AbstractEventDispatcher * causer, int x, int y ) override;
|
||||
bool movePickedAction ( AbstractEventDispatcher * causer, int x, int y ) override;
|
||||
void resetAction ( AbstractEventDispatcher * causer, int x, int y ) override;
|
||||
bool contextMenuAction ( AbstractEventDispatcher * causer, int x, int y ) override;
|
||||
bool completeStateAction ( AbstractEventDispatcher * causer, int x, int y ) override;
|
||||
bool deleteAction ( AbstractEventDispatcher * causer, int x, int y ) override;
|
||||
bool undoAction ( AbstractEventDispatcher * causer, int x, int y ) override;
|
||||
|
||||
|
||||
/** @} */
|
||||
|
||||
|
||||
/**
|
||||
Retrieve and set 3D coordinates.
|
||||
@{
|
||||
*/
|
||||
virtual Point3D singleCoordinate3D( unsigned int idx = 0, CoordinateSystem cs = CoordinateSystem::Geo ) const = 0;
|
||||
|
||||
virtual QVector<Point3D> coordinateVector3D( CoordinateSystem cs = CoordinateSystem::Geo ) const = 0;
|
||||
|
||||
virtual void setCoordinateVector( const QVector<Point3D> & coordinateVector, CoordinateSystem cs = CoordinateSystem::Geo ) = 0;
|
||||
/** @} */
|
||||
|
||||
|
||||
|
||||
|
||||
protected:
|
||||
|
||||
QRectF sceneBbox() const override;
|
||||
|
||||
QImage markerImage();
|
||||
QImage markerSelectionImage();
|
||||
|
||||
|
||||
|
||||
private:
|
||||
|
||||
QPixmap * _markerPixmap;
|
||||
QPixmap * _markerSelectionPixmap;
|
||||
|
||||
}; /* Rubberband3D */
|
||||
|
||||
} } /* namespace SituationMap::RB */
|
||||
+359
@@ -0,0 +1,359 @@
|
||||
|
||||
/**
|
||||
** @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 */
|
||||
+130
@@ -0,0 +1,130 @@
|
||||
/**
|
||||
**
|
||||
** @RDE_HEADER@
|
||||
** Definition 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
|
||||
**
|
||||
** -----------------------------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "rubberband_multi_point_feature.h"
|
||||
|
||||
|
||||
namespace SituationMap { namespace RB
|
||||
{
|
||||
|
||||
class RubberbandLineHandle;
|
||||
class RubberbandFrameHandle;
|
||||
|
||||
/**
|
||||
@class RubberbandArrow rubberband_arrow.h
|
||||
@brief Implementation of a rubberband for lines with arrow.
|
||||
@see RubberbandFactory, Rubberband, RubberbandMultiPointFeature
|
||||
|
||||
Implementation of rubberbands used to input corridors. There are two different modes \c InputCenterLine and \c InputBoundary. In the
|
||||
InputCenterLine mode the center line of the corridor has to be defined. The rubberband displays then the border geometry.
|
||||
In the InputBoundary mode one side of the border has to be defined. The \c coordinateVector methodes always working on the input geometry.
|
||||
*/
|
||||
class SITUATIONMAP_EXPORT RubberbandArrow : public RubberbandMultiPointFeature
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
/**
|
||||
@name Construction & Destruction
|
||||
@{
|
||||
*/
|
||||
private:
|
||||
|
||||
friend class RubberbandFactory;
|
||||
explicit RubberbandArrow( SituationMap::Map * map, QObject * parent = nullptr );
|
||||
|
||||
public:
|
||||
~RubberbandArrow();
|
||||
/** @} */
|
||||
|
||||
|
||||
/**
|
||||
Sets coordinates to modify to internal coordinate list.
|
||||
|
||||
@param coordinateVec List of coordinates to modify.
|
||||
@param cs Defines the coordinate system of returned coordinates.
|
||||
*/
|
||||
void setCoordinateVector( const QVector<QPointF> & coordinateVec, CoordinateSystem cs = CoordinateSystem::Geo ) override;
|
||||
|
||||
/**
|
||||
Sets coordinates to modify to internal coordinate list. In \c InputCenterLine mode the coordinates will be interpreted as
|
||||
center line of the corridor. In \c InputBoundary the coordinates are defining one border. Id \c corridorWidth is negative
|
||||
the coordinates are the right border otherwise the left one.
|
||||
|
||||
@param coordinateVec List of coordinates to modify.
|
||||
@param arrowHalfWidth Half width of arrow in pixel.
|
||||
@param arrowLength Length of arrow in pixel.
|
||||
@param cs Defines the coordinate system of returned coordinates.
|
||||
*/
|
||||
void setCoordinateVectorArrow(const QVector<QPointF> & coordinateVec, unsigned int arrowHalfWidth, unsigned int arrowLength, CoordinateSystem cs = CoordinateSystem::Geo );
|
||||
|
||||
|
||||
/**
|
||||
Return the width of the corridor.
|
||||
*/
|
||||
unsigned int arrowHalfWidth() const;
|
||||
unsigned int arrowLength() const;
|
||||
|
||||
|
||||
bool selectAction ( AbstractEventDispatcher * causer, int x, int y ) override;
|
||||
bool setCoordinateAction ( AbstractEventDispatcher * causer, int x, int y ) override;
|
||||
bool movePickedAction ( AbstractEventDispatcher * causer, int x, int y ) override;
|
||||
bool moveAction ( AbstractEventDispatcher * causer, int x, int y ) override;
|
||||
bool completeStateAction ( AbstractEventDispatcher * causer, int x, int y ) override;
|
||||
|
||||
|
||||
protected:
|
||||
/*
|
||||
Forward declaration of InternalData to hold private member variables. Becareful the base class Rubberband
|
||||
has similary a class for internal data member with name "InternalData". Don't be confused it is not the same.
|
||||
*/
|
||||
struct InternalData;
|
||||
|
||||
InternalData * _internal;
|
||||
|
||||
unsigned int _arrowSceneHalfWidth;
|
||||
unsigned int _arrowSceneLength;
|
||||
|
||||
void update() override;
|
||||
|
||||
|
||||
void updateArrowPath();
|
||||
void updateHandleScenePosition();
|
||||
|
||||
void constructArrow( const QPointF & p );
|
||||
void constructArrowHandle();
|
||||
|
||||
QPointF getArrowHandleScenePosition();
|
||||
QPointF getArrowHandlePosition();
|
||||
|
||||
|
||||
|
||||
}; /* RubberbandCorridor */
|
||||
|
||||
} } /* namespace SituationMap::RB */
|
||||
+654
@@ -0,0 +1,654 @@
|
||||
|
||||
/**
|
||||
**
|
||||
** @RDE_HEADER@
|
||||
** Implementation of base class for rubberbands
|
||||
** $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_base.h"
|
||||
#include "rubberband_base_internal.h"
|
||||
#include "rubberband_handle_proxy.h"
|
||||
|
||||
#include "rubberband_factory.h"
|
||||
|
||||
#include <Common/exception.h>
|
||||
|
||||
#include <Map/coord_translation_functor.h>
|
||||
#include <MapImpl/map_impl.h>
|
||||
|
||||
// Qt
|
||||
#include <QtCore/QCoreApplication>
|
||||
#include <QtCore/QMetaMethod>
|
||||
|
||||
#include <QtWidgets/QGraphicsView>
|
||||
#include <QtWidgets/QWidget>
|
||||
#include <QtWidgets/QHBoxLayout>
|
||||
#include <QtWidgets/QPushButton>
|
||||
#include <QtGui/QPixmap>
|
||||
|
||||
#include "apply.xpm"
|
||||
#include "abort.xpm"
|
||||
#include "undo.xpm"
|
||||
|
||||
static SituationMap::Map * currentFactoryMap = nullptr;
|
||||
static bool allowMultipleRubberbands = false;
|
||||
|
||||
|
||||
namespace SituationMap { namespace RB
|
||||
{
|
||||
QPixmap * RubberbandBase::BaseInternalData::_applyIcon = nullptr;
|
||||
QPixmap * RubberbandBase::BaseInternalData::_abortIcon = nullptr;
|
||||
QPixmap * RubberbandBase::BaseInternalData::_undoIcon = nullptr;
|
||||
|
||||
RubberbandBase::BaseInternalData::BaseInternalData( SituationMap::Map * map, RubberbandBase * me )
|
||||
: _map(map)
|
||||
, _mapCtFunctor(map->coordTranslationFunctor())
|
||||
, _isActive(false)
|
||||
, _applyIsPossible(false)
|
||||
, _undoIsPossible(false)
|
||||
, _hasUndoButton(false)
|
||||
, _lastClickPosition(-1,-1)
|
||||
, _buttonBoxSceneAnchor()
|
||||
, _buttonBoxFixPosition(-1,-1)
|
||||
, _buttonProxy()
|
||||
, _updateFunctorList()
|
||||
, _logger(getLogger("RubberbandBase"))
|
||||
{
|
||||
QGraphicsView * view = map->getQGraphicsView();
|
||||
|
||||
if (view)
|
||||
{
|
||||
_restoreCursor = view->viewport()->cursor(); // workaround Qt bug. remove when fixed
|
||||
}
|
||||
|
||||
_buttonBox = new QWidget();
|
||||
_buttonBox->setObjectName(QLatin1String("RBButtonBoxWidget"));
|
||||
_buttonBox->hide();
|
||||
_buttonBox->setAttribute( Qt::WidgetAttribute::WA_NoSystemBackground, true );
|
||||
|
||||
_applyButton = new QPushButton( (_applyIcon) ? *_applyIcon : QPixmap(apply_xpm), QString(), _buttonBox );
|
||||
_applyButton -> setAttribute( Qt::WidgetAttribute::WA_NoSystemBackground, true );
|
||||
_applyButton -> setObjectName(QLatin1String("RBApply"));
|
||||
_applyButton -> setAttribute(Qt::WA_AcceptTouchEvents);
|
||||
_applyButton -> grabGesture( Qt::GestureType::TapGesture );
|
||||
me->connect( _applyButton, &QPushButton::clicked, me, &RubberbandBase::onDo_applyButtonClicked );
|
||||
|
||||
_cancelButton = new QPushButton( (_abortIcon) ? *_abortIcon : QPixmap(abort_xpm), QString(), _buttonBox );
|
||||
_cancelButton -> setAttribute( Qt::WidgetAttribute::WA_NoSystemBackground, true );
|
||||
_cancelButton -> setObjectName(QLatin1String("RBCancel"));
|
||||
_cancelButton -> setAttribute(Qt::WA_AcceptTouchEvents);
|
||||
_cancelButton -> grabGesture( Qt::GestureType::TapGesture );
|
||||
me->connect( _cancelButton, &QPushButton::clicked, me, &RubberbandBase::onDo_cancelButtonClicked );
|
||||
|
||||
_undoButton = new QPushButton( (_undoIcon) ? *_undoIcon : QPixmap(undo_xpm), QString(), _buttonBox );
|
||||
_undoButton -> setAttribute( Qt::WidgetAttribute::WA_NoSystemBackground, true );
|
||||
_undoButton -> setObjectName(QLatin1String("RBUndo"));
|
||||
_undoButton -> setAttribute(Qt::WA_AcceptTouchEvents);
|
||||
_undoButton -> grabGesture( Qt::GestureType::TapGesture );
|
||||
_undoButton -> hide();
|
||||
me->connect( _undoButton, &QPushButton::clicked, me, &RubberbandBase::onDo_undoButtonClicked );
|
||||
|
||||
_buttonLayout = new QHBoxLayout( _buttonBox );
|
||||
_buttonLayout->setObjectName(QLatin1String("RBButtonBoxLayoutHBox"));
|
||||
|
||||
_buttonLayout -> addWidget( _undoButton );
|
||||
_buttonLayout -> addWidget( _cancelButton );
|
||||
_buttonLayout -> addWidget( _applyButton );
|
||||
|
||||
} /* InternalData */
|
||||
|
||||
|
||||
Rubberband::BaseInternalData::~BaseInternalData()
|
||||
{
|
||||
_map = nullptr;
|
||||
_mapCtFunctor = nullptr;
|
||||
|
||||
_buttonProxy = nullptr; // delete RefPointer
|
||||
if (_buttonBox) _buttonBox -> deleteLater(); // delete all widgets of button box
|
||||
|
||||
_buttonBox = nullptr;
|
||||
_buttonLayout = nullptr;
|
||||
_applyButton = nullptr;
|
||||
_cancelButton = nullptr;
|
||||
_undoButton = nullptr;
|
||||
|
||||
} /* ~InternalData */
|
||||
|
||||
|
||||
bool RubberbandBase::BaseInternalData::buttonProxyActive( const QPointF & pos ) const
|
||||
{
|
||||
if (_buttonProxy)
|
||||
{
|
||||
return ((_buttonProxy->isVisible()) && (_buttonProxy->isPositionInside(pos)));
|
||||
}
|
||||
return false;
|
||||
} /* bool RubberbandBase::BaseInternalData::buttonProxyActive( const QPointF & pos ) const*/
|
||||
|
||||
|
||||
void RubberbandBase::BaseInternalData::enableAndShowOnlyPossibleButtons()
|
||||
{
|
||||
_applyButton->setEnabled(_applyIsPossible);
|
||||
|
||||
if (_undoButton)
|
||||
{
|
||||
if (_hasUndoButton)
|
||||
{
|
||||
_undoButton -> show();
|
||||
}
|
||||
_undoButton -> setEnabled(_undoIsPossible);
|
||||
}
|
||||
} /* void RubberbandBase::InternalData::showOnlyPossibleButtons() */
|
||||
|
||||
|
||||
static QHash<SituationMap::Map*, QList<RubberbandBase*>> &activeRubberbands()
|
||||
{
|
||||
static QHash<SituationMap::Map*, QList<RubberbandBase*>> hashTable;
|
||||
return hashTable;
|
||||
} // activeRubberbands()
|
||||
|
||||
|
||||
void RubberbandBase::currentFactoryMap(SituationMap::Map * map) { ::currentFactoryMap = map; }
|
||||
void RubberbandBase::allowMultipleRubberbands( bool ok ) { ::allowMultipleRubberbands = ok; }
|
||||
|
||||
|
||||
void * RubberbandBase::operator new(size_t bytes)
|
||||
{
|
||||
QString exceptionMsg;
|
||||
|
||||
// be careful it is not thread safe here
|
||||
if (::currentFactoryMap)
|
||||
{
|
||||
bool doNew( ::allowMultipleRubberbands );
|
||||
|
||||
if (!doNew)
|
||||
{
|
||||
doNew = true;
|
||||
const auto rubberbands = SituationMap::RB::activeRubberbands().value(::currentFactoryMap);
|
||||
for (const auto rbnd : rubberbands)
|
||||
{
|
||||
if (rbnd->rubberbandIsAlive())
|
||||
{
|
||||
doNew = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (doNew)
|
||||
{
|
||||
RubberbandBase::currentFactoryMap( nullptr );
|
||||
RubberbandBase::allowMultipleRubberbands( false );
|
||||
return ::operator new(bytes);
|
||||
}
|
||||
else exceptionMsg = QLatin1String("Another rubberband is already alive at moment");
|
||||
RubberbandBase::currentFactoryMap( nullptr );
|
||||
}
|
||||
else exceptionMsg = QLatin1String("Use rubberband factory to create rubberbands. Calling new directly is forbidden!");
|
||||
|
||||
RubberbandBase::currentFactoryMap( nullptr );
|
||||
RubberbandBase::allowMultipleRubberbands( false );
|
||||
|
||||
/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
* because "return nullptr;" is not compliante with the c++ standard
|
||||
* throw exception instead
|
||||
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
|
||||
throw Exception( __FILE__, __LINE__, exceptionMsg );
|
||||
|
||||
} /* RubberbandBase::operator new */
|
||||
|
||||
|
||||
QList<RubberbandBase*> RubberbandBase::activeRubberbands( SituationMap::Map * map )
|
||||
{
|
||||
QList<RubberbandBase*> ret;
|
||||
const auto rubberbands = SituationMap::RB::activeRubberbands().value(map);
|
||||
for (const auto rbnd : rubberbands)
|
||||
{
|
||||
if (rbnd && rbnd->rubberbandIsAlive())
|
||||
ret += rbnd;
|
||||
}
|
||||
return ret;
|
||||
} /* RubberbandBase::activeRubberbands */
|
||||
|
||||
void RubberbandBase::deleteAllActiveRubberbands(Map *map)
|
||||
{
|
||||
const QList<SituationMap::RB::RubberbandBase*> &rbCont = RubberbandBase::activeRubberbands(map);
|
||||
qDeleteAll(rbCont);
|
||||
} /* RubberbandBase::deleteAllActiveRubberbands */
|
||||
|
||||
|
||||
bool RubberbandBase::isRubberbandActive(SituationMap::Map * map)
|
||||
{
|
||||
return (activeRubberbands(map).size() > 0);
|
||||
} /* RubberbandBase::isRubberbandActive */
|
||||
|
||||
|
||||
void RubberbandBase::abortActiveRubberbands( SituationMap::Map * map )
|
||||
{
|
||||
const QList<RubberbandBase*> & rbList = activeRubberbands(map);
|
||||
for (auto rb : rbList)
|
||||
{
|
||||
emit rb->abort(rb);
|
||||
rb->doAutoDelete();
|
||||
}
|
||||
} /* RubberbandBase::abortActiveRubberbands */
|
||||
|
||||
|
||||
void RubberbandBase::deleteMySelf()
|
||||
{
|
||||
if (_viewPortEventDispatcher) _viewPortEventDispatcher -> onDo_kickTheBucket();
|
||||
if (_viewPortEventDispatcher) _viewPortEventDispatcher -> onDo_delete();
|
||||
if (_windowEventDispatcher) _windowEventDispatcher -> onDo_delete();
|
||||
|
||||
_viewPortEventDispatcher = nullptr;
|
||||
_windowEventDispatcher = nullptr;
|
||||
_baseInternal->_isActive = false;
|
||||
|
||||
deleteLater();
|
||||
} /* RubberbandBase::deleteMySelf */
|
||||
|
||||
|
||||
RubberbandBase::RubberbandBase( SituationMap::Map * map, QObject * parent, bool isActive )
|
||||
: QObject( parent )
|
||||
, EventActionInterface()
|
||||
, _baseInternal( new RubberbandBase::BaseInternalData(map,this) )
|
||||
, _drawColor(QColor("black"))
|
||||
, _fillColor(QColor("black"))
|
||||
, _handleDrawColor(QColor("black"))
|
||||
, _handleFillColor(QColor("yellow"))
|
||||
, _handleSelectionColor(QColor("red"))
|
||||
, _frameColor(QColor("black"))
|
||||
, _frameFillColor(QColor(150,150,0,50))
|
||||
, _frameSelectionColor(QColor(255,0,0,50))
|
||||
, _frameHandleMargin(10)
|
||||
, _pickingRatio(0)
|
||||
, _finishAfterConstruction(true)
|
||||
, _autoDelete(false)
|
||||
, _viewPortEventDispatcher(nullptr)
|
||||
, _windowEventDispatcher (nullptr)
|
||||
, _userData(nullptr)
|
||||
{
|
||||
_fillColor.setAlpha(100);
|
||||
|
||||
if (isActive) activate();
|
||||
|
||||
/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
* In case of multiple rubberbands can be active, it is forbidden to
|
||||
* create a rubberband of the same type twice anyway.
|
||||
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
|
||||
bool rubberbandOfSameTypeIsActive = false;
|
||||
const auto rubberbands = SituationMap::RB::activeRubberbands().value(map);
|
||||
for (auto rbnd : rubberbands)
|
||||
{
|
||||
// Just to check the class names with debugger
|
||||
// const char * rbndName = typeid(*rbnd).name();
|
||||
// const char * thisName = typeid(*this).name();
|
||||
|
||||
if (( typeid(*rbnd) == typeid(*this)) && rbnd->rubberbandIsAlive())
|
||||
{
|
||||
rubberbandOfSameTypeIsActive = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (rubberbandOfSameTypeIsActive)
|
||||
{
|
||||
// disable dispatcher, so the rubberband is not alive yet.
|
||||
if (_viewPortEventDispatcher)
|
||||
{
|
||||
_viewPortEventDispatcher -> onDo_kickTheBucket();
|
||||
_viewPortEventDispatcher -> onDo_delete();
|
||||
}
|
||||
if (_windowEventDispatcher) _windowEventDispatcher->onDo_delete();
|
||||
_viewPortEventDispatcher = nullptr;
|
||||
_windowEventDispatcher = nullptr;
|
||||
}
|
||||
else
|
||||
{
|
||||
SituationMap::RB::activeRubberbands()[map].append( this );
|
||||
if (_windowEventDispatcher)
|
||||
{
|
||||
_windowEventDispatcher->setCursor(QCursor(Qt::CrossCursor));
|
||||
_windowEventDispatcher->grab();
|
||||
}
|
||||
if (_viewPortEventDispatcher)
|
||||
{
|
||||
_viewPortEventDispatcher->setCursor(QCursor(Qt::CrossCursor));
|
||||
_viewPortEventDispatcher->grab();
|
||||
}
|
||||
}
|
||||
|
||||
if (map)
|
||||
{
|
||||
/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
*
|
||||
* Sending signals of RubberbandFactory to inform about rubberband creation and destroy would be
|
||||
* better placed in RubberbandFactory source (rubberband_factory.cpp) but there it's a lot of
|
||||
* more writing stuff ...
|
||||
*
|
||||
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
|
||||
SituationMap::RB::RubberbandFactory & rbndFactory = map -> rubberbandFactory();
|
||||
emit rbndFactory.rubberbandCreated();
|
||||
|
||||
connect( this, &QObject::destroyed, &rbndFactory, &SituationMap::RB::RubberbandFactory::rubberbandDestroyed );
|
||||
}
|
||||
|
||||
} /* RubberbandBase::RubberbandBase */
|
||||
|
||||
|
||||
RubberbandBase::~RubberbandBase()
|
||||
{
|
||||
if (_viewPortEventDispatcher) _viewPortEventDispatcher -> onDo_kickTheBucket();
|
||||
if (_viewPortEventDispatcher) _viewPortEventDispatcher -> onDo_delete();
|
||||
if (_windowEventDispatcher) _windowEventDispatcher -> onDo_delete();
|
||||
|
||||
_viewPortEventDispatcher = nullptr;
|
||||
_windowEventDispatcher = nullptr;
|
||||
|
||||
/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
* Test if map has been already destroyed. If map exists all is nice ...
|
||||
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
|
||||
if (_baseInternal->_map)
|
||||
{
|
||||
SituationMap::RB::activeRubberbands()[_baseInternal->_map].removeOne( this );
|
||||
emit finished( this );
|
||||
}
|
||||
else
|
||||
{
|
||||
/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
* ... otherwise we have to search the rubberband
|
||||
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
|
||||
const auto rubberbands = SituationMap::RB::activeRubberbands();
|
||||
for (auto rubberList : rubberbands)
|
||||
rubberList.removeOne(this);
|
||||
}
|
||||
|
||||
delete _baseInternal;
|
||||
_baseInternal = nullptr;
|
||||
|
||||
} /* RubberbandBase::~RubberbandBase */
|
||||
|
||||
|
||||
QPointF RubberbandBase::projectCoordinateToMap( CoordinateSystem cs, const QPointF & loc ) const
|
||||
{
|
||||
return (cs != CoordinateSystem::Geo || !_baseInternal->_mapCtFunctor) ? loc : _baseInternal->_mapCtFunctor->geographicToMap( loc );
|
||||
} /* RubberbandBase::projectCoordinateToMap */
|
||||
|
||||
|
||||
QPointF RubberbandBase::projectCoordinateFromMap( CoordinateSystem cs, const QPointF & loc ) const
|
||||
{
|
||||
return (cs != CoordinateSystem::Geo || !_baseInternal->_mapCtFunctor) ? loc : _baseInternal->_mapCtFunctor->mapToGeographic( loc );
|
||||
} /* RubberbandBase::projectCoordinateFromMap */
|
||||
|
||||
|
||||
QPointF RubberbandBase::projectCoordinateFromMap( CoordinateSystem cs, const Esri::ArcGISRuntime::Point & loc ) const
|
||||
{
|
||||
return (cs != CoordinateSystem::Geo || !_baseInternal->_mapCtFunctor) ? QPointF(loc.x(), loc.y()) : _baseInternal->_mapCtFunctor->mapToGeographic( loc );
|
||||
} /* RubberbandBase::projectCoordinateFromMap */
|
||||
|
||||
|
||||
|
||||
void RubberbandBase::activate()
|
||||
{
|
||||
if (!_baseInternal->_map) return;
|
||||
|
||||
if (!_baseInternal->_isActive)
|
||||
{
|
||||
QGraphicsView * view = _baseInternal->_map->getQGraphicsView();
|
||||
if (view)
|
||||
{
|
||||
_viewPortEventDispatcher = new EventDispatcher(view->viewport(), this);
|
||||
_windowEventDispatcher = new EventDelegater(view, _viewPortEventDispatcher);
|
||||
_baseInternal->_isActive = true;
|
||||
|
||||
MapImpl *mapImpl = static_cast<MapImpl*>(_baseInternal->_map.data());
|
||||
|
||||
connect(_viewPortEventDispatcher.data(), &EventDispatcher::mouseMovedEvent,
|
||||
mapImpl, &MapImpl::onHandleMouseMove);
|
||||
}
|
||||
}
|
||||
} /* RubberbandBase::activate */
|
||||
|
||||
|
||||
bool RubberbandBase::autoSelectAction(int x, int y)
|
||||
{
|
||||
_viewPortEventDispatcher->_leftPressHandled = true;
|
||||
return selectAction(nullptr,x,y);
|
||||
} /* RubberbandBase::autoSelectAction */
|
||||
|
||||
|
||||
void RubberbandBase::installExternalUpdate(const std::function<bool(RubberbandBase*)> & updateFunctor)
|
||||
{
|
||||
_baseInternal->_updateFunctorList << updateFunctor;
|
||||
} // void RubberbandBase::installExternalUpdate( const std::function<bool(RubberbandBase*)> & updateFunctor)
|
||||
|
||||
|
||||
void RubberbandBase::externalUpdate()
|
||||
{
|
||||
for (const auto &update : qAsConst(_baseInternal->_updateFunctorList))
|
||||
{
|
||||
if (!update(this))
|
||||
break;
|
||||
}
|
||||
} // void RubberbandBase::externalUpdate()
|
||||
|
||||
|
||||
|
||||
void RubberbandBase::updateButtonPosition()
|
||||
{
|
||||
if ((_baseInternal->_lastClickPosition.x() < 0) || (_baseInternal->_lastClickPosition.y() < 0))
|
||||
_baseInternal->_buttonBoxSceneAnchor = sceneBbox().bottomRight();
|
||||
else
|
||||
_baseInternal->_buttonBoxSceneAnchor = _baseInternal->_lastClickPosition;
|
||||
|
||||
// _internal->_mapView->update();
|
||||
} /* RubberbandBase::updateButtonPosition */
|
||||
|
||||
|
||||
void RubberbandBase::setFixedButtonBoxPosition( QPoint widgetPos )
|
||||
{
|
||||
_baseInternal->_buttonBoxFixPosition = widgetPos;
|
||||
activateButtons();
|
||||
} /* RubberbandBase::setFixedButtonBoxPosition */
|
||||
|
||||
|
||||
void RubberbandBase::unsetFixedButtonBoxPosition()
|
||||
{
|
||||
_baseInternal->_buttonBoxFixPosition = QPoint(-1,-1);
|
||||
|
||||
if (_baseInternal->_buttonProxy)
|
||||
{
|
||||
_baseInternal->_buttonProxy->setPos( _baseInternal->_buttonBoxSceneAnchor );
|
||||
}
|
||||
} /* RubberbandBase::unsetFixedButtonBoxPosition */
|
||||
|
||||
|
||||
bool RubberbandBase::isButtonBoxPositionFixed() { return ((_baseInternal->_buttonBoxFixPosition.x() >= 0) && (_baseInternal->_buttonBoxFixPosition.y() >= 0)); }
|
||||
|
||||
|
||||
void RubberbandBase::onDo_updateButtonFixCoordinates()
|
||||
{
|
||||
if (!_baseInternal->_buttonProxy) return;
|
||||
|
||||
if (isButtonBoxPositionFixed())
|
||||
{
|
||||
// Don't use bottom right corner of rubberband bbox to place the buttons,
|
||||
// rather than use fixed window position.
|
||||
|
||||
const QPoint & pos = _baseInternal->_buttonBoxFixPosition;
|
||||
_baseInternal->_buttonProxy->setPos( pixel2ScenePosition(pos.x(),pos.y()) );
|
||||
}
|
||||
} /* RubberbandStateSelect::onDo_updateButtonFixCoordinates */
|
||||
|
||||
|
||||
void RubberbandBase::activateButtons()
|
||||
{
|
||||
DEBUG_LOG(_baseInternal->_logger) << LOGFUNCTION;
|
||||
if (!_baseInternal->_buttonProxy)
|
||||
{
|
||||
_baseInternal->_buttonProxy = new RubberbandHandleProxy( _baseInternal->_map->getQGraphicsView(), _baseInternal->_buttonBox );
|
||||
_baseInternal->_buttonProxy->setRestoreCursor( _baseInternal->_restoreCursor ); // workaround Qt bug. remove when fixed
|
||||
|
||||
connect( _baseInternal->_buttonProxy.get(), &RubberbandHandleProxy::adjusted, this, [this]()
|
||||
{
|
||||
this->_baseInternal->_buttonBoxSceneAnchor = this->_baseInternal->_buttonProxy->getCoordinate()._sceneCoordinate;
|
||||
} );
|
||||
}
|
||||
|
||||
_baseInternal->enableAndShowOnlyPossibleButtons();
|
||||
|
||||
if (isButtonBoxPositionFixed())
|
||||
{
|
||||
const QPoint & pos = _baseInternal->_buttonBoxFixPosition;
|
||||
_baseInternal->_buttonProxy->setPos( pixel2ScenePosition(pos.x(),pos.y()) );
|
||||
_baseInternal->_buttonProxy->setSceneOffset( QPointF(0,0) );
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
_baseInternal->_buttonProxy->setPos( _baseInternal->_buttonBoxSceneAnchor );
|
||||
_baseInternal->_buttonProxy->setSceneOffset( QPointF(_frameHandleMargin+5,_frameHandleMargin+5) );
|
||||
}
|
||||
|
||||
_baseInternal->_buttonProxy->show();
|
||||
|
||||
} /* Rubberband::activateButtons */
|
||||
|
||||
|
||||
void RubberbandBase::deactivateButtons()
|
||||
{
|
||||
DEBUG_LOG(_baseInternal->_logger) << LOGFUNCTION;
|
||||
if (isButtonBoxPositionFixed()) return;
|
||||
if (_baseInternal->_buttonProxy) _baseInternal->_buttonProxy->hide();
|
||||
} /* RubberbandBase::deactivateButtons() */
|
||||
|
||||
|
||||
void RubberbandBase::adjustButtons()
|
||||
{
|
||||
if (_baseInternal->_buttonProxy)
|
||||
{
|
||||
activateButtons();
|
||||
}
|
||||
} /* RubberbandBase::adjustButtons */
|
||||
|
||||
|
||||
void RubberbandBase::applyButtonClicked()
|
||||
{
|
||||
completeStateAction( _viewPortEventDispatcher, 0.0, 0.0 );
|
||||
} /* RubberbandBase::applyButtonClicked */
|
||||
|
||||
|
||||
void RubberbandBase::cancelButtonClicked()
|
||||
{
|
||||
abortAction( _viewPortEventDispatcher, 0.0, 0.0 );
|
||||
} /* RubberbandBase::cancelButtonClicked */
|
||||
|
||||
|
||||
void RubberbandBase::undoButtonClicked()
|
||||
{
|
||||
undoAction( _viewPortEventDispatcher, 0.0, 0.0 );
|
||||
} /* RubberbandBase::undoButtonClicked */
|
||||
|
||||
|
||||
void RubberbandBase::resetIconsToDefault()
|
||||
{
|
||||
if (BaseInternalData::_applyIcon) { delete BaseInternalData::_applyIcon; BaseInternalData::_applyIcon = nullptr; }
|
||||
if (BaseInternalData::_abortIcon) { delete BaseInternalData::_abortIcon; BaseInternalData::_abortIcon = nullptr; }
|
||||
if (BaseInternalData::_undoIcon ) { delete BaseInternalData::_undoIcon; BaseInternalData::_undoIcon = nullptr; }
|
||||
} /* RubberbandBase::resetIconsToDefault */
|
||||
|
||||
|
||||
void RubberbandBase::setIconApply(const QPixmap & icon)
|
||||
{
|
||||
if (BaseInternalData::_applyIcon == nullptr) BaseInternalData::_applyIcon = new QPixmap(icon);
|
||||
else *BaseInternalData::_applyIcon = icon;
|
||||
} /* RubberbandBase::setIconApply */
|
||||
|
||||
|
||||
void RubberbandBase::setIconAbort(const QPixmap & icon)
|
||||
{
|
||||
if (BaseInternalData::_abortIcon == nullptr) BaseInternalData::_abortIcon = new QPixmap(icon);
|
||||
else *BaseInternalData::_abortIcon = icon;
|
||||
} /* RubberbandBase::setIconAbort */
|
||||
|
||||
|
||||
void RubberbandBase::setIconUndo(const QPixmap & icon)
|
||||
{
|
||||
if (BaseInternalData::_undoIcon == nullptr) BaseInternalData::_undoIcon = new QPixmap(icon);
|
||||
else *BaseInternalData::_undoIcon = icon;
|
||||
} /* RubberbandBase::setIconUndo */
|
||||
|
||||
|
||||
QPointF RubberbandBase::pixel2ScenePosition( int x, int y ) const
|
||||
{
|
||||
QGraphicsView * view = _baseInternal->_map->getQGraphicsView();
|
||||
return (view) ? view->mapToScene(x, y) : QPointF(x,y);
|
||||
} /* RubberbandBase::pixel2ScenePosition */
|
||||
|
||||
|
||||
bool RubberbandBase::buttonPositionAction(AbstractEventDispatcher *, int x, int y)
|
||||
{
|
||||
QPointF scenePos(pixel2ScenePosition(x,y));
|
||||
|
||||
if (!_baseInternal->buttonProxyActive(scenePos))
|
||||
{
|
||||
_baseInternal->_buttonBoxSceneAnchor = scenePos;
|
||||
adjustButtons();
|
||||
}
|
||||
return false;
|
||||
} /* bool RubberbandBase::buttonPositionAction(AbstractEventDispatcher * causer, int x, int y) */
|
||||
|
||||
|
||||
void RubberbandBase::unlinkEventDispatcher( AbstractEventDispatcher* )
|
||||
{
|
||||
_viewPortEventDispatcher = nullptr;
|
||||
_windowEventDispatcher = nullptr;
|
||||
|
||||
} /* RubberbandBase::unlinkEventDispatcher */
|
||||
|
||||
|
||||
bool RubberbandBase::abortAction( AbstractEventDispatcher * causer, int, int )
|
||||
{
|
||||
_baseInternal->_buttonBox->hide();
|
||||
|
||||
if (causer) causer->onDo_kickTheBucket();
|
||||
|
||||
emit abort( this );
|
||||
doAutoDelete();
|
||||
return true;
|
||||
} /* RubberbandBase::abortAction */
|
||||
|
||||
|
||||
bool RubberbandBase::applyAndEndAction( AbstractEventDispatcher * causer, int,int )
|
||||
{
|
||||
_baseInternal->_buttonBox->hide();
|
||||
|
||||
if (causer) causer->onDo_kickTheBucket();
|
||||
|
||||
emit apply( this );
|
||||
doAutoDelete();
|
||||
return true;
|
||||
} /* RubberbandBase::applyAndEndAction */
|
||||
|
||||
} } /* namespace SituationMap::RB */
|
||||
+500
@@ -0,0 +1,500 @@
|
||||
/**
|
||||
**
|
||||
** @RDE_HEADER@
|
||||
** Definition of base class for rubberbands
|
||||
** $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
|
||||
**
|
||||
** -----------------------------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
|
||||
#include "event_dispatcher.h"
|
||||
#include "event_delegater.h"
|
||||
|
||||
#include <Map/map.h>
|
||||
#include <Common/ref_pointer.h>
|
||||
|
||||
#include <QtCore/QList>
|
||||
#include <QtCore/QObject>
|
||||
#include <QtCore/QPointer>
|
||||
|
||||
#include <QtGui/QColor>
|
||||
|
||||
#include <memory>
|
||||
|
||||
|
||||
namespace Esri {
|
||||
namespace ArcGISRuntime {
|
||||
class MapGraphicsView;
|
||||
class Point;
|
||||
} }
|
||||
|
||||
|
||||
|
||||
namespace SituationMap
|
||||
{
|
||||
|
||||
/**
|
||||
Namespace for all rubberband stuff (is part of namespace SituationMap)
|
||||
*/
|
||||
namespace RB
|
||||
{
|
||||
/**
|
||||
*/
|
||||
enum class CoordinateSystem
|
||||
{
|
||||
Map,
|
||||
Geo
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
@class RubberbandBase rubberband_base.h
|
||||
@brief Base class of all Rubberbands
|
||||
|
||||
Rubberbands are used to create or modifiy geometries like lines, circles, polygons etc. by processing
|
||||
Qt input events like keyboard and mouse events. To create a rubberband the RubberbandFactory has to be used.
|
||||
At end of rubberband processing the signal \c abort or\c apply are emitted. To delete the rubberband the
|
||||
function deleteMySelf must be called. To use the delete operator is dangerous because at end of signal
|
||||
processing some program code may be performed.
|
||||
|
||||
Example to how to use rubberband:
|
||||
|
||||
@code
|
||||
|
||||
SituationMap::Map & map = ...
|
||||
|
||||
const RubberbandFactory & rubberbandFactory = map.rubberbandFactory();
|
||||
|
||||
RubberbandPointFeature * rubberband = rubberbandFactory.create<RubberbandPointFeature>();
|
||||
if (rubberband != nullptr)
|
||||
{
|
||||
QObject::connect( rubberband, &SiMapRubBnd::Rubberband::apply, [=](SiMapRubBnd::Rubberband * rubberband )
|
||||
{
|
||||
// rubberband has finished input
|
||||
if (rubberband)
|
||||
{
|
||||
const QVector<QPointF> & vertexList = rubberband->coordinateVector();
|
||||
|
||||
// do something with vertexList
|
||||
|
||||
rubberband->deleteMySelf(); // notice don't call here delete rubberband directly !!!
|
||||
}
|
||||
} );
|
||||
|
||||
QObject::connect( rubberband, &SiMapRubBnd::Rubberband::abort, this, [=](SiMapRubBnd::Rubberband * rubberband )
|
||||
{
|
||||
// Rubberband has been aborted by user
|
||||
if (rubberband)
|
||||
{
|
||||
rubberband->deleteMySelf(); // notice don't call here delete rubberband directly !!!
|
||||
}
|
||||
} );
|
||||
}
|
||||
|
||||
@endcode
|
||||
|
||||
Following keyboard commands are available in active rubberbands:
|
||||
|
||||
| Key | Modifier | Funktion |
|
||||
| :----: |:-------: | :--------------------------------------------------------------------------- |
|
||||
| Esc | | Rubberband abbrechen |
|
||||
| Return | | Rubberband abschließen und Eingabe übernehmen wenn möglich, sonst Abbruch |
|
||||
| Left | | Selektierten Handle (Punkt,Frame) um 1 Pixel nach links schieben |
|
||||
| Right | | Selektierten Handle (Punkt,Frame) um 1 Pixel nach rechts schieben |
|
||||
| Up | | Selektierten Handle (Punkt,Frame) um 1 Pixel nach oben schieben |
|
||||
| Down | | Selektierten Handle (Punkt,Frame) um 1 Pixel nach unten schieben |
|
||||
| Left | Shift | Selektierten Handle (Punkt,Frame) um 10 Pixel nach links schieben |
|
||||
| Right | Shift | Selektierten Handle (Punkt,Frame) um 10 Pixel nach rechts schieben |
|
||||
| Up | Shift | Selektierten Handle (Punkt,Frame) um 10 Pixel nach oben schieben |
|
||||
| Down | Shift | Selektierten Handle (Punkt,Frame) um 10 Pixel nach unten schieben |
|
||||
|
||||
@see EventDispatcher
|
||||
@see Rubberband, RubberbandPointFeature, RubberbandPointCluster, RubberbandMultiPointFeature, RubberbandRectangle, RubberbandEllipse, RubberbandCorridor, RubberbandArrow
|
||||
Rubberband3D, RubberbandPointFeature3D, RubberbandMultiPointFeature3D
|
||||
|
||||
*/
|
||||
|
||||
class SITUATIONMAP_EXPORT RubberbandBase : public QObject, public EventDispatcher::EventActionInterface
|
||||
{
|
||||
/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
* Because class EventDispatcher::EventActionInterface is a pure virtual interface function the classic way of declaration would be
|
||||
*
|
||||
* SITUATIONMAP_EXPORT Rubberband : public QObject, public virtual EventDispatcher::EventActionInterface
|
||||
*
|
||||
* But with Visual Studio 2013 virtual inheritance combined with constructor delegation doesn't work and may crash the program. In
|
||||
* this case the virtual inheritance of EventActionInterface isn't need because in the derived classes multiple inheritance will
|
||||
* not be used.
|
||||
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
|
||||
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
|
||||
/**
|
||||
@name Construction & Destruction
|
||||
@{
|
||||
*/
|
||||
|
||||
public:
|
||||
|
||||
/**
|
||||
Constructs a Rubberband for a situation map. Use \c RubberbandFactor to create a rubberband.
|
||||
In case of the user actions the autoDelete mechanism can be used to delete the rubberband. Sometimes
|
||||
the application wants to finish a running rubberband. This can be done by calling \c deleteMySelf. The
|
||||
rubberband will be destroyed also automatically if the parent QObject or the map (see
|
||||
SituationMap::Map::beginDestroy signal) will be destroyed.
|
||||
|
||||
@param map Pointer to SituationMap::Map
|
||||
@param parent Pointer to QObject to use as parent.
|
||||
@isActive If set to false the Rubberband is not active and have to be actived to start the input.
|
||||
@see RubberbandFactory
|
||||
*/
|
||||
RubberbandBase( SituationMap::Map * map, QObject * parent, bool isActive = true );
|
||||
|
||||
~RubberbandBase();
|
||||
/** @} */
|
||||
|
||||
/**
|
||||
Activate rubberband if it has been created with \c isActive = false.
|
||||
*/
|
||||
void activate();
|
||||
|
||||
/**
|
||||
Provides a list of active rubberbands for a situation map.
|
||||
*/
|
||||
static QList<RubberbandBase*> activeRubberbands( SituationMap::Map * map );
|
||||
|
||||
/**
|
||||
Delete active rubberbands for a situation map.
|
||||
*/
|
||||
static void deleteAllActiveRubberbands( SituationMap::Map * map );
|
||||
|
||||
/**
|
||||
Use deleteMySelft instead of delete operator to avoid dangling this pointerin Qt signal processing. It calls delete this; later on.
|
||||
*/
|
||||
void deleteMySelf();
|
||||
|
||||
/**
|
||||
If setting auto delete flag to true the delete will be done automatically after sending signal abort or apply.
|
||||
The default value of auto delete flag is false.
|
||||
@{
|
||||
*/
|
||||
inline void setAutoDelete(bool on) { _autoDelete = on; }
|
||||
|
||||
|
||||
inline bool autoDelete() const { return _autoDelete; }
|
||||
/** @} */
|
||||
|
||||
/**
|
||||
Returns true if the rubberband is already alive. Should be tested after creation of a rubberband because it is
|
||||
possibled to create not living rubberbands, e.g. a rubberband was create twice and the first one has not finished
|
||||
*/
|
||||
inline bool rubberbandIsAlive() const { return !_viewPortEventDispatcher.isNull(); }
|
||||
|
||||
/** A single user action step has finished. Interim results can be used to show a preview now.
|
||||
*/
|
||||
void userActionFinished() override { emit interimResultsChanged(this); }
|
||||
|
||||
/**
|
||||
@name ColorSettings Methodes to define visual behaviour of rubberband
|
||||
@{
|
||||
*/
|
||||
inline void setDrawColor (const QColor & col ) { _drawColor = col; update(); } ///< set color for general drawing
|
||||
inline void setFillColor (const QColor & col ) { _fillColor = col; update(); } ///< set color for general filling
|
||||
inline void setHandleDrawColor (const QColor & col ) { _handleDrawColor = col; update(); } ///< set color for drawing handles
|
||||
inline void setHandleFillColor (const QColor & col ) { _handleFillColor = col; update(); } ///< set color for filling handles
|
||||
inline void setHandleSelectionColor(const QColor & col ) { _handleSelectionColor = col; update(); } ///< set handle selection color
|
||||
inline void setFrameColor (const QColor & col ) { _frameColor = col; update(); } ///< set frame handle outline color
|
||||
inline void setFrameFillColor (const QColor & col ) { _frameFillColor = col; update(); } ///< set frame handle fill color
|
||||
inline void setFrameHandleMargin (int margin ) { _frameHandleMargin = margin; update(); } ///< set margin of frame in pixel
|
||||
|
||||
inline void setPickingRatio (unsigned int size ) { _pickingRatio = size; update(); } ///< set size of point handles
|
||||
inline void setLineHandleWidth (unsigned int width ) { _lineHandleWidth = width; update(); } ///< set width of line handles
|
||||
|
||||
inline const QColor getDrawColor () const { return _drawColor; } ///< get color for general drawing
|
||||
inline const QColor getFillColor () const { return _fillColor; } ///< get color for general filling
|
||||
inline const QColor getHandleDrawColor() const { return _handleDrawColor; } ///< get color for drawing handles
|
||||
inline const QColor getHandleFillColor() const { return _handleFillColor; } ///< get color for filling handles
|
||||
inline const QColor getHandleSelectionColor() const { return _handleSelectionColor; } ///< get handle selection color
|
||||
inline const QColor getFrameColor() const { return _frameColor; } ///< get frame handle outline color
|
||||
inline const QColor getFrameFillColor() const { return _frameFillColor; } ///< get frame handle fill color
|
||||
inline int getFrameHandleMargin() const { return _frameHandleMargin; } ///< get margin of frame in pixel
|
||||
|
||||
inline unsigned int getPickingRatio() const { return _pickingRatio; } ///< get size of point handles
|
||||
/** @} */
|
||||
|
||||
bool applyAndEndAction ( AbstractEventDispatcher * causer, int x, int y ) override;
|
||||
bool abortAction ( AbstractEventDispatcher * causer, int x, int y ) override;
|
||||
|
||||
/**
|
||||
@name Set icons for rubberband buttons
|
||||
|
||||
In case of the application doesn't use the default rubberband icons other icons can be set with the setIcon functions. This redefine
|
||||
of the button icons have to be done before creating a rubberband.
|
||||
@{
|
||||
*/
|
||||
static void setIconApply( const QPixmap & );
|
||||
static void setIconAbort( const QPixmap & );
|
||||
static void setIconUndo ( const QPixmap & );
|
||||
|
||||
static void resetIconsToDefault();
|
||||
/** @} */
|
||||
|
||||
/**
|
||||
Start Rubberband mouse input automatically by program
|
||||
*/
|
||||
bool autoSelectAction( int x, int y );
|
||||
|
||||
/**
|
||||
If set to true the rubberband will send apply signal after leaving construction state and ends
|
||||
otherwise it continues in modification state. Default value is true.
|
||||
*/
|
||||
inline void enableFinishAfterConstruction(bool flag) { _finishAfterConstruction = flag; }
|
||||
|
||||
|
||||
/**
|
||||
Defines fixed widget position of rubberband button box
|
||||
*/
|
||||
void setFixedButtonBoxPosition( QPoint widgetPos );
|
||||
|
||||
|
||||
/**
|
||||
Undefines fixed widget position. The rubberband button box will be placed at the bottom right coner of
|
||||
the rubberbands bounding box.
|
||||
*/
|
||||
void unsetFixedButtonBoxPosition();
|
||||
|
||||
/**
|
||||
Returns true if a fixed widget position of rubberband button box is used.
|
||||
*/
|
||||
bool isButtonBoxPositionFixed();
|
||||
|
||||
/**
|
||||
@name EventHandlerInterface Methodes of AbstractEventDispatcher::EventActionInterface
|
||||
The interface between EventDispatcher and Rubberband are defined in class AbstractEventDispatcher.
|
||||
To Implement the interface these methodes have to be override again in the derived classes of the Rubberband class. */
|
||||
/**
|
||||
@{
|
||||
*/
|
||||
|
||||
bool buttonPositionAction ( AbstractEventDispatcher * causer, int x, int y ) override;
|
||||
|
||||
void unlinkEventDispatcher ( AbstractEventDispatcher * causer ) override;
|
||||
|
||||
/** @} */
|
||||
|
||||
|
||||
/**
|
||||
Returns true if the coordinates are valid elsewise false
|
||||
*/
|
||||
virtual bool coordinatesAreValid() const { return true; }
|
||||
|
||||
|
||||
/**
|
||||
Returns count of coordinates
|
||||
*/
|
||||
virtual unsigned int coordinateCount() const = 0;
|
||||
|
||||
/**
|
||||
Returns constructed or modified coordinates
|
||||
@param cs Defines the coordinate system of returned coordinates.
|
||||
*/
|
||||
virtual QVector<QPointF> coordinateVector( CoordinateSystem cs = CoordinateSystem::Geo ) const = 0;
|
||||
|
||||
/**
|
||||
Returns a single coordinate from rubberbands coordinate list
|
||||
@param idx index of coordinate
|
||||
@param cs Defines the coordinate system of returned coordinate.
|
||||
*/
|
||||
virtual QPointF singleCoordinate( unsigned int idx = 0, CoordinateSystem cs = CoordinateSystem::Geo ) const = 0;
|
||||
|
||||
/**
|
||||
Sets coordinates to modify to internal coordinate list
|
||||
|
||||
@param pntList List of coordinates to modify
|
||||
@param cs Defines the coordinate system of input coordinates.
|
||||
*/
|
||||
virtual void setCoordinateVector( const QVector<QPointF> & pntList, CoordinateSystem cs = CoordinateSystem::Geo ) = 0;
|
||||
|
||||
/**
|
||||
Set user defined informations to this rubberband
|
||||
*/
|
||||
inline void setUserData(void * p)
|
||||
{
|
||||
_userData = p;
|
||||
}
|
||||
|
||||
/**
|
||||
returns the user defined informations, which are set with methode userData(void*)
|
||||
*/
|
||||
inline void * userData() { return _userData; }
|
||||
|
||||
|
||||
/**
|
||||
Draw rubberband manually by calling the update function. In general it is not neccessary to call draw function.
|
||||
But in some cases, for example the color setting functions, the graphic view update will not be done automatically.
|
||||
Here calling draw forces an update of graphic view.
|
||||
*/
|
||||
inline void draw() { update(); }
|
||||
|
||||
|
||||
/**
|
||||
Sets call back function to realize an external update. The updateFunctor should return false to abort update process. In other case it have to return true.
|
||||
*/
|
||||
void installExternalUpdate(const std::function<bool(RubberbandBase*)> & updateFunctor);
|
||||
|
||||
|
||||
/**
|
||||
Returns true if there is a active rubberband on map.
|
||||
@param map Pointer to map
|
||||
*/
|
||||
static bool isRubberbandActive( SituationMap::Map * map );
|
||||
|
||||
/**
|
||||
Abort all active rubberbands on map.
|
||||
@param map Pointer to map
|
||||
*/
|
||||
static void abortActiveRubberbands( SituationMap::Map * map );
|
||||
|
||||
|
||||
protected:
|
||||
|
||||
Q_REQUIRED_RESULT QPointF projectCoordinateToMap( CoordinateSystem cs, const QPointF &loc ) const;
|
||||
Q_REQUIRED_RESULT QPointF projectCoordinateFromMap( CoordinateSystem cs, const QPointF & loc ) const;
|
||||
Q_REQUIRED_RESULT QPointF projectCoordinateFromMap( CoordinateSystem cs, const Esri::ArcGISRuntime::Point & loc ) const;
|
||||
|
||||
inline void doAutoDelete() { if (_autoDelete) deleteMySelf(); }
|
||||
|
||||
void updateButtonPosition();
|
||||
|
||||
QPointF pixel2ScenePosition( int x, int y ) const;
|
||||
|
||||
virtual void update() = 0;
|
||||
|
||||
void externalUpdate();
|
||||
|
||||
/*
|
||||
Forward declaration of internal container class for member variables. The derived classes of Rubberband
|
||||
often have also a declaration of InternalData for there own internal members.
|
||||
*/
|
||||
class BaseInternalData;
|
||||
|
||||
BaseInternalData *_baseInternal;
|
||||
|
||||
QColor _drawColor;
|
||||
QColor _fillColor;
|
||||
QColor _handleDrawColor;
|
||||
QColor _handleFillColor;
|
||||
QColor _handleSelectionColor;
|
||||
QColor _frameColor;
|
||||
QColor _frameFillColor;
|
||||
QColor _frameSelectionColor;
|
||||
int _frameHandleMargin;
|
||||
|
||||
unsigned int _lineHandleWidth;
|
||||
|
||||
unsigned int _pickingRatio;
|
||||
|
||||
bool _finishAfterConstruction;
|
||||
bool _autoDelete;
|
||||
|
||||
QPointer<EventDispatcher> _viewPortEventDispatcher;
|
||||
QPointer<EventDelegater> _windowEventDispatcher;
|
||||
|
||||
virtual QRectF sceneBbox() const = 0;
|
||||
|
||||
virtual void activateButtons();
|
||||
virtual void deactivateButtons();
|
||||
virtual void adjustButtons();
|
||||
virtual void applyButtonClicked();
|
||||
virtual void cancelButtonClicked();
|
||||
virtual void undoButtonClicked();
|
||||
|
||||
protected slots:
|
||||
|
||||
void onDo_applyButtonClicked() { applyButtonClicked(); }
|
||||
void onDo_cancelButtonClicked() { cancelButtonClicked(); }
|
||||
void onDo_undoButtonClicked() { undoButtonClicked(); }
|
||||
|
||||
void onDo_updateButtonFixCoordinates();
|
||||
|
||||
private:
|
||||
|
||||
void * _userData;
|
||||
|
||||
friend class RubberbandFactory;
|
||||
|
||||
static void * operator new(size_t);
|
||||
|
||||
/**
|
||||
The function \c allowMultipleRubberbands set a flag to allow new to create more than one rubberband
|
||||
per situation map for the next new operator call. The function is used in class RubberbandFactory. The
|
||||
value will be resetted to \c false at end of new operator.
|
||||
*/
|
||||
static void allowMultipleRubberbands( bool ok );
|
||||
|
||||
/**
|
||||
The function \c currentFactoryMap defines the calling situation map for the next new operator call. The
|
||||
function is used in class RubberbandFactory.The value will be resetted to \c nullptr at end of new operator.
|
||||
*/
|
||||
static void currentFactoryMap( SituationMap::Map * map );
|
||||
|
||||
|
||||
signals:
|
||||
|
||||
/**
|
||||
The abort signal will be emitted, when the abortAction has been called by one of the attached event handlers.
|
||||
Before emtting the signal the event handler are closed and deleted. To avoid memory leaks the application has to
|
||||
ensure that the delete function is called for this rubberband. See also example code at beginning.
|
||||
|
||||
@param rbnd pointer to this Rubberband
|
||||
*/
|
||||
void abort( RubberbandBase * rbnd );
|
||||
|
||||
/**
|
||||
The apply signal will be emitted, when the applyAndEndAction has been called by one of the attached event handler. The connected slot can now
|
||||
read the geometry information. Before emtting the signal the event handler are closed and deleted.To avoid memory leaks the application has to
|
||||
ensure that the delete function is called for this rubberband. See also example code at beginning.
|
||||
|
||||
@param rbnd pointer to this Rubberband.
|
||||
*/
|
||||
void apply( RubberbandBase * rbnd );
|
||||
|
||||
/**
|
||||
The finished signal will be emitted, when the rubberband is going to terminate and all user actions are done.
|
||||
|
||||
@param rbnd pointer to this Rubberband.
|
||||
*/
|
||||
void finished( RubberbandBase * rbnd );
|
||||
|
||||
/**
|
||||
The coordinatesChanged signal will be emitted , when the user has changed, removed or added coordinates. Can be used to implement
|
||||
a preview of interim results.
|
||||
*/
|
||||
void interimResultsChanged( RubberbandBase * rbnd );
|
||||
|
||||
}; /* Rubberband */
|
||||
|
||||
} } /* namespace SituationMap::RB */
|
||||
@@ -0,0 +1,118 @@
|
||||
/**
|
||||
**
|
||||
** @RDE_HEADER@
|
||||
** Definition of internal data of base class for rubberbands
|
||||
** $Id$
|
||||
** $HeadURL$
|
||||
** $Author$
|
||||
**
|
||||
** -----------------------------------------------------------------------------------------------
|
||||
**
|
||||
** Hardware-Environment: Intel-PC
|
||||
** Software-Environment: Windows 7, Qt 5.4. ArcGIS 10.2.5
|
||||
**
|
||||
** Language ........: C++ 11
|
||||
**
|
||||
** -----------------------------------------------------------------------------------------------
|
||||
**
|
||||
** Author ...........: Joerg Turla, SPD G, Tel. 3132
|
||||
**
|
||||
** -----------------------------------------------------------------------------------------------
|
||||
**
|
||||
** Notes .........:
|
||||
**
|
||||
** 16.06.2015, JT : First edition for use with Qt5
|
||||
**
|
||||
** -----------------------------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
|
||||
#include <QtCore/QList>
|
||||
#include <QtCore/QPointer>
|
||||
|
||||
#include <Common/ref_pointer.h>
|
||||
#include <Common/situation_map_logging.h>
|
||||
|
||||
#include "rubberband_base.h"
|
||||
|
||||
|
||||
|
||||
class QHBoxLayout;
|
||||
class QWidget;
|
||||
class QPushButton;
|
||||
class QGraphicsScene;
|
||||
class QGraphicsView;
|
||||
|
||||
|
||||
namespace Esri {
|
||||
namespace ArcGISRuntime {
|
||||
class MapGraphicsView;
|
||||
} }
|
||||
|
||||
|
||||
namespace SituationMap
|
||||
{
|
||||
class Map;
|
||||
}
|
||||
|
||||
namespace SituationMap { namespace RB
|
||||
{
|
||||
|
||||
class RubberbandHandleProxy;
|
||||
|
||||
/**
|
||||
@class Rubberband::BaseInternalData rubberband_base_internal.h
|
||||
@brief Definition of internal data of rubberband base class.
|
||||
*/
|
||||
class RubberbandBase::BaseInternalData
|
||||
{
|
||||
public:
|
||||
|
||||
static QPixmap * _applyIcon;
|
||||
static QPixmap * _abortIcon;
|
||||
static QPixmap * _undoIcon;
|
||||
|
||||
QPointer<SituationMap::Map> _map;
|
||||
|
||||
SituationMap::CoordTranslationFunctor * _mapCtFunctor;
|
||||
|
||||
bool _isActive;
|
||||
|
||||
bool _applyIsPossible;
|
||||
bool _undoIsPossible;
|
||||
bool _hasUndoButton;
|
||||
|
||||
QPointF _lastClickPosition;
|
||||
|
||||
QPointF _buttonBoxSceneAnchor;
|
||||
QPoint _buttonBoxFixPosition;
|
||||
SituationMap::RefPointer<RubberbandHandleProxy> _buttonProxy;
|
||||
QPointer<QWidget> _buttonBox;
|
||||
QHBoxLayout * _buttonLayout;
|
||||
QPushButton * _undoButton;
|
||||
QPushButton * _cancelButton;
|
||||
QPushButton * _applyButton;
|
||||
|
||||
QCursor _restoreCursor; // workaround Qt bug. remove when fixed
|
||||
|
||||
QVector<std::function<bool(RubberbandBase*)>> _updateFunctorList;
|
||||
|
||||
LOGGER_T _logger;
|
||||
|
||||
explicit BaseInternalData( SituationMap::Map * map, RubberbandBase * me );
|
||||
|
||||
virtual ~BaseInternalData();
|
||||
|
||||
bool buttonProxyActive( const QPointF & pos ) const;
|
||||
|
||||
void enableAndShowOnlyPossibleButtons();
|
||||
|
||||
BaseInternalData( const BaseInternalData & ) = delete;
|
||||
BaseInternalData & operator = ( const BaseInternalData & ) = delete;
|
||||
|
||||
}; /* BaseInternalData */
|
||||
|
||||
|
||||
} } /* namespace SituationMap::RB */
|
||||
+991
@@ -0,0 +1,991 @@
|
||||
|
||||
/**
|
||||
**
|
||||
** @RDE_HEADER@
|
||||
** Implementation of rubberband class to define multi point feature geoemtry
|
||||
** $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 .........:
|
||||
**
|
||||
** 17.06.2015, JT : First edition for use with Qt5
|
||||
**
|
||||
** -----------------------------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
#include "rubberband_corridor.h"
|
||||
#include "rubberband_drawable.h"
|
||||
#include "rubberband_frame_handle.h"
|
||||
#include "rubberband_handle_proxy.h"
|
||||
#include "rubberband_line_handle.h"
|
||||
#include "rubberband_point_handle.h"
|
||||
|
||||
#include "drawable_painter_path.h"
|
||||
|
||||
#include "rubberband_internal.h"
|
||||
#include "rubberband_base_internal.h"
|
||||
|
||||
#include <MathUtils/clipper.hpp>
|
||||
|
||||
#include <arcgis/Map.h>
|
||||
#include <arcgis/MapGraphicsView.h>
|
||||
|
||||
|
||||
namespace SituationMap { namespace RB
|
||||
{
|
||||
|
||||
struct RubberbandCorridor::InternalData
|
||||
{
|
||||
SituationMap::RefPointer<RubberbandPointHandle> _widthHandle;
|
||||
qreal _corridorSceneWidth = 0.0;
|
||||
SituationMap::RefPointer<RubberbandLineHandle> _widthLine;
|
||||
SituationMap::RefPointer<DrawablePainterPath> _geoBufferItem;
|
||||
SituationMap::RefPointer<DrawablePainterPath> _centerLineItem;
|
||||
QRectF _sceneBbox;
|
||||
|
||||
}; /* class RubberbandCorridor::InternalData */
|
||||
|
||||
|
||||
RubberbandCorridor::RubberbandCorridor( SituationMap::Map * map, QObject * parent ) : RubberbandCorridor( map, InputMode::InputBoundary, 0, parent ) {;}
|
||||
|
||||
|
||||
RubberbandCorridor::RubberbandCorridor( SituationMap::Map * map, InputMode mode, qreal width, QObject * parent )
|
||||
: RubberbandMultiPointFeature(map, false, parent) // Map*, bool complexGeometry, QObject* parent
|
||||
, _internal(new InternalData)
|
||||
, _inputMode(mode)
|
||||
, _corridorWidth(width)
|
||||
, _minimumCorridorWidth( 0.0 )
|
||||
, _maximumCorridorWidth( std::numeric_limits<qreal>::infinity() )
|
||||
, _corridorBorderColor("black")
|
||||
, _corridorFillColor("yellow")
|
||||
{
|
||||
_corridorFillColor.setAlphaF( 0.5 );
|
||||
_isClosed = false;
|
||||
|
||||
setCheckMaxAngle(160.0 / 180.0*M_PI); // restrict angle between line segments
|
||||
} /* RubberbandCorridor::RubberbandCorridor */
|
||||
|
||||
|
||||
RubberbandCorridor::~RubberbandCorridor()
|
||||
{
|
||||
delete _internal;
|
||||
_internal = nullptr;
|
||||
} /* RubberbandCorridor::~RubberbandCorridor */
|
||||
|
||||
|
||||
void RubberbandCorridor::minimumCorridorWidth( qreal min )
|
||||
{
|
||||
min = fabs(min);
|
||||
if (min < _maximumCorridorWidth)
|
||||
{
|
||||
_minimumCorridorWidth = min;
|
||||
if ((_minimumCorridorWidth) > _corridorWidth)
|
||||
{
|
||||
_corridorWidth = _minimumCorridorWidth;
|
||||
constructWidthHandle();
|
||||
}
|
||||
}
|
||||
} /* RubberbandCorridor::minimumCorridorWidth */
|
||||
|
||||
|
||||
void RubberbandCorridor::maximumCorridorWidth( qreal max )
|
||||
{
|
||||
max = fabs(max);
|
||||
if (max > _minimumCorridorWidth)
|
||||
{
|
||||
_maximumCorridorWidth = max;
|
||||
if ((_maximumCorridorWidth) < _corridorWidth)
|
||||
{
|
||||
_corridorWidth = _maximumCorridorWidth;
|
||||
constructWidthHandle();
|
||||
}
|
||||
}
|
||||
} /* RubberbandCorridor::maximumCorridorWidth */
|
||||
|
||||
|
||||
bool RubberbandCorridor::isEnabledConstructionWidthState() const
|
||||
{
|
||||
return _state.testFlag( RubberbandState::ConstructionWidthState );
|
||||
} /* RubberbandCorridor::isEnabledConstructionWidthState */
|
||||
|
||||
void RubberbandCorridor::enableConstructionWidthState()
|
||||
{
|
||||
_state &= ~QFlags<RubberbandState>(RubberbandState::ModificationState);
|
||||
_state |= RubberbandState::ConstructionWidthState;
|
||||
} /* RubberbandCorridor::enableConstructionWidthState */
|
||||
|
||||
void RubberbandCorridor::disenableConstructionWidthState()
|
||||
{
|
||||
_state &= ~QFlags<RubberbandState>(RubberbandState::ConstructionWidthState);
|
||||
_state |= RubberbandState::ModificationState;
|
||||
} /* RubberbandCorridor::disenableConstructionWidthState */
|
||||
|
||||
|
||||
qreal RubberbandCorridor::corridorWidth() const
|
||||
{
|
||||
return _corridorWidth;
|
||||
} /* RubberbandCorridor::corridorWidth */
|
||||
|
||||
|
||||
void RubberbandCorridor::setCoordinateVector(const QVector<QPointF> & coordinateVec, CoordinateSystem cs )
|
||||
{
|
||||
setCoordinateVectorWidth( coordinateVec, 0.0, cs );
|
||||
} /* RubberbandCorridor::setCoordinateVector */
|
||||
|
||||
|
||||
void RubberbandCorridor::setCoordinateVectorWidth(const QVector<QPointF> & coordinateVec, qreal corridorWidth, CoordinateSystem cs )
|
||||
{
|
||||
if (coordinateVec.size() < 2) return;
|
||||
|
||||
if (corridorWidth < 0)
|
||||
{
|
||||
QVector<QPointF> reverseVec;
|
||||
reverseVec.reserve(coordinateVec.size());
|
||||
for (const auto &point : coordinateVec)
|
||||
{
|
||||
reverseVec.push_front(point);
|
||||
}
|
||||
RubberbandMultiPointFeature::setCoordinateVector(reverseVec, cs);
|
||||
}
|
||||
else RubberbandMultiPointFeature::setCoordinateVector( coordinateVec, cs );
|
||||
|
||||
_corridorWidth = fabs(corridorWidth);
|
||||
|
||||
enableModificationState();
|
||||
constructWidthHandle();
|
||||
|
||||
_baseInternal->_applyIsPossible = true;
|
||||
|
||||
activateButtons();
|
||||
update();
|
||||
|
||||
} /* RubberbandCorridor::setCoordinateVectorWidth */
|
||||
|
||||
|
||||
|
||||
QVector<QPointF> RubberbandCorridor::centerLine( CoordinateSystem cs )
|
||||
{
|
||||
if (_inputMode == InputMode::InputCenterLine)
|
||||
{
|
||||
return RubberbandMultiPointFeature::coordinateVector( cs );
|
||||
}
|
||||
|
||||
QVector<QPointF> cLine;
|
||||
QVector<QPointF> cLineRet;
|
||||
|
||||
// getCenterLineFromHandleBorder( cLine, _corridorWidth * ((_internal->_corridorSceneWidth >= 0) ? 0.5 : -0.5), true );
|
||||
getCenterLineFromHandleBorder( cLine, _corridorWidth * 0.5, true );
|
||||
cLineRet.reserve(cLine.size());
|
||||
for (const auto &point : qAsConst(cLine))
|
||||
cLineRet.push_back(projectCoordinateFromMap( cs, point ));
|
||||
return cLineRet;
|
||||
} /* RubberbandCorridor::centerLine */
|
||||
|
||||
|
||||
void RubberbandCorridor::setCenterLine( const QVector<QPointF> & coordinateVec, qreal corridorWidth, CoordinateSystem cs )
|
||||
{
|
||||
if (_inputMode == InputMode::InputBoundary)
|
||||
{
|
||||
const QVector<QPointF> &borderLine = getCenterLineFromBorder( coordinateVec, corridorWidth*-0.5,cs);
|
||||
setCoordinateVectorWidth( borderLine, corridorWidth, CoordinateSystem::Map);
|
||||
return;
|
||||
}
|
||||
|
||||
setCoordinateVectorWidth( coordinateVec, corridorWidth, cs );
|
||||
} /* RubberbandCorridor::setCenterLine */
|
||||
|
||||
|
||||
QVector<QPointF> RubberbandCorridor::frontLine(CoordinateSystem cs)
|
||||
{
|
||||
if (_inputMode == InputMode::InputBoundary)
|
||||
{
|
||||
const QVector<QPointF> & fLine = RubberbandMultiPointFeature::coordinateVector(cs);
|
||||
if (_internal->_corridorSceneWidth >= 0) return fLine;
|
||||
// reverse order of coordinates
|
||||
QVector<QPointF> fLineRet;
|
||||
fLineRet.reserve(fLine.size());
|
||||
for (const auto & point : fLine)
|
||||
{
|
||||
fLineRet.push_front(point);
|
||||
}
|
||||
return fLineRet;
|
||||
}
|
||||
|
||||
// In case of InputMode::InputCenterLine construct centerLine
|
||||
|
||||
QVector<QPointF> fLine;
|
||||
getCenterLineFromHandleBorder(fLine, _corridorWidth*-1.0, true);
|
||||
|
||||
if (_internal->_corridorSceneWidth >= 0)
|
||||
{
|
||||
for (QPointF & point : fLine)
|
||||
{
|
||||
point = projectCoordinateFromMap(cs, point);
|
||||
}
|
||||
return fLine;
|
||||
}
|
||||
|
||||
// reverse order of coordinates
|
||||
QVector<QPointF> fLineRet;
|
||||
fLineRet.reserve(fLine.size());
|
||||
for (const auto & point : qAsConst(fLine))
|
||||
{
|
||||
fLineRet.push_front( projectCoordinateFromMap(cs,point) );
|
||||
}
|
||||
|
||||
return fLineRet;
|
||||
|
||||
} /* RubberbandCorridor::frontLine */
|
||||
|
||||
|
||||
void RubberbandCorridor::setFrontLine(const QVector<QPointF> & coordinateVec, qreal corridorWidth, CoordinateSystem cs)
|
||||
{
|
||||
if (_inputMode == InputMode::InputBoundary)
|
||||
{
|
||||
setCoordinateVectorWidth(coordinateVec, corridorWidth, cs);
|
||||
}
|
||||
|
||||
// In case of InputMode::InputCenterLine construct centerLine
|
||||
|
||||
const QVector<QPointF> ¢erLine = getCenterLineFromBorder( coordinateVec, corridorWidth*0.5, cs);
|
||||
setCoordinateVectorWidth(centerLine, corridorWidth, CoordinateSystem::Map);
|
||||
|
||||
} /* RubberbandCorridor::setFrontLine */
|
||||
|
||||
|
||||
void RubberbandCorridor::constructWidth( const QPointF & scenePos )
|
||||
{
|
||||
if (Rubberband::_internal->_handleList.size() < 2) return;
|
||||
|
||||
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.y()-p1.y(), p1.x()-p0.x() );
|
||||
rv /= sqrt(rv.x()*rv.x()+rv.y()*rv.y());
|
||||
|
||||
QPointF pScene = scenePos - p1;
|
||||
|
||||
qreal scalarProduct = pScene.x()*rv.x() + pScene.y()*rv.y();
|
||||
|
||||
if (_inputMode == InputMode::InputCenterLine) scalarProduct *= 2;
|
||||
|
||||
_internal->_corridorSceneWidth = scalarProduct;
|
||||
|
||||
rv *= scalarProduct;
|
||||
|
||||
RubberbandHandle::RubberbandCoordinate pointW( Rubberband::_internal->_mapView, p1+rv );
|
||||
|
||||
rv = QPointF( pointW._mapCoordinate.x() - static_cast<RubberbandPointHandle*>(Rubberband::_internal->_handleList.end()[-1].get())->getCoordinate()._mapCoordinate.x()
|
||||
, pointW._mapCoordinate.y() - static_cast<RubberbandPointHandle*>(Rubberband::_internal->_handleList.end()[-1].get())->getCoordinate()._mapCoordinate.y() );
|
||||
|
||||
|
||||
// _corridorWidth = sqrt(rv.x()*rv.x()+rv.y()*rv.y());
|
||||
_corridorWidth = (scalarProduct > 0 ) ? sqrt(rv.x()*rv.x()+rv.y()*rv.y()) : - sqrt(rv.x()*rv.x()+rv.y()*rv.y());
|
||||
|
||||
bool constrainsComplied = true;
|
||||
|
||||
if (_corridorWidth != 0.0)
|
||||
{
|
||||
qreal constraintFactor = 1.0;
|
||||
if (_minimumCorridorWidth > fabs(_corridorWidth)) { constraintFactor = _minimumCorridorWidth / _corridorWidth; constrainsComplied = false; }
|
||||
if (_maximumCorridorWidth < fabs(_corridorWidth)) { constraintFactor = _maximumCorridorWidth / fabs(_corridorWidth); constrainsComplied = false; }
|
||||
_corridorWidth *= constraintFactor;
|
||||
_internal->_corridorSceneWidth *= constraintFactor;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (_minimumCorridorWidth > 0)
|
||||
{
|
||||
_corridorWidth = _minimumCorridorWidth;
|
||||
|
||||
const QPointF & whp = calcWidthHandlePosition();
|
||||
Esri::ArcGISRuntime::MapGraphicsView * mapView = Rubberband::_internal->_mapView;
|
||||
RubberbandDrawable::RubberbandCoordinate widthCoordinate( mapView, convert( whp, mapView->map()->spatialReference() ));
|
||||
|
||||
const QPointF & p0 = static_cast<RubberbandPointHandle*>(Rubberband::_internal->_handleList.end()[-1].get())->getCoordinate()._sceneCoordinate;
|
||||
const QPointF & p1 = widthCoordinate._sceneCoordinate;
|
||||
|
||||
QPointF rv( p0.y()-p1.y(), p1.x()-p0.x() );
|
||||
|
||||
_internal->_corridorSceneWidth = sqrt(rv.x()*rv.x()+rv.y()*rv.y());
|
||||
if (_inputMode == InputMode::InputCenterLine) _internal->_corridorSceneWidth *= 2;
|
||||
}
|
||||
}
|
||||
|
||||
markFailedConstrains( scenePos, !constrainsComplied );
|
||||
|
||||
} /* RubberbandCorridor::constructWidth */
|
||||
|
||||
|
||||
QPointF RubberbandCorridor::getWidthHandleScenePosition() const
|
||||
{
|
||||
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.y()-p1.y(), p1.x()-p0.x() );
|
||||
|
||||
rv /= sqrt(rv.x()*rv.x()+rv.y()*rv.y());
|
||||
|
||||
if ((std::numeric_limits<qreal>::infinity() != rv.x()) && (std::numeric_limits<qreal>::infinity() != rv.y()))
|
||||
{
|
||||
rv *= _internal->_corridorSceneWidth;
|
||||
if (_inputMode == InputMode::InputCenterLine) rv *= 0.5;
|
||||
return p1 + rv;
|
||||
}
|
||||
return p1;
|
||||
|
||||
} /* RubberbandCorridor::getWidthHandleScenePosition */
|
||||
|
||||
|
||||
QPointF RubberbandCorridor::calcWidthHandlePosition()
|
||||
{
|
||||
qreal p0X = static_cast<RubberbandPointHandle*>(Rubberband::_internal->_handleList.end()[-2].get())->getCoordinate()._mapCoordinate.x();
|
||||
qreal p0Y = static_cast<RubberbandPointHandle*>(Rubberband::_internal->_handleList.end()[-2].get())->getCoordinate()._mapCoordinate.y();
|
||||
qreal p1X = static_cast<RubberbandPointHandle*>(Rubberband::_internal->_handleList.end()[-1].get())->getCoordinate()._mapCoordinate.x();
|
||||
qreal p1Y = static_cast<RubberbandPointHandle*>(Rubberband::_internal->_handleList.end()[-1].get())->getCoordinate()._mapCoordinate.y();
|
||||
|
||||
QPointF p( p1Y-p0Y, p1X-p0X );
|
||||
qreal lp = _corridorWidth / sqrt(p.x()*p.x()+p.y()*p.y());
|
||||
|
||||
if (std::numeric_limits<qreal>::infinity() != lp)
|
||||
{
|
||||
p *= lp;
|
||||
if (_inputMode == InputMode::InputCenterLine) p *= 0.5;
|
||||
p = QPointF(p1X,p1Y) + p;
|
||||
}
|
||||
else p = QPointF(p1X,p1Y);
|
||||
return p;
|
||||
} /* RubberbandCorridor::calcWidthHandlePosition */
|
||||
|
||||
|
||||
void RubberbandCorridor::constructWidthHandle()
|
||||
{
|
||||
if (Rubberband::_internal->_handleList.size() < 2) return;
|
||||
|
||||
if ((fabs(_corridorWidth) <= _minimumCorridorWidth) || (fabs(_corridorWidth) >= _maximumCorridorWidth))
|
||||
{
|
||||
enableConstructionWidthState();
|
||||
deactivateButtons();
|
||||
}
|
||||
|
||||
const QPointF & p = calcWidthHandlePosition();
|
||||
const Esri::ArcGISRuntime::Point mapP( convert(p, Rubberband::_internal->_mapView->map()->spatialReference()) );
|
||||
|
||||
_internal->_widthHandle = new RubberbandPointHandle( Rubberband::_internal->_mapView, Rubberband::_internal->_mapScene, mapP );
|
||||
|
||||
qreal pX = static_cast<RubberbandPointHandle*>(Rubberband::_internal->_handleList.end()[-1].get())->getCoordinate()._mapCoordinate.x();
|
||||
qreal pY = static_cast<RubberbandPointHandle*>(Rubberband::_internal->_handleList.end()[-1].get())->getCoordinate()._mapCoordinate.y();
|
||||
|
||||
_internal->_widthLine = new RubberbandLineHandle( Rubberband::_internal->_mapView, Rubberband::_internal->_mapScene, QPointF(pX,pY), p, 2, true );
|
||||
|
||||
pX = static_cast<RubberbandPointHandle*>(Rubberband::_internal->_handleList.end()[-1].get())->getCoordinate()._sceneCoordinate.x();
|
||||
pY = static_cast<RubberbandPointHandle*>(Rubberband::_internal->_handleList.end()[-1].get())->getCoordinate()._sceneCoordinate.y();
|
||||
|
||||
const QPointF & pScene = _internal->_widthHandle->getCoordinate()._sceneCoordinate;
|
||||
|
||||
pX -= pScene.x();
|
||||
pY -= pScene.y();
|
||||
|
||||
_internal->_corridorSceneWidth = sqrt(pX*pX+pY*pY);
|
||||
if (_inputMode == InputMode::InputCenterLine) _internal->_corridorSceneWidth *= 2;
|
||||
|
||||
// connect signal to call updateBufferGeometry when zooming or resizing the window
|
||||
// connect( _internal->_widthHandle.get(), &RubberbandHandle::adjusted, [this]() { this->updateBufferGeometry(); } );
|
||||
// doesn't work because not all handles are adjusted this time ...
|
||||
|
||||
// but we have to ensure that coordinateSceneWidth have all ways the correct value:
|
||||
connect( _internal->_widthHandle.get(), &RubberbandHandle::adjusted, this, &RubberbandCorridor::onDo_adjustCorridorSceneWidth );
|
||||
|
||||
} /* RubberbandCorridor::constructWidthHandle */
|
||||
|
||||
|
||||
void RubberbandCorridor::onDo_adjustCorridorSceneWidth()
|
||||
{
|
||||
if (Rubberband::_internal->_handleList.size() > 1)
|
||||
{
|
||||
qreal pX = static_cast<RubberbandPointHandle*>(this->Rubberband::_internal->_handleList.end()[-1].get())->getCoordinate()._sceneCoordinate.x();
|
||||
qreal pY = static_cast<RubberbandPointHandle*>(this->Rubberband::_internal->_handleList.end()[-1].get())->getCoordinate()._sceneCoordinate.y();
|
||||
const QPointF & pScene = this->_internal->_widthHandle->getCoordinate()._sceneCoordinate;
|
||||
|
||||
pX -= pScene.x();
|
||||
pY -= pScene.y();
|
||||
|
||||
qreal sceneWidth = sqrt(pX*pX+pY*pY);
|
||||
if (_inputMode == InputMode::InputCenterLine) sceneWidth *= 2;
|
||||
|
||||
_internal->_corridorSceneWidth = (_internal->_corridorSceneWidth >= 0) ? sceneWidth : -sceneWidth;
|
||||
}
|
||||
} /* RubberbandCorridor::onDo_adjustCorridorSceneWidth */
|
||||
|
||||
|
||||
void RubberbandCorridor::updateHandleScenePosition()
|
||||
{
|
||||
if (!_internal->_widthHandle) return;
|
||||
|
||||
QPointF pos = getWidthHandleScenePosition();
|
||||
|
||||
DEBUG_LOG(Rubberband::_internal->_logger) << LOGFUNCTION << " old handle Position = " << _internal->_widthHandle->getCoordinate()._sceneCoordinate.x()
|
||||
<< " ; " << _internal->_widthHandle->getCoordinate()._sceneCoordinate.y()
|
||||
<< " new handle position = " << pos.x() << " ; " << pos.y()
|
||||
<< " width = " << _corridorWidth
|
||||
<< " scene width = " << _internal->_corridorSceneWidth;
|
||||
|
||||
_internal->_widthHandle->updateCoordinate( pos );
|
||||
|
||||
const QPointF & lp1 = static_cast<RubberbandPointHandle*>(Rubberband::_internal->_handleList.end()[-1].get())->getCoordinate()._sceneCoordinate;
|
||||
|
||||
_internal->_widthLine->updateCoordinate( 0, lp1 );
|
||||
_internal->_widthLine->updateCoordinate( 1, pos );
|
||||
|
||||
} /* RubberbandCorridor::updateHandleScenePosition */
|
||||
|
||||
|
||||
bool RubberbandCorridor::getCenterLineFromHandleBorder( QVector<QPointF> & centerLine, qreal corridorWidth, bool mapCoordinates )
|
||||
{
|
||||
ClipperLib::ClipperOffset pathOffset;
|
||||
ClipperLib::Path borderPath;
|
||||
ClipperLib::Path offsetPath;
|
||||
int precision = (mapCoordinates) ? 1000 : 10;
|
||||
qreal baseX = 0.0;
|
||||
qreal baseY = 0.0;
|
||||
bool initBase = true;
|
||||
|
||||
for (auto handle : qAsConst(Rubberband::_internal->_handleList))
|
||||
{
|
||||
RubberbandPointHandle * pointHandlePtr = dynamic_cast<RubberbandPointHandle*>(handle.get());
|
||||
const RubberbandPointHandle::RubberbandCoordinate & pointCoordinate = pointHandlePtr->getCoordinate();
|
||||
|
||||
qreal x = (mapCoordinates) ? pointCoordinate._mapCoordinate.x() : pointCoordinate._sceneCoordinate.x();
|
||||
qreal y = (mapCoordinates) ? pointCoordinate._mapCoordinate.y() : -pointCoordinate._sceneCoordinate.y();
|
||||
|
||||
if (mapCoordinates)
|
||||
{
|
||||
// use relative coordinates to avoid to large numbers
|
||||
if (initBase)
|
||||
{
|
||||
baseX = x; baseY = y; x = 0.0; y = 0.0;
|
||||
initBase = false;
|
||||
}
|
||||
else { x -= baseX; y -= baseY; }
|
||||
}
|
||||
borderPath << ClipperLib::IntPoint(int(x*precision),int(y*precision));
|
||||
}
|
||||
|
||||
bool ok = pathOffset.PathOffset( borderPath, offsetPath, int(corridorWidth*precision) );
|
||||
|
||||
ClipperLib::Path::const_iterator it = offsetPath.begin();
|
||||
|
||||
if (mapCoordinates)
|
||||
{
|
||||
for (; it != offsetPath.end(); ++it)
|
||||
{
|
||||
centerLine << QPointF(qreal(it->X)/qreal(precision)+baseX, qreal(it->Y)/qreal(precision)+baseY);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for (; it != offsetPath.end(); ++it)
|
||||
{
|
||||
centerLine << QPointF(qreal(it->X)/qreal(precision)+baseX, qreal(-it->Y)/qreal(precision)-baseY);
|
||||
}
|
||||
}
|
||||
|
||||
return ok;
|
||||
} /* RubberbandCorridor::getCenterLineFromHandleBorder */
|
||||
|
||||
|
||||
QVector<QPointF> RubberbandCorridor::getCenterLineFromBorder(const QVector<QPointF> & borderLine, qreal corridorWidth, CoordinateSystem cs)
|
||||
{
|
||||
const int precision = 1000;
|
||||
|
||||
QVector<QPointF> centerLine;
|
||||
|
||||
ClipperLib::ClipperOffset pathOffset;
|
||||
ClipperLib::Path borderPath;
|
||||
ClipperLib::Path offsetPath;
|
||||
|
||||
qreal baseX = 0.0;
|
||||
qreal baseY = 0.0;
|
||||
bool initBase = true;
|
||||
|
||||
for (const auto &point : borderLine)
|
||||
{
|
||||
const QPointF & mapPoint = projectCoordinateToMap(cs, point);
|
||||
|
||||
qreal x = mapPoint.x();
|
||||
qreal y = mapPoint.y();
|
||||
|
||||
// use relative coordinates to avoid to large numbers
|
||||
if (initBase)
|
||||
{
|
||||
baseX = x; baseY = y; x = 0.0; y = 0.0;
|
||||
initBase = false;
|
||||
}
|
||||
else { x -= baseX; y -= baseY; }
|
||||
|
||||
borderPath << ClipperLib::IntPoint(int(x*precision), int(y*precision));
|
||||
}
|
||||
|
||||
if (pathOffset.PathOffset(borderPath, offsetPath, int(corridorWidth*precision)))
|
||||
{
|
||||
centerLine.reserve(100);
|
||||
for (const auto &p : offsetPath)
|
||||
{
|
||||
centerLine << QPointF( qreal(p.X)/qreal(precision)+baseX, qreal(p.Y)/qreal(precision)+baseY );
|
||||
}
|
||||
}
|
||||
return centerLine;
|
||||
} // RubberbandCorridor::getCenterLineFromBorder
|
||||
|
||||
|
||||
|
||||
void RubberbandCorridor::updateBufferGeometry()
|
||||
{
|
||||
if (!_internal->_widthHandle) return;
|
||||
|
||||
QVector<QPointF> centerLine;
|
||||
qreal corridorWidth = 0.0;
|
||||
bool centerLineOk = true;
|
||||
|
||||
centerLine.reserve(Rubberband::_internal->_handleList.size() );
|
||||
|
||||
switch (_inputMode)
|
||||
{
|
||||
case InputMode::InputBoundary:
|
||||
{
|
||||
corridorWidth = _internal->_corridorSceneWidth * 0.5;
|
||||
centerLineOk = getCenterLineFromHandleBorder( centerLine, corridorWidth, false );
|
||||
if (_internal->_centerLineItem == nullptr)
|
||||
{
|
||||
_internal->_centerLineItem = new DrawablePainterPath( Rubberband::_internal->_mapView );
|
||||
}
|
||||
_internal -> _centerLineItem -> setDrawColor( centerLineOk ? _drawColor : QColor(255,0,0) );
|
||||
_internal -> _centerLineItem -> setFillColor( QColor(0,0,0,0) ); // turn off filling
|
||||
_internal -> _centerLineItem -> dottedPath( centerLineOk );
|
||||
_internal -> _centerLineItem -> setVisibility( true );
|
||||
_internal -> _centerLineItem -> enableClosedLine( !centerLineOk );
|
||||
_internal -> _centerLineItem -> setPath( centerLine );
|
||||
|
||||
} break;
|
||||
|
||||
case InputMode::InputCenterLine:
|
||||
{
|
||||
corridorWidth = _internal->_corridorSceneWidth * 0.5;
|
||||
for (auto handle : qAsConst(Rubberband::_internal->_handleList))
|
||||
{
|
||||
RubberbandPointHandle * pointHandlePtr = dynamic_cast<RubberbandPointHandle*>(handle.get());
|
||||
const RubberbandPointHandle::RubberbandCoordinate & pointCoordinate = pointHandlePtr->getCoordinate();
|
||||
|
||||
qreal x = pointCoordinate._sceneCoordinate.x();
|
||||
qreal y = pointCoordinate._sceneCoordinate.y();
|
||||
|
||||
centerLine.append( QPointF(x,y) );
|
||||
}
|
||||
_internal -> _centerLineItem = nullptr;
|
||||
} break;
|
||||
}
|
||||
|
||||
ClipperLib::ClipperOffset pathOffset;
|
||||
ClipperLib::Path borderPath;
|
||||
ClipperLib::Paths offsetPathVec;
|
||||
QVector<RubberbandHandle::RubberbandCoordinate> vertexSet;
|
||||
|
||||
for (auto point : qAsConst(centerLine))
|
||||
borderPath << ClipperLib::IntPoint(int(point.x()*10),int(-point.y()*10));
|
||||
|
||||
pathOffset.AddPath( borderPath, ClipperLib::JoinType::jtSquare, ClipperLib::EndType::etOpenButt);
|
||||
pathOffset.Execute( offsetPathVec, int(fabs(corridorWidth)*10) );
|
||||
|
||||
if (centerLineOk)
|
||||
{
|
||||
if (_internal->_geoBufferItem) _internal->_geoBufferItem->setVisibility(false);
|
||||
|
||||
for (auto path : offsetPathVec)
|
||||
{
|
||||
ClipperLib::Path::const_iterator it = path.begin();
|
||||
|
||||
for (; it != path.end(); ++it)
|
||||
{
|
||||
vertexSet.append( RubberbandHandle::RubberbandCoordinate( Rubberband::_internal->_mapView
|
||||
, QPointF(qreal(it->X)/10.0,qreal(-it->Y)/10.0) ));
|
||||
}
|
||||
|
||||
if (!vertexSet.empty())
|
||||
{
|
||||
if (!_internal->_geoBufferItem)
|
||||
{
|
||||
_internal->_geoBufferItem = new DrawablePainterPath( Rubberband::_internal->_mapView );
|
||||
}
|
||||
|
||||
_internal -> _geoBufferItem -> setVisibility( true );
|
||||
_internal -> _geoBufferItem -> enableClosedLine( true );
|
||||
_internal -> _geoBufferItem -> setDrawColor( _corridorBorderColor );
|
||||
_internal -> _geoBufferItem -> setFillColor( _corridorFillColor );
|
||||
_internal -> _geoBufferItem -> setPath( vertexSet );
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
else if (_internal->_geoBufferItem) _internal->_geoBufferItem->setVisibility(false);
|
||||
|
||||
RubberbandFrameHandle * frameHandle = getFrameHandle();
|
||||
|
||||
if (frameHandle)
|
||||
{
|
||||
if (vertexSet.isEmpty())
|
||||
{
|
||||
for (auto handle : qAsConst(Rubberband::_internal->_handleList))
|
||||
{
|
||||
RubberbandPointHandle * pointHandlePtr = dynamic_cast<RubberbandPointHandle*>(handle.get());
|
||||
|
||||
vertexSet.append(pointHandlePtr->getCoordinate() );
|
||||
}
|
||||
|
||||
if (_internal->_widthHandle != nullptr)
|
||||
{
|
||||
vertexSet.append( _internal->_widthHandle->getCoordinate() );
|
||||
}
|
||||
}
|
||||
DEBUG_LOG(Rubberband::_internal->_logger) << LOGFUNCTION << " frameHandle->updateFrameShape( vertexSet );";
|
||||
frameHandle->updateFrameShape( vertexSet );
|
||||
}
|
||||
|
||||
if (!vertexSet.isEmpty())
|
||||
{
|
||||
qreal minX = vertexSet.first()._sceneCoordinate.x();
|
||||
qreal maxX = minX;
|
||||
qreal minY = vertexSet.first()._sceneCoordinate.y();
|
||||
qreal maxY = minY;
|
||||
|
||||
for (const auto &v : qAsConst(vertexSet))
|
||||
{
|
||||
const QPointF & p = v._sceneCoordinate;
|
||||
if (p.x() < minX) minX = p.x();
|
||||
if (p.y() < minY) minY = p.y();
|
||||
if (p.x() > maxX) maxX = p.x();
|
||||
if (p.y() > maxY) maxY = p.y();
|
||||
}
|
||||
_internal->_sceneBbox.setCoords( minX, minY, maxX, maxY );
|
||||
|
||||
if (!isButtonBoxPositionFixed())
|
||||
{
|
||||
RubberbandBase::_baseInternal->_buttonBoxSceneAnchor = QPointF(maxX,maxY);
|
||||
}
|
||||
}
|
||||
else _internal->_sceneBbox = QRectF();
|
||||
} /* RubberbandCorridor::updateBufferGeometry*/
|
||||
|
||||
|
||||
bool RubberbandCorridor::bufferPolygon( QVector<QPointF> & coordinateVec, CoordinateSystem cs )
|
||||
{
|
||||
coordinateVec.clear();
|
||||
|
||||
const QVector<QPointF> & cLine = centerLine( CoordinateSystem::Map );
|
||||
|
||||
if (cLine.size() < 2) return false;
|
||||
|
||||
ClipperLib::ClipperOffset pathOffset;
|
||||
ClipperLib::Path borderPath;
|
||||
ClipperLib::Paths offsetPathVec;
|
||||
int precision = 1000;
|
||||
const QPointF & basePoint = cLine.first();
|
||||
|
||||
for (const auto &point : cLine)
|
||||
{
|
||||
borderPath << ClipperLib::IntPoint(int((point.x()-basePoint.x())*precision),
|
||||
int((point.y()-basePoint.y())*precision));
|
||||
}
|
||||
|
||||
pathOffset.AddPath( borderPath, ClipperLib::JoinType::jtSquare, ClipperLib::EndType::etOpenButt);
|
||||
pathOffset.Execute( offsetPathVec, int(fabs(_corridorWidth*0.5)*precision) );
|
||||
|
||||
if (offsetPathVec.empty()) return false;
|
||||
|
||||
const ClipperLib::Path & bufferCoordinates = offsetPathVec.front();
|
||||
|
||||
if (bufferCoordinates.empty()) return false;
|
||||
|
||||
coordinateVec.reserve(bufferCoordinates.size());
|
||||
|
||||
for (const ClipperLib::IntPoint & p : bufferCoordinates)
|
||||
{
|
||||
const QPointF & vertex = QPointF( qreal(p.X)/qreal(precision), qreal(p.Y)/qreal(precision) ) + basePoint;
|
||||
coordinateVec << projectCoordinateFromMap( cs, vertex );
|
||||
}
|
||||
return true;
|
||||
} /* RubberbandCorridor::bufferPolygon */
|
||||
|
||||
|
||||
void RubberbandCorridor::resetAction(AbstractEventDispatcher * causer, int x, int y )
|
||||
{
|
||||
if (rubberbandIsAlive())
|
||||
{
|
||||
if (!isEnabledConstructionWidthState())
|
||||
{
|
||||
if (isEnabledConstructionState())
|
||||
{
|
||||
RubberbandMultiPointFeature::resetAction(causer,x,y);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
RubberbandMultiPointFeature::resetAction(causer,x,y);
|
||||
} /* RubberbandCorridor::resetAction */
|
||||
|
||||
|
||||
bool RubberbandCorridor::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 (!isEnabledConstructionWidthState())
|
||||
{
|
||||
if (isEnabledConstructionState()) return RubberbandMultiPointFeature::selectAction(causer,x,y);
|
||||
if (_internal->_widthHandle->isPositionInside(scenePos))
|
||||
{
|
||||
_internal->_widthHandle->setSelection();
|
||||
eventHandled = true;
|
||||
}
|
||||
else return RubberbandMultiPointFeature::selectAction(causer,x,y);
|
||||
}
|
||||
else eventHandled = true;
|
||||
|
||||
|
||||
if (eventHandled)
|
||||
{
|
||||
update();
|
||||
deactivateButtons();
|
||||
}
|
||||
return eventHandled;
|
||||
} /* RubberbandCorridor::selectAction */
|
||||
|
||||
|
||||
bool RubberbandCorridor::setCoordinateAction(AbstractEventDispatcher * causer, int x, int y)
|
||||
{
|
||||
Q_UNUSED(causer);
|
||||
|
||||
markFailedConstrains( QPointF(), false );
|
||||
|
||||
if (!rubberbandIsAlive()) return false;
|
||||
|
||||
bool eventHandled = false;
|
||||
QPointF scenePos(pixel2ScenePosition(x,y));
|
||||
|
||||
if (isEnabledConstructionWidthState())
|
||||
{
|
||||
Rubberband::_internal->_lastClickPosition = scenePos;
|
||||
constructWidth( scenePos );
|
||||
updateHandleScenePosition();
|
||||
disenableConstructionWidthState();
|
||||
enableModificationState();
|
||||
eventHandled = true;
|
||||
markFailedConstrains( QPointF(), false );
|
||||
}
|
||||
else
|
||||
{
|
||||
if (isEnabledConstructionState())
|
||||
{
|
||||
bool handled = RubberbandMultiPointFeature::setCoordinateAction(causer,x,y);
|
||||
if (isEnabledConstructionWidthState())
|
||||
{
|
||||
// guarantee that buttons are of
|
||||
deactivateButtons();
|
||||
}
|
||||
return handled;
|
||||
}
|
||||
|
||||
if (_internal->_widthHandle->isSelected())
|
||||
{
|
||||
_internal->_widthHandle->setSelection(false);
|
||||
constructWidth( scenePos );
|
||||
markFailedConstrains( QPointF(), false );
|
||||
eventHandled = true;
|
||||
RubberbandMultiPointFeature::setCoordinateAction(causer,x,y);
|
||||
}
|
||||
else return RubberbandMultiPointFeature::setCoordinateAction(causer,x,y);
|
||||
}
|
||||
|
||||
if (eventHandled) update();
|
||||
|
||||
updateButtonPosition();
|
||||
|
||||
activateButtons();
|
||||
|
||||
return eventHandled;
|
||||
} /* RubberbandCorridor::setCoordinateAction */
|
||||
|
||||
|
||||
bool RubberbandCorridor::movePickedAction(AbstractEventDispatcher * causer, int x, int y )
|
||||
{
|
||||
adjustConnectedPreviewPixmap(x,y);
|
||||
|
||||
if (!rubberbandIsAlive()) return false;
|
||||
|
||||
if ((isEnabledConstructionWidthState()) || ((_internal->_widthHandle) && (_internal->_widthHandle->isSelected())))
|
||||
{
|
||||
QPointF scenePos(pixel2ScenePosition(x,y));
|
||||
|
||||
constructWidth( scenePos );
|
||||
update();
|
||||
return false;
|
||||
}
|
||||
|
||||
return RubberbandMultiPointFeature::movePickedAction(causer,x,y);
|
||||
|
||||
} /* RubberbandCorridor::movePickedAction */
|
||||
|
||||
|
||||
bool RubberbandCorridor::moveAction(AbstractEventDispatcher * causer, int x, int y)
|
||||
{
|
||||
adjustConnectedPreviewPixmap(x,y);
|
||||
|
||||
QPointF scenePos(pixel2ScenePosition(x,y));
|
||||
|
||||
if (isEnabledConstructionWidthState())
|
||||
{
|
||||
constructWidth( scenePos );
|
||||
update();
|
||||
return false;
|
||||
}
|
||||
|
||||
if (_internal->_widthHandle)
|
||||
{
|
||||
if (_internal->_widthHandle->isPositionInside(scenePos))
|
||||
{
|
||||
_internal->_widthHandle->setSelection(true);
|
||||
return true;
|
||||
}
|
||||
_internal->_widthHandle->setSelection(false);
|
||||
}
|
||||
return RubberbandMultiPointFeature::moveAction(causer,x,y);
|
||||
} /* RubberbandCorridor::moveAction */
|
||||
|
||||
|
||||
bool RubberbandCorridor::completeStateAction(AbstractEventDispatcher * causer, int x, int y)
|
||||
{
|
||||
if ((rubberbandIsAlive()) && (Rubberband::_internal->_mapView) && (Rubberband::_internal->_mapScene))
|
||||
{
|
||||
if (isEnabledConstructionWidthState())
|
||||
{
|
||||
if (!_finishAfterConstruction)
|
||||
{
|
||||
disenableSelectedState();
|
||||
enableModificationState();
|
||||
update();
|
||||
return true;
|
||||
}
|
||||
}
|
||||
if (isEnabledConstructionState())
|
||||
{
|
||||
if ((unsigned int)Rubberband::_internal->_handleList.size() >= _minimumPointCount)
|
||||
{
|
||||
disenableConstructionState();
|
||||
|
||||
if ((fabs(_corridorWidth) <= _minimumCorridorWidth) || (fabs(_corridorWidth) >= _maximumCorridorWidth))
|
||||
{
|
||||
enableConstructionWidthState();
|
||||
|
||||
deSelectHandles();
|
||||
disenableSelectedState();
|
||||
|
||||
deactivateButtons();
|
||||
|
||||
updatePreviewLine(QPointF(0,0));
|
||||
|
||||
constructWidth( static_cast<RubberbandPointHandle*>(Rubberband::_internal->_handleList.end()[-1].get())->getCoordinate()._sceneCoordinate );
|
||||
constructWidthHandle();
|
||||
|
||||
if (_internal->_widthHandle)
|
||||
{
|
||||
_internal->_widthHandle->setSelection(true);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (_finishAfterConstruction)
|
||||
{
|
||||
return applyAndEndAction(causer,x,y);
|
||||
}
|
||||
else
|
||||
{
|
||||
deSelectHandles();
|
||||
constructWidthHandle();
|
||||
disenableSelectedState();
|
||||
enableModificationState();
|
||||
}
|
||||
}
|
||||
}
|
||||
update();
|
||||
return true;
|
||||
}
|
||||
return applyAndEndAction(causer,x,y);
|
||||
}
|
||||
return false;
|
||||
} /* RubberbandCorridor::completeStateAction */
|
||||
|
||||
|
||||
void RubberbandCorridor::activateButtons()
|
||||
{
|
||||
if (isEnabledConstructionWidthState())
|
||||
{
|
||||
_baseInternal->_applyIsPossible = false;
|
||||
_baseInternal->_undoIsPossible = false;
|
||||
RubberbandMultiPointFeature::activateButtons();
|
||||
}
|
||||
else RubberbandMultiPointFeature::activateButtons();
|
||||
|
||||
} /* RubberbandCorridor::activateButtons */
|
||||
|
||||
|
||||
QRectF RubberbandCorridor::sceneBbox() const
|
||||
{
|
||||
if (_internal->_sceneBbox.isValid()) return _internal->_sceneBbox;
|
||||
else return Rubberband::sceneBbox();
|
||||
} /* RubberbandCorridor::sceneBbox */
|
||||
|
||||
|
||||
void RubberbandCorridor::update()
|
||||
{
|
||||
RubberbandMultiPointFeature::update();
|
||||
|
||||
DEBUG_LOG(Rubberband::_internal->_logger) << LOGFUNCTION;
|
||||
|
||||
_isClosed = false;
|
||||
|
||||
if (_internal->_widthHandle)
|
||||
{
|
||||
_internal->_widthHandle -> setDrawColor(_handleDrawColor);
|
||||
_internal->_widthHandle -> setFillColor(_handleFillColor);
|
||||
_internal->_widthHandle -> setSelectionColor(_handleSelectionColor);
|
||||
_internal->_widthHandle -> setPickingRatio( _pickingRatio );
|
||||
|
||||
updateHandleScenePosition();
|
||||
updateBufferGeometry();
|
||||
}
|
||||
|
||||
} /* RubberbandCorridor::update */
|
||||
|
||||
|
||||
} } /* namespace SituationMap::RB */
|
||||
+239
@@ -0,0 +1,239 @@
|
||||
/**
|
||||
**
|
||||
** @RDE_HEADER@
|
||||
** Definition of rubberband class to define multi point feature geoemtry
|
||||
** $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 .........:
|
||||
**
|
||||
** 17.06.2015, JT : First edition for use with Qt5
|
||||
**
|
||||
** -----------------------------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "rubberband_multi_point_feature.h"
|
||||
|
||||
|
||||
namespace SituationMap { namespace RB
|
||||
{
|
||||
/**
|
||||
@class RubberbandCorridor rubberband_corridor.h
|
||||
@brief Implementation of a rubberband for corridors.
|
||||
@see RubberbandFactory, Rubberband, RubberbandMultiPointFeature
|
||||
|
||||
Implementation of rubberbands used to input corridors. There are two different modes \c InputCenterLine and \c InputBoundary. In the
|
||||
InputCenterLine mode the center line of the corridor has to be defined. The rubberband displays then the border geometry.
|
||||
In the InputBoundary mode one side of the border has to be defined. The \c coordinateVector methodes always working on the input geometry.
|
||||
*/
|
||||
class SITUATIONMAP_EXPORT RubberbandCorridor : public RubberbandMultiPointFeature
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
|
||||
enum class InputMode
|
||||
{
|
||||
InputCenterLine,
|
||||
InputBoundary
|
||||
}; /* InputMethode */
|
||||
|
||||
|
||||
/**
|
||||
@name Construction & Destruction
|
||||
@{
|
||||
|
||||
Construction of one instance of class RubberbandCorridor.
|
||||
|
||||
@param map Pointer to SituationMap class instance
|
||||
@param mode Two mode are distinguished. In \c InputCenterLine mode the coordinates will be interpreted as center line of the corridor.
|
||||
In \c InputBoundary the coordinates are defining one border.
|
||||
@param width With of a corridor in meters. In \c InputBoundary the coordinates are defining one border. If \c corridorWidth is negative
|
||||
the coordinates are the right border otherwise the left one.
|
||||
*/
|
||||
|
||||
private:
|
||||
|
||||
friend class RubberbandFactory;
|
||||
|
||||
explicit RubberbandCorridor( SituationMap::Map * map, QObject * parent );
|
||||
explicit RubberbandCorridor( SituationMap::Map * map, InputMode mode = InputMode::InputBoundary, qreal width = 0, QObject * parent = nullptr );
|
||||
|
||||
|
||||
public:
|
||||
|
||||
~RubberbandCorridor();
|
||||
/** @} */
|
||||
|
||||
/**
|
||||
@addtogroup States Methodes to query and modify rubberband states
|
||||
@{
|
||||
*/
|
||||
bool isEnabledConstructionWidthState() const;
|
||||
void enableConstructionWidthState();
|
||||
void disenableConstructionWidthState();
|
||||
/** @} */
|
||||
|
||||
|
||||
|
||||
inline bool isEnabledInputBoundary() const { return _inputMode == InputMode::InputBoundary; }
|
||||
inline void setInputBoundary() { _inputMode = InputMode::InputBoundary; }
|
||||
inline void setInputCenterline() { _inputMode = InputMode::InputCenterLine; }
|
||||
|
||||
/**
|
||||
Sets coordinates to modify to internal coordinate list.
|
||||
|
||||
@param coordinateVec List of coordinates to modify
|
||||
@param cs Defines the coordinate system of returned coordinates.
|
||||
*/
|
||||
void setCoordinateVector( const QVector<QPointF> & coordinateVec, CoordinateSystem cs = CoordinateSystem::Geo ) override;
|
||||
|
||||
/**
|
||||
Sets coordinates to modify to internal coordinate list. In \c InputCenterLine mode the coordinates will be interpreted as
|
||||
center line of the corridor. In \c InputBoundary the coordinates are defining one border. If \c corridorWidth is negative
|
||||
the coordinates are the right border otherwise the left one.
|
||||
|
||||
@param coordinateVec List of coordinates to modify
|
||||
@param corridorWidth Width of corridor in meters.
|
||||
@param cs Defines the coordinate system of returned coordinates.
|
||||
*/
|
||||
void setCoordinateVectorWidth(const QVector<QPointF> & coordinateVec, qreal corridorWidth, CoordinateSystem cs = CoordinateSystem::Geo );
|
||||
|
||||
/**
|
||||
Returns the center line of the corridor
|
||||
|
||||
@param cs Defines the coordinate system of returned coordinates.
|
||||
*/
|
||||
QVector<QPointF> centerLine( CoordinateSystem cs = CoordinateSystem::Geo );
|
||||
|
||||
/**
|
||||
Sets the center line of the corridor.
|
||||
|
||||
@param coordinateVec List of coordinates of border to modify
|
||||
@param corridorWidth Width of corridor in meters
|
||||
@param cs Defines the coordinate system of returned coordinates.
|
||||
*/
|
||||
void setCenterLine( const QVector<QPointF> & coordinateVec, qreal corridorWidth, CoordinateSystem cs = CoordinateSystem::Geo );
|
||||
|
||||
/**
|
||||
Returns the front line of the rubberband.
|
||||
|
||||
@param cs Defines the coordinate system of returned coordinates.
|
||||
*/
|
||||
QVector<QPointF> frontLine(CoordinateSystem cs = CoordinateSystem::Geo);
|
||||
|
||||
/**
|
||||
Sets the front line of the corridor.
|
||||
|
||||
@param coordinateVec List of coordinates of border to modify
|
||||
@param corridorWidth Width of corridor in meters
|
||||
@param cs Defines the coordinate system of returned coordinates.
|
||||
*/
|
||||
void setFrontLine(const QVector<QPointF> & coordinateVec, qreal corridorWidth, CoordinateSystem cs = CoordinateSystem::Geo);
|
||||
|
||||
/**
|
||||
Provides the buffer polygon (outline) of the corridor.
|
||||
|
||||
@param coordinateVec Coordinate list of buffer polygon
|
||||
@param cs Defines the coordinate system of returned coordinates.
|
||||
@return true on success otherwise false
|
||||
*/
|
||||
bool bufferPolygon( QVector<QPointF> & coordinateVec, CoordinateSystem cs = CoordinateSystem::Geo );
|
||||
|
||||
/**
|
||||
Return the width of the corridor.
|
||||
*/
|
||||
qreal corridorWidth() const;
|
||||
|
||||
/**
|
||||
Set the width of the corridor.
|
||||
*/
|
||||
inline void setCorridorWidth(qreal width) { _corridorWidth = width;}
|
||||
|
||||
/**
|
||||
@name Constrains for corridor width
|
||||
@{
|
||||
*/
|
||||
void minimumCorridorWidth( qreal min );
|
||||
void maximumCorridorWidth( qreal max );
|
||||
|
||||
qreal minimumCorridorWidth() const { return _minimumCorridorWidth; }
|
||||
qreal maximumCorridorWidth() const { return _maximumCorridorWidth; }
|
||||
/** @} */
|
||||
|
||||
|
||||
bool selectAction ( AbstractEventDispatcher * causer, int x, int y ) override;
|
||||
bool setCoordinateAction ( AbstractEventDispatcher * causer, int x, int y ) override;
|
||||
bool movePickedAction ( AbstractEventDispatcher * causer, int x, int y ) override;
|
||||
bool moveAction ( AbstractEventDispatcher * causer, int x, int y ) override;
|
||||
void resetAction ( AbstractEventDispatcher * causer, int x, int y ) override;
|
||||
|
||||
bool completeStateAction ( AbstractEventDispatcher * causer, int x, int y ) override;
|
||||
|
||||
QColor getCorridorBorderColor() const { return _corridorBorderColor; }
|
||||
QColor getCorridorFillColor() const { return _corridorFillColor; }
|
||||
|
||||
void setCorridorBorderColor( const QColor & color ) { _corridorBorderColor = color; }
|
||||
void setCorridorFillColor ( const QColor & color ) { _corridorFillColor = color; }
|
||||
|
||||
protected:
|
||||
/*
|
||||
Forward declaration of InternalData to hold private member variables. Becareful the base class Rubberband
|
||||
has similary a class for internal data member with name "InternalData". Don't be confused it is not the same.
|
||||
*/
|
||||
struct InternalData;
|
||||
|
||||
InternalData * _internal;
|
||||
|
||||
InputMode _inputMode;
|
||||
qreal _corridorWidth;
|
||||
|
||||
qreal _minimumCorridorWidth;
|
||||
qreal _maximumCorridorWidth;
|
||||
|
||||
QColor _corridorBorderColor;
|
||||
QColor _corridorFillColor;
|
||||
|
||||
void activateButtons() override;
|
||||
|
||||
QRectF sceneBbox() const override;
|
||||
|
||||
void update() override;
|
||||
|
||||
QPointF calcWidthHandlePosition();
|
||||
|
||||
void constructWidth( const QPointF & );
|
||||
void constructWidthHandle();
|
||||
|
||||
QPointF getWidthHandleScenePosition() const;
|
||||
|
||||
bool getCenterLineFromHandleBorder(QVector<QPointF> & centerLine, qreal corridorWidth, bool mapCoordinates);
|
||||
|
||||
QVector<QPointF> getCenterLineFromBorder(const QVector<QPointF> & borderLine, qreal corridorWidth, CoordinateSystem cs );
|
||||
|
||||
void updateHandleScenePosition();
|
||||
void updateBufferGeometry();
|
||||
|
||||
private slots:
|
||||
|
||||
void onDo_adjustCorridorSceneWidth();
|
||||
|
||||
}; /* RubberbandCorridor */
|
||||
|
||||
} } /* namespace SituationMap::RB */
|
||||
+155
@@ -0,0 +1,155 @@
|
||||
|
||||
/**
|
||||
**
|
||||
** @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_drawable.h"
|
||||
|
||||
|
||||
// ESRI
|
||||
#include <arcgis/Map.h>
|
||||
|
||||
|
||||
|
||||
namespace SituationMap { namespace RB
|
||||
{
|
||||
|
||||
Esri::ArcGISRuntime::Point convert(const QPointF &point, const Esri::ArcGISRuntime::SpatialReference& spatialReference)
|
||||
{
|
||||
return Esri::ArcGISRuntime::Point(point.x(), point.y(), spatialReference);
|
||||
} // convert
|
||||
|
||||
|
||||
RubberbandDrawable::RubberbandDrawable( QGraphicsView * view )
|
||||
: _scene((view) ? view->scene() : nullptr)
|
||||
, _mapView()
|
||||
, _isVisible(true)
|
||||
, _lineWidth(1)
|
||||
, _zBufferValue((unsigned int) ZBufferPlane::Drawables)
|
||||
, _logger(getLogger("RubberbandDrawable"))
|
||||
|
||||
{
|
||||
doConnecting();
|
||||
} /* RubberbandDrawable::RubberbandDrawable */
|
||||
|
||||
RubberbandDrawable::RubberbandDrawable( Esri::ArcGISRuntime::MapGraphicsView * mapView )
|
||||
: _scene(mapView->scene())
|
||||
, _mapView(mapView)
|
||||
, _isVisible(true)
|
||||
, _lineWidth(1)
|
||||
, _zBufferValue((unsigned int) ZBufferPlane::Drawables)
|
||||
, _logger(getLogger("RubberbandDrawable"))
|
||||
|
||||
{
|
||||
doConnecting();
|
||||
} /* RubberbandDrawable::RubberbandDrawable */
|
||||
|
||||
RubberbandDrawable::RubberbandDrawable( Esri::ArcGISRuntime::MapGraphicsView * mapView, QGraphicsScene * scene)
|
||||
: _scene(scene)
|
||||
, _mapView(mapView)
|
||||
, _isVisible(true)
|
||||
, _lineWidth(1)
|
||||
, _zBufferValue((unsigned int) ZBufferPlane::Drawables)
|
||||
, _logger(getLogger("RubberbandDrawable"))
|
||||
|
||||
{
|
||||
doConnecting();
|
||||
} /* RubberbandDrawable::RubberbandDrawable */
|
||||
|
||||
|
||||
#ifdef ADJUST_COORDINATES_EVERY_PAINT_EVENT
|
||||
bool RubberbandDrawable::eventFilter( QObject*, QEvent * e )
|
||||
{
|
||||
if (e)
|
||||
{
|
||||
if (e->type() == QEvent::Paint)
|
||||
{
|
||||
/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
* Sometimes the signals extentChanges and rectChanged of Esri Map Widget are not emitted. In this case
|
||||
* the position update of handles and drawabled fails and they are drawn at wrong positions on map. As
|
||||
* workaround updates coordinates at every paint event.
|
||||
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
|
||||
DEBUG_LOG(_logger) << LOGFUNCTION << " paint event";
|
||||
onDo_adjustCoordinates();
|
||||
}
|
||||
}
|
||||
return false;
|
||||
} /* RubberbandDrawable::eventFilter */
|
||||
#endif
|
||||
|
||||
void RubberbandDrawable::doConnecting()
|
||||
{
|
||||
if (nullptr == _mapView) return;
|
||||
|
||||
#ifdef ADJUST_COORDINATES_EVERY_PAINT_EVENT
|
||||
_view -> installEventFilter( this );
|
||||
#endif
|
||||
|
||||
/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
* It is really important to specify the connnection type as following. Because the onDo_adjustCoordinates
|
||||
* should be call as soon as possible to get smooth changes of map. The connection type is DirectConnnection here.
|
||||
* The rectChanged signal is some times emitted, when the calculation of screen coordinates to map coordinates
|
||||
* and vice versa has not been updated to the new map window size. In this case all calculations provides wrong
|
||||
* results. Using the connection type QueuedConnection defers the call of onDo_adjustWindow.
|
||||
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
|
||||
// Check Quartz
|
||||
connect( _mapView.data(), &Esri::ArcGISRuntime::MapGraphicsView::viewpointChanged,
|
||||
this, &RubberbandDrawable::onDo_adjustCoordinates, Qt::ConnectionType::DirectConnection );
|
||||
connect( _mapView.data(), &Esri::ArcGISRuntime::MapGraphicsView::rectChanged ,
|
||||
this, &RubberbandDrawable::onDo_adjustWindow , Qt::ConnectionType::QueuedConnection );
|
||||
|
||||
} /* RubberbandDrawable::doConnecting */
|
||||
|
||||
|
||||
void RubberbandDrawable::onDo_adjustCoordinates()
|
||||
{
|
||||
adjustCoordinates();
|
||||
forceUpdateViewWidget();
|
||||
} /* RubberbandDrawable::onDo_adjustCoordinates */
|
||||
|
||||
|
||||
void RubberbandDrawable::onDo_adjustWindow( const QRectF &r )
|
||||
{
|
||||
adjustWindow(r);
|
||||
forceUpdateViewWidget();
|
||||
} /* RubberbandDrawable::onDo_adjustWindow */
|
||||
|
||||
|
||||
void RubberbandDrawable::makeLineStyle( bool dottedLine, QPen & lineStyle )
|
||||
{
|
||||
lineStyle.setColor( _drawColor );
|
||||
lineStyle.setWidth( int(_lineWidth) );
|
||||
|
||||
if (dottedLine) lineStyle.setStyle( Qt::DashDotLine );
|
||||
else lineStyle.setStyle( Qt::SolidLine );
|
||||
} /* DrawablePainterPathItem::makeLineStyle */
|
||||
|
||||
|
||||
RubberbandDrawable::~RubberbandDrawable() { if (_mapView) _mapView->removeEventFilter(this); }
|
||||
|
||||
|
||||
} } /* namespace SituationMap::RB */
|
||||
+212
@@ -0,0 +1,212 @@
|
||||
/**
|
||||
**
|
||||
** @RDE_HEADER@
|
||||
** Definition of base class for rubberband drawing objects
|
||||
** $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
|
||||
**
|
||||
** -----------------------------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
|
||||
#include <QtCore/QObject>
|
||||
|
||||
#include <QtGui/QColor>
|
||||
|
||||
#include <arcgis/MapGraphicsView.h>
|
||||
#include <arcgis/Point.h>
|
||||
|
||||
#include <Common/referenced.h>
|
||||
#include <Common/situation_map_logging.h>
|
||||
|
||||
|
||||
class QGraphicsScene;
|
||||
|
||||
namespace SituationMap { namespace RB
|
||||
{
|
||||
|
||||
Esri::ArcGISRuntime::Point convert(const QPointF &point, const Esri::ArcGISRuntime::SpatialReference& spatialReference);
|
||||
|
||||
|
||||
|
||||
/**
|
||||
@class RubberbandDrawable rubberband_drawable.h
|
||||
@brief Base class of all rubberband drawables and handles for rubberband internal use.
|
||||
*/
|
||||
class RubberbandDrawable : public QObject, public SituationMap::Referenced
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
|
||||
enum class ZBufferPlane
|
||||
{
|
||||
FrameHandle = 10,
|
||||
Drawables = 20,
|
||||
LineHandle = 30,
|
||||
ArrowSymbol = 31,
|
||||
PointHandle = 40,
|
||||
Widget = 100
|
||||
}; /* InputMethode */
|
||||
|
||||
|
||||
/**
|
||||
Manages scene and map coordinates.
|
||||
*/
|
||||
struct RubberbandCoordinate
|
||||
{
|
||||
QPointF _sceneCoordinate;
|
||||
Esri::ArcGISRuntime::Point _mapCoordinate;
|
||||
|
||||
|
||||
RubberbandCoordinate()
|
||||
{}
|
||||
|
||||
explicit RubberbandCoordinate( const QPointF & sceneCoordinate)
|
||||
{
|
||||
updateSceneCoordinate( sceneCoordinate );
|
||||
} /* RubberbandCoordinate */
|
||||
|
||||
explicit RubberbandCoordinate( Esri::ArcGISRuntime::MapGraphicsView * mapView, const QPointF & sceneCoordinate)
|
||||
{
|
||||
updateSceneCoordinate( mapView, sceneCoordinate );
|
||||
} /* RubberbandCoordinate */
|
||||
|
||||
|
||||
explicit RubberbandCoordinate( Esri::ArcGISRuntime::MapGraphicsView * mapView, const Esri::ArcGISRuntime::Point & mapCoordinate)
|
||||
: _mapCoordinate(mapCoordinate)
|
||||
{
|
||||
mapToScene( mapView );
|
||||
} /* RubberbandCoordinate */
|
||||
|
||||
|
||||
inline QPointF mapToScene(Esri::ArcGISRuntime::MapGraphicsView * mapView)
|
||||
{
|
||||
if (!_mapCoordinate.isValid())
|
||||
return QPointF();
|
||||
const QPointF pixelCoordinate = mapView->locationToScreen(_mapCoordinate);
|
||||
_sceneCoordinate = mapView->mapToScene( pixelCoordinate.x(), pixelCoordinate.y() );
|
||||
return _sceneCoordinate;
|
||||
} /* QPointF mapToScene(Esri::ArcGISRuntime::MapGraphicsView * mapView) */
|
||||
|
||||
|
||||
inline void updateSceneCoordinate( Esri::ArcGISRuntime::MapGraphicsView * mapView, const QPointF & sceneCoordinate)
|
||||
{
|
||||
if (mapView)
|
||||
{
|
||||
_sceneCoordinate = sceneCoordinate;
|
||||
QPoint pixelCoordinate = mapView->mapFromScene(sceneCoordinate);
|
||||
_mapCoordinate = mapView->screenToLocation( pixelCoordinate.x(), pixelCoordinate.y() );
|
||||
}
|
||||
else updateSceneCoordinate( sceneCoordinate );
|
||||
} /* void updateSceneCoordinate( Esri::ArcGISRuntime::MapGraphicsView * mapView, const QPointF & sceneCoordinate) */
|
||||
|
||||
|
||||
inline void updateSceneCoordinate( const QPointF & sceneCoordinate )
|
||||
{
|
||||
_sceneCoordinate = sceneCoordinate;
|
||||
_mapCoordinate = Esri::ArcGISRuntime::Point();
|
||||
} /* void updateSceneCoordinate( const QPointF & sceneCoordinate ) */
|
||||
|
||||
bool isNull() const
|
||||
{
|
||||
return _sceneCoordinate.isNull();
|
||||
}
|
||||
|
||||
}; /* RubberbandCoordinate */
|
||||
|
||||
/**
|
||||
@name Construction & Destruction
|
||||
@{
|
||||
*/
|
||||
explicit RubberbandDrawable( QGraphicsView *view );
|
||||
explicit RubberbandDrawable( Esri::ArcGISRuntime::MapGraphicsView * );
|
||||
explicit RubberbandDrawable( Esri::ArcGISRuntime::MapGraphicsView *, QGraphicsScene * );
|
||||
~RubberbandDrawable();
|
||||
/** @} */
|
||||
|
||||
inline bool isVisible() const { return _isVisible; }
|
||||
inline void setVisibility(bool on = true) { _isVisible = on; updateGraphic(); }
|
||||
|
||||
inline void setDrawColor (const QColor & col) { _drawColor = col; updateGraphic(); }
|
||||
inline void setFillColor (const QColor & col) { _fillColor = col; updateGraphic(); }
|
||||
inline void setLineWidth(unsigned int width) { _lineWidth = width; updateGraphic(); }
|
||||
|
||||
inline void zBufferPlane( ZBufferPlane zPlane ) { _zBufferValue = (unsigned int) zPlane; }
|
||||
|
||||
inline void setZValue(qreal zValue) { _zValue = zValue; updateGraphic(); }
|
||||
inline qreal zValue() const { return _zValue; }
|
||||
|
||||
protected:
|
||||
|
||||
QPointer<QGraphicsScene> _scene;
|
||||
QPointer<Esri::ArcGISRuntime::MapGraphicsView> _mapView;
|
||||
|
||||
bool _isVisible;
|
||||
QColor _drawColor;
|
||||
QColor _fillColor;
|
||||
unsigned int _lineWidth;
|
||||
qreal _zBufferValue;
|
||||
qreal _zValue{0}; // combine _zBufferValue and _zValue???
|
||||
|
||||
LOGGER_T _logger;
|
||||
|
||||
#ifdef ADJUST_COORDINATES_EVERY_PAINT_EVENT
|
||||
bool eventFilter(QObject*, QEvent*) override;
|
||||
#endif
|
||||
|
||||
virtual void updateGraphic() = 0;
|
||||
|
||||
void makeLineStyle( bool dottedLine, QPen & lineStyle );
|
||||
|
||||
inline void forceUpdateViewWidget() { _mapView->viewport()->update(); }
|
||||
|
||||
virtual void adjustCoordinates() = 0;
|
||||
virtual void adjustWindow( const QRectF& ) = 0;
|
||||
|
||||
|
||||
QColor transparentFillColor() const
|
||||
{
|
||||
QColor fillColor(_fillColor);
|
||||
|
||||
if (fillColor.alphaF() > 0.85)
|
||||
{
|
||||
fillColor.setAlphaF( fillColor.alphaF()*0.5 );
|
||||
}
|
||||
return fillColor;
|
||||
} // QColor transparentFillColor()
|
||||
|
||||
|
||||
protected slots:
|
||||
|
||||
void onDo_adjustCoordinates();
|
||||
void onDo_adjustWindow(const QRectF & );
|
||||
|
||||
private:
|
||||
|
||||
|
||||
|
||||
void doConnecting();
|
||||
|
||||
}; /* RubberbandDrawable */
|
||||
|
||||
} } /* namespace SituationMap::RB */
|
||||
+455
@@ -0,0 +1,455 @@
|
||||
|
||||
/**
|
||||
**
|
||||
** @RDE_HEADER@
|
||||
** Implementation of rubberband class to define point feature geoemtry
|
||||
** $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 .........:
|
||||
**
|
||||
** 17.06.2015, JT : First edition for use with Qt5
|
||||
**
|
||||
** -----------------------------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
#include "rubberband_ellipse.h"
|
||||
#include "drawable_ellipse.h"
|
||||
#include "rubberband_point_handle.h"
|
||||
|
||||
#include "rubberband_internal.h"
|
||||
#include "rubberband_base_internal.h"
|
||||
|
||||
#include <MathUtils/math_const.h>
|
||||
#include <MathUtils/simple_helper.h>
|
||||
#include <LtsCoordTrans/lts_coord_trans.h>
|
||||
|
||||
namespace SituationMap { namespace RB
|
||||
{
|
||||
|
||||
struct RubberbandEllipse::InternalData
|
||||
{
|
||||
SituationMap::RefPointer<DrawableEllipse> _ellipseSymbol;
|
||||
int _alphaFill = 50; // alpha value used for fill color of ellipse
|
||||
|
||||
QPointF _sectorOStart = QPointF(1,0);
|
||||
QPointF _sectorOEnd = QPointF(1,0);
|
||||
SituationMap::RefPointer<RubberbandPointHandle> _sectorStartHandle;
|
||||
SituationMap::RefPointer<RubberbandPointHandle> _sectorEndHandle;
|
||||
|
||||
bool _sectorEnabled = false;
|
||||
bool _sectorFixedAngleEnabled = false;
|
||||
|
||||
}; /* RubberbandEllipse::InternalData */
|
||||
|
||||
|
||||
RubberbandEllipse::RubberbandEllipse( SituationMap::Map * map, QObject * parent )
|
||||
: RubberbandRectangle(map,parent), _internal(new InternalData)
|
||||
{
|
||||
useDottedLineHandles(true);
|
||||
} /* RubberbandEllipse::RubberbandEllipse */
|
||||
|
||||
|
||||
RubberbandEllipse::~RubberbandEllipse()
|
||||
{
|
||||
delete _internal;
|
||||
_internal = nullptr;
|
||||
} /* RubberbandEllipse::~RubberbandEllipse */
|
||||
|
||||
|
||||
QPointF RubberbandEllipse::getRotatedPoint(QPointF sector) const
|
||||
{
|
||||
qreal sinRect = 0, cosRect = 1;
|
||||
getSceneRotation( sinRect, cosRect);
|
||||
double angleRad = SituationMap::MathUtils::getMathAngle(QPointF(cosRect,sinRect));// angle rad
|
||||
//double angleDeg = SituationMap::MathUtils::getMathAngle(QPointF(cosRect,sinRect)) * LtsCoordTrans::rad2deg();
|
||||
const double clockwiseAngle = ((360*LtsCoordTrans::deg2rad()) - angleRad);// angle in rad;
|
||||
|
||||
// map clockwise rotation
|
||||
QPointF point = sector;
|
||||
point.setX( sector.x()*std::cos(clockwiseAngle) + sector.y()*std::sin(clockwiseAngle));
|
||||
point.setY( -sector.x()*std::sin(clockwiseAngle) + sector.y()*std::cos(clockwiseAngle));
|
||||
|
||||
return point;
|
||||
}
|
||||
|
||||
void RubberbandEllipse::setSectorStart(qreal sinPhi, qreal cosPhi)
|
||||
{
|
||||
_internal->_sectorOStart = QPointF( cosPhi, sinPhi );
|
||||
update();
|
||||
} /* RubberbandEllipse::setSectorStart */
|
||||
|
||||
|
||||
void RubberbandEllipse::setSectorEnd(qreal sinPhi, qreal cosPhi)
|
||||
{
|
||||
_internal->_sectorOEnd = QPointF( cosPhi, sinPhi );
|
||||
update();
|
||||
} /* RubberbandEllipse::setSectorEnd */
|
||||
|
||||
|
||||
QPointF RubberbandEllipse::sectorStart() const
|
||||
{
|
||||
return getRotatedPoint(_internal->_sectorOStart);
|
||||
} /* RubberbandEllipse::sectorStart */
|
||||
|
||||
|
||||
QPointF RubberbandEllipse::sectorEnd() const
|
||||
{
|
||||
return getRotatedPoint(_internal->_sectorOEnd);
|
||||
} /* RubberbandEllipse::sectorEnd */
|
||||
|
||||
|
||||
bool RubberbandEllipse::hasSector() const
|
||||
{
|
||||
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 phiStart = getAngle(_internal->_sectorOStart.y(),_internal->_sectorOStart.y());
|
||||
int phiEnd = getAngle( _internal->_sectorOEnd.y(), _internal->_sectorOEnd.y());
|
||||
return phiStart != phiEnd;
|
||||
} /* RubberbandEllipse::hasSector */
|
||||
|
||||
void RubberbandEllipse::enableSector(bool on) { _internal -> _sectorEnabled = on; }
|
||||
bool RubberbandEllipse::isSectorEnabled() const { return _internal -> _sectorEnabled; }
|
||||
|
||||
void RubberbandEllipse::setSectorAngleFixed(bool on)
|
||||
{
|
||||
_internal -> _sectorFixedAngleEnabled = on;
|
||||
}
|
||||
|
||||
bool RubberbandEllipse::isSectorFixedAngeEnabled() const
|
||||
{
|
||||
return _internal->_sectorFixedAngleEnabled;
|
||||
}
|
||||
|
||||
|
||||
bool RubberbandEllipse::selectAction(AbstractEventDispatcher * causer, int x, int y)
|
||||
{
|
||||
if (rubberbandIsAlive())
|
||||
{
|
||||
QPointF scenePos(pixel2ScenePosition(x,y));
|
||||
|
||||
_baseInternal->_lastClickPosition = scenePos;
|
||||
|
||||
if (_internal -> _sectorEnabled)
|
||||
{
|
||||
if ((_internal->_sectorEndHandle.valid()) && (_internal->_sectorEndHandle->isPositionInside(scenePos)))
|
||||
{
|
||||
_internal->_sectorEndHandle->setSelection(true);
|
||||
enableSelectedState();
|
||||
update();
|
||||
deactivateButtons();
|
||||
return true;
|
||||
}
|
||||
|
||||
if ((_internal->_sectorStartHandle.valid()) && (_internal->_sectorStartHandle->isPositionInside(scenePos)))
|
||||
{
|
||||
_internal->_sectorStartHandle->setSelection(true);
|
||||
enableSelectedState();
|
||||
update();
|
||||
deactivateButtons();
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return RubberbandRectangle::selectAction(causer,x,y);
|
||||
} /* RubberbandEllipse::selectAction */
|
||||
|
||||
|
||||
bool RubberbandEllipse::moveAction(AbstractEventDispatcher * causer, int x, int y)
|
||||
{
|
||||
if (rubberbandIsAlive())
|
||||
{
|
||||
QPointF scenePos(pixel2ScenePosition(x,y));
|
||||
if (_internal -> _sectorEnabled)
|
||||
{
|
||||
if (_internal->_sectorEndHandle.valid())
|
||||
{
|
||||
if (_internal->_sectorEndHandle->isPositionInside(scenePos))
|
||||
{
|
||||
_internal->_sectorEndHandle->setSelection(true);
|
||||
update();
|
||||
return false;
|
||||
}
|
||||
else _internal->_sectorEndHandle->setSelection(false);
|
||||
}
|
||||
|
||||
if (_internal->_sectorStartHandle.valid())
|
||||
{
|
||||
if (_internal->_sectorStartHandle->isPositionInside(scenePos))
|
||||
{
|
||||
_internal->_sectorStartHandle->setSelection(true);
|
||||
update();
|
||||
return false;
|
||||
}
|
||||
else _internal->_sectorStartHandle->setSelection(false);
|
||||
}
|
||||
}
|
||||
}
|
||||
return RubberbandRectangle::moveAction(causer,x,y);
|
||||
} /* RubberbandEllipse::moveAction */
|
||||
|
||||
|
||||
bool RubberbandEllipse::setCoordinateAction(AbstractEventDispatcher * causer, int x, int y)
|
||||
{
|
||||
if (rubberbandIsAlive())
|
||||
{
|
||||
if (_internal -> _sectorEnabled)
|
||||
{
|
||||
if ((_internal->_sectorEndHandle.valid()) && (_internal->_sectorEndHandle->isSelected()))
|
||||
{
|
||||
_internal->_sectorEndHandle->setSelection(false);
|
||||
update();
|
||||
activateButtons();
|
||||
return true;
|
||||
}
|
||||
|
||||
if ((_internal->_sectorStartHandle.valid()) && (_internal->_sectorStartHandle->isSelected()))
|
||||
{
|
||||
_internal->_sectorStartHandle->setSelection(false);
|
||||
update();
|
||||
activateButtons();
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return RubberbandRectangle::setCoordinateAction(causer,x,y);
|
||||
} /* RubberbandEllipse::setCoordinateAction */
|
||||
|
||||
|
||||
bool RubberbandEllipse::movePickedAction(AbstractEventDispatcher * causer, int x, int y)
|
||||
{
|
||||
if (rubberbandIsAlive())
|
||||
{
|
||||
auto updateHandle = [this](RubberbandPointHandle * handle, const RubberbandHandle::RubberbandCoordinate & pos, QPointF & oVector ) -> bool
|
||||
{
|
||||
if (handle == nullptr) return false;
|
||||
if (!handle->isSelected()) return false;
|
||||
if (isSectorFixedAngeEnabled()) return false;
|
||||
|
||||
qreal sinRect = 0;
|
||||
qreal cosRect = 1;
|
||||
const QPointF & center = getCenter();
|
||||
|
||||
getSceneRotation( sinRect, cosRect);
|
||||
|
||||
qreal cosA = pos._mapCoordinate.x() - center.x();
|
||||
qreal sinA = pos._mapCoordinate.y() - center.y();
|
||||
qreal len = sqrt(cosA*cosA+sinA*sinA);
|
||||
|
||||
cosA /= len;
|
||||
sinA /= len;
|
||||
|
||||
oVector.setX( cosA*cosRect + sinA*sinRect );
|
||||
oVector.setY( sinA*cosRect - cosA*sinRect );
|
||||
update();
|
||||
return true;
|
||||
}; // updateHandle
|
||||
|
||||
QPointF scenePos(pixel2ScenePosition(x,y));
|
||||
|
||||
RubberbandHandle::RubberbandCoordinate pos(Rubberband::_internal->_mapView, scenePos );
|
||||
|
||||
if (updateHandle( _internal->_sectorEndHandle.get() , pos, _internal->_sectorOEnd )) return false;
|
||||
if (updateHandle( _internal->_sectorStartHandle.get(), pos, _internal->_sectorOStart )) return false;
|
||||
}
|
||||
return RubberbandRectangle::movePickedAction(causer,x,y);
|
||||
} /* RubberbandEllipse::movePickedAction */
|
||||
|
||||
|
||||
void RubberbandEllipse::updateSectorHandles()
|
||||
{
|
||||
|
||||
auto ellipse = []( qreal a, qreal b, qreal sinA, qreal cosA ) -> QPointF
|
||||
{
|
||||
/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
*
|
||||
* Qt does not use the paramater equation of a ellipse to draw sectors. Instead of a simpler term
|
||||
* is used. For simpleness we use the same of.
|
||||
*
|
||||
qreal e2 = 1 - (b*b) / (a*a);
|
||||
qreal cos2 = cosA * cosA;
|
||||
qreal f = b / sqrt(1-e2*cos2);
|
||||
return QPointF( f*cosA, f*sinA );
|
||||
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
|
||||
|
||||
return QPointF(a*cosA,b*sinA);
|
||||
};
|
||||
|
||||
auto rotate = [] ( const QPointF & p, qreal sinA, qreal cosA ) -> QPointF { return QPointF( p.x()*cosA - p.y()*sinA, p.y()*cosA + p.x()*sinA ); };
|
||||
|
||||
qreal a = getWidth() * 0.5;
|
||||
qreal b = getHeight() * 0.5;
|
||||
QPointF startP = ellipse(a,b,_internal->_sectorOStart.y(),_internal->_sectorOStart.x() );
|
||||
QPointF endP = ellipse(a,b,_internal->_sectorOEnd.y() ,_internal->_sectorOEnd.x() );
|
||||
|
||||
qreal sinRect = 0;
|
||||
qreal cosRect = 1;
|
||||
|
||||
getSceneRotation( sinRect, cosRect);
|
||||
|
||||
startP = rotate(startP, sinRect, cosRect) + getCenter();
|
||||
endP = rotate( endP, sinRect, cosRect) + getCenter();
|
||||
|
||||
const Esri::ArcGISRuntime::Point &mapStartP = convert( startP, Rubberband::_internal->_mapView->map()->spatialReference() );
|
||||
const Esri::ArcGISRuntime::Point &mapEndP = convert( endP, Rubberband::_internal->_mapView->map()->spatialReference() );
|
||||
|
||||
if (!_internal->_sectorStartHandle.valid())
|
||||
{
|
||||
_internal->_sectorStartHandle = new RubberbandPointHandle( Rubberband::_internal->_mapView, Rubberband::_internal->_mapScene, mapStartP );
|
||||
}
|
||||
else _internal->_sectorStartHandle->setCoordinate( RubberbandHandle::RubberbandCoordinate(Rubberband::_internal->_mapView,mapStartP) );
|
||||
|
||||
_internal->_sectorStartHandle -> setVisibility((isSectorEnabled() && !isSectorFixedAngeEnabled())/*_internal->_sectorEnabled*/);
|
||||
_internal->_sectorStartHandle -> setDrawColor(_handleDrawColor);
|
||||
_internal->_sectorStartHandle -> setFillColor( _handleFillColor );
|
||||
_internal->_sectorStartHandle -> setSelectionColor(_handleSelectionColor);
|
||||
|
||||
if (!_internal->_sectorEndHandle.valid())
|
||||
{
|
||||
_internal->_sectorEndHandle = new RubberbandPointHandle( Rubberband::_internal->_mapView, Rubberband::_internal->_mapScene, mapEndP );
|
||||
}
|
||||
else _internal->_sectorEndHandle->setCoordinate( RubberbandHandle::RubberbandCoordinate(Rubberband::_internal->_mapView,mapEndP) );
|
||||
|
||||
_internal->_sectorEndHandle -> setVisibility(isSectorEnabled() && !isSectorFixedAngeEnabled()/*_internal->_sectorEnabled*/);
|
||||
_internal->_sectorEndHandle -> setDrawColor(_handleDrawColor);
|
||||
_internal->_sectorEndHandle -> setFillColor( _handleFillColor );
|
||||
_internal->_sectorEndHandle -> setSelectionColor(_handleSelectionColor);
|
||||
|
||||
} /* RubberbandEllipse::updateSectorHandles */
|
||||
|
||||
|
||||
void RubberbandEllipse::update()
|
||||
{
|
||||
|
||||
RubberbandRectangle::update();
|
||||
|
||||
if (isEnabledModificationState())
|
||||
{
|
||||
updateSectorHandles();
|
||||
|
||||
QPointF center = getCenter();
|
||||
qreal width2 = getWidth()*0.5;
|
||||
qreal height2 = getHeight()*0.5;
|
||||
qreal sinRect = 0.0;
|
||||
qreal cosRect = 1.0;
|
||||
|
||||
getSceneRotation( sinRect, cosRect );
|
||||
|
||||
if (_internal->_ellipseSymbol == nullptr)
|
||||
{
|
||||
_internal->_ellipseSymbol = new DrawableEllipse( Rubberband::_internal->_mapView );
|
||||
}
|
||||
|
||||
QColor drawColor = _drawColor;
|
||||
|
||||
_internal->_ellipseSymbol->setDrawColor( drawColor );
|
||||
drawColor.setAlpha(_internal->_alphaFill);
|
||||
if (_internal -> _sectorEnabled){
|
||||
_fillColor.setAlpha(_internal->_alphaFill+10);
|
||||
_internal->_ellipseSymbol->setFillColor( _fillColor );
|
||||
}
|
||||
else
|
||||
{
|
||||
_fillColor.setAlpha(0);
|
||||
_internal->_ellipseSymbol->setFillColor( _fillColor );
|
||||
}
|
||||
|
||||
_internal->_ellipseSymbol->setRect( center, width2, height2, sinRect, cosRect, _internal->_sectorOStart, _internal->_sectorOEnd );
|
||||
|
||||
}
|
||||
} /* RubberbandEllipse::update */
|
||||
|
||||
|
||||
void RubberbandEllipse::buildTmpConstruction( SituationMap::RefPointer<RubberbandDrawable> &tmpGraphic, QPointF &start, QPointF &end )
|
||||
{
|
||||
if (!tmpGraphic.valid())
|
||||
{
|
||||
tmpGraphic = new DrawableEllipse( Rubberband::_internal->_mapView );
|
||||
tmpGraphic -> setDrawColor( _drawColor );
|
||||
tmpGraphic -> setFillColor( _fillColor );
|
||||
tmpGraphic -> setLineWidth( 1 );
|
||||
tmpGraphic -> zBufferPlane( RubberbandDrawable::ZBufferPlane::Drawables );
|
||||
}
|
||||
|
||||
QVector<QPointF> path;
|
||||
QPointF sceneCenter;
|
||||
qreal sceneWidth;
|
||||
qreal sceneHeight;
|
||||
qreal sinMap;
|
||||
qreal cosMap;
|
||||
|
||||
getMapRotation( sinMap, cosMap );
|
||||
|
||||
auto rotate = [sinMap, cosMap](qreal x, qreal y) -> QPointF
|
||||
{
|
||||
qreal px = x*cosMap - y*sinMap;
|
||||
qreal py = y*cosMap + x*sinMap;
|
||||
return QPointF(px,py);
|
||||
}; // rotate
|
||||
|
||||
buildTmpConstructionPath( start-end + start, end, path, sceneCenter, sceneWidth, sceneHeight );
|
||||
|
||||
DrawableEllipse * tmpEllipse = static_cast<DrawableEllipse*>(tmpGraphic.get());
|
||||
|
||||
RubberbandHandle::RubberbandCoordinate mapCenter( Rubberband::_internal->_mapView, start );
|
||||
RubberbandHandle::RubberbandCoordinate mapRadius( Rubberband::_internal->_mapView, start+rotate(sceneWidth*0.5,sceneHeight*0.5) );
|
||||
|
||||
qreal w = mapRadius._mapCoordinate.x() - mapCenter._mapCoordinate.x();
|
||||
qreal h = mapRadius._mapCoordinate.y() - mapCenter._mapCoordinate.y();
|
||||
|
||||
tmpEllipse->setRect( QPointF(mapCenter._mapCoordinate.x(),mapCenter._mapCoordinate.y()), w, h, 0, 1 );
|
||||
} /* RubberbandEllipse::buildTmpConstruction */
|
||||
|
||||
|
||||
void RubberbandEllipse::getTmpConstructionParameter(const QPointF & start, const QPointF & end, QPointF & sceneCenter, qreal & sceneWidth, qreal & sceneHeight)
|
||||
{
|
||||
QVector<QPointF> path;
|
||||
qreal sinMap;
|
||||
qreal cosMap;
|
||||
|
||||
getMapRotation( sinMap, cosMap );
|
||||
|
||||
auto rotate = [sinMap, cosMap]( qreal x, qreal y ) -> QPointF
|
||||
{
|
||||
qreal px = x*cosMap - y*sinMap;
|
||||
qreal py = y*cosMap + x*sinMap;
|
||||
return QPointF(px,py);
|
||||
}; // rotate
|
||||
|
||||
auto length = [](qreal x, qreal y) -> qreal { return sqrt(x*x+y*y); };
|
||||
|
||||
buildTmpConstructionPath( start, end, path, sceneCenter, sceneWidth, sceneHeight );
|
||||
|
||||
RubberbandHandle::RubberbandCoordinate mapCenter ( Rubberband::_internal->_mapView, start );
|
||||
RubberbandHandle::RubberbandCoordinate mapRadiusX( Rubberband::_internal->_mapView, start+rotate(sceneWidth,0) );
|
||||
RubberbandHandle::RubberbandCoordinate mapRadiusY( Rubberband::_internal->_mapView, start+rotate(0,sceneHeight) );
|
||||
|
||||
qreal w = length( mapRadiusX._sceneCoordinate.x()-mapCenter._sceneCoordinate.x(), mapRadiusX._sceneCoordinate.y()-mapCenter._sceneCoordinate.y() );
|
||||
qreal h = length( mapRadiusY._sceneCoordinate.x()-mapCenter._sceneCoordinate.x(), mapRadiusY._sceneCoordinate.y()-mapCenter._sceneCoordinate.y() );
|
||||
|
||||
sceneCenter = start;
|
||||
sceneWidth = 2*w;
|
||||
sceneHeight = 2*h;
|
||||
} /* RubberbandEllipse::getTmpConstructionParameter */
|
||||
|
||||
|
||||
} } /* namespace SituationMap::RB */
|
||||
@@ -0,0 +1,95 @@
|
||||
/**
|
||||
**
|
||||
** @RDE_HEADER@
|
||||
** Definition of rubberband class to define point feature geoemtry
|
||||
** $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 .........:
|
||||
**
|
||||
** 17.06.2015, JT : First edition for use with Qt5
|
||||
**
|
||||
** -----------------------------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "rubberband_rectangle.h"
|
||||
|
||||
|
||||
namespace SituationMap { namespace RB
|
||||
{
|
||||
|
||||
|
||||
/**
|
||||
@class RubberbandEllipse rubberband_ellipse.h
|
||||
@brief Implementation of a rubberband to input ellipses and circles
|
||||
@see Rubberband, RubberbandRectangle
|
||||
*/
|
||||
class SITUATIONMAP_EXPORT RubberbandEllipse : public RubberbandRectangle
|
||||
{
|
||||
Q_OBJECT
|
||||
/**
|
||||
@name Construction & Destruction
|
||||
@{
|
||||
*/
|
||||
|
||||
friend class RubberbandFactory;
|
||||
explicit RubberbandEllipse( SituationMap::Map * map, QObject * parent = nullptr );
|
||||
|
||||
public:
|
||||
|
||||
virtual ~RubberbandEllipse();
|
||||
|
||||
RubberbandEllipse(const RubberbandEllipse &) = delete;
|
||||
RubberbandEllipse & operator = (const RubberbandEllipse &) = delete;
|
||||
/** @} */
|
||||
|
||||
void setSectorStart( qreal sinPhi, qreal cosPhi );
|
||||
void setSectorEnd( qreal sinPhi, qreal cosPhi );
|
||||
|
||||
QPointF getRotatedPoint(QPointF sector)const;
|
||||
bool hasSector() const;
|
||||
QPointF sectorStart() const;
|
||||
QPointF sectorEnd() const;
|
||||
|
||||
void enableSector( bool on = true );
|
||||
bool isSectorEnabled() const;
|
||||
void setSectorAngleFixed(bool on); // true: start and end sectors positon can't be modifed
|
||||
bool isSectorFixedAngeEnabled() const;
|
||||
|
||||
bool selectAction ( AbstractEventDispatcher * causer, int x, int y ) override;
|
||||
bool setCoordinateAction ( AbstractEventDispatcher * causer, int x, int y ) override;
|
||||
bool movePickedAction ( AbstractEventDispatcher * causer, int x, int y ) override;
|
||||
bool moveAction ( AbstractEventDispatcher * causer, int x, int y ) override;
|
||||
|
||||
protected:
|
||||
|
||||
void updateSectorHandles();
|
||||
|
||||
void update() override;
|
||||
|
||||
struct InternalData;
|
||||
|
||||
InternalData * _internal;
|
||||
|
||||
void buildTmpConstruction( SituationMap::RefPointer<RubberbandDrawable> & tmpGraphic, QPointF & start, QPointF & end ) override;
|
||||
void getTmpConstructionParameter( const QPointF & start, const QPointF & end, QPointF & sceneCenter, qreal & sceneWidth, qreal & sceneHeight ) override;
|
||||
|
||||
}; /* RubberbandPointFeature */
|
||||
|
||||
} } /* namespace SituationMap::RB */
|
||||
@@ -0,0 +1,236 @@
|
||||
|
||||
/**
|
||||
**
|
||||
** @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 <MathUtils/math_const.h>
|
||||
|
||||
#include <arcgis/MapGraphicsView.h>
|
||||
#include <arcgis/Map.h>
|
||||
|
||||
#include <QtWidgets/QGraphicsScene>
|
||||
#include <QtWidgets/QGraphicsEllipseItem>
|
||||
|
||||
#include <math.h>
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
} }
|
||||
@@ -0,0 +1,96 @@
|
||||
/**
|
||||
**
|
||||
** @RDE_HEADER@
|
||||
** Definition 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
|
||||
**
|
||||
** -----------------------------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <QtCore/QPointF>
|
||||
|
||||
#include <QtGui/QPen>
|
||||
|
||||
#include "rubberband_handle.h"
|
||||
|
||||
class QGraphicsEllipse;
|
||||
class QGraphicsScene;
|
||||
|
||||
namespace SituationMap
|
||||
{
|
||||
namespace RB
|
||||
{
|
||||
|
||||
/**
|
||||
@class RubberbandEllipseHandle rubberband_line_handle.h
|
||||
@brief Implementation of a line handle for rubberband internal use.
|
||||
@see RubberbandHandle
|
||||
*/
|
||||
class RubberbandEllipseHandle : public RubberbandHandle
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
|
||||
RubberbandEllipseHandle(Esri::ArcGISRuntime::MapGraphicsView * mapView ,QGraphicsScene * scene);
|
||||
~RubberbandEllipseHandle();
|
||||
|
||||
bool isPositionInside(const QPointF &scenePosition) const override;
|
||||
|
||||
// virtual void updateCoordinates(const QVector<QPointF> &scenePositionVector);
|
||||
// virtual void updateCoordinate(unsigned index, const QPointF &scenePosition);
|
||||
|
||||
QPointF getRadius();
|
||||
|
||||
void setRect(const RubberbandDrawable::RubberbandCoordinate ¢er,
|
||||
qreal radiusX, qreal radiusY,
|
||||
qreal sin, qreal cos,
|
||||
const QPointF & sectorStart = QPointF(), const QPointF & sectorEnd = QPointF());
|
||||
|
||||
|
||||
void dottedLine(bool on = true) { _dottedLine = on; }
|
||||
|
||||
protected:
|
||||
|
||||
QGraphicsEllipseItem *_ellipseSymbol{nullptr};
|
||||
QPen _lineStyle;
|
||||
RubberbandDrawable::RubberbandCoordinate _center;
|
||||
qreal _radiusX{0.0};
|
||||
qreal _radiusY{0.0};
|
||||
qreal _sinRect{0.0};
|
||||
qreal _cosRect{0.0};
|
||||
QPointF _sectorStart;
|
||||
QPointF _sectorEnd;
|
||||
|
||||
bool _dottedLine{false};
|
||||
|
||||
void updateGraphic() override;
|
||||
|
||||
void adjustCoordinates() override;
|
||||
void adjustWindow(const QRectF&) override;
|
||||
|
||||
|
||||
}; // RubberbandEllipseHandle
|
||||
|
||||
}
|
||||
} // namespace SituationMap::RB
|
||||
+634
@@ -0,0 +1,634 @@
|
||||
/**
|
||||
**
|
||||
** @RDE_HEADER@
|
||||
** Implementation of base class for rubberbands
|
||||
** $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
|
||||
** 30.09.2015, JT : New create method for creating rubberbands fitting to a special sidc code
|
||||
**
|
||||
** -----------------------------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
|
||||
#include "rubberband_factory.h"
|
||||
#include "rubberband_corridor.h"
|
||||
#include <Symbology/sidc_builder_base.h>
|
||||
|
||||
#include <cmath>
|
||||
#include <Map/coord_translation_functor.h>
|
||||
|
||||
namespace SituationMap { namespace RB
|
||||
{
|
||||
|
||||
class RubberbandFactory::Defaults
|
||||
{
|
||||
public:
|
||||
|
||||
QColor _rubberbandDrawColor = QColor();
|
||||
QColor _rubberbandFillColor = QColor();
|
||||
QColor _rubberbandHandleDrawColor = QColor();
|
||||
QColor _rubberbandHandleFillColor = QColor();
|
||||
QColor _rubberbandSelectionColor = QColor();
|
||||
QColor _rubberbandFrameColor = QColor();
|
||||
QColor _rubberbandFrameFillColor = QColor();
|
||||
int _rubberbandFrameHandleMargin = 0;
|
||||
QPoint _rubberbandPreviewOffset = QPoint();
|
||||
unsigned int _rubberbandPreviewSize = 0;
|
||||
unsigned int _rubberbandPickingRatio = 0;
|
||||
unsigned int _rubberbandLineHandleWidth = 0;
|
||||
|
||||
}; // RubberbandFactory::Defaults
|
||||
|
||||
|
||||
RubberbandFactory::RubberbandFactory( SituationMap::Map * map )
|
||||
: QObject()
|
||||
, _map(map)
|
||||
, _defaults(new Defaults())
|
||||
, _allowMultipleRubberbands(false)
|
||||
, _logger(getLogger("RubberbandFactory"))
|
||||
{}
|
||||
|
||||
RubberbandFactory::~RubberbandFactory() { delete _defaults; }
|
||||
|
||||
|
||||
class SymbolConstruction
|
||||
{
|
||||
public:
|
||||
|
||||
enum class Mode
|
||||
{
|
||||
Unknown = 0,
|
||||
|
||||
Point,
|
||||
|
||||
ArcCurve,
|
||||
Triangle,
|
||||
MultiPoint,
|
||||
|
||||
PolyLine,
|
||||
PolyLineWidth,
|
||||
|
||||
Polygon,
|
||||
Rectangle,
|
||||
Circular,
|
||||
Corridor
|
||||
}; // Mode
|
||||
|
||||
Mode _mode;
|
||||
unsigned int _minPoints;
|
||||
unsigned int _maxPoints;
|
||||
|
||||
explicit SymbolConstruction( const AdvancedSymbology::GeometryType & geomType, const QString & gctString )
|
||||
: _mode(Mode::Unknown), _minPoints(-1), _maxPoints(-1)
|
||||
{
|
||||
if (QLatin1String("gct_arrow") == gctString) { _mode = Mode::PolyLine; _minPoints = 2; _maxPoints = 0; }
|
||||
if (QLatin1String("gct_arrow_with_offset") == gctString) { _mode = Mode::PolyLineWidth; _minPoints = 2; _maxPoints = 0; }
|
||||
if (QLatin1String("gct_arrow_with_tail") == gctString) { _mode = Mode::Triangle; _minPoints = 3; _maxPoints = 3; }
|
||||
|
||||
if (QLatin1String("gct_circle") == gctString) { _mode = Mode::MultiPoint; _minPoints = 2; _maxPoints = 2; }
|
||||
if (QLatin1String("gct_circular") == gctString) { _mode = Mode::Circular; _minPoints = 1; _maxPoints = 1; }
|
||||
|
||||
if (QLatin1String("gct_freehand_arrow") == gctString) { _mode = Mode::ArcCurve; _minPoints = 3; _maxPoints = 3; }
|
||||
if (QLatin1String("gct_freehand_line") == gctString) { _mode = Mode::ArcCurve; _minPoints = 3; _maxPoints = 3; }
|
||||
if (QLatin1String("gct_freehand_reverse_arrow") == gctString) { _mode = Mode::ArcCurve; _minPoints = 3; _maxPoints = 3; }
|
||||
if (QLatin1String("gct_freehand_u") == gctString) { _mode = Mode::ArcCurve; _minPoints = 4; _maxPoints = 4; }
|
||||
|
||||
if (QLatin1String("gct_hook") == gctString) { _mode = Mode::MultiPoint; _minPoints = 3; _maxPoints = 3; }
|
||||
if (QLatin1String("gct_horns") == gctString) { _mode = Mode::MultiPoint; _minPoints = 4; _maxPoints = 4; }
|
||||
|
||||
if (QLatin1String("gct_open_triangle") == gctString) { _mode = Mode::Triangle; _minPoints = 3; _maxPoints = 3; }
|
||||
|
||||
if (QLatin1String("gct_parallel_lines") == gctString) { _mode = Mode::PolyLineWidth; _minPoints = 2; _maxPoints = 2; }
|
||||
if (QLatin1String("gct_parallel_lines_mid_line") == gctString) { _mode = Mode::PolyLineWidth; _minPoints = 2; _maxPoints = 2; }
|
||||
|
||||
if (QLatin1String("gct_parallel_lines_with_ticks") == gctString)
|
||||
{
|
||||
_mode = Mode::MultiPoint;
|
||||
// ESRI implmentation seems to differ from symbology standard and takes always 4 input
|
||||
// coordinates here to construct the symbol!
|
||||
//
|
||||
// if (AdvancedSymbology::GeometryType::Polygon == geomType) _minPoints = _maxPoints = 4;
|
||||
// else _minPoints = _maxPoints = 3;
|
||||
_minPoints = _maxPoints = 4;
|
||||
}
|
||||
|
||||
if (QLatin1String("gct_rectangular") == gctString) { _mode = Mode::Corridor; _minPoints = 2; _maxPoints = 2; }
|
||||
if (QLatin1String("gct_rectangular_1_pt") == gctString) { _mode = Mode::Rectangle; _minPoints = 1; _maxPoints = 1; }
|
||||
|
||||
if (QLatin1String("gct_t") == gctString) { _mode = Mode::MultiPoint; _minPoints = 3; _maxPoints = 3; }
|
||||
if (QLatin1String("gct_triple_arrow") == gctString) { _mode = Mode::MultiPoint; _minPoints = 3; _maxPoints = 3; }
|
||||
|
||||
if (QLatin1String("gct_two_line") == gctString) { _mode = Mode::Triangle; _minPoints = 3; _maxPoints = 3; }
|
||||
if (QLatin1String("gct_two_line_3_or_4_pt") == gctString) { _mode = Mode::MultiPoint; _minPoints = 3; _maxPoints = 4; }
|
||||
|
||||
if (QLatin1String("gct_u_or_t_shape") == gctString) { _mode = Mode::MultiPoint; _minPoints = 3; _maxPoints = 3; }
|
||||
|
||||
if (Mode::Unknown == _mode)
|
||||
{
|
||||
// gct string is empty or not supported yet
|
||||
switch (geomType)
|
||||
{
|
||||
case AdvancedSymbology::GeometryType::Point : { _mode = Mode::Point; _minPoints = 1; _maxPoints = 1; } break;
|
||||
case AdvancedSymbology::GeometryType::Polyline : { _mode = Mode::PolyLine; _minPoints = 2; _maxPoints = 0; } break;
|
||||
case AdvancedSymbology::GeometryType::Polygon : { _mode = Mode::Polygon; _minPoints = 3; _maxPoints = 0; } break;
|
||||
case AdvancedSymbology::GeometryType::Undefined : break;
|
||||
default : break;
|
||||
} // switch
|
||||
}
|
||||
} // SymbolConstruction( const QString & gctString )
|
||||
|
||||
~SymbolConstruction() = default;
|
||||
|
||||
Mode mode() const { return _mode; }
|
||||
unsigned int minPoints() const { return _minPoints; }
|
||||
unsigned int maxPoints() const { return _maxPoints; }
|
||||
|
||||
bool unlimitedMaxPoints() const { return (_maxPoints == 0); }
|
||||
|
||||
}; // SymbolConstruction
|
||||
|
||||
|
||||
struct ActivateRubberbandInfo
|
||||
{
|
||||
Rubberband * _rubberband;
|
||||
SymbolConstruction _symbolConstruction;
|
||||
|
||||
explicit ActivateRubberbandInfo( Rubberband * r, const SymbolConstruction & sc ) : _rubberband(r), _symbolConstruction(sc) {;}
|
||||
~ActivateRubberbandInfo() = default;
|
||||
|
||||
ActivateRubberbandInfo() = delete;
|
||||
|
||||
}; // ActivateRubberbandInfo
|
||||
|
||||
|
||||
QString toString( SymbolConstruction::Mode mode )
|
||||
{
|
||||
switch (mode)
|
||||
{
|
||||
case SymbolConstruction::Mode::Unknown : return QStringLiteral("Unknown Rubberband"); break;
|
||||
case SymbolConstruction::Mode::Point : return QStringLiteral("Point Rubberband"); break;
|
||||
case SymbolConstruction::Mode::PolyLine : return QStringLiteral("Polyline Rubberband"); break;
|
||||
case SymbolConstruction::Mode::PolyLineWidth : return QStringLiteral("PolylineWidth Rubberband"); break;
|
||||
case SymbolConstruction::Mode::Polygon : return QStringLiteral("Polygon Rubberband"); break;
|
||||
case SymbolConstruction::Mode::Triangle : return QStringLiteral("Triangle Rubberband"); break;
|
||||
case SymbolConstruction::Mode::ArcCurve : return QStringLiteral("ArcCurve Rubberband"); break;
|
||||
case SymbolConstruction::Mode::Rectangle : return QStringLiteral("Rectangle Rubberband"); break;
|
||||
case SymbolConstruction::Mode::Circular : return QStringLiteral("Circular Rubberband"); break;
|
||||
case SymbolConstruction::Mode::Corridor : return QStringLiteral("Corridor Rubberband"); break;
|
||||
case SymbolConstruction::Mode::MultiPoint : return QStringLiteral("MultiPoint Rubberband"); break;
|
||||
}
|
||||
return QString();
|
||||
} // QString toString( SymbolConstruction::Mode mode )
|
||||
|
||||
|
||||
static bool defaultSymbolRubberbandCoordinates( Map * map, Rubberband * rbnd, const QPointF & pixelPos, const SymbolConstruction & symbolConstruction );
|
||||
|
||||
|
||||
Rubberband * RubberbandFactory::createSymbol(const QString & sidc, QObject * parent) const { return createSymbol(sidc,QPoint(-1,-1),parent); }
|
||||
|
||||
Rubberband * RubberbandFactory::createSymbol( const QString & sidc, const QPoint & winPos, QObject * parent ) const
|
||||
{
|
||||
if (Mode::Mode_2D != _map->mode()) return nullptr;
|
||||
|
||||
const QString & baseSymbolCode = AdvancedSymbology::SidcBuilderBase::concreteSidcToBaseSymbolCode( sidc );
|
||||
const AdvancedSymbology::SymbolProperties & symbolProperties = _map->symbolDictionary().symbolProperties( baseSymbolCode );
|
||||
const AdvancedSymbology::GeometryType & geomType = symbolProperties.geometryType();
|
||||
|
||||
SymbolConstruction symbolConstruction( geomType, symbolProperties.gctString() );
|
||||
|
||||
Rubberband::currentFactoryMap(_map);
|
||||
Rubberband::allowMultipleRubberbands(_allowMultipleRubberbands);
|
||||
Rubberband *rubberband = nullptr;
|
||||
|
||||
DEBUG_LOG(_logger) << LOGFUNCTION << QStringLiteral(" - %1").arg(toString(geomType), 30);
|
||||
DEBUG_LOG(_logger) << LOGFUNCTION << QStringLiteral(" - %1").arg(symbolProperties.gctString(), 30);
|
||||
DEBUG_LOG(_logger) << LOGFUNCTION << QStringLiteral(" - %1").arg(toString(symbolConstruction.mode()),30);
|
||||
|
||||
bool rubberbandConstructionMode = ((winPos.x() < 0) || (winPos.y() < 0));
|
||||
|
||||
try
|
||||
{
|
||||
switch (geomType)
|
||||
{
|
||||
case AdvancedSymbology::GeometryType::Point :
|
||||
{
|
||||
rubberband = new RubberbandPointFeature(_map, parent);
|
||||
} break;
|
||||
|
||||
case AdvancedSymbology::GeometryType::Polyline :
|
||||
{
|
||||
switch (symbolConstruction.mode())
|
||||
{
|
||||
case SymbolConstruction::Mode::PolyLine :
|
||||
{
|
||||
RubberbandMultiPointFeature * r = new RubberbandMultiPointFeature(_map,false,parent);
|
||||
if (r)
|
||||
{
|
||||
r->minimumPointCount( symbolConstruction.minPoints() );
|
||||
r->maximumPointCount( symbolConstruction.maxPoints() );
|
||||
r->enableFinishAfterConstruction(true);
|
||||
rubberband = r;
|
||||
}
|
||||
} break;
|
||||
|
||||
case SymbolConstruction::Mode::PolyLineWidth :
|
||||
{
|
||||
RubberbandMultiPointFeature * r = new RubberbandPolylineWidth(_map,parent);
|
||||
if (r)
|
||||
{
|
||||
r->minimumPointCount( symbolConstruction.minPoints() );
|
||||
r->maximumPointCount( symbolConstruction.maxPoints() );
|
||||
r->enableFinishAfterConstruction(true);
|
||||
rubberband = r;
|
||||
}
|
||||
} break;
|
||||
|
||||
case SymbolConstruction::Mode::ArcCurve :
|
||||
case SymbolConstruction::Mode::MultiPoint :
|
||||
case SymbolConstruction::Mode::Triangle :
|
||||
{
|
||||
RubberbandPointCluster * r = new RubberbandPointCluster(_map,parent,false);
|
||||
if (r)
|
||||
{
|
||||
r->minimumPointCount(symbolConstruction.minPoints());
|
||||
r->maximumPointCount(symbolConstruction.maxPoints());
|
||||
r->enableFinishAfterConstruction(true);
|
||||
|
||||
rubberband = r;
|
||||
|
||||
if ((!symbolConstruction.unlimitedMaxPoints()) && rubberbandConstructionMode)
|
||||
{
|
||||
// Rubberband is not active here because we need one position to initialize
|
||||
// the coordinates
|
||||
Rubberband::currentFactoryMap(_map);
|
||||
|
||||
RubberbandPointFeature * askPosition = new RubberbandPointFeature(_map, parent);
|
||||
|
||||
setDefaults(askPosition);
|
||||
|
||||
askPosition -> enableFinishAfterConstruction(true);
|
||||
askPosition -> setUserData( new ActivateRubberbandInfo(rubberband, symbolConstruction) );
|
||||
askPosition -> setPreviewSidc(sidc);
|
||||
askPosition -> setAutoDelete(true);
|
||||
|
||||
connect(askPosition, &SituationMap::RB::Rubberband::apply, this, &RubberbandFactory::onActivateRubberband );
|
||||
connect(askPosition, &SituationMap::RB::Rubberband::abort, this, &RubberbandFactory::onAbortRubberband );
|
||||
}
|
||||
else rubberband->activate();
|
||||
}
|
||||
} break;
|
||||
|
||||
default:
|
||||
{
|
||||
rubberband = new RubberbandPointCluster(_map,parent);
|
||||
if (rubberband) rubberband->activate();
|
||||
} break;
|
||||
} // switch
|
||||
} break;
|
||||
|
||||
case AdvancedSymbology::GeometryType::Polygon :
|
||||
{
|
||||
switch (symbolConstruction.mode())
|
||||
{
|
||||
case SymbolConstruction::Mode::Circular :
|
||||
{
|
||||
RubberbandEllipse * r = new RubberbandEllipse(_map, parent);
|
||||
if (r)
|
||||
{
|
||||
r->enableSector(false);
|
||||
r->constrainOrthogonal(true);
|
||||
r->constrainQuadratic(true);
|
||||
r->enableFinishAfterConstruction(true);
|
||||
}
|
||||
rubberband = r;
|
||||
} break;
|
||||
|
||||
case SymbolConstruction::Mode::Rectangle :
|
||||
{
|
||||
RubberbandRectangle * r = new RubberbandRectangle(_map, parent);
|
||||
if (r)
|
||||
{
|
||||
r->constrainOrthogonal(false);
|
||||
r->enableFinishAfterConstruction(true);
|
||||
}
|
||||
rubberband = r;
|
||||
} break;
|
||||
|
||||
case SymbolConstruction::Mode::Corridor :
|
||||
{
|
||||
RubberbandCorridor * r = new RubberbandCorridor(_map, RubberbandCorridor::InputMode::InputCenterLine, 0, parent);
|
||||
if (r)
|
||||
{
|
||||
r->setCorridorBorderColor( QColor("Black") );
|
||||
r->setCorridorFillColor( QColor(255,255,0,100) );
|
||||
r->minimumPointCount( symbolConstruction.minPoints() );
|
||||
r->maximumPointCount( symbolConstruction.maxPoints() );
|
||||
r->enableFinishAfterConstruction(true);
|
||||
|
||||
rubberband = r;
|
||||
}
|
||||
} break;
|
||||
|
||||
case SymbolConstruction::Mode::MultiPoint :
|
||||
{
|
||||
RubberbandPointCluster * r = new RubberbandPointCluster(_map,parent,false);
|
||||
if (r)
|
||||
{
|
||||
r->minimumPointCount(symbolConstruction.minPoints());
|
||||
r->maximumPointCount(symbolConstruction.maxPoints());
|
||||
r->enableFinishAfterConstruction(true);
|
||||
|
||||
rubberband = r;
|
||||
|
||||
if ((!symbolConstruction.unlimitedMaxPoints()) && rubberbandConstructionMode)
|
||||
{
|
||||
// Rubberband is not active here because we need one position to initialize
|
||||
// the coordinates
|
||||
Rubberband::currentFactoryMap(_map);
|
||||
|
||||
RubberbandPointFeature * askPosition = new RubberbandPointFeature(_map, parent);
|
||||
|
||||
setDefaults(askPosition);
|
||||
|
||||
askPosition -> enableFinishAfterConstruction(true);
|
||||
askPosition -> setUserData( new ActivateRubberbandInfo(rubberband, symbolConstruction) );
|
||||
askPosition -> setPreviewSidc(sidc);
|
||||
askPosition -> setAutoDelete(true);
|
||||
|
||||
connect(askPosition, &SituationMap::RB::Rubberband::apply, this, &RubberbandFactory::onActivateRubberband );
|
||||
connect(askPosition, &SituationMap::RB::Rubberband::abort, this, &RubberbandFactory::onAbortRubberband );
|
||||
}
|
||||
else rubberband->activate();
|
||||
}
|
||||
} break;
|
||||
|
||||
case SymbolConstruction::Mode::Polygon :
|
||||
default:
|
||||
{
|
||||
RubberbandMultiPointFeature * rubberArea = new RubberbandMultiPointFeature( _map, parent );
|
||||
if (rubberArea)
|
||||
{
|
||||
rubberArea -> enableClosed(true);
|
||||
}
|
||||
rubberband = rubberArea;
|
||||
} break;
|
||||
} // switch
|
||||
} break;
|
||||
|
||||
default : break;
|
||||
|
||||
} //switch
|
||||
}
|
||||
catch (const SituationMap::Exception &) {;}
|
||||
|
||||
if (rubberband)
|
||||
{
|
||||
setDefaults( rubberband );
|
||||
rubberband -> setAutoDelete(true);
|
||||
rubberband -> setPreviewSidc( sidc );
|
||||
|
||||
if (!rubberbandConstructionMode)
|
||||
{
|
||||
QPointF pixelPos( winPos.x(), winPos.y() );
|
||||
if (!defaultSymbolRubberbandCoordinates(_map, rubberband, pixelPos, symbolConstruction))
|
||||
{
|
||||
ERROR_LOG(_logger) << LOGFUNCTION << "Can't init symbol rubberband coordinate list, undefined proposal.";
|
||||
rubberband->deleteMySelf();
|
||||
rubberband = nullptr;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return rubberband;
|
||||
} /* RubberbandFactory::create */
|
||||
|
||||
|
||||
static bool defaultSymbolRubberbandCoordinates( Map * map, Rubberband * rbnd, const QPointF & pixelPos, const SymbolConstruction & symbolConstruction )
|
||||
{
|
||||
QVector<QPointF> pointList;
|
||||
|
||||
pointList.reserve( symbolConstruction.maxPoints() );
|
||||
|
||||
switch (symbolConstruction.mode())
|
||||
{
|
||||
case SymbolConstruction::Mode::ArcCurve:
|
||||
{
|
||||
if (4 == symbolConstruction.maxPoints())
|
||||
{
|
||||
pointList.append(pixelPos + QPointF(-150,-100));
|
||||
pointList.append(pixelPos + QPointF(-100,-100));
|
||||
pointList.append(pixelPos + QPointF(-100, 100));
|
||||
pointList.append(pixelPos + QPointF(-150, 100));
|
||||
}
|
||||
|
||||
if (3 == symbolConstruction.maxPoints())
|
||||
{
|
||||
pointList.append(pixelPos + QPointF(-150, 100));
|
||||
pointList.append(pixelPos + QPointF(+150, -20));
|
||||
pointList.append(pixelPos);
|
||||
}
|
||||
} break;
|
||||
|
||||
case SymbolConstruction::Mode::MultiPoint:
|
||||
{
|
||||
if (4 == symbolConstruction.maxPoints())
|
||||
{
|
||||
pointList.append(pixelPos + QPointF(-100, 100));
|
||||
pointList.append(pixelPos + QPointF( 100, 100));
|
||||
pointList.append(pixelPos + QPointF(-150,-100));
|
||||
pointList.append(pixelPos + QPointF( 150,-100));
|
||||
}
|
||||
if (3 == symbolConstruction.maxPoints())
|
||||
{
|
||||
pointList.append(pixelPos + QPointF(-150, 0));
|
||||
pointList.append(pixelPos + QPointF( 150, 0));
|
||||
pointList.append(pixelPos + QPointF(-150,-100));
|
||||
}
|
||||
if (2 == symbolConstruction.maxPoints())
|
||||
{
|
||||
pointList.append(pixelPos);
|
||||
pointList.append(pixelPos + QPointF(150, 150));
|
||||
}
|
||||
} break;
|
||||
|
||||
case SymbolConstruction::Mode::Polygon:
|
||||
case SymbolConstruction::Mode::Triangle:
|
||||
{
|
||||
pointList.append(pixelPos);
|
||||
pointList.append(pixelPos + QPointF(-150, +150));
|
||||
pointList.append(pixelPos + QPointF(+150, +150));
|
||||
} break;
|
||||
|
||||
case SymbolConstruction::Mode::Point:
|
||||
{
|
||||
pointList.append(pixelPos);
|
||||
} break;
|
||||
|
||||
case SymbolConstruction::Mode::Circular:
|
||||
case SymbolConstruction::Mode::Rectangle:
|
||||
{
|
||||
pointList.append(pixelPos + QPointF(-150, 150));
|
||||
pointList.append(pixelPos + QPointF( 150, 150));
|
||||
pointList.append(pixelPos + QPointF( 150,-150));
|
||||
pointList.append(pixelPos + QPointF(-150,-150));
|
||||
} break;
|
||||
|
||||
case SymbolConstruction::Mode::PolyLineWidth:
|
||||
{
|
||||
pointList.append(pixelPos + QPointF( 50, 0));
|
||||
pointList.append(pixelPos + QPointF(-150, 0));
|
||||
pointList.append(pixelPos + QPointF( 0, +50));
|
||||
} break;
|
||||
|
||||
case SymbolConstruction::Mode::Corridor:
|
||||
case SymbolConstruction::Mode::PolyLine:
|
||||
{
|
||||
pointList.append(pixelPos);
|
||||
pointList.append(pixelPos + QPointF(150, 150));
|
||||
} break;
|
||||
|
||||
case SymbolConstruction::Mode::Unknown:
|
||||
default:
|
||||
{
|
||||
// empty
|
||||
} break;
|
||||
|
||||
} // switch
|
||||
|
||||
if (!pointList.isEmpty())
|
||||
{
|
||||
for (int i = 0; i < pointList.size(); ++i) { pointList[i] = map->viewPortWindowPointToGeoCoordinate(pointList[i]); }
|
||||
|
||||
if (SymbolConstruction::Mode::Corridor == symbolConstruction.mode())
|
||||
{
|
||||
SituationMap::CoordTranslationFunctor * cf = map->coordTranslationFunctor();
|
||||
QPointF p1 = pointList[0];
|
||||
QPointF p2 = pointList[1];
|
||||
|
||||
if (cf)
|
||||
{
|
||||
p1 = cf->geographicToMap(p1);
|
||||
p2 = cf->geographicToMap(p2);
|
||||
}
|
||||
p1 -= p2;
|
||||
qreal wCorr = sqrt(p1.x()*p1.x()+p1.y()*p1.y()) * 0.15;
|
||||
RubberbandCorridor * rbndCorr = static_cast<RubberbandCorridor*>(rbnd);
|
||||
rbndCorr->setCoordinateVectorWidth(pointList,wCorr);
|
||||
}
|
||||
else rbnd->setCoordinateVector(pointList);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
} /* RubberbandFactory::defaultSymbolRubberbandCoordinates */
|
||||
|
||||
|
||||
void RubberbandFactory::onActivateRubberband( RubberbandBase * rubberband )
|
||||
{
|
||||
if (nullptr == rubberband) return;
|
||||
|
||||
ActivateRubberbandInfo * arbInfo = static_cast<ActivateRubberbandInfo*>( rubberband->userData() );
|
||||
|
||||
if (nullptr == arbInfo) return;
|
||||
|
||||
const QPointF & position = rubberband->singleCoordinate();
|
||||
const QPointF & pixelPos = _map->geoCoordinateToViewPortWindowPoint(position);
|
||||
|
||||
if (defaultSymbolRubberbandCoordinates( _map, arbInfo->_rubberband, pixelPos, arbInfo->_symbolConstruction))
|
||||
{
|
||||
arbInfo->_rubberband->activate();
|
||||
}
|
||||
else
|
||||
{
|
||||
arbInfo->_rubberband->deleteMySelf();
|
||||
ERROR_LOG(_logger) << LOGFUNCTION << "Can't init symbol rubberband coordinate list, undefined proposal.";
|
||||
}
|
||||
delete arbInfo;
|
||||
rubberband->setUserData(nullptr);
|
||||
} /* RubberbandFactory::onActivateRubberband */
|
||||
|
||||
|
||||
void RubberbandFactory::onAbortRubberband( RubberbandBase * rubberband )
|
||||
{
|
||||
if (nullptr == rubberband) return;
|
||||
|
||||
ActivateRubberbandInfo * arbInfo = static_cast<ActivateRubberbandInfo*>(rubberband->userData());
|
||||
if (arbInfo)
|
||||
{
|
||||
arbInfo->_rubberband->deleteMySelf();
|
||||
delete arbInfo;
|
||||
}
|
||||
rubberband->setUserData(nullptr);
|
||||
} /* RubberbandFactory::onAbortRubberband */
|
||||
|
||||
|
||||
void RubberbandFactory::setRubberbandDrawColor ( const QColor & c ) { _defaults->_rubberbandDrawColor = c; }
|
||||
void RubberbandFactory::setRubberbandFillColor ( const QColor & c ) { _defaults->_rubberbandFillColor = c; }
|
||||
void RubberbandFactory::setRubberbandHandleDrawColor ( const QColor & c ) { _defaults->_rubberbandHandleDrawColor = c; }
|
||||
void RubberbandFactory::setRubberbandHandleFillColor ( const QColor & c ) { _defaults->_rubberbandHandleFillColor = c; }
|
||||
void RubberbandFactory::setRubberbandSelectionColor ( const QColor & c ) { _defaults->_rubberbandSelectionColor = c; }
|
||||
void RubberbandFactory::setRubberbandFrameColor ( const QColor & c ) { _defaults->_rubberbandFrameColor = c; }
|
||||
void RubberbandFactory::setRubberbandFrameFillColor ( const QColor & c ) { _defaults->_rubberbandFrameFillColor = c; }
|
||||
void RubberbandFactory::setRubberbandFrameHandleMargin ( int m ) { _defaults->_rubberbandFrameHandleMargin = m; }
|
||||
void RubberbandFactory::setRubberbandPreviewOffset ( const QPoint & o ) { _defaults->_rubberbandPreviewOffset = o; }
|
||||
void RubberbandFactory::setRubberbandPreviewSize ( unsigned int s ) { _defaults->_rubberbandPreviewSize = s; }
|
||||
void RubberbandFactory::setRubberbandPickingRatio ( unsigned int s ) { _defaults->_rubberbandPickingRatio = s; }
|
||||
void RubberbandFactory::setRubberbandLineHandleWidth ( unsigned int s ) { _defaults->_rubberbandLineHandleWidth = s; }
|
||||
|
||||
|
||||
void RubberbandFactory::setDefaults(RubberbandBase * rband) const
|
||||
{
|
||||
if (nullptr == rband) return;
|
||||
|
||||
if ( _defaults->_rubberbandDrawColor.isValid() ) rband->setDrawColor ( _defaults->_rubberbandDrawColor );
|
||||
if ( _defaults->_rubberbandFillColor.isValid() ) rband->setFillColor ( _defaults->_rubberbandFillColor );
|
||||
if ( _defaults->_rubberbandHandleDrawColor.isValid()) rband->setHandleDrawColor ( _defaults->_rubberbandHandleDrawColor );
|
||||
if ( _defaults->_rubberbandHandleFillColor.isValid()) rband->setHandleFillColor ( _defaults->_rubberbandHandleFillColor );
|
||||
if ( _defaults->_rubberbandSelectionColor.isValid() ) rband->setHandleSelectionColor( _defaults->_rubberbandSelectionColor );
|
||||
if ( _defaults->_rubberbandFrameColor.isValid() ) rband->setFrameColor ( _defaults->_rubberbandFrameColor );
|
||||
if ( _defaults->_rubberbandFrameFillColor.isValid() ) rband->setFrameFillColor ( _defaults->_rubberbandFrameFillColor );
|
||||
|
||||
rband->setFrameHandleMargin( _defaults->_rubberbandFrameHandleMargin );
|
||||
} /* RubberbandFactory::setDefaults */
|
||||
|
||||
|
||||
void RubberbandFactory::setDefaults(Rubberband * rband) const
|
||||
{
|
||||
if (nullptr == rband) return;
|
||||
|
||||
setDefaults( static_cast<RubberbandBase*>(rband) );
|
||||
if (_defaults->_rubberbandPreviewSize > 0) rband->setPreviewSize ( _defaults->_rubberbandPreviewSize );
|
||||
if (_defaults->_rubberbandPickingRatio > 0) rband->setPickingRatio ( _defaults->_rubberbandPickingRatio );
|
||||
|
||||
if (!_defaults->_rubberbandPreviewOffset.isNull()) rband->setPreviewOffset( _defaults->_rubberbandPreviewOffset );
|
||||
|
||||
if (_defaults->_rubberbandLineHandleWidth > 0) rband->setLineHandleWidth ( _defaults->_rubberbandLineHandleWidth );
|
||||
|
||||
RubberbandCorridor *rbCorridor = qobject_cast<RubberbandCorridor*>(rband);
|
||||
if (rbCorridor)
|
||||
{
|
||||
rbCorridor->setCorridorBorderColor(rband->getDrawColor());
|
||||
rbCorridor->setCorridorFillColor(rband->getFillColor());
|
||||
}
|
||||
|
||||
} /* RubberbandFactory::setDefaults */
|
||||
|
||||
|
||||
} } /* namespace SituationMap::RB */
|
||||
+290
@@ -0,0 +1,290 @@
|
||||
/**
|
||||
**
|
||||
** @RDE_HEADER@
|
||||
** Definition of base class for rubberbands
|
||||
** $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
|
||||
**
|
||||
** -----------------------------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "event_dispatcher.h"
|
||||
#include "event_delegater.h"
|
||||
|
||||
#include "rubberband_base.h"
|
||||
#include "rubberband.h"
|
||||
#include "rubberband_arrow.h"
|
||||
#include "rubberband_corridor.h"
|
||||
#include "rubberband_ellipse.h"
|
||||
#include "rubberband_free_hand.h"
|
||||
#include "rubberband_multi_point_feature.h"
|
||||
#include "rubberband_multi_ellipse_feature.h"
|
||||
#include "rubberband_point_cluster.h"
|
||||
#include "rubberband_point_feature.h"
|
||||
#include "rubberband_polyline_width.h"
|
||||
#include "rubberband_rectangle.h"
|
||||
#include "rubberband_smooth_line.h"
|
||||
#include "rubberband_state_select.h"
|
||||
#include "rubberband_transform.h"
|
||||
#include "rubberband_transform_move.h"
|
||||
#include "rubberband_transform_rotate.h"
|
||||
#include "rubberband_transform_scale.h"
|
||||
|
||||
#include "rubberband_3d.h"
|
||||
#include "rubberband_point_feature_3d.h"
|
||||
#include "rubberband_multi_point_feature_3d.h"
|
||||
|
||||
#include <Common/exception.h>
|
||||
#include <Common/situation_map_logging.h>
|
||||
|
||||
#include <QtCore/QObject>
|
||||
|
||||
namespace SituationMap { namespace RB
|
||||
{
|
||||
/**
|
||||
@brief Factory class to create rubberbands
|
||||
|
||||
Rubberbands are used to create or modifiy 2D geometries like lines, circles, polygons etc. on a 2D map view
|
||||
|
||||
Rubberbands are used to create or modifiy 2D geometries like lines, circles, polygons etc. by processing
|
||||
Qt input events like keyboard and mouse events. Following rubberbands are available:
|
||||
|
||||
| Class Name | Description |
|
||||
| :----------------------------- | : --------------------------------------------------------------------------------------- |
|
||||
| RubberbandPointFeature | Rubberband to edit a single position for a point feature. |
|
||||
| RubberbandPointCluster | Rubberband to edit multiple positions to define a cluster of point features. |
|
||||
| RubberbandMultiPointFeature | Rubberband to edit a polyline or polygon to define line or areal features. |
|
||||
| RubberbandSmoothLine | Like RubberbandMultiPointFeature with rounded edges. |
|
||||
| RubberbandPolylineWidth | Rubberband like RubberbandMultiPointFeature for symbols with additional width coordinate. |
|
||||
| RubberbandArrow | Rubberband to edit a polyline with an arrow at the end. |
|
||||
| RubberbandCorridor | Rubberband to edit corridors by defining a polyline and a width. |
|
||||
| RubberbandRectangle | Rubberband to edit a rectangle or square. |
|
||||
| RubberbandEllipse | Rubberband to edit a ellipse or circle. |
|
||||
| RubberbandFreeHand | Rubberband to input a free hand line. |
|
||||
| RubberbandStateSelect | Rubberband to set states to coordinates. |
|
||||
| RubberbandTransform | Rubberband to manipulate moving, rotating and scaling in a single step |
|
||||
| RubberbandTransformMove | Rubberband to define moving transformations |
|
||||
| RubberbandTransformRotate | Rubberband to define rotating transformations |
|
||||
| RubberbandTransformScale | Rubberband to define scaling transformations |
|
||||
|
||||
On a 3D map scene following rubberbands are available:
|
||||
|
||||
| Class Name | Description |
|
||||
| :----------------------------- | : --------------------------------------------------------------------------------------- |
|
||||
| RubberbandPointFeature3D | Rubberband to edit a single position for a point feature. |
|
||||
| RubberbandMultiPointFeature3D | Rubberband to edit a polyline or polygon to define line or areal features. |
|
||||
|
||||
|
||||
@see Rubberband, RubberbandPointFeature, RubberbandPointCluster, RubberbandMultiPointFeature, RubberbandSmoothLine, RubberbandPolylineWidth
|
||||
RubberbandRectangle, RubberbandEllipse, RubberbandCorridor, RubberbandArrow, RubberbandFreeHand, RubberbandStateSelect
|
||||
RubberbandTransform, RubberbandTransformMove, RubberbandTransformRotate, RubberbandTransformScale,
|
||||
Rubberband3D, RubberbandPointFeature3D, RubberbandMultiPointFeature3D
|
||||
|
||||
*/
|
||||
class SITUATIONMAP_EXPORT RubberbandFactory : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
|
||||
explicit RubberbandFactory( SituationMap::Map * map );
|
||||
virtual ~RubberbandFactory();
|
||||
|
||||
/**
|
||||
@brief template methode to create a rubberband instance
|
||||
|
||||
Creates with new a rubberband from type RubberbandClass. RubberbandClass must be inherited
|
||||
from class SiMapRubBnd::Rubberband otherwise a nullptr will be retruned. After use the
|
||||
pointer have to be freed with delete.
|
||||
|
||||
Expample to create a rubberband:
|
||||
@code
|
||||
|
||||
SituationMap::Map & map = ...
|
||||
|
||||
const RubberbandFactory & rubberbandFactory = map.rubberbandFactory();
|
||||
|
||||
RubberbandPointFeature * rubberband = rubberbandFactory.create<RubberbandPointFeature>();
|
||||
if (rubberband != nullptr) doSomething(rubberband);
|
||||
|
||||
@endcode
|
||||
|
||||
@param parent Parent of rubberband object. If parent is nullptr \c _map will be used as parent
|
||||
|
||||
@see Rubberband, RubberbandPointFeature, RubberbandPointCluster, RubberbandMultiPointFeature, RubberbandRectangle, RubberbandEllipse, RubberbandCorridor, RubberbandArrow
|
||||
*/
|
||||
template<class RubberbandClass> RubberbandClass * create( QObject * parent = nullptr ) const
|
||||
{
|
||||
RubberbandClass * rubberband = nullptr;
|
||||
|
||||
if ((std::is_base_of<Rubberband, RubberbandClass>::value) && (Mode::Mode_2D == _map->mode()))
|
||||
{
|
||||
// be careful it is not thread safe here
|
||||
Rubberband::currentFactoryMap(_map);
|
||||
Rubberband::allowMultipleRubberbands(_allowMultipleRubberbands);
|
||||
|
||||
try
|
||||
{
|
||||
rubberband = new RubberbandClass( _map, parent );
|
||||
}
|
||||
catch (const SituationMap::Exception &) {;}
|
||||
setDefaults( rubberband );
|
||||
}
|
||||
return rubberband;
|
||||
}
|
||||
|
||||
/**
|
||||
Creates a new corridor rubberband and defines the input method of the rubberband
|
||||
@param inputMethode Defines the input method of the rubberband
|
||||
@param width With of a corridor in meters.
|
||||
@param parent Parent of rubberband object. If parent is nullptr \c _map will be used as parent
|
||||
@see RubberbandCorridor
|
||||
*/
|
||||
RubberbandCorridor * create( RubberbandCorridor::InputMode inputMode, qreal width = 0, QObject * parent = nullptr ) const
|
||||
{
|
||||
if (!_map->isReady() || (Mode::Mode_2D != _map->mode()) )
|
||||
return nullptr;
|
||||
|
||||
Rubberband::currentFactoryMap(_map);
|
||||
Rubberband::allowMultipleRubberbands(_allowMultipleRubberbands);
|
||||
|
||||
RubberbandCorridor * rubberband = nullptr;
|
||||
try
|
||||
{
|
||||
rubberband = new RubberbandCorridor( _map, inputMode, width, parent );
|
||||
}
|
||||
catch (const SituationMap::Exception &) {;}
|
||||
setDefaults( rubberband );
|
||||
return rubberband;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
Creates a new rubberband fitting to the sidc code
|
||||
@param sidc sidc of symbol that will be created with rubberband.
|
||||
|
||||
@see RubberbandPointFeature, RubberbandMultiPointFeature
|
||||
*/
|
||||
Rubberband * createSymbol( const QString & sidc, QObject * parent = nullptr ) const;
|
||||
|
||||
/**
|
||||
Creates a new rubberband fitting to the sidc code
|
||||
@param sidc sidc of symbol that will be created with rubberband.
|
||||
@param winPos Default position of the rubberband on window
|
||||
|
||||
@see RubberbandPointFeature, RubberbandMultiPointFeature
|
||||
*/
|
||||
Rubberband * createSymbol( const QString & sidc, const QPoint & winPos, QObject * parent = nullptr ) const;
|
||||
|
||||
|
||||
/**
|
||||
@brief template methode to create a rubberband instance in 3D maps
|
||||
|
||||
Creates with new a rubberband from type RubberbandClass. RubberbandClass must be inherited
|
||||
from class SiMapRubBnd::Rubberband otherwise a nullptr will be retruned. After use the
|
||||
pointer have to be freed with delete.
|
||||
|
||||
Expample to create a rubberband:
|
||||
@code
|
||||
|
||||
SituationMap::Map & map = ...
|
||||
|
||||
const RubberbandFactory & rubberbandFactory = map.rubberbandFactory();
|
||||
|
||||
RubberbandPointFeature * rubberband = rubberbandFactory.create<RubberbandPointFeature>();
|
||||
if (rubberband != nullptr) doSomething(rubberband);
|
||||
|
||||
@endcode
|
||||
|
||||
@param parent Parent of rubberband object. If parent is nullptr \c _map will be used as parent
|
||||
|
||||
@see Rubberband, RubberbandPointFeature, RubberbandPointCluster, RubberbandMultiPointFeature, RubberbandRectangle, RubberbandEllipse, RubberbandCorridor, RubberbandArrow
|
||||
*/
|
||||
template<class RubberbandClass> RubberbandClass * create3D( QObject * parent = nullptr ) const
|
||||
{
|
||||
RubberbandClass * rubberband = nullptr;
|
||||
|
||||
if ((std::is_base_of<Rubberband3D, RubberbandClass>::value) && (Mode::Mode_3D == _map->mode()))
|
||||
{
|
||||
// be careful it is not thread safe here
|
||||
RubberbandBase::currentFactoryMap(_map);
|
||||
RubberbandBase::allowMultipleRubberbands(_allowMultipleRubberbands);
|
||||
|
||||
try
|
||||
{
|
||||
rubberband = new RubberbandClass( _map, parent );
|
||||
}
|
||||
catch (const SituationMap::Exception &) {;}
|
||||
setDefaults( rubberband );
|
||||
}
|
||||
return rubberband;
|
||||
};
|
||||
|
||||
/**
|
||||
If pass \c true multiple rubberbands per time can be created per map. Creating a rubberbad of the same type twice per time will return one
|
||||
rubberband that is not alive. Default is \c false. In this case creating a second rubberband before the first has finsihed (rubberband is not alive)
|
||||
will retrun \c nullptr.
|
||||
*/
|
||||
void allowMultipleRubberbands(bool on) { _allowMultipleRubberbands = on; }
|
||||
|
||||
bool allowMultipleRubberbands() const { return _allowMultipleRubberbands; }
|
||||
|
||||
void setRubberbandDrawColor( const QColor & );
|
||||
void setRubberbandFillColor( const QColor & );
|
||||
void setRubberbandHandleDrawColor( const QColor & );
|
||||
void setRubberbandHandleFillColor( const QColor & );
|
||||
void setRubberbandSelectionColor( const QColor & );
|
||||
void setRubberbandFrameColor( const QColor & );
|
||||
void setRubberbandFrameFillColor( const QColor & );
|
||||
void setRubberbandFrameHandleMargin( int );
|
||||
void setRubberbandPreviewOffset( const QPoint & );
|
||||
void setRubberbandPreviewSize( unsigned int );
|
||||
void setRubberbandPickingRatio( unsigned int );
|
||||
void setRubberbandLineHandleWidth( unsigned int );
|
||||
|
||||
signals:
|
||||
|
||||
void rubberbandCreated();
|
||||
void rubberbandDestroyed();
|
||||
|
||||
private:
|
||||
|
||||
class Defaults;
|
||||
|
||||
SituationMap::Map * _map;
|
||||
Defaults * _defaults;
|
||||
bool _allowMultipleRubberbands;
|
||||
|
||||
LOGGER_T _logger;
|
||||
|
||||
void setDefaults( RubberbandBase * ) const;
|
||||
void setDefaults( Rubberband * ) const;
|
||||
|
||||
private slots:
|
||||
|
||||
void onActivateRubberband( RubberbandBase * rubberband );
|
||||
void onAbortRubberband ( RubberbandBase * rubberband );
|
||||
|
||||
}; /* RubberbandFactory */
|
||||
|
||||
} } /* namespace SituationMap::RB */
|
||||
@@ -0,0 +1,314 @@
|
||||
|
||||
/**
|
||||
**
|
||||
** @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 ¢er, 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 */
|
||||
@@ -0,0 +1,153 @@
|
||||
/**
|
||||
**
|
||||
** @RDE_HEADER@
|
||||
** Definition 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
|
||||
**
|
||||
** -----------------------------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <QtCore/QPointF>
|
||||
|
||||
#include <QtWidgets/QGraphicsPolygonItem>
|
||||
#include <cmath>
|
||||
|
||||
#include <Common/ref_pointer.h>
|
||||
|
||||
#include "rubberband_handle.h"
|
||||
#include "rubberband_line_handle.h"
|
||||
|
||||
class QGraphicsScene;
|
||||
|
||||
namespace SituationMap { namespace RB
|
||||
{
|
||||
|
||||
|
||||
/**
|
||||
@class RubberbandFrameHandle rubberband_frame_handle.h
|
||||
@brief Implementation of a frame handle for rubberband internal use.
|
||||
@see RubberbandHandle
|
||||
*/
|
||||
class RubberbandFrameHandle : public RubberbandHandle
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
|
||||
RubberbandFrameHandle( Esri::ArcGISRuntime::MapGraphicsView * mapView
|
||||
, QGraphicsScene * scene
|
||||
, qreal sceneMargin );
|
||||
|
||||
~RubberbandFrameHandle();
|
||||
|
||||
inline void updateFrameShape(const QVector<RubberbandCoordinate> & vertexList)
|
||||
{
|
||||
updateFrameShape( vertexList, 0.0, 1.0 );
|
||||
} /* updateFrameShape */
|
||||
|
||||
|
||||
void updateFrameShape( const QVector<RubberbandCoordinate> & vertexList, qreal sinA, qreal cosA );
|
||||
|
||||
bool isPositionInside( const QPointF & scenePosition ) const override;
|
||||
|
||||
virtual void updateCoordinate( const QPointF & scenePosition );
|
||||
virtual void moveCoordinate ( const QPointF & sceneDelta );
|
||||
|
||||
virtual RubberbandCoordinate getCoordinate() const;
|
||||
|
||||
inline qreal frameRotationAngle() const
|
||||
{
|
||||
qreal phi = acos(_frameRotationCos);
|
||||
return (_frameRotationSin < 0.0) ? -phi : phi;
|
||||
} /* frameRotationAngle */
|
||||
|
||||
|
||||
inline void frameRotationAngle( qreal & sinA, qreal & cosA )
|
||||
{
|
||||
sinA = _frameRotationSin;
|
||||
cosA = _frameRotationCos;
|
||||
} /* frameRotationAngle */
|
||||
|
||||
inline qreal frameSceneMargin() const { return _frameSceneMargin; }
|
||||
|
||||
inline void updateFrameRotationAngle( qreal sinA, qreal cosA )
|
||||
{
|
||||
_frameRotationSin = sinA;
|
||||
_frameRotationCos = cosA;
|
||||
updateFrameShape();
|
||||
} /* updateFrameRotationAngle */
|
||||
|
||||
|
||||
inline void updateFrameRotationAngle( qreal x )
|
||||
{
|
||||
_frameRotationSin = sin(x);
|
||||
_frameRotationCos = cos(x);
|
||||
updateFrameShape();
|
||||
} /* updateFrameRotationAngle */
|
||||
|
||||
|
||||
inline void updateFrameSceneMargin(qreal x) { _frameSceneMargin = x; updateFrameShape(); }
|
||||
|
||||
|
||||
inline void drawDisabled(bool v)
|
||||
{
|
||||
_drawDisabled = v;
|
||||
if (_drawDisabled) _frameSymbol->hide();
|
||||
else _frameSymbol->show();
|
||||
} /* drawDisabled */
|
||||
|
||||
|
||||
inline bool drawDisabled() const { return _drawDisabled; }
|
||||
|
||||
|
||||
protected:
|
||||
|
||||
QGraphicsPolygonItem * _frameSymbol;
|
||||
qreal _frameSceneMargin;
|
||||
qreal _frameRotationSin;
|
||||
qreal _frameRotationCos;
|
||||
qreal _frameWidth;
|
||||
qreal _frameHeight;
|
||||
RubberbandCoordinate _frameCenterCoordinate;
|
||||
RubberbandCoordinate _frameVertexCoordinate[4];
|
||||
qreal _mapRotateSin;
|
||||
qreal _mapRotateCos;
|
||||
bool _drawDisabled;
|
||||
|
||||
QList<SituationMap::RefPointer<RubberbandLineHandle>> _frameLineHandleList;
|
||||
|
||||
void updateGraphic() override;
|
||||
|
||||
void updateFrameShape();
|
||||
void updateFramePolygonItem();
|
||||
|
||||
void buildFrameVertexCoordinates();
|
||||
|
||||
void adjustCoordinates() override;
|
||||
void adjustWindow( const QRectF& ) override;
|
||||
|
||||
QPointF getMapRotation() { return QPointF( _mapRotateCos, _mapRotateSin ); }
|
||||
|
||||
}; /* RubberbandFrameHandle */
|
||||
|
||||
} } /* namespace SituationMap::RB */
|
||||
@@ -0,0 +1,267 @@
|
||||
|
||||
/**
|
||||
**
|
||||
** @RDE_HEADER@
|
||||
** Implementation of rubberband class to define point feature geoemtry
|
||||
** $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_free_hand.h"
|
||||
#include "rubberband_point_handle.h"
|
||||
#include "rubberband_drawable.h"
|
||||
#include "drawable_line.h"
|
||||
#include "drawable_painter_path.h"
|
||||
#include "rubberband_handle_proxy.h"
|
||||
|
||||
#include "rubberband_internal.h"
|
||||
#include "rubberband_base_internal.h"
|
||||
|
||||
#include <arcgis/MapGraphicsView.h>
|
||||
|
||||
namespace SituationMap { namespace RB
|
||||
{
|
||||
|
||||
struct RubberbandFreeHand::InternalData
|
||||
{
|
||||
QVector<RubberbandDrawable::RubberbandCoordinate> _coordinateList;
|
||||
QVector<unsigned int> _inOneGoIndex;
|
||||
QPoint _lastWindowPos;
|
||||
bool _coordinateRecordingActive = false;
|
||||
SituationMap::RefPointer<DrawableLine> _cursorPreviewLine;
|
||||
SituationMap::RefPointer<DrawableLine> _cursorPreviewCloseLine;
|
||||
SituationMap::RefPointer<DrawablePainterPath> _pathItem;
|
||||
}; /* RubberbandFreeHand::InternalData */
|
||||
|
||||
|
||||
RubberbandFreeHand::RubberbandFreeHand( SituationMap::Map * map, QObject * parent )
|
||||
: Rubberband(map,parent)
|
||||
, _internal(new RubberbandFreeHand::InternalData)
|
||||
, _isClosed(false)
|
||||
{
|
||||
} /* RubberbandFreeHand::RubberbandFreeHand */
|
||||
|
||||
|
||||
RubberbandFreeHand::~RubberbandFreeHand()
|
||||
{
|
||||
delete _internal;
|
||||
_internal = nullptr;
|
||||
} /* RubberbandFreeHand::~RubberbandFreeHand */
|
||||
|
||||
|
||||
bool RubberbandFreeHand::selectAction( AbstractEventDispatcher * causer, int x, int y )
|
||||
{
|
||||
if (Rubberband::selectAction(causer, x, y))
|
||||
{
|
||||
deactivateButtons();
|
||||
_internal->_coordinateRecordingActive = true;
|
||||
_internal->_inOneGoIndex << _internal->_coordinateList.size();
|
||||
return movePickedAction(causer,x,y);
|
||||
}
|
||||
return false;
|
||||
} /* RubberbandFreeHand::selectAction */
|
||||
|
||||
|
||||
bool RubberbandFreeHand::movePickedAction( AbstractEventDispatcher *, int x, int y )
|
||||
{
|
||||
if (_internal->_coordinateRecordingActive)
|
||||
{
|
||||
QPointF scenePos(pixel2ScenePosition(x,y));
|
||||
if (_internal->_coordinateList.isEmpty())
|
||||
{
|
||||
_internal->_lastWindowPos.setX(x);
|
||||
_internal->_lastWindowPos.setY(y);
|
||||
_internal->_coordinateList.append(RubberbandDrawable::RubberbandCoordinate(Rubberband::_internal->_mapView,scenePos));
|
||||
return true;
|
||||
}
|
||||
|
||||
if ((std::abs(_internal->_lastWindowPos.x() - x) > 2) || (std::abs(_internal->_lastWindowPos.y() - y) > 2))
|
||||
{
|
||||
_internal->_lastWindowPos.setX(x);
|
||||
_internal->_lastWindowPos.setY(y);
|
||||
|
||||
_internal->_coordinateList.append(RubberbandDrawable::RubberbandCoordinate(Rubberband::_internal->_mapView,scenePos));
|
||||
}
|
||||
|
||||
update();
|
||||
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
} /* RubberbandFreeHand::movePickedAction */
|
||||
|
||||
|
||||
bool RubberbandFreeHand::moveAction( AbstractEventDispatcher *, int x, int y )
|
||||
{
|
||||
if (!_internal->_coordinateList.isEmpty())
|
||||
{
|
||||
const RubberbandDrawable::RubberbandCoordinate & firstPos = _internal->_coordinateList.first();
|
||||
const RubberbandDrawable::RubberbandCoordinate & lastPos = _internal->_coordinateList.last();
|
||||
|
||||
QPointF scenePos(pixel2ScenePosition(x,y));
|
||||
|
||||
if (!_internal->_cursorPreviewLine) _internal->_cursorPreviewLine = new DrawableLine( Rubberband::_internal->_mapView, Rubberband::_internal->_mapScene );
|
||||
if ((isClosedEnabled()) && (!_internal->_cursorPreviewCloseLine))
|
||||
{
|
||||
_internal->_cursorPreviewCloseLine = new DrawableLine( Rubberband::_internal->_mapView, Rubberband::_internal->_mapScene );
|
||||
}
|
||||
_internal -> _cursorPreviewLine -> setVisibility( true );
|
||||
_internal -> _cursorPreviewLine -> setDrawColor( _handleSelectionColor );
|
||||
_internal -> _cursorPreviewLine -> setLine( lastPos, RubberbandDrawable::RubberbandCoordinate( Rubberband::_internal->_mapView, scenePos ));
|
||||
|
||||
if (_internal->_cursorPreviewCloseLine)
|
||||
{
|
||||
_internal -> _cursorPreviewCloseLine -> setVisibility( true );
|
||||
_internal -> _cursorPreviewCloseLine -> setDrawColor( _handleSelectionColor );
|
||||
_internal -> _cursorPreviewCloseLine -> setLine( firstPos, RubberbandDrawable::RubberbandCoordinate( Rubberband::_internal->_mapView, scenePos ));
|
||||
}
|
||||
}
|
||||
return false;
|
||||
} /* RubberbandFreeHand::moveAction */
|
||||
|
||||
|
||||
bool RubberbandFreeHand::setCoordinateAction( AbstractEventDispatcher * causer, int x, int y )
|
||||
{
|
||||
_internal->_coordinateRecordingActive = false;
|
||||
|
||||
if (Rubberband::setCoordinateAction(causer,x,y))
|
||||
{
|
||||
QPointF scenePos(pixel2ScenePosition(x,y));
|
||||
activateButtons();
|
||||
_baseInternal->buttonProxyActive( scenePos );
|
||||
}
|
||||
return false;
|
||||
} /* RubberbandFreeHand::setCoordinateAction */
|
||||
|
||||
|
||||
void RubberbandFreeHand::activateButtons()
|
||||
{
|
||||
_baseInternal->_hasUndoButton = true;
|
||||
_baseInternal->_applyIsPossible = true;
|
||||
_baseInternal->_undoIsPossible = !_internal->_inOneGoIndex.isEmpty();
|
||||
|
||||
Rubberband::activateButtons();
|
||||
} /* RubberbandFreeHand::activateButtons */
|
||||
|
||||
|
||||
bool RubberbandFreeHand::undoAction( AbstractEventDispatcher*, int, int )
|
||||
{
|
||||
if (!_internal->_inOneGoIndex.isEmpty())
|
||||
{
|
||||
unsigned int coordinateIdx = _internal->_inOneGoIndex.takeLast();
|
||||
|
||||
while (coordinateIdx < (unsigned int)_internal->_coordinateList.size())
|
||||
{
|
||||
_internal->_coordinateList.removeLast();
|
||||
}
|
||||
update();
|
||||
activateButtons();
|
||||
}
|
||||
return true;
|
||||
} /* RubberbandFreeHand::undoAction */
|
||||
|
||||
|
||||
bool RubberbandFreeHand::completeStateAction( AbstractEventDispatcher * causer, int x, int y )
|
||||
{
|
||||
if (rubberbandIsAlive())
|
||||
{
|
||||
return applyAndEndAction(causer,x,y);
|
||||
}
|
||||
return false;
|
||||
} /* RubberbandFreeHand::completeStateAction */
|
||||
|
||||
|
||||
unsigned int RubberbandFreeHand::coordinateCount() const
|
||||
{
|
||||
return _internal->_coordinateList.size();
|
||||
} /* RubberbandFreeHand::coordinateCount */
|
||||
|
||||
|
||||
QVector<QPointF> RubberbandFreeHand::coordinateVector( CoordinateSystem cs ) const
|
||||
{
|
||||
QVector<QPointF> coordinateVector;
|
||||
coordinateVector.reserve(_internal->_coordinateList.size());
|
||||
|
||||
for (const RubberbandDrawable::RubberbandCoordinate &pos : qAsConst(_internal->_coordinateList))
|
||||
coordinateVector.push_back(projectCoordinateFromMap( cs, pos._mapCoordinate ));
|
||||
|
||||
return coordinateVector;
|
||||
|
||||
} /* RubberbandFreeHand::coordinateVector */
|
||||
|
||||
|
||||
QPointF RubberbandFreeHand::singleCoordinate(unsigned int idx, CoordinateSystem cs ) const
|
||||
{
|
||||
if (idx >= (unsigned int)_internal->_coordinateList.size()) return QPointF();
|
||||
|
||||
const Esri::ArcGISRuntime::Point & pos = _internal->_coordinateList.at(idx)._mapCoordinate;
|
||||
|
||||
return projectCoordinateFromMap( cs, pos );
|
||||
|
||||
} /* RubberbandFreeHand::singleCoordinate */
|
||||
|
||||
|
||||
void RubberbandFreeHand::update()
|
||||
{
|
||||
if (_internal->_coordinateList.size() > 1)
|
||||
{
|
||||
if (!_internal->_pathItem)
|
||||
{
|
||||
_internal->_pathItem = new DrawablePainterPath( Rubberband::_internal->_mapView );
|
||||
}
|
||||
_internal -> _pathItem -> setVisibility(true);
|
||||
_internal -> _pathItem -> setLineWidth( 2 );
|
||||
_internal -> _pathItem -> enableClosedLine( _isClosed );
|
||||
_internal -> _pathItem -> setDrawColor( _drawColor );
|
||||
_internal -> _pathItem -> setFillColor( _fillColor );
|
||||
_internal -> _pathItem -> setPath( _internal->_coordinateList );
|
||||
}
|
||||
else
|
||||
{
|
||||
if (_internal -> _pathItem) _internal->_pathItem->setVisibility(false);
|
||||
if (_internal->_coordinateList.isEmpty())
|
||||
{
|
||||
if (_internal -> _cursorPreviewLine ) _internal -> _cursorPreviewLine -> setVisibility(false);
|
||||
if (_internal -> _cursorPreviewCloseLine) _internal -> _cursorPreviewCloseLine -> setVisibility(false);
|
||||
}
|
||||
}
|
||||
if (!_internal->_coordinateList.isEmpty())
|
||||
{
|
||||
QPointF bottomRight( std::numeric_limits<double>::min(), std::numeric_limits<double>::min() );
|
||||
|
||||
for (const RubberbandDrawable::RubberbandCoordinate &coordinate : qAsConst(_internal->_coordinateList))
|
||||
{
|
||||
const QPointF & p = coordinate._sceneCoordinate;
|
||||
if (bottomRight.x() < p.x()) bottomRight.setX(p.x());
|
||||
if (bottomRight.y() < p.y()) bottomRight.setY(p.y());
|
||||
}
|
||||
|
||||
if (isButtonBoxPositionFixed())
|
||||
{
|
||||
RubberbandBase::_baseInternal->_buttonBoxSceneAnchor = bottomRight;
|
||||
}
|
||||
}
|
||||
} /* RubberbandFreeHand::update */
|
||||
|
||||
|
||||
} } /* namespace SituationMap::RB */
|
||||
+102
@@ -0,0 +1,102 @@
|
||||
/**
|
||||
**
|
||||
** @RDE_HEADER@
|
||||
** Definition of rubberband class for free hand drawing
|
||||
** $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 .........:
|
||||
**
|
||||
** 06.10.2015, JT : First edition for use with Qt5
|
||||
**
|
||||
** -----------------------------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "rubberband.h"
|
||||
|
||||
|
||||
namespace SituationMap { namespace RB
|
||||
{
|
||||
|
||||
/**
|
||||
@class RubberbandPointCluster rubberband_point_cluster.h
|
||||
@brief Implementation of a rubberband to input single coodinates for building point feature clusters
|
||||
@see Rubberband, RubberbandPointFeature
|
||||
*/
|
||||
class SITUATIONMAP_EXPORT RubberbandFreeHand : public Rubberband
|
||||
{
|
||||
Q_OBJECT
|
||||
/**
|
||||
@name Construction & Destruction
|
||||
@{
|
||||
*/
|
||||
|
||||
friend class RubberbandFactory;
|
||||
explicit RubberbandFreeHand( SituationMap::Map * map, QObject * parent = nullptr );
|
||||
|
||||
public:
|
||||
|
||||
~RubberbandFreeHand();
|
||||
/** @} */
|
||||
|
||||
bool selectAction ( AbstractEventDispatcher * causer, int x, int y ) override;
|
||||
bool movePickedAction ( AbstractEventDispatcher * causer, int x, int y ) override;
|
||||
bool moveAction ( AbstractEventDispatcher * causer, int x, int y ) override;
|
||||
bool setCoordinateAction ( AbstractEventDispatcher * causer, int x, int y ) override;
|
||||
bool completeStateAction ( AbstractEventDispatcher * causer, int x, int y ) override;
|
||||
bool undoAction ( AbstractEventDispatcher * causer, int x, int y ) override;
|
||||
|
||||
unsigned int coordinateCount() const override;
|
||||
|
||||
virtual QVector<QPointF> coordinateVector( CoordinateSystem cs = CoordinateSystem::Geo ) const override;
|
||||
|
||||
virtual QPointF singleCoordinate( unsigned int idx = 0, CoordinateSystem cs = CoordinateSystem::Geo ) const override;
|
||||
|
||||
/**
|
||||
If set to true a polygon the rubberband draws a polygon otherwise a polyline.
|
||||
*/
|
||||
inline void enableClosed( bool flag ) { _isClosed = flag; }
|
||||
|
||||
/**
|
||||
Gets the value of the close flag
|
||||
*/
|
||||
inline bool isClosedEnabled() const { return _isClosed; }
|
||||
|
||||
|
||||
private:
|
||||
|
||||
virtual void setCoordinateVector( const QVector<QPointF> & /*pntList*/, CoordinateSystem /*cs*/ = CoordinateSystem::Geo ) override {}
|
||||
|
||||
protected:
|
||||
|
||||
/*
|
||||
Forward declaration of internal container class for member variables. The derived classes of Rubberband
|
||||
often have also a declaration of InternalData for there own internal members.
|
||||
*/
|
||||
struct InternalData;
|
||||
|
||||
InternalData * _internal;
|
||||
bool _isClosed;
|
||||
|
||||
void activateButtons() override;
|
||||
void update() override;
|
||||
|
||||
}; /* RubberbandFreeHand */
|
||||
|
||||
} } /* namespace SituationMap::RB */
|
||||
@@ -0,0 +1,70 @@
|
||||
/**
|
||||
**
|
||||
** @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_handle.h"
|
||||
|
||||
namespace SituationMap { namespace RB
|
||||
{
|
||||
|
||||
|
||||
RubberbandHandle::RubberbandHandle( QGraphicsView *view )
|
||||
: RubberbandDrawable(view)
|
||||
, _pickingRatio(5)
|
||||
, _isSelected(false)
|
||||
, _isSelectable(true)
|
||||
, _userData(nullptr)
|
||||
{
|
||||
} /* RubberbandHandle::RubberbandHandle */
|
||||
|
||||
|
||||
|
||||
RubberbandHandle::RubberbandHandle( Esri::ArcGISRuntime::MapGraphicsView * mapView )
|
||||
: RubberbandDrawable( mapView )
|
||||
, _pickingRatio(5)
|
||||
, _isSelected(false)
|
||||
, _isSelectable(true)
|
||||
, _userData(nullptr)
|
||||
{
|
||||
} /* RubberbandHandle::RubberbandHandle */
|
||||
|
||||
|
||||
RubberbandHandle::RubberbandHandle( Esri::ArcGISRuntime::MapGraphicsView * mapView, QGraphicsScene * scene)
|
||||
: RubberbandDrawable( mapView, scene )
|
||||
, _pickingRatio(5)
|
||||
, _isSelected(false)
|
||||
, _isSelectable(true)
|
||||
, _userData(nullptr)
|
||||
{
|
||||
} /* RubberbandHandle::RubberbandHandle */
|
||||
|
||||
|
||||
RubberbandHandle::~RubberbandHandle()
|
||||
{
|
||||
} /* RubberbandHandle::~Rubberbandhandle */
|
||||
|
||||
} } /* namespace SituationMap::RB */
|
||||
+100
@@ -0,0 +1,100 @@
|
||||
/**
|
||||
**
|
||||
** @RDE_HEADER@
|
||||
** Definition 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
|
||||
**
|
||||
** -----------------------------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "rubberband_drawable.h"
|
||||
|
||||
namespace SituationMap { namespace RB
|
||||
{
|
||||
|
||||
/**
|
||||
@class RubberbandHandle rubberband_handle.h
|
||||
@brief Base class of all rubberband handles for rubberband internal use.
|
||||
*/
|
||||
class RubberbandHandle : public RubberbandDrawable
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
|
||||
/**
|
||||
@name Construction & Destruction
|
||||
@{
|
||||
*/
|
||||
explicit RubberbandHandle( QGraphicsView * );
|
||||
explicit RubberbandHandle( Esri::ArcGISRuntime::MapGraphicsView * );
|
||||
explicit RubberbandHandle( Esri::ArcGISRuntime::MapGraphicsView *, QGraphicsScene * );
|
||||
|
||||
~RubberbandHandle();
|
||||
/** @} */
|
||||
|
||||
|
||||
virtual bool isPositionInside( const QPointF & scenePosition ) const = 0;
|
||||
|
||||
inline bool isSelected() const { return _isSelected; }
|
||||
inline void setSelection( bool on = true ) { _isSelected = _isSelectable && on; updateGraphic(); }
|
||||
|
||||
inline bool isSelectable() const { return _isSelectable; }
|
||||
inline void setSelectable(bool on = true) { _isSelectable = on; if (!on) { _isSelected = false; updateGraphic(); } }
|
||||
|
||||
inline void setSelectionColor( const QColor & col ) { _selectionColor = col; updateGraphic(); }
|
||||
|
||||
inline void setUserData( void * ptr ) { _userData = ptr; }
|
||||
inline void* userData() { return _userData; }
|
||||
|
||||
inline unsigned int pickingRatio() const { return _pickingRatio; }
|
||||
inline void setPickingRatio(unsigned int value) { if (value > 5) _pickingRatio = value; }
|
||||
|
||||
inline bool isFirst() const { return _is_first; }
|
||||
inline void setIsFirst(bool on = true) { _is_first = on; }
|
||||
|
||||
protected:
|
||||
|
||||
void updateGraphic() override = 0;
|
||||
|
||||
void adjustCoordinates() override = 0;
|
||||
void adjustWindow( const QRectF& ) override = 0;
|
||||
|
||||
unsigned int _pickingRatio;
|
||||
bool _isSelected;
|
||||
bool _isSelectable;
|
||||
QColor _selectionColor;
|
||||
bool _is_first{false};
|
||||
|
||||
private:
|
||||
|
||||
void * _userData;
|
||||
|
||||
signals:
|
||||
|
||||
void adjusted();
|
||||
|
||||
}; /* RubberbandHandle */
|
||||
|
||||
} } /* namespace SituationMap::RB */
|
||||
@@ -0,0 +1,167 @@
|
||||
|
||||
/**
|
||||
**
|
||||
** @RDE_HEADER@
|
||||
** Implementation of class RubberbandHandleProxy to forward adjust signals from view
|
||||
** $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 .........:
|
||||
**
|
||||
** 10.07.2015, JT : First edition for use with Qt5
|
||||
**
|
||||
** -----------------------------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
#include "rubberband_handle_proxy.h"
|
||||
|
||||
#include <MathUtils/math_const.h>
|
||||
|
||||
#include <QtCore/QRectF>
|
||||
|
||||
#define BUG_iOSQz_000005
|
||||
|
||||
|
||||
namespace SituationMap { namespace RB
|
||||
{
|
||||
|
||||
void RubberbandHandleProxy::init( QWidget * widget )
|
||||
{
|
||||
zBufferPlane( ZBufferPlane::Widget );
|
||||
|
||||
_widgetsProxy = new QGraphicsProxyWidget();
|
||||
_widgetsProxy -> setWidget( widget );
|
||||
_widgetsProxy -> setZValue( _zBufferValue );
|
||||
|
||||
#ifdef BUG_iOSQz_000005
|
||||
// Bug iOSQz-000005 'QGraphicsProxyWidget will crash'
|
||||
// Adding a widget will let the application crash
|
||||
// Workaround: 'proxy->setOpacity(0.99);'
|
||||
|
||||
_widgetsProxy->setOpacity(0.99);
|
||||
#endif
|
||||
|
||||
_scene->addItem( _widgetsProxy );
|
||||
|
||||
} /* RubberbandHandleProxy::init */
|
||||
|
||||
|
||||
RubberbandHandleProxy::RubberbandHandleProxy( QGraphicsView * view, QWidget * widget )
|
||||
: RubberbandHandle(view)
|
||||
, _coordinate()
|
||||
, _sceneOffset(0, 0)
|
||||
, _rotateSceneOffset(true)
|
||||
, _restoreView(view)
|
||||
{
|
||||
init( widget );
|
||||
} /* RubberbandHandleProxy::RubberbandHandleProxy */
|
||||
|
||||
|
||||
RubberbandHandleProxy::RubberbandHandleProxy( Esri::ArcGISRuntime::MapGraphicsView * view, QWidget * widget )
|
||||
: RubberbandHandle(view)
|
||||
, _coordinate()
|
||||
, _sceneOffset(0, 0)
|
||||
, _rotateSceneOffset(true)
|
||||
, _restoreView(view)
|
||||
{
|
||||
init( widget );
|
||||
} /* RubberbandHandleProxy::RubberbandHandleProxy */
|
||||
|
||||
|
||||
RubberbandHandleProxy::RubberbandHandleProxy( Esri::ArcGISRuntime::MapGraphicsView * view, QGraphicsScene * scene, QWidget * widget )
|
||||
: RubberbandHandle(view, scene)
|
||||
, _coordinate()
|
||||
, _sceneOffset(0, 0)
|
||||
, _rotateSceneOffset(true)
|
||||
, _restoreView(view)
|
||||
{
|
||||
init( widget );
|
||||
} /* RubberbandHandleProxy::RubberbandHandleProxy */
|
||||
|
||||
|
||||
RubberbandHandleProxy::~RubberbandHandleProxy()
|
||||
{
|
||||
if (_scene)
|
||||
{
|
||||
if (_widgetsProxy)
|
||||
{
|
||||
_widgetsProxy->setWidget(nullptr);
|
||||
_scene->removeItem(_widgetsProxy);
|
||||
delete _widgetsProxy;
|
||||
}
|
||||
}
|
||||
_widgetsProxy = nullptr;
|
||||
|
||||
if (_restoreView && _restoreView->viewport())
|
||||
_restoreView->viewport()->setCursor(_restoreCursor); // workaround Qt bug. remove when fixed
|
||||
|
||||
} /* RubberbandHandleProxy::~RubberbandHandleProxy */
|
||||
|
||||
|
||||
QPointF RubberbandHandleProxy::getRotatedSceneOffset() const
|
||||
{
|
||||
if ((_mapView) && (_rotateSceneOffset))
|
||||
{
|
||||
auto rotate = [](const QPointF & p, qreal sinA, qreal cosA) -> QPointF { return QPointF(p.x()*cosA+p.y()*sinA,p.y()*cosA-p.x()*sinA); };
|
||||
|
||||
qreal mapRotatePhi = _mapView->mapRotation() * MathConst::pi / 180.0;
|
||||
|
||||
qreal sinMap = sin(mapRotatePhi);
|
||||
qreal cosMap = cos(mapRotatePhi);
|
||||
|
||||
return rotate( _sceneOffset, sinMap, cosMap );
|
||||
}
|
||||
else return _sceneOffset;
|
||||
} /* RubberbandHandleProxy::getRotatedSceneOffset */
|
||||
|
||||
|
||||
void RubberbandHandleProxy::setPos(const QPointF & pos)
|
||||
{
|
||||
_coordinate.updateSceneCoordinate( _mapView, pos );
|
||||
if (_widgetsProxy)
|
||||
{
|
||||
_widgetsProxy -> setPos(pos+getRotatedSceneOffset());
|
||||
_widgetsProxy -> setZValue( _zBufferValue );
|
||||
}
|
||||
} /* RubberbandHandleProxy::setPos */
|
||||
|
||||
|
||||
bool RubberbandHandleProxy::isPositionInside( const QPointF & scenePosition ) const
|
||||
{
|
||||
const QRectF & bbox = _widgetsProxy->windowFrameGeometry();
|
||||
return bbox.contains(scenePosition);
|
||||
} /* RubberbandHandleProxy::isPositionInside */
|
||||
|
||||
|
||||
void RubberbandHandleProxy::adjustCoordinates()
|
||||
{
|
||||
const QPointF & scenePosition = _coordinate.mapToScene(_mapView);
|
||||
if (_widgetsProxy)
|
||||
{
|
||||
_widgetsProxy -> setZValue( _zBufferValue );
|
||||
_widgetsProxy -> setPos(scenePosition+getRotatedSceneOffset());
|
||||
}
|
||||
emit adjusted();
|
||||
} /* RubberbandHandleProxy::adjustCoordinates */
|
||||
|
||||
|
||||
void RubberbandHandleProxy::adjustWindow( const QRectF & )
|
||||
{
|
||||
onDo_adjustCoordinates();
|
||||
} /* RubberbandHandleProxy::adjustWindow */
|
||||
|
||||
} } /* namespace SituationMap::RB */
|
||||
@@ -0,0 +1,104 @@
|
||||
/**
|
||||
**
|
||||
** @RDE_HEADER@
|
||||
** Definition of class RubberbandHandleProxy to forward adjust signals from View
|
||||
** $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 .........:
|
||||
**
|
||||
** 10.07.2015, JT : First edition for use with Qt5
|
||||
**
|
||||
** -----------------------------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "rubberband_handle.h"
|
||||
|
||||
#include <QtWidgets/QGraphicsProxyWidget>
|
||||
|
||||
class QGraphicsView;
|
||||
class QGraphicsScene;
|
||||
|
||||
namespace SituationMap { namespace RB
|
||||
{
|
||||
|
||||
/**
|
||||
@class RubberbandHandleProxy rubberband_handle_proxy.h
|
||||
@brief Implementation of a procx to handle small menues and other widgets like buttons
|
||||
@see RubberbandHandle
|
||||
*/
|
||||
class RubberbandHandleProxy : public RubberbandHandle
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
|
||||
/**
|
||||
@name Construction & Destruction
|
||||
@{
|
||||
*/
|
||||
RubberbandHandleProxy( QGraphicsView *view, QWidget * widget );
|
||||
|
||||
RubberbandHandleProxy( Esri::ArcGISRuntime::MapGraphicsView * view, QWidget * widget );
|
||||
RubberbandHandleProxy( Esri::ArcGISRuntime::MapGraphicsView * view, QGraphicsScene * scene, QWidget * widget );
|
||||
|
||||
~RubberbandHandleProxy();
|
||||
/** @} */
|
||||
|
||||
bool isPositionInside( const QPointF & scenePosition ) const override;
|
||||
|
||||
void setPos(const QPointF & pos);
|
||||
|
||||
const RubberbandCoordinate & getCoordinate() const { return _coordinate; }
|
||||
|
||||
inline void setSceneOffset(const QPointF & offset) { _sceneOffset = offset; }
|
||||
|
||||
inline void show() { setVisibility(false); if (_widgetsProxy) { _widgetsProxy->show(); setVisibility(true); } }
|
||||
inline void hide() { setVisibility(false); if (_widgetsProxy) { _widgetsProxy->hide(); setVisibility(false); } }
|
||||
|
||||
inline void setRotateSceneOffset(bool on = true) { _rotateSceneOffset = on; }
|
||||
|
||||
inline void setRestoreCursor( const QCursor & cursor ) { _restoreCursor = cursor; } // workaround Qt bug. remove when fixed
|
||||
|
||||
protected:
|
||||
|
||||
RubberbandCoordinate _coordinate;
|
||||
QGraphicsProxyWidget * _widgetsProxy = nullptr;
|
||||
QPointF _sceneOffset;
|
||||
bool _rotateSceneOffset;
|
||||
|
||||
QPointer<QGraphicsView> _restoreView;
|
||||
QCursor _restoreCursor; // workaround Qt bug. remove when fixed
|
||||
|
||||
void updateGraphic() override {}
|
||||
|
||||
void adjustCoordinates() override;
|
||||
void adjustWindow( const QRectF& ) override;
|
||||
|
||||
private:
|
||||
|
||||
QPointF getRotatedSceneOffset() const;
|
||||
|
||||
private:
|
||||
|
||||
void init( QWidget * widget );
|
||||
|
||||
}; /* RubberbandHandleProxy */
|
||||
|
||||
} } /* namespace SituationMap::RB */
|
||||
@@ -0,0 +1,98 @@
|
||||
/**
|
||||
**
|
||||
** @RDE_HEADER@
|
||||
** Definition of internal data of base class for rubberbands
|
||||
** $Id$
|
||||
** $HeadURL$
|
||||
** $Author$
|
||||
**
|
||||
** -----------------------------------------------------------------------------------------------
|
||||
**
|
||||
** Hardware-Environment: Intel-PC
|
||||
** Software-Environment: Windows 7, Qt 5.4. ArcGIS 10.2.5
|
||||
**
|
||||
** Language ........: C++ 11
|
||||
**
|
||||
** -----------------------------------------------------------------------------------------------
|
||||
**
|
||||
** Author ...........: Joerg Turla, SPD G, Tel. 3132
|
||||
**
|
||||
** -----------------------------------------------------------------------------------------------
|
||||
**
|
||||
** Notes .........:
|
||||
**
|
||||
** 16.06.2015, JT : First edition for use with Qt5
|
||||
**
|
||||
** -----------------------------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
#include "rubberband_internal.h"
|
||||
#include "rubberband.h"
|
||||
|
||||
#include "rubberband_drawable.h"
|
||||
#include "rubberband_handle.h"
|
||||
#include "rubberband_handle_proxy.h"
|
||||
|
||||
#include <Map/map.h>
|
||||
#include <MapImpl/map_impl.h>
|
||||
|
||||
|
||||
|
||||
|
||||
namespace SituationMap { namespace RB
|
||||
{
|
||||
|
||||
Rubberband::InternalData::InternalData( SituationMap::Map * map )
|
||||
: _mapView(nullptr)
|
||||
, _mapScene(nullptr)
|
||||
, _handleList()
|
||||
, _constructionObjectDraw(nullptr)
|
||||
, _connectedPreviewPixmap(nullptr)
|
||||
, _lastClickPosition(-1,-1)
|
||||
, _constrainFailedMarker(nullptr)
|
||||
, _logger(getLogger("Rubberband"))
|
||||
{
|
||||
SituationMap::MapImpl * mapImpl = dynamic_cast<SituationMap::MapImpl*>(map);
|
||||
|
||||
if (mapImpl)
|
||||
{
|
||||
_mapView = mapImpl -> getEsriMapGraphicsView();
|
||||
|
||||
if (_mapView != nullptr)
|
||||
{
|
||||
_mapScene = _mapView -> scene();
|
||||
}
|
||||
}
|
||||
} /* InternalData */
|
||||
|
||||
Rubberband::InternalData::~InternalData()
|
||||
{
|
||||
/* Because of using shared RefPointer we don't need to call delete for every handle,
|
||||
* just clear the handle-list.
|
||||
for (auto handle : _handleList)
|
||||
{
|
||||
handle = nullptr;;
|
||||
}
|
||||
*/
|
||||
_handleList.clear();
|
||||
|
||||
delete _constructionObjectDraw;
|
||||
|
||||
_constructionObjectDraw = nullptr;
|
||||
|
||||
if (_mapScene)
|
||||
{
|
||||
if (nullptr != _connectedPreviewPixmap)
|
||||
{
|
||||
_mapScene->removeItem( _connectedPreviewPixmap );
|
||||
delete _connectedPreviewPixmap;
|
||||
_connectedPreviewPixmap = nullptr;
|
||||
}
|
||||
|
||||
delete _constrainFailedMarker;
|
||||
}
|
||||
_mapView = nullptr;
|
||||
_mapScene = nullptr;
|
||||
} /* ~InternalData */
|
||||
|
||||
} } /* namespace SituationMap::RB */
|
||||
@@ -0,0 +1,98 @@
|
||||
/**
|
||||
**
|
||||
** @RDE_HEADER@
|
||||
** Definition of internal data of base class for rubberbands
|
||||
** $Id$
|
||||
** $HeadURL$
|
||||
** $Author$
|
||||
**
|
||||
** -----------------------------------------------------------------------------------------------
|
||||
**
|
||||
** Hardware-Environment: Intel-PC
|
||||
** Software-Environment: Windows 7, Qt 5.4. ArcGIS 10.2.5
|
||||
**
|
||||
** Language ........: C++ 11
|
||||
**
|
||||
** -----------------------------------------------------------------------------------------------
|
||||
**
|
||||
** Author ...........: Joerg Turla, SPD G, Tel. 3132
|
||||
**
|
||||
** -----------------------------------------------------------------------------------------------
|
||||
**
|
||||
** Notes .........:
|
||||
**
|
||||
** 16.06.2015, JT : First edition for use with Qt5
|
||||
**
|
||||
** -----------------------------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
|
||||
#include <QtCore/QList>
|
||||
#include <QtCore/QPointer>
|
||||
|
||||
#include <Common/ref_pointer.h>
|
||||
#include <Common/situation_map_logging.h>
|
||||
|
||||
#include "rubberband.h"
|
||||
|
||||
#include "rubberband_handle.h"
|
||||
#include "rubberband_drawable.h"
|
||||
|
||||
|
||||
class QHBoxLayout;
|
||||
class QWidget;
|
||||
class QPushButton;
|
||||
class QGraphicsScene;
|
||||
|
||||
|
||||
namespace Esri {
|
||||
namespace ArcGISRuntime {
|
||||
class MapGraphicsView;
|
||||
} }
|
||||
|
||||
|
||||
namespace SituationMap
|
||||
{
|
||||
class Map;
|
||||
class CoordTranslationFunctor;
|
||||
}
|
||||
|
||||
namespace SituationMap { namespace RB
|
||||
{
|
||||
|
||||
class RubberbandHandleProxy;
|
||||
|
||||
/**
|
||||
@class Rubberband::InternalData rubberband_internal.h
|
||||
@brief Definition of internal data of rubberband base class.
|
||||
*/
|
||||
struct Rubberband::InternalData
|
||||
{
|
||||
Q_DISABLE_COPY(InternalData)
|
||||
|
||||
QPointer<Esri::ArcGISRuntime::MapGraphicsView> _mapView;
|
||||
QPointer<QGraphicsScene> _mapScene;
|
||||
|
||||
QList<SituationMap::RefPointer<RubberbandHandle>> _handleList;
|
||||
RubberbandDrawable * _constructionObjectDraw;
|
||||
QGraphicsPixmapItem * _connectedPreviewPixmap;
|
||||
|
||||
|
||||
|
||||
QPointF _lastClickPosition;
|
||||
|
||||
QGraphicsPixmapItem * _constrainFailedMarker;
|
||||
|
||||
LOGGER_T _logger;
|
||||
|
||||
explicit InternalData( SituationMap::Map * map );
|
||||
|
||||
~InternalData();
|
||||
|
||||
void markFailedConstrains( QPoint pos, bool on );
|
||||
}; /* InternalData */
|
||||
|
||||
|
||||
} } /* namespace SituationMap::RB */
|
||||
@@ -0,0 +1,231 @@
|
||||
|
||||
/**
|
||||
**
|
||||
** @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_line_handle.h"
|
||||
|
||||
#include <arcgis/MapGraphicsView.h>
|
||||
|
||||
#include <QtWidgets/QGraphicsScene>
|
||||
#include <QtWidgets/QGraphicsLineItem>
|
||||
|
||||
#include <math.h>
|
||||
|
||||
namespace SituationMap { namespace RB
|
||||
{
|
||||
|
||||
RubberbandLineHandle::RubberbandLineHandle( Esri::ArcGISRuntime::MapGraphicsView * mapView
|
||||
, QGraphicsScene * scene
|
||||
, const QPointF & p1
|
||||
, const QPointF & p2
|
||||
, unsigned int lineWidth
|
||||
, bool dottedLine )
|
||||
: RubberbandHandle(mapView,scene)
|
||||
, _lineSymbol(nullptr)
|
||||
, _lineStyle()
|
||||
, _coordinates()
|
||||
, _dottedLine(dottedLine)
|
||||
{
|
||||
_lineWidth = lineWidth;
|
||||
|
||||
zBufferPlane( ZBufferPlane::LineHandle );
|
||||
_lineStyle.setWidth(_lineWidth);
|
||||
|
||||
if (_scene != nullptr)
|
||||
{
|
||||
QGraphicsLineItem * line = new QGraphicsLineItem();
|
||||
|
||||
_lineSymbol = line;
|
||||
|
||||
_coordinates.resize(2);
|
||||
_coordinates[0].updateSceneCoordinate(mapView,p1);
|
||||
_coordinates[1].updateSceneCoordinate(mapView,p2);
|
||||
|
||||
if (_lineSymbol != nullptr)
|
||||
{
|
||||
_scene -> addItem( _lineSymbol );
|
||||
line->setLine( _coordinates[0]._sceneCoordinate.x(), _coordinates[0]._sceneCoordinate.y()
|
||||
, _coordinates[1]._sceneCoordinate.x(), _coordinates[1]._sceneCoordinate.y() );
|
||||
|
||||
line -> setZValue(10);
|
||||
line -> setFlags( QGraphicsItem::ItemIgnoresTransformations );
|
||||
|
||||
makeLineStyle( _dottedLine, _lineStyle );
|
||||
|
||||
line -> setPen( _lineStyle );
|
||||
}
|
||||
}
|
||||
} /* RubberbandLineHandle::RubberbandLineHandle */
|
||||
|
||||
|
||||
RubberbandLineHandle::~RubberbandLineHandle()
|
||||
{
|
||||
if (_scene)
|
||||
{
|
||||
if (_lineSymbol)
|
||||
{
|
||||
_scene->removeItem(_lineSymbol);
|
||||
delete _lineSymbol;
|
||||
}
|
||||
}
|
||||
_coordinates.clear();
|
||||
|
||||
} /* RubberbandHandle::~Rubberbandhandle */
|
||||
|
||||
void RubberbandLineHandle::adjustCoordinates()
|
||||
{
|
||||
if (_coordinates.size() >= 2)
|
||||
{
|
||||
_coordinates[0].mapToScene( _mapView );
|
||||
_coordinates[1].mapToScene( _mapView );
|
||||
|
||||
static_cast<QGraphicsLineItem*>(_lineSymbol)->setLine( _coordinates[0]._sceneCoordinate.x(), _coordinates[0]._sceneCoordinate.y()
|
||||
, _coordinates[1]._sceneCoordinate.x(), _coordinates[1]._sceneCoordinate.y() );
|
||||
}
|
||||
|
||||
DEBUG_LOG(_logger) << LOGFUNCTION << " map-coordinate = " << QString::number(_coordinates[0]._mapCoordinate.x(),'f',15)
|
||||
<< " ; " << QString::number(_coordinates[0]._mapCoordinate.y(),'f',15)
|
||||
<< " scene-coordinate = " << _coordinates[1]._sceneCoordinate.x() << " ; " << _coordinates[1]._sceneCoordinate.y();
|
||||
emit adjusted();
|
||||
} /* RubberbandLineHandle::adjustCoordinates */
|
||||
|
||||
|
||||
void RubberbandLineHandle::adjustWindow( const QRectF& )
|
||||
{
|
||||
onDo_adjustCoordinates();
|
||||
} /* RubberbandLineHandle::adjustWindow */
|
||||
|
||||
|
||||
void RubberbandLineHandle::updateGraphic()
|
||||
{
|
||||
if (_lineSymbol)
|
||||
{
|
||||
QGraphicsLineItem * line = static_cast<QGraphicsLineItem*>( _lineSymbol);
|
||||
|
||||
makeLineStyle( _dottedLine, _lineStyle );
|
||||
|
||||
if (_isSelected)
|
||||
{
|
||||
_lineStyle.setWidth( _lineStyle.width() + 1 );
|
||||
_lineStyle.setColor( _selectionColor );
|
||||
}
|
||||
line -> setPen( _lineStyle );
|
||||
line -> setVisible( _isVisible );
|
||||
}
|
||||
} /* RubberbandLineHandle::updateGraphic */
|
||||
|
||||
|
||||
void RubberbandLineHandle::updateCoordinates(const QVector<QPointF> & scenePositionVector)
|
||||
{
|
||||
if (scenePositionVector.size() == 2)
|
||||
{
|
||||
if (_coordinates.isEmpty()) _coordinates.resize(2);
|
||||
_coordinates[0].updateSceneCoordinate(_mapView,scenePositionVector[0]);
|
||||
_coordinates[1].updateSceneCoordinate(_mapView,scenePositionVector[1]);
|
||||
|
||||
if (_lineSymbol != nullptr)
|
||||
{
|
||||
QGraphicsLineItem * line = static_cast<QGraphicsLineItem*>( _lineSymbol);
|
||||
line->setLine( _coordinates[0]._sceneCoordinate.x(), _coordinates[0]._sceneCoordinate.y()
|
||||
, _coordinates[1]._sceneCoordinate.x(), _coordinates[1]._sceneCoordinate.y() );
|
||||
}
|
||||
}
|
||||
} /* RubberbandLineHandle::updateCoordinates */
|
||||
|
||||
|
||||
void RubberbandLineHandle::updateCoordinate( unsigned index, const QPointF & scenePosition )
|
||||
{
|
||||
if (index < 2)
|
||||
{
|
||||
_coordinates[index].updateSceneCoordinate(_mapView,scenePosition);
|
||||
QGraphicsLineItem * line = static_cast<QGraphicsLineItem*>( _lineSymbol);
|
||||
line->setLine( _coordinates[0]._sceneCoordinate.x(), _coordinates[0]._sceneCoordinate.y()
|
||||
, _coordinates[1]._sceneCoordinate.x(), _coordinates[1]._sceneCoordinate.y() );
|
||||
}
|
||||
} /* RubberbandLineHandle::updateCoordinate */
|
||||
|
||||
|
||||
QVector<RubberbandHandle::RubberbandCoordinate> RubberbandLineHandle::getCoordinates() const
|
||||
{
|
||||
return _coordinates;
|
||||
} /* RubberbandLineHandle::getCoordinates */
|
||||
|
||||
|
||||
RubberbandHandle::RubberbandCoordinate RubberbandLineHandle::getCoordinate( unsigned index ) const
|
||||
{
|
||||
if (index < 2)
|
||||
{
|
||||
return _coordinates[index];
|
||||
}
|
||||
return RubberbandCoordinate();
|
||||
} /* RubberbandLineHandle::getCoordinate */
|
||||
|
||||
|
||||
bool RubberbandLineHandle::isPositionInside( const QPointF & scenePosition ) const
|
||||
{
|
||||
if (_lineSymbol)
|
||||
{
|
||||
if (_lineSymbol->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;
|
||||
} /* RubberbandLineHandle::isPositionInside */
|
||||
|
||||
} } /* namespace SituationMap::RB */
|
||||
@@ -0,0 +1,81 @@
|
||||
/**
|
||||
**
|
||||
** @RDE_HEADER@
|
||||
** Definition 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
|
||||
**
|
||||
** -----------------------------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <QtCore/QPointF>
|
||||
|
||||
#include <QtGui/QPen>
|
||||
|
||||
#include "rubberband_handle.h"
|
||||
|
||||
class QGraphicsItem;
|
||||
class QGraphicsScene;
|
||||
|
||||
namespace SituationMap { namespace RB
|
||||
{
|
||||
|
||||
/**
|
||||
@class RubberbandLineHandle rubberband_line_handle.h
|
||||
@brief Implementation of a line handle for rubberband internal use.
|
||||
@see RubberbandHandle
|
||||
*/
|
||||
class RubberbandLineHandle : public RubberbandHandle
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
|
||||
RubberbandLineHandle( Esri::ArcGISRuntime::MapGraphicsView * mapView ,QGraphicsScene * scene , const QPointF & p1, const QPointF & p2, unsigned int lineWidth = 2, bool dottedLine = false );
|
||||
~RubberbandLineHandle();
|
||||
|
||||
bool isPositionInside( const QPointF & scenePosition ) const override;
|
||||
|
||||
virtual void updateCoordinates( const QVector<QPointF> & scenePositionVector );
|
||||
virtual void updateCoordinate( unsigned index, const QPointF & scenePosition );
|
||||
|
||||
virtual QVector<RubberbandCoordinate> getCoordinates() const;
|
||||
virtual RubberbandCoordinate getCoordinate( unsigned index ) const;
|
||||
|
||||
void dottedLine(bool on = true) { _dottedLine = on; }
|
||||
|
||||
protected:
|
||||
|
||||
QGraphicsItem * _lineSymbol;
|
||||
QPen _lineStyle;
|
||||
QVector<RubberbandCoordinate> _coordinates;
|
||||
bool _dottedLine;
|
||||
|
||||
void updateGraphic() override;
|
||||
|
||||
void adjustCoordinates() override;
|
||||
void adjustWindow( const QRectF& ) override;
|
||||
|
||||
|
||||
}; /* RubberbandLineHandle */
|
||||
|
||||
} } /* namespace SituationMap::RB */
|
||||
File diff suppressed because it is too large.
Load diff
@@ -0,0 +1,254 @@
|
||||
/**
|
||||
* @RDE_HEADER@
|
||||
* Rubberband class to define multiple ellipse/circle
|
||||
* $Id$
|
||||
* $HeadURL$
|
||||
* $Author$
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "rubberband.h"
|
||||
|
||||
|
||||
namespace SituationMap
|
||||
{
|
||||
namespace RB
|
||||
{
|
||||
class RubberbandHandle;
|
||||
class RubberbandFrameHandle;
|
||||
class DrawableEllipse;
|
||||
|
||||
/**
|
||||
@class RubberbandMultiEllipseFeature rubberband_multi_circle_feature.h
|
||||
@brief Implementation of a rubberband to input multi point features, like areals or linears
|
||||
@see Rubberband
|
||||
*/
|
||||
class SITUATIONMAP_EXPORT RubberbandMultiEllipseFeature : public Rubberband
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
|
||||
/**
|
||||
@name Construction & Destruction
|
||||
@{
|
||||
*/
|
||||
|
||||
private:
|
||||
|
||||
friend class RubberbandFactory;
|
||||
friend class RubberbandArrow;
|
||||
friend class RubberbandCorridor;
|
||||
friend class RubberbandPolylineWidth;
|
||||
friend class RubberbandSmoothLine;
|
||||
|
||||
/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
Constructor delegation doesn't work with Visual Studio 2013
|
||||
|
||||
explicit RubberbandMultiEllipseFeature( SituationMap::Map * map );
|
||||
explicit RubberbandMultiEllipseFeature( SituationMap::Map * map, bool complexGeometry );
|
||||
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
|
||||
|
||||
/**
|
||||
Construction of RubberbandMultiEllipseFeature in most common cases. The parameter parent is
|
||||
optional.
|
||||
*/
|
||||
explicit RubberbandMultiEllipseFeature(SituationMap::Map *map, QObject *parent = nullptr);
|
||||
|
||||
/**
|
||||
Construction of RubberbandMultiEllipseFeature in case of controlling complex geometry objects, like
|
||||
splines or multi point symbols. In this case set complexGeometry true.
|
||||
*/
|
||||
explicit RubberbandMultiEllipseFeature(SituationMap::Map *map, bool complexGeometry, QObject *parent = nullptr);
|
||||
|
||||
public:
|
||||
|
||||
~RubberbandMultiEllipseFeature();
|
||||
/** @} */
|
||||
|
||||
bool selectAction(AbstractEventDispatcher *causer, int x, int y) override;
|
||||
bool setCoordinateAction(AbstractEventDispatcher *causer, int x, int y) override;
|
||||
bool moveAction(AbstractEventDispatcher *causer, int x, int y) override;
|
||||
bool movePickedAction(AbstractEventDispatcher *causer, int x, int y) override;
|
||||
void resetAction(AbstractEventDispatcher *causer, int x, int y) override;
|
||||
bool contextMenuAction(AbstractEventDispatcher *causer, int x, int y) override;
|
||||
bool completeStateAction(AbstractEventDispatcher *causer, int x, int y) override;
|
||||
bool deleteAction(AbstractEventDispatcher *causer, int x, int y) override;
|
||||
bool undoAction(AbstractEventDispatcher *causer, int x, int y) override;
|
||||
bool applyAndEndAction(AbstractEventDispatcher *causer, int x, int y) override;
|
||||
|
||||
/**
|
||||
* @brief If set to true only quadratic rectangles can be created.
|
||||
*/
|
||||
void constrainQuadratic( bool on );
|
||||
|
||||
|
||||
/**
|
||||
@name Setting Constrains
|
||||
@{
|
||||
*/
|
||||
|
||||
/**
|
||||
Defines minimum count of verticies that has to be defined by users input to complete the rubberband with apply signal. The default value is 2.
|
||||
*/
|
||||
inline void minimumRadiusCount(unsigned int x)
|
||||
{
|
||||
_minimumPointCount = x+1;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
Defines maximum count of verticies that can be aceppted by the rubberband. A values of 0 stands for undefined. The default is 0.
|
||||
*/
|
||||
inline void maximumRadiusCount(unsigned int x)
|
||||
{
|
||||
_maximumPointCount = x+1;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
Defines the maximum length of a segment (distance between to adjaced verticies). A value of 0 stands for no limit is set. The default is 0.
|
||||
*/
|
||||
inline void maximumSegmentLength(qreal x) { _maximumSegmentLength = (x > 0) ? x : 0.0; }
|
||||
inline qreal getMaximumSegmentLength() const { return _maximumSegmentLength; }
|
||||
|
||||
/**
|
||||
Defines the maximum length of the complete polyline. \c enableClosed must be set to false. A value of 0 stands for no limit is set. The default is 0.
|
||||
*/
|
||||
inline void maximumLength(qreal x) { _maximumLength = (x > 0) ? x : 0.0; }
|
||||
/** @} */
|
||||
inline qreal getMaximumLength() const { return _maximumLength; }
|
||||
|
||||
|
||||
QPointF centerCoordinate(CoordinateSystem cs = CoordinateSystem::Geo) const;
|
||||
|
||||
/**
|
||||
* @brief radii get vector of radius (QPointF containing radiusX and radius Y in meter)
|
||||
* @return radii
|
||||
*/
|
||||
QVector<QPointF> radii() const;
|
||||
QPointF getBiggestRadius() const;
|
||||
|
||||
|
||||
struct RadiusWithContraints
|
||||
{
|
||||
// to be able to supply int, avoid explicit:
|
||||
RadiusWithContraints(double radius = 0.0, double minRadius = 0.0, double maxRadius = 0.0)
|
||||
: m_radius(radius),
|
||||
m_minRadius(minRadius),
|
||||
m_maxRadius(maxRadius)
|
||||
{}
|
||||
double m_radius{0};
|
||||
double m_minRadius{0};
|
||||
double m_maxRadius{0};
|
||||
};
|
||||
|
||||
bool setCenterAndRadii(const QPointF ¢er, CoordinateSystem cs, const QVector<QPointF> &radii); // no constraints
|
||||
|
||||
bool setCenterAndRadii2(const QPointF ¢er, CoordinateSystem cs,
|
||||
const QVector<RubberbandMultiEllipseFeature::RadiusWithContraints> &radiiWithConstraints);
|
||||
|
||||
void prepareFixedNumberOfRadiiWithConstraints(const QVector<RubberbandMultiEllipseFeature::RadiusWithContraints> &radiiContraints);
|
||||
|
||||
|
||||
// get SectorStartEnd
|
||||
QPointF getRotatedPoint(const QPointF §or)const;
|
||||
|
||||
|
||||
void enableSector(bool on);
|
||||
bool isSectorEnabled() const;
|
||||
|
||||
/**
|
||||
* @brief sectorStart in mathematical sense (starts counter-clockwise from 3 o'clock)
|
||||
* @return sectorStart
|
||||
*/
|
||||
QPointF sectorStart() const;
|
||||
|
||||
qreal sectorStartDegMath() const; // in mathematical sense (starts counter-clockwise from 3 o'clock)
|
||||
|
||||
/**
|
||||
* @brief sectorEnd in mathematical sense (starts counter-clockwise from 3 o'clock)
|
||||
* @return sectorEnd
|
||||
*/
|
||||
QPointF sectorEnd() const;
|
||||
|
||||
qreal sectorEndDegMath() const; // in mathematical sense (starts counter-clockwise from 3 o'clock)
|
||||
|
||||
void setSectorStart(qreal sinPhi, qreal cosPhi);
|
||||
void setSectorEnd(qreal sinPhi, qreal cosPhi);
|
||||
|
||||
void setSectorAngleFixed(bool on); // true: start and end sectors positon can't be modifed
|
||||
bool isSectorFixedAngeEnabled() const;
|
||||
|
||||
|
||||
virtual QVector<QPointF> coordinateVector(CoordinateSystem cs = CoordinateSystem::Geo) const override;
|
||||
virtual QPointF singleCoordinate( unsigned int idx = 0, CoordinateSystem cs = CoordinateSystem::Geo ) const override;
|
||||
|
||||
virtual void setCoordinateVector(const QVector<QPointF> &, CoordinateSystem cs = CoordinateSystem::Geo) override;
|
||||
|
||||
signals:
|
||||
|
||||
/**
|
||||
The signal will be emitted, when the mouse cursor has changed and the rubberband is in construction mode and is accepting new input coordinates.
|
||||
*/
|
||||
void currentCursorPositionChanged(const Point3D &mapCoord);
|
||||
|
||||
|
||||
protected:
|
||||
|
||||
/*
|
||||
Forward declaration of InternalData to hold private member variables. Be careful the base class Rubberband
|
||||
has similary a class for internal data member with name "InternalData". Don't be confused it is not the same.
|
||||
*/
|
||||
struct InternalData;
|
||||
|
||||
InternalData *_internal;
|
||||
|
||||
bool _isClosed{false};
|
||||
|
||||
unsigned int _minimumRadius = 0;
|
||||
unsigned int _maximumRadius = 0;
|
||||
|
||||
unsigned int _minimumPointCount{2}; // 2 Punkte == 1 Kreis
|
||||
unsigned int _maximumPointCount{0};
|
||||
|
||||
qreal _maximumSegmentLength;
|
||||
qreal _maximumLength;
|
||||
|
||||
void activateButtons() override;
|
||||
|
||||
void update() override;
|
||||
void updateFrameHandle(const QPointF &sceneCoordinate); // Unfortunately, RubberbandCoordinate can´t be forwarded, so use sceneCoordinate
|
||||
|
||||
void getSceneRotation(qreal &sinA, qreal &cosA) const;
|
||||
void updateSectorHandles();
|
||||
|
||||
void updateRotationHandle();
|
||||
QPointF getScenePositionRotationHandle() const;
|
||||
QPointF getSceneOffsetRotationHandle(qreal margin);
|
||||
|
||||
|
||||
// some helper methodes
|
||||
bool getRadiusXY(const QPointF &scenePos, qreal &radiusX_out, qreal &radiusY_out);
|
||||
|
||||
RubberbandHandle *constructPoint(const QPointF &scenePos);
|
||||
void constructPoint(const QPointF &point, CoordinateSystem cs);
|
||||
|
||||
bool selectHandles(int x, int y, const QPointF &scenePos);
|
||||
void updateHandles(const QPointF &scenePos, const QPointF &deltaMove);
|
||||
|
||||
bool checkLengthConstrains(unsigned int checkHandleIdx, const QPointF &scenePos);
|
||||
bool checkLengthConstrains(const QPointF &scenePos, const QPointF &deltaScenePos);
|
||||
|
||||
|
||||
bool checkMinMaxRadiusConstraint(const QPointF &curScenePos);
|
||||
bool checkMinMaxRadiusConstraint(qreal radiusX, qreal radiusY, int idxOfConstraint = -1);
|
||||
|
||||
void updatePreviewEllipse(const QPointF &scenePosition);
|
||||
|
||||
RubberbandFrameHandle *getFrameHandle() const;
|
||||
|
||||
}; /* RubberbandMultiEllipseFeature */
|
||||
|
||||
}
|
||||
} /* namespace SituationMap::RB */
|
||||
File diff suppressed because it is too large.
Load diff
@@ -0,0 +1,209 @@
|
||||
/**
|
||||
**
|
||||
** @RDE_HEADER@
|
||||
** Definition of rubberband class to define multi point feature geoemtry
|
||||
** $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 .........:
|
||||
**
|
||||
** 10.04.2015, JT : First edition for use with Qt5
|
||||
**
|
||||
** -----------------------------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "rubberband.h"
|
||||
|
||||
|
||||
namespace SituationMap { namespace RB
|
||||
{
|
||||
class RubberbandHandle;
|
||||
class RubberbandFrameHandle;
|
||||
|
||||
/**
|
||||
@class RubberbandMultiPointFeature rubberband_multi_point_feature.h
|
||||
@brief Implementation of a rubberband to input multi point features, like areals or linears
|
||||
@see Rubberband
|
||||
*/
|
||||
class SITUATIONMAP_EXPORT RubberbandMultiPointFeature : public Rubberband
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
|
||||
/**
|
||||
@name Construction & Destruction
|
||||
@{
|
||||
*/
|
||||
|
||||
private:
|
||||
|
||||
friend class RubberbandFactory;
|
||||
friend class RubberbandArrow;
|
||||
friend class RubberbandCorridor;
|
||||
friend class RubberbandPolylineWidth;
|
||||
friend class RubberbandSmoothLine;
|
||||
|
||||
/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
Constructor delegation doesn't work with Visual Studio 2013
|
||||
|
||||
explicit RubberbandMultiPointFeature( SituationMap::Map * map );
|
||||
explicit RubberbandMultiPointFeature( SituationMap::Map * map, bool complexGeometry );
|
||||
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
|
||||
|
||||
/**
|
||||
Construction of RubberbandMultiPointFeature in most common cases. The parameter parent is
|
||||
optional.
|
||||
*/
|
||||
explicit RubberbandMultiPointFeature( SituationMap::Map * map, QObject * parent = nullptr );
|
||||
|
||||
/**
|
||||
Construction of RubberbandMultiPointFeature in case of controlling complex geometry objects, like
|
||||
splines or multi point symbols. In this case set complexGeometry true.
|
||||
*/
|
||||
explicit RubberbandMultiPointFeature( SituationMap::Map * map, bool complexGeometry, QObject * parent = nullptr );
|
||||
|
||||
public:
|
||||
|
||||
~RubberbandMultiPointFeature();
|
||||
/** @} */
|
||||
|
||||
bool selectAction ( AbstractEventDispatcher * causer, int x, int y ) override;
|
||||
bool setCoordinateAction ( AbstractEventDispatcher * causer, int x, int y ) override;
|
||||
bool moveAction ( AbstractEventDispatcher * causer, int x, int y ) override;
|
||||
bool movePickedAction ( AbstractEventDispatcher * causer, int x, int y ) override;
|
||||
void resetAction ( AbstractEventDispatcher * causer, int x, int y ) override;
|
||||
bool contextMenuAction ( AbstractEventDispatcher * causer, int x, int y ) override;
|
||||
bool completeStateAction ( AbstractEventDispatcher * causer, int x, int y ) override;
|
||||
bool deleteAction ( AbstractEventDispatcher * causer, int x, int y ) override;
|
||||
bool undoAction ( AbstractEventDispatcher * causer, int x, int y ) override;
|
||||
bool applyAndEndAction ( AbstractEventDispatcher * causer, int x, int y ) override;
|
||||
|
||||
|
||||
/**
|
||||
If set to true a polygon the rubberband draws a polygon otherwise a polyline.
|
||||
*/
|
||||
inline void enableClosed( bool flag )
|
||||
{
|
||||
_isClosed = flag;
|
||||
if (( _isClosed) && (_minimumPointCount < 3)) _minimumPointCount = 3;
|
||||
if ((!_isClosed) && (_minimumPointCount < 2)) _minimumPointCount = 2;
|
||||
} /* enableClosed */
|
||||
|
||||
/**
|
||||
Gets the value of the close flag
|
||||
*/
|
||||
inline bool isClosedEnabled() const { return _isClosed; }
|
||||
|
||||
/**
|
||||
@name Setting Constrains
|
||||
@{
|
||||
*/
|
||||
|
||||
/**
|
||||
Defines minimum count of verticies that has to be defined by users input to complete the rubberband with apply signal. The default value is 0.
|
||||
*/
|
||||
inline void minimumPointCount( unsigned int x )
|
||||
{
|
||||
if (( _isClosed) && (x < 3)) x = 3;
|
||||
if ((!_isClosed) && (x < 2)) x = 2;
|
||||
_minimumPointCount = x;
|
||||
} /* minimumPointCount */
|
||||
|
||||
|
||||
/**
|
||||
Defines maximum count of verticies that can be aceppted by the rubberband. A values of 0 stands for undefined. The default is 0.
|
||||
*/
|
||||
inline void maximumPointCount( unsigned int x )
|
||||
{
|
||||
if (x > 0)
|
||||
{
|
||||
if (( _isClosed) && (x < 3)) x = 3;
|
||||
if ((!_isClosed) && (x < 2)) x = 2;
|
||||
}
|
||||
_maximumPointCount = x;
|
||||
} /* maximumPointCount */
|
||||
|
||||
|
||||
/**
|
||||
Defines the maximum length of a segment (distance between to adjaced verticies). A value of 0 stands for no limit is set. The default is 0.
|
||||
*/
|
||||
inline void maximumSegmentLength( qreal x ) { _maximumSegmentLength = (x > 0) ? x : 0.0; }
|
||||
inline qreal getMaximumSegmentLength() const{ return _maximumSegmentLength; }
|
||||
|
||||
/**
|
||||
Defines the maximum length of the complete polyline. \c enableClosed must be set to false. A value of 0 stands for no limit is set. The default is 0.
|
||||
*/
|
||||
inline void maximumLength( qreal x ) { _maximumLength = (x > 0) ? x : 0.0; }
|
||||
/** @} */
|
||||
inline qreal getMaximumLength() const { return _maximumLength; }
|
||||
|
||||
|
||||
virtual QVector<QPointF> coordinateVector( CoordinateSystem cs = CoordinateSystem::Geo ) const override;
|
||||
virtual QPointF singleCoordinate( unsigned int idx = 0, CoordinateSystem cs = CoordinateSystem::Geo ) const override;
|
||||
|
||||
virtual void setCoordinateVector( const QVector<QPointF> &, CoordinateSystem cs = CoordinateSystem::Geo ) override;
|
||||
|
||||
signals:
|
||||
|
||||
/**
|
||||
The signal will be emitted, when the mouse cursor has changed and the rubberband is in construction mode and is accepting new input coordinates.
|
||||
*/
|
||||
void currentCursorPositionChanged(const Point3D &mapCoord);
|
||||
|
||||
|
||||
protected:
|
||||
|
||||
/*
|
||||
Forward declaration of InternalData to hold private member variables. Becareful the base class Rubberband
|
||||
has similary a class for internal data member with name "InternalData". Don't be confused it is not the same.
|
||||
*/
|
||||
struct InternalData;
|
||||
|
||||
InternalData * _internal;
|
||||
|
||||
bool _isClosed;
|
||||
|
||||
unsigned int _minimumPointCount;
|
||||
unsigned int _maximumPointCount;
|
||||
|
||||
qreal _maximumSegmentLength;
|
||||
qreal _maximumLength;
|
||||
|
||||
void activateButtons() override;
|
||||
|
||||
void update() override;
|
||||
|
||||
// some helper methodes
|
||||
RubberbandHandle * constructPoint( QPointF scenePos );
|
||||
|
||||
void constructPoint(const QPointF &point, CoordinateSystem cs );
|
||||
|
||||
bool selectHandles( int x, int y, const QPointF & scenePos );
|
||||
|
||||
bool checkLengthConstrains( unsigned int checkHandleIdx, QPointF & scenePos );
|
||||
bool checkLengthConstrains( const QPointF & scenePos, const QPointF & deltaScenePos );
|
||||
void updatePreviewLine( const QPointF & scenePosition );
|
||||
|
||||
RubberbandFrameHandle * getFrameHandle() const;
|
||||
|
||||
void setCheckMaxAngle( double phi );
|
||||
|
||||
}; /* RubberbandMultiPointFeature */
|
||||
|
||||
} } /* namespace SituationMap::RB */
|
||||
@@ -0,0 +1,660 @@
|
||||
/**
|
||||
**
|
||||
** @RDE_HEADER@
|
||||
** Implementation of rubberband class to define point feature geometry in 3d
|
||||
** $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 <limits>
|
||||
|
||||
#include "rubberband_multi_point_feature_3d.h"
|
||||
#include "rubberband_base_internal.h"
|
||||
|
||||
#include "event_mouse_navigator.h"
|
||||
|
||||
#include <Map/map.h>
|
||||
#include <Map/layer_factory.h>
|
||||
|
||||
#include <MapImpl/map_impl.h>
|
||||
#include <MapImpl/coordinate_translation.h>
|
||||
#include <MapImpl/screen_to_location_helper.h>
|
||||
#include <MapImpl/location_to_elevation_helper.h>
|
||||
|
||||
#include <MathUtils/math_const.h>
|
||||
|
||||
#include <GraphicalObjects/graphical_object_picture_marker.h>
|
||||
#include <GraphicalObjects/graphical_object_path.h>
|
||||
|
||||
#include <QtGui/QGuiApplication>
|
||||
|
||||
#include <arcgis/IdentifyGraphicsOverlayResult.h>
|
||||
|
||||
namespace SituationMap { namespace RB
|
||||
{
|
||||
|
||||
class RubberbandMultiPointFeature3D::InternalData
|
||||
{
|
||||
public:
|
||||
|
||||
QVector<GraphicalObjectPictureMarker*> m_marker;
|
||||
GraphicalObjectPath *m_path;
|
||||
|
||||
QVector<QPointF> m_coordinates;
|
||||
|
||||
int m_currentIndex;
|
||||
int m_selectionIndex;
|
||||
Esri::ArcGISRuntime::TaskWatcher m_pickingTask;
|
||||
Esri::ArcGISRuntime::TaskWatcher m_selectionTask;
|
||||
QPoint m_pickingPoint;
|
||||
QPointF * m_startMove;
|
||||
ScreenToLocationHelper * m_screenToMap;
|
||||
QPointer<LocationToElevationHelper> m_toElevation;
|
||||
PositionCont m_positionList3D;
|
||||
bool m_doCompleteAction;
|
||||
|
||||
|
||||
InternalData()
|
||||
: m_marker()
|
||||
, m_path(nullptr)
|
||||
, m_coordinates()
|
||||
, m_currentIndex(-1)
|
||||
, m_selectionIndex(-1)
|
||||
, m_pickingTask()
|
||||
, m_selectionTask()
|
||||
, m_pickingPoint()
|
||||
, m_startMove(nullptr)
|
||||
, m_screenToMap()
|
||||
, m_toElevation(nullptr)
|
||||
, m_positionList3D()
|
||||
, m_doCompleteAction(false)
|
||||
{
|
||||
m_marker.reserve(100);
|
||||
m_coordinates.reserve(100);
|
||||
} // InternalData()
|
||||
|
||||
~InternalData()
|
||||
{
|
||||
delete m_startMove;
|
||||
for (auto marker : qAsConst(m_marker))
|
||||
delete marker;
|
||||
delete m_path;
|
||||
delete m_screenToMap;
|
||||
} // ~InternalData()
|
||||
|
||||
}; // RubberbandPointFeature3D::InternalData
|
||||
|
||||
|
||||
RubberbandMultiPointFeature3D::RubberbandMultiPointFeature3D( SituationMap::Map * map, QObject * parent, bool isActive )
|
||||
: Rubberband3D(map,parent,isActive)
|
||||
, _internal( new RubberbandMultiPointFeature3D::InternalData() )
|
||||
, _isClosed(false)
|
||||
, _isCircular(false)
|
||||
{
|
||||
MapImpl *mapImpl = static_cast<MapImpl*>(_baseInternal->_map.data());
|
||||
Esri::ArcGISRuntime::SceneGraphicsView *view = mapImpl->getEsriSceneGraphicsView();
|
||||
|
||||
connect( view, &Esri::ArcGISRuntime::SceneGraphicsView::identifyGraphicsOverlaysCompleted, this, &RubberbandMultiPointFeature3D::onGetPickingResult );
|
||||
_internal->m_screenToMap = new ScreenToLocationHelper(view);
|
||||
connect( _internal->m_screenToMap, &ScreenToLocationHelper::mouseScenePositionChanged, this, &RubberbandMultiPointFeature3D::onMapPosition ); // ToDO
|
||||
|
||||
} // RubberbandMultiPointFeature3D::RubberbandMultiPointFeature3D( SituationMap::Map * map, QObject * parent = nullptr, bool isActive )
|
||||
|
||||
|
||||
RubberbandMultiPointFeature3D::~RubberbandMultiPointFeature3D()
|
||||
{
|
||||
delete _internal;
|
||||
_internal = nullptr;
|
||||
} // RubberbandMultiPointFeature3D::~RubberbandMultiPointFeature3D()
|
||||
|
||||
void RubberbandMultiPointFeature3D::activateButtons()
|
||||
{
|
||||
_baseInternal->_hasUndoButton = false;
|
||||
_baseInternal->_undoIsPossible = false;
|
||||
_baseInternal->_applyIsPossible = (_internal->m_coordinates.size() > ((_isClosed && !_isCircular) ? 2 : 1));
|
||||
|
||||
RubberbandBase::activateButtons();
|
||||
|
||||
} /* RubberbandMultiPointFeature3D::activateButtons */
|
||||
|
||||
|
||||
void circleShape( GraphicalObjectPath *pathObj, const PositionCont &positionList )
|
||||
{
|
||||
if (positionList.size() < 2) return;
|
||||
|
||||
PositionCont circleShape;
|
||||
|
||||
double cx = positionList[0].x();
|
||||
double cy = positionList[0].y();
|
||||
double rx = positionList[1].x()-cx;
|
||||
double ry = positionList[1].y()-cy;
|
||||
|
||||
double corrLon = cos(cy / 57.2957795147); // correct factor from nautic simulation to get a real circle
|
||||
double dPhi = MathConst::pi / 50; // delta angle to rasterize the circle to a polyline
|
||||
|
||||
auto sqr = [](double x) -> double { return x * x; };
|
||||
double r = sqrt(sqr(rx*corrLon) + sqr(ry) );
|
||||
|
||||
double phi = 0.0;
|
||||
while (phi < MathConst::pi_two)
|
||||
{
|
||||
double sinPhi = sin(phi);
|
||||
double cosPhi = cos(phi);
|
||||
double px = cx + r * cosPhi / corrLon;
|
||||
double py = cy + r*sinPhi;
|
||||
|
||||
circleShape.append(Point3D(px, py, 0.0));
|
||||
phi += dPhi;
|
||||
}
|
||||
|
||||
pathObj->setPositions(circleShape);
|
||||
|
||||
} // circleShape
|
||||
|
||||
|
||||
void RubberbandMultiPointFeature3D::onMapPosition(const Point3D &mapCoordinate)
|
||||
{
|
||||
if (_internal->m_currentIndex < 0) return;
|
||||
|
||||
if (qIsNaN(mapCoordinate.x())) return; // illegal map position
|
||||
if (qIsNaN(mapCoordinate.y())) return;
|
||||
|
||||
if ((!_internal->m_toElevation) && (RubberbandBase::_baseInternal->_map->layerFactory().elevationAvailable()))
|
||||
{
|
||||
_internal->m_toElevation = RubberbandBase::_baseInternal->_map->layerFactory().locationToElevation(); // layerFactory has ownership
|
||||
}
|
||||
|
||||
if ((std::numeric_limits<int>::max()) == _internal->m_currentIndex)
|
||||
{
|
||||
// move all coordinates
|
||||
if (_internal->m_startMove)
|
||||
{
|
||||
QPointF deltaMove = mapCoordinate.toPointF() - *(_internal->m_startMove);
|
||||
|
||||
_internal->m_positionList3D.clear();
|
||||
_internal->m_positionList3D.reserve(_internal->m_coordinates.size());
|
||||
|
||||
for (int i = 0; i < _internal->m_coordinates.size(); ++i)
|
||||
{
|
||||
const QPointF & pos = _internal->m_coordinates[i] += deltaMove;
|
||||
_internal->m_marker[i]->setOrigin( pos );
|
||||
|
||||
if (_internal->m_toElevation)
|
||||
{
|
||||
QMetaObject::Connection conn;
|
||||
|
||||
conn = connect(_internal->m_toElevation.data(), &SituationMap::LocationToElevationHelper::elevationCompleted, this, [this,pos,conn](double elevation)
|
||||
{
|
||||
disconnect(conn);
|
||||
_internal->m_positionList3D << Point3D(pos.x(),pos.y(),elevation);
|
||||
if (_internal->m_positionList3D.size() == _internal->m_coordinates.size())
|
||||
{
|
||||
if (_internal->m_path) _internal->m_path->setPositions( _internal->m_positionList3D );
|
||||
update();
|
||||
}
|
||||
|
||||
// qCritical() << "elevation at (" << pos.x() << " , " << pos.y() << ") : " << elevation;
|
||||
|
||||
});
|
||||
_internal->m_toElevation->locationToElevation(pos);
|
||||
}
|
||||
else
|
||||
{
|
||||
_internal->m_positionList3D << Point3D::fromQPointF(pos);
|
||||
}
|
||||
}
|
||||
|
||||
if (_internal->m_toElevation)
|
||||
{
|
||||
if (_internal->m_path) _internal->m_path->setPositions( _internal->m_positionList3D );
|
||||
update();
|
||||
}
|
||||
}
|
||||
else _internal->m_startMove = new QPointF(mapCoordinate.toPointF());
|
||||
return;
|
||||
}
|
||||
|
||||
if (_internal->m_currentIndex >= _internal->m_coordinates.size()) return;
|
||||
|
||||
MapImpl *mapImpl = static_cast<MapImpl*>(_baseInternal->_map.data());
|
||||
Esri::ArcGISRuntime::SceneGraphicsView *view = mapImpl->getEsriSceneGraphicsView();
|
||||
Esri::ArcGISRuntime::GraphicsOverlay *graphicsLayer = mapImpl->getGraphicsLayer(mapImpl->layerFactory().rubberbandLayer());
|
||||
|
||||
if (nullptr == view) return;
|
||||
|
||||
for (int idx = _internal->m_positionList3D.size(); idx <= _internal->m_currentIndex; ++idx)
|
||||
{
|
||||
_internal->m_positionList3D << mapCoordinate;
|
||||
}
|
||||
_internal->m_coordinates[_internal->m_currentIndex] = mapCoordinate.toPointF();
|
||||
_internal->m_positionList3D[_internal->m_currentIndex] = mapCoordinate;
|
||||
|
||||
// qCritical() << "elevation idx=" << _internal->m_currentIndex <<" at (" << mapCoordinate.x() << " , " << mapCoordinate.y() << ") : " << mapCoordinate.z();
|
||||
|
||||
GraphicalObjectPictureMarker *&marker = _internal->m_marker[_internal->m_currentIndex];
|
||||
|
||||
if (nullptr == marker)
|
||||
{
|
||||
marker = new GraphicalObjectPictureMarker( view, graphicsLayer, QStringLiteral("RubberbandMultiPointFeature3D"), INVALID_MAP_ID );
|
||||
|
||||
marker->setImage(markerImage());
|
||||
marker->setOrigin( mapCoordinate );
|
||||
marker->updateView();
|
||||
marker->setPickable(true);
|
||||
|
||||
Esri::ArcGISRuntime::Graphic *graphic = marker->graphic();
|
||||
if (graphic)
|
||||
{
|
||||
Esri::ArcGISRuntime::AttributeListModel *attLisModel = graphic->attributes();
|
||||
if (attLisModel)
|
||||
{
|
||||
// qCritical() << "Rubberband3D-Item =" << _internal->m_currentIndex;
|
||||
attLisModel->insertAttribute(QStringLiteral("Rubberband3D-Item"),_internal->m_currentIndex);
|
||||
}
|
||||
}
|
||||
}
|
||||
else marker->setOrigin( mapCoordinate );
|
||||
|
||||
if (_internal->m_coordinates.size() > ((_isClosed && !_isCircular) ? 2 : 1))
|
||||
{
|
||||
|
||||
if (nullptr == _internal->m_path)
|
||||
{
|
||||
bool isPolygon = (_isClosed || _isCircular);
|
||||
|
||||
_internal->m_path = new GraphicalObjectPath(isPolygon ? GraphicalObjectPathType::Polygon : GraphicalObjectPathType::Polyline, view, graphicsLayer, QStringLiteral("RubberbandMultiPointFeature3D"), INVALID_MAP_ID);
|
||||
|
||||
_internal->m_path->rLineStyle().setLineColor(_handleDrawColor);
|
||||
_internal->m_path->rLineStyle().setLinePattern(LinePattern::Solid);
|
||||
_internal->m_path->rLineStyle().setLineWidth(3);
|
||||
_internal->m_path->setPickable(false);
|
||||
if (isPolygon)
|
||||
{
|
||||
_internal->m_path->rFillStyle().setFillColor(_frameFillColor);
|
||||
}
|
||||
|
||||
if (_isCircular)
|
||||
{
|
||||
circleShape(_internal->m_path, _internal->m_positionList3D);
|
||||
}
|
||||
else _internal->m_path->setPositions(_internal->m_positionList3D);
|
||||
|
||||
_internal->m_path->updateView();
|
||||
}
|
||||
else
|
||||
{
|
||||
if (_isCircular)
|
||||
{
|
||||
circleShape(_internal->m_path, _internal->m_positionList3D);
|
||||
}
|
||||
else _internal->m_path->setPositions(_internal->m_positionList3D);
|
||||
}
|
||||
}
|
||||
|
||||
if (_isCircular && (0 == _internal->m_currentIndex) && (1 == _internal->m_coordinates.size()))
|
||||
{
|
||||
_internal->m_coordinates << _internal->m_coordinates.first();
|
||||
_internal->m_positionList3D << _internal->m_positionList3D.first();
|
||||
_internal->m_marker << nullptr;
|
||||
_internal->m_currentIndex++;
|
||||
|
||||
// qCritical() << QCursor::pos() << " != " << view->viewport()->mapToGlobal(_internal->m_pickingPoint);
|
||||
|
||||
_internal->m_doCompleteAction = (QCursor::pos() != view->viewport()->mapToGlobal(_internal->m_pickingPoint));
|
||||
|
||||
if (!_internal->m_doCompleteAction)
|
||||
{
|
||||
// Click with out moving the mouse, set a default size of the circle and let the user do some editing
|
||||
// The rubberband doesn't complete automatically in this case.
|
||||
_internal->m_screenToMap->screenToLocation(_internal->m_pickingPoint.x()+100, _internal->m_pickingPoint.y());
|
||||
}
|
||||
}
|
||||
|
||||
update();
|
||||
|
||||
if (!QGuiApplication::mouseButtons().testFlag(Qt::MouseButton::LeftButton))
|
||||
{
|
||||
if (_isCircular && _internal->m_doCompleteAction && (1 == _internal->m_currentIndex))
|
||||
{
|
||||
completeStateAction(nullptr, 0, 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
updateButtonPosition();
|
||||
activateButtons();
|
||||
}
|
||||
}
|
||||
|
||||
} // void RubberbandMultiPointFeature3D::onMapPosition(const QPointF &mapCoordinate)
|
||||
|
||||
|
||||
void RubberbandMultiPointFeature3D::onGetPickingResult(const QUuid &taskId, const QList<Esri::ArcGISRuntime::IdentifyGraphicsOverlayResult*> &identifyResults)
|
||||
{
|
||||
if (_internal->m_pickingTask.taskId() == taskId)
|
||||
{
|
||||
for (auto iResult : identifyResults)
|
||||
{
|
||||
const QList<Esri::ArcGISRuntime::Graphic*> &gResults = iResult->graphics();
|
||||
for (auto pickedGraphic : gResults)
|
||||
{
|
||||
if (pickedGraphic->attributes())
|
||||
{
|
||||
bool ok = false;
|
||||
int pickedIndex = pickedGraphic->attributes()->attributeValue(QStringLiteral("Rubberband3D-Item")).toInt(&ok);
|
||||
|
||||
if (ok)
|
||||
{
|
||||
qCritical() << "Picking index " << pickedIndex;
|
||||
_internal->m_currentIndex = pickedIndex;
|
||||
_internal->m_screenToMap->screenToLocation(_internal->m_pickingPoint.x(), _internal->m_pickingPoint.y());
|
||||
|
||||
if (pickedIndex < _internal->m_marker.size())
|
||||
{
|
||||
GraphicalObjectPictureMarker *&marker = _internal->m_marker[pickedIndex];
|
||||
|
||||
if (marker)
|
||||
{
|
||||
marker->setImage(markerSelectionImage());
|
||||
marker->updateView();
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
} // foreach pickedGraphic
|
||||
} // foreach iResult
|
||||
|
||||
if ((!_isCircular) || (_internal->m_coordinates.size() < 2))
|
||||
{
|
||||
// add new coordinate and calculate map location
|
||||
_internal->m_currentIndex = _internal->m_marker.size();
|
||||
_internal->m_marker << nullptr;
|
||||
_internal->m_coordinates << QPointF();
|
||||
|
||||
_internal->m_screenToMap->screenToLocation(_internal->m_pickingPoint.x(), _internal->m_pickingPoint.y());
|
||||
}
|
||||
}
|
||||
|
||||
if (_internal->m_selectionTask.taskId() == taskId)
|
||||
{
|
||||
for (auto iResult : identifyResults)
|
||||
{
|
||||
const QList<Esri::ArcGISRuntime::Graphic*> &gResults = iResult->graphics();
|
||||
for (auto pickedGraphic : gResults)
|
||||
{
|
||||
if (pickedGraphic->attributes())
|
||||
{
|
||||
bool ok = false;
|
||||
int pickedIndex = pickedGraphic->attributes()->attributeValue(QStringLiteral("Rubberband3D-Item")).toInt(&ok);
|
||||
|
||||
if ((ok) && (pickedIndex < _internal->m_marker.size()))
|
||||
{
|
||||
GraphicalObjectPictureMarker *&marker = _internal->m_marker[pickedIndex];
|
||||
|
||||
if (marker)
|
||||
{
|
||||
_internal->m_selectionIndex = pickedIndex;
|
||||
marker->setImage(markerSelectionImage());
|
||||
marker->updateView();
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if ((_internal->m_selectionIndex >= 0) && (_internal->m_selectionIndex < _internal->m_marker.size()))
|
||||
{
|
||||
GraphicalObjectPictureMarker *&marker = _internal->m_marker[_internal->m_selectionIndex];
|
||||
|
||||
if (marker)
|
||||
{
|
||||
marker->setImage(markerImage());
|
||||
marker->updateView();
|
||||
}
|
||||
_internal->m_selectionIndex = -1;
|
||||
}
|
||||
} // void RubberbandMultiPointFeature3D::onGetPickingResult(const QUuid &taskId, const QList<Esri::ArcGISRuntime::IdentifyGraphicsOverlayResult*> &identifyResults)
|
||||
|
||||
|
||||
bool RubberbandMultiPointFeature3D::selectAction(AbstractEventDispatcher *, int x, int y)
|
||||
{
|
||||
delete _internal->m_startMove;
|
||||
_internal->m_startMove = nullptr;
|
||||
|
||||
if (rubberbandIsAlive())
|
||||
{
|
||||
if (_baseInternal->buttonProxyActive(QPointF(x,y))) return false;
|
||||
|
||||
MapImpl *mapImpl = static_cast<MapImpl*>(_baseInternal->_map.data());
|
||||
|
||||
_internal->m_pickingTask.cancel(); // cancel old task
|
||||
_internal->m_pickingPoint = QPoint(x,y);
|
||||
_internal->m_pickingTask = mapImpl->getEsriGeoView()->identifyGraphicsOverlays(x,y,EventMouseNavigator::pickTolerance(),false,std::numeric_limits<int>::max());
|
||||
_internal->m_currentIndex = -1;
|
||||
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
} // bool RubberbandMultiPointFeature3D::selectAction(AbstractEventDispatcher *, int x, int y)
|
||||
|
||||
|
||||
bool RubberbandMultiPointFeature3D::setCoordinateAction(AbstractEventDispatcher *, int x, int y)
|
||||
{
|
||||
delete _internal->m_startMove;
|
||||
_internal->m_startMove = nullptr;
|
||||
|
||||
if (rubberbandIsAlive())
|
||||
{
|
||||
_baseInternal->_lastClickPosition = QPointF(x,y);
|
||||
|
||||
if (_baseInternal->buttonProxyActive(_baseInternal->_lastClickPosition)) return false;
|
||||
|
||||
_internal->m_screenToMap->screenToLocation(x,y);
|
||||
|
||||
if ((_internal->m_currentIndex >= 0) && (_internal->m_currentIndex < _internal->m_marker.size()))
|
||||
{
|
||||
GraphicalObjectPictureMarker *&marker = _internal->m_marker[_internal->m_currentIndex];
|
||||
|
||||
if (marker)
|
||||
{
|
||||
marker->setImage(markerImage());
|
||||
marker->updateView();
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
} // bool RubberbandMultiPointFeature3D::setCoordinateAction(AbstractEventDispatcher *, int x, int y)
|
||||
|
||||
|
||||
bool RubberbandMultiPointFeature3D::movePickedAction(AbstractEventDispatcher *, int x, int y)
|
||||
{
|
||||
if (rubberbandIsAlive())
|
||||
{
|
||||
_internal->m_screenToMap->screenToLocation(x,y);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
} // bool RubberbandMultiPointFeature3D::movePickedAction(AbstractEventDispatcher *, int x, int y)
|
||||
|
||||
|
||||
bool RubberbandMultiPointFeature3D::moveAction( AbstractEventDispatcher*, int x, int y )
|
||||
{
|
||||
if (rubberbandIsAlive())
|
||||
{
|
||||
if (_baseInternal->buttonProxyActive(QPointF(x,y))) return false;
|
||||
|
||||
MapImpl *mapImpl = static_cast<MapImpl*>(_baseInternal->_map.data());
|
||||
|
||||
_internal->m_selectionTask.cancel(); // cancel old task
|
||||
_internal->m_selectionTask = mapImpl->getEsriGeoView()->identifyGraphicsOverlays(x,y,EventMouseNavigator::pickTolerance(),false,std::numeric_limits<int>::max());
|
||||
|
||||
if ((_internal->m_selectionIndex >= 0) && (_internal->m_selectionIndex < _internal->m_marker.size()))
|
||||
{
|
||||
GraphicalObjectPictureMarker *&marker = _internal->m_marker[_internal->m_selectionIndex];
|
||||
|
||||
if (marker)
|
||||
{
|
||||
marker->setImage(markerImage());
|
||||
marker->updateView();
|
||||
}
|
||||
}
|
||||
_internal->m_selectionIndex = -1;
|
||||
}
|
||||
return false;
|
||||
} // bool RubberbandMultiPointFeature3D::moveAction(AbstractEventDispatcher*,int,int)
|
||||
|
||||
|
||||
|
||||
bool RubberbandMultiPointFeature3D::completeStateAction ( AbstractEventDispatcher * causer, int x, int y )
|
||||
{
|
||||
if (_internal->m_coordinates.size() > ((_isClosed && !_isCircular) ? 2 : 1))
|
||||
{
|
||||
return applyAndEndAction(causer,x,y);
|
||||
}
|
||||
return false;
|
||||
} // bool RubberbandMultiPointFeature3D::completeStateAction ( AbstractEventDispatcher * causer, int x, int y )
|
||||
|
||||
|
||||
bool RubberbandMultiPointFeature3D::contextMenuAction ( AbstractEventDispatcher*,int,int ) { return rubberbandIsAlive(); }
|
||||
bool RubberbandMultiPointFeature3D::deleteAction ( AbstractEventDispatcher*,int,int ) { return rubberbandIsAlive(); }
|
||||
bool RubberbandMultiPointFeature3D::undoAction ( AbstractEventDispatcher*,int,int ) { return rubberbandIsAlive(); }
|
||||
|
||||
|
||||
unsigned int RubberbandMultiPointFeature3D::coordinateCount() const
|
||||
{
|
||||
return (_internal->m_coordinates.size());
|
||||
} // unsigned int RubberbandMultiPointFeature3D::coordinateCount() const
|
||||
|
||||
|
||||
void RubberbandMultiPointFeature3D::update()
|
||||
{
|
||||
for (auto marker : qAsConst(_internal->m_marker))
|
||||
if (marker) marker->updateView();
|
||||
if (_internal->m_path)
|
||||
_internal->m_path->updateView();
|
||||
|
||||
externalUpdate();
|
||||
|
||||
} // RubberbandMultiPointFeature3D::update()
|
||||
|
||||
|
||||
QVector<QPointF> RubberbandMultiPointFeature3D::coordinateVector( CoordinateSystem cs ) const
|
||||
{
|
||||
QVector<QPointF> coordinateVector;
|
||||
coordinateVector.reserve(_internal->m_coordinates.size());
|
||||
|
||||
for (const auto &mapCoordinate : qAsConst(_internal->m_coordinates))
|
||||
coordinateVector << projectCoordinateFromMap( cs, mapCoordinate );
|
||||
return coordinateVector;
|
||||
} // QVector<QPointF> RubberbandMultiPointFeature3D::coordinateVector( CoordinateSystem cs ) const
|
||||
|
||||
|
||||
QPointF RubberbandMultiPointFeature3D::singleCoordinate( unsigned int idx, CoordinateSystem cs ) const
|
||||
{
|
||||
if (coordinateCount() > idx)
|
||||
return coordinateVector(cs).at(idx);
|
||||
|
||||
return QPointF();
|
||||
} // QPointF RubberbandMultiPointFeature3D::singleCoordinate( unsigned int idx, CoordinateSystem cs ) const
|
||||
|
||||
|
||||
void RubberbandMultiPointFeature3D::setCoordinateVector( const QVector<QPointF> & coordinateVector, CoordinateSystem cs )
|
||||
{
|
||||
_internal->m_coordinates.clear();
|
||||
for (const auto &geoCoordinate : coordinateVector)
|
||||
_internal->m_coordinates << projectCoordinateToMap( cs, geoCoordinate );
|
||||
|
||||
if ((!_internal->m_toElevation) && (_baseInternal->_map->layerFactory().elevationAvailable()))
|
||||
{
|
||||
_internal->m_toElevation = _baseInternal->_map->layerFactory().locationToElevation(); // layerFactory has ownership
|
||||
}
|
||||
|
||||
// now get elevations
|
||||
_internal->m_positionList3D.clear();
|
||||
for (const auto &pos : qAsConst(_internal->m_coordinates))
|
||||
{
|
||||
if (_internal->m_toElevation)
|
||||
{
|
||||
QMetaObject::Connection conn;
|
||||
|
||||
conn = connect(_internal->m_toElevation.data(), &SituationMap::LocationToElevationHelper::elevationCompleted, this, [this,pos,conn](double elevation)
|
||||
{
|
||||
disconnect(conn);
|
||||
|
||||
_internal->m_positionList3D << Point3D(pos.x(),pos.y(),elevation);
|
||||
if (_internal->m_positionList3D.size() == _internal->m_coordinates.size())
|
||||
{
|
||||
if (_internal->m_path) _internal->m_path->setPositions( _internal->m_positionList3D );
|
||||
update();
|
||||
}
|
||||
});
|
||||
_internal->m_toElevation->locationToElevation(pos);
|
||||
}
|
||||
else _internal->m_positionList3D << Point3D::fromQPointF(pos);
|
||||
}
|
||||
} // void RubberbandMultiPointFeature3D::setCoordinateVector( const QVector<QPointF> & coordinateVector, CoordinateSystem cs )
|
||||
|
||||
|
||||
void RubberbandMultiPointFeature3D::setCoordinateVector(const QVector<Point3D> & coordinateVector, CoordinateSystem cs)
|
||||
{
|
||||
_internal->m_coordinates.clear();
|
||||
_internal->m_positionList3D.clear();
|
||||
|
||||
for (const auto &geoCoordinate : coordinateVector)
|
||||
{
|
||||
const QPointF & projCoordinate = projectCoordinateToMap( cs, geoCoordinate.toPointF() );
|
||||
_internal->m_coordinates << projCoordinate;
|
||||
_internal->m_positionList3D << Point3D(projCoordinate.x(),projCoordinate.y(),geoCoordinate.z());
|
||||
}
|
||||
} // void RubberbandMultiPointFeature3D::setCoordinateVector(const QVector<Point3D> & coordinateVector, CoordinateSystem cs)
|
||||
|
||||
|
||||
QVector<Point3D> RubberbandMultiPointFeature3D::coordinateVector3D(CoordinateSystem cs) const
|
||||
{
|
||||
QVector<Point3D> coordinateVector;
|
||||
|
||||
coordinateVector.reserve(_internal->m_coordinates.size());
|
||||
|
||||
for (const auto &mapCoordinate : qAsConst(_internal->m_coordinates))
|
||||
coordinateVector << Point3D::fromQPointF( projectCoordinateFromMap(cs,mapCoordinate) );
|
||||
|
||||
return coordinateVector;
|
||||
} // QVector<Point3D> RubberbandMultiPointFeature3D::coordinateVector3D(CoordinateSystem cs) const
|
||||
|
||||
|
||||
Point3D RubberbandMultiPointFeature3D::singleCoordinate3D(unsigned int idx, CoordinateSystem cs) const
|
||||
{
|
||||
if (coordinateCount() > idx)
|
||||
{
|
||||
return coordinateVector3D(cs).at(idx);
|
||||
}
|
||||
return Point3D();
|
||||
} // Point3D RubberbandMultiPointFeature3D::singleCoordinate3D(unsigned int idx, CoordinateSystem cs) const
|
||||
|
||||
|
||||
|
||||
} } /* namespace SituationMap::RB */
|
||||
@@ -0,0 +1,136 @@
|
||||
/**
|
||||
**
|
||||
** @RDE_HEADER@
|
||||
** Definition of rubberband class to define multipoint feature geometry in 3d
|
||||
** $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
|
||||
**
|
||||
** -----------------------------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "rubberband_3d.h"
|
||||
|
||||
namespace Esri
|
||||
{
|
||||
namespace ArcGISRuntime
|
||||
{
|
||||
class IdentifyGraphicsOverlayResult;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
namespace SituationMap { namespace RB
|
||||
{
|
||||
|
||||
/**
|
||||
@class RubberbandPointFeature rubberband_point_feature.h
|
||||
@brief Implementation of a rubberband to input single coodinates for building point features
|
||||
@see Rubberband3D
|
||||
*/
|
||||
class SITUATIONMAP_EXPORT RubberbandMultiPointFeature3D : public Rubberband3D
|
||||
{
|
||||
Q_OBJECT
|
||||
/**
|
||||
@name Construction & Destruction
|
||||
@{
|
||||
*/
|
||||
|
||||
friend class RubberbandFactory;
|
||||
|
||||
explicit RubberbandMultiPointFeature3D( SituationMap::Map * map, QObject * parent = nullptr, bool isActive = true );
|
||||
|
||||
public:
|
||||
|
||||
virtual ~RubberbandMultiPointFeature3D();
|
||||
|
||||
RubberbandMultiPointFeature3D(const RubberbandMultiPointFeature3D &) = delete;
|
||||
RubberbandMultiPointFeature3D & operator = (const RubberbandMultiPointFeature3D &) = delete;
|
||||
/** @} */
|
||||
|
||||
bool selectAction ( AbstractEventDispatcher * causer, int x, int y ) override;
|
||||
bool setCoordinateAction ( AbstractEventDispatcher * causer, int x, int y ) override;
|
||||
bool moveAction ( AbstractEventDispatcher * causer, int x, int y ) override;
|
||||
bool movePickedAction ( AbstractEventDispatcher * causer, int x, int y ) override;
|
||||
bool contextMenuAction ( AbstractEventDispatcher * causer, int x, int y ) override;
|
||||
bool completeStateAction ( AbstractEventDispatcher * causer, int x, int y ) override;
|
||||
bool deleteAction ( AbstractEventDispatcher * causer, int x, int y ) override;
|
||||
bool undoAction ( AbstractEventDispatcher * causer, int x, int y ) override;
|
||||
|
||||
|
||||
inline void enableClosed( bool flag )
|
||||
{
|
||||
_isClosed = flag;
|
||||
} /* enableClosed */
|
||||
|
||||
/**
|
||||
Gets the value of the close flag
|
||||
*/
|
||||
inline bool isClosedEnabled() const { return _isClosed; }
|
||||
|
||||
unsigned int coordinateCount() const override;
|
||||
|
||||
QVector<QPointF> coordinateVector( CoordinateSystem cs = CoordinateSystem::Geo ) const override;
|
||||
|
||||
QPointF singleCoordinate( unsigned int idx = 0, CoordinateSystem cs = CoordinateSystem::Geo ) const override;
|
||||
|
||||
void setCoordinateVector( const QVector<QPointF> & coordinateVector, CoordinateSystem cs = CoordinateSystem::Geo ) override;
|
||||
|
||||
Point3D singleCoordinate3D( unsigned int idx = 0, CoordinateSystem cs = CoordinateSystem::Geo ) const override;
|
||||
QVector<Point3D> coordinateVector3D( CoordinateSystem cs = CoordinateSystem::Geo ) const override;
|
||||
|
||||
void setCoordinateVector( const QVector<Point3D> & coordinateVector, CoordinateSystem cs = CoordinateSystem::Geo ) override;
|
||||
|
||||
inline void enableCircular(bool flag)
|
||||
{
|
||||
_isCircular = flag;
|
||||
} // enableCircular
|
||||
|
||||
inline bool isCircularEnabled() const { return _isCircular; }
|
||||
|
||||
protected:
|
||||
|
||||
virtual bool buttonProxyActive( const QPointF & scenePos) const { Q_UNUSED(scenePos); return false; }
|
||||
|
||||
void activateButtons() override;
|
||||
|
||||
void update() override;
|
||||
|
||||
/*
|
||||
Forward declaration of internal container class for member variables. The derived classes of Rubberband
|
||||
often have also a declaration of InternalData for there own internal members.
|
||||
*/
|
||||
class InternalData;
|
||||
|
||||
InternalData * _internal;
|
||||
|
||||
bool _isClosed;
|
||||
bool _isCircular;
|
||||
|
||||
protected slots:
|
||||
|
||||
void onGetPickingResult(const QUuid &taskId, const QList<Esri::ArcGISRuntime::IdentifyGraphicsOverlayResult*> &identifyResults);
|
||||
void onMapPosition( const Point3D &mapCoordinate );
|
||||
|
||||
}; /* RubberbandMultiPointFeature3D */
|
||||
|
||||
} } /* namespace SituationMap::RB */
|
||||
@@ -0,0 +1,133 @@
|
||||
|
||||
/**
|
||||
**
|
||||
** @RDE_HEADER@
|
||||
** Implementation of rubberband class to define point feature geoemtry
|
||||
** $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_point_cluster.h"
|
||||
#include "rubberband_point_handle.h"
|
||||
#include "rubberband_drawable.h"
|
||||
#include "rubberband_handle_proxy.h"
|
||||
#include "transient_tactical_symbol.h"
|
||||
|
||||
#include "rubberband_internal.h"
|
||||
#include "rubberband_base_internal.h"
|
||||
|
||||
namespace SituationMap { namespace RB
|
||||
{
|
||||
|
||||
struct RubberbandPointCluster::InternalData
|
||||
{
|
||||
Q_DISABLE_COPY(InternalData)
|
||||
InternalData() = default;
|
||||
SituationMap::RefPointer<TransientTacticalSymbol> _previewSymbol;
|
||||
}; /* RubberbandMultiPointFeature::InternalData */
|
||||
|
||||
|
||||
RubberbandPointCluster::RubberbandPointCluster( SituationMap::Map * map, QObject * parent, bool isActive ) : RubberbandPointCluster( map, INT_MAX, parent, isActive ) {;}
|
||||
|
||||
|
||||
RubberbandPointCluster::RubberbandPointCluster( SituationMap::Map * map, unsigned int maxCoordinates, QObject * parent, bool isActive )
|
||||
: RubberbandPointFeature(map,parent,isActive), _internal(new InternalData()), _minimalPointCount(1)
|
||||
{
|
||||
_maximalPointCount = maxCoordinates;
|
||||
} /* RubberbandPointCluster::RubberbandPointCluster */
|
||||
|
||||
|
||||
RubberbandPointCluster::~RubberbandPointCluster()
|
||||
{
|
||||
delete _internal;
|
||||
} /* RubberbandPointCluster::~RubberbandPointCluster */
|
||||
|
||||
|
||||
void RubberbandPointCluster::activateButtons()
|
||||
{
|
||||
_baseInternal->_hasUndoButton = isEnabledConstructionState();
|
||||
_baseInternal->_applyIsPossible = (static_cast<unsigned int>(Rubberband::_internal->_handleList.size()) >= _minimalPointCount);
|
||||
_baseInternal->_undoIsPossible = (isEnabledConstructionState() && (static_cast<unsigned int>(Rubberband::_internal->_handleList.size()) > _minimalPointCount));
|
||||
Rubberband::activateButtons();
|
||||
} /* RubberbandMultiPointFeature::activateButton */
|
||||
|
||||
|
||||
void RubberbandPointCluster::setCoordinateVector(const QVector<QPointF> & coordinateVector, CoordinateSystem cs )
|
||||
{
|
||||
RubberbandPointFeature::setCoordinateVector( coordinateVector, cs );
|
||||
enableModificationState();
|
||||
activateButtons();
|
||||
} /* RubberbandPointCluster::setCoordinateVector */
|
||||
|
||||
|
||||
bool RubberbandPointCluster::setCoordinateAction( AbstractEventDispatcher * causer, int x, int y )
|
||||
{
|
||||
bool ok = false;
|
||||
|
||||
if (rubberbandIsAlive())
|
||||
{
|
||||
ok = RubberbandPointFeature::setCoordinateAction(causer,x,y);
|
||||
if (ok) activateButtons();
|
||||
}
|
||||
return ok;
|
||||
} /* RubberbandPointCluster::setCoordinateAction */
|
||||
|
||||
|
||||
void RubberbandPointCluster::update()
|
||||
{
|
||||
RubberbandPointFeature::update();
|
||||
if (!_previewSidc.isEmpty())
|
||||
{
|
||||
if (!_internal->_previewSymbol)
|
||||
{
|
||||
_internal->_previewSymbol = new TransientTacticalSymbol( static_cast<MapImpl*>(_baseInternal->_map.data()), _previewSidc );
|
||||
}
|
||||
|
||||
QVector<RubberbandHandle::RubberbandCoordinate> coordinateList;
|
||||
coordinateList.reserve( Rubberband::_internal->_handleList.size() );
|
||||
|
||||
for (auto handlePoint : qAsConst(Rubberband::_internal->_handleList))
|
||||
{
|
||||
RubberbandPointHandle * handlePointPtr = dynamic_cast<RubberbandPointHandle*>(handlePoint.get());
|
||||
if (handlePointPtr)
|
||||
{
|
||||
coordinateList.append( handlePointPtr->getCoordinate() );
|
||||
}
|
||||
}
|
||||
_internal->_previewSymbol->update( coordinateList );
|
||||
}
|
||||
else _internal->_previewSymbol = nullptr;
|
||||
} /* RubberbandPointCluster::update */
|
||||
|
||||
|
||||
bool RubberbandPointCluster::deleteAction(AbstractEventDispatcher * causer, int x, int y)
|
||||
{
|
||||
if (rubberbandIsAlive())
|
||||
{
|
||||
if (static_cast<unsigned int>(RubberbandPointFeature::_internal->_handleList.size()) <= _minimalPointCount) return true;
|
||||
return RubberbandPointFeature::deleteAction(causer,x,y);
|
||||
}
|
||||
return false;
|
||||
} /* RubberbandPointCluster::deleteAction */
|
||||
|
||||
} } /* namespace SituationMap::RB */
|
||||
@@ -0,0 +1,102 @@
|
||||
/**
|
||||
**
|
||||
** @RDE_HEADER@
|
||||
** Definition of rubberband class to define multiple point feature geoemtry
|
||||
** $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 .........:
|
||||
**
|
||||
** 18.06.2015, JT : First edition for use with Qt5
|
||||
**
|
||||
** -----------------------------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <limits>
|
||||
|
||||
#include "rubberband_point_feature.h"
|
||||
|
||||
|
||||
namespace SituationMap { namespace RB
|
||||
{
|
||||
|
||||
/**
|
||||
@class RubberbandPointCluster rubberband_point_cluster.h
|
||||
@brief Implementation of a rubberband to input single coodinates for building point feature clusters
|
||||
@see Rubberband, RubberbandPointFeature
|
||||
*/
|
||||
class SITUATIONMAP_EXPORT RubberbandPointCluster : public RubberbandPointFeature
|
||||
{
|
||||
Q_OBJECT
|
||||
/**
|
||||
@name Construction & Destruction
|
||||
@{
|
||||
*/
|
||||
|
||||
friend class RubberbandFactory;
|
||||
|
||||
RubberbandPointCluster( SituationMap::Map * map, QObject * parent, bool isActive = true );
|
||||
|
||||
RubberbandPointCluster( SituationMap::Map * map
|
||||
, unsigned int maxCoordinates = std::numeric_limits<unsigned int>::max()
|
||||
, QObject * parent = nullptr
|
||||
, bool isActive = true );
|
||||
|
||||
public:
|
||||
|
||||
virtual ~RubberbandPointCluster();
|
||||
|
||||
RubberbandPointCluster(const RubberbandPointCluster &) = delete;
|
||||
RubberbandPointCluster & operator = (const RubberbandPointCluster &) = delete;
|
||||
/** @} */
|
||||
|
||||
bool setCoordinateAction( AbstractEventDispatcher * causer, int x, int y ) override;
|
||||
bool deleteAction ( AbstractEventDispatcher * causer, int x, int y ) override;
|
||||
|
||||
|
||||
/**
|
||||
Defines the minimum number of coordinates to input. Default is 1
|
||||
*/
|
||||
inline void minimumPointCount(unsigned int n) { _minimalPointCount = (n > 0) ? n : 1; }
|
||||
|
||||
/**
|
||||
Returns the setting for minimum number of coordinates to input.
|
||||
*/
|
||||
inline unsigned int getMinimumPointCount() { return _minimalPointCount; }
|
||||
|
||||
void setCoordinateVector(const QVector<QPointF> & coordinateVector, CoordinateSystem cs = CoordinateSystem::Geo ) override;
|
||||
|
||||
protected:
|
||||
|
||||
/*
|
||||
Forward declaration of InternalData to hold private member variables. Becareful the base class Rubberband
|
||||
has similary a class for internal data member with name "InternalData". Don't be confused it is not the same.
|
||||
*/
|
||||
struct InternalData;
|
||||
|
||||
InternalData * _internal;
|
||||
unsigned int _minimalPointCount;
|
||||
|
||||
void activateButtons() override;
|
||||
|
||||
void update() override;
|
||||
|
||||
}; /* RubberbandPointCluster */
|
||||
|
||||
} } /* namespace SituationMap::RB */
|
||||
@@ -0,0 +1,311 @@
|
||||
|
||||
/**
|
||||
**
|
||||
** @RDE_HEADER@
|
||||
** Implementationof rubberband class to define point feature geoemtry
|
||||
** $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_point_feature.h"
|
||||
#include "rubberband_point_handle.h"
|
||||
#include "rubberband_drawable.h"
|
||||
|
||||
#include "rubberband_internal.h"
|
||||
#include "rubberband_base_internal.h"
|
||||
|
||||
#include <arcgis/Map.h>
|
||||
#include <arcgis/MapGraphicsView.h>
|
||||
|
||||
|
||||
namespace SituationMap { namespace RB
|
||||
{
|
||||
|
||||
RubberbandPointFeature::RubberbandPointFeature( SituationMap::Map * map, QObject * parent, bool isActive )
|
||||
: Rubberband(map,parent,isActive), _maximalPointCount(1)
|
||||
{
|
||||
} /* RubberbandPointFeature::RubberbandPointFeature */
|
||||
|
||||
|
||||
RubberbandPointFeature::~RubberbandPointFeature()
|
||||
{
|
||||
} /* RubberbandPointFeature::~RubberbandPointFeature */
|
||||
|
||||
|
||||
QVector<QPointF> RubberbandPointFeature::coordinateVector( CoordinateSystem cs ) const
|
||||
{
|
||||
QVector<QPointF> coordinateVector;
|
||||
coordinateVector.reserve(_internal->_handleList.size());
|
||||
|
||||
for (auto handle : qAsConst(_internal->_handleList))
|
||||
{
|
||||
RubberbandPointHandle * handlePointPtr = dynamic_cast<RubberbandPointHandle*>(handle.get());
|
||||
|
||||
coordinateVector.push_back(projectCoordinateFromMap( cs, handlePointPtr->getCoordinate()._mapCoordinate ));
|
||||
}
|
||||
return coordinateVector;
|
||||
} /* RubberbandPointFeature::coordinateVector */
|
||||
|
||||
QVector<QPointF> RubberbandPointFeature::coordinateVectorPixel() const
|
||||
{
|
||||
QVector<QPointF> coordinateVector;
|
||||
coordinateVector.reserve(_internal->_handleList.size());
|
||||
|
||||
for (auto handle : qAsConst(_internal->_handleList))
|
||||
{
|
||||
RubberbandPointHandle *handlePointPtr = dynamic_cast<RubberbandPointHandle*>(handle.get());
|
||||
coordinateVector.push_back(handlePointPtr->getPixelCoordinate());
|
||||
}
|
||||
return coordinateVector;
|
||||
}
|
||||
|
||||
|
||||
QPointF RubberbandPointFeature::singleCoordinate(unsigned int idx, CoordinateSystem cs ) const
|
||||
{
|
||||
if (idx < (unsigned int) _internal->_handleList.size())
|
||||
{
|
||||
const RubberbandPointHandle * handle = dynamic_cast<const RubberbandPointHandle*>(_internal->_handleList[idx].get());
|
||||
|
||||
return projectCoordinateFromMap( cs, handle->getCoordinate()._mapCoordinate );
|
||||
}
|
||||
return QPointF();
|
||||
} /* RubberbandPointFeature::singleCoordinate */
|
||||
|
||||
|
||||
void RubberbandPointFeature::setCoordinateVector(const QVector<QPointF> & coordinateVector, CoordinateSystem cs )
|
||||
{
|
||||
_internal->_handleList.clear();
|
||||
|
||||
for (auto p : coordinateVector)
|
||||
{
|
||||
const QPointF &mapPos = projectCoordinateToMap( cs, p );
|
||||
|
||||
RubberbandPointHandle * handlePointPtr = new RubberbandPointHandle( _internal->_mapView
|
||||
, _internal->_mapScene
|
||||
, Esri::ArcGISRuntime::Point(mapPos.x(),mapPos.y(),Rubberband::_internal->_mapView->map()->spatialReference()) );
|
||||
_internal->_handleList.append( SituationMap::RefPointer<RubberbandHandle>(handlePointPtr) );
|
||||
}
|
||||
update();
|
||||
} /* RubberbandPointFeature::setCoordinateVector */
|
||||
|
||||
|
||||
bool RubberbandPointFeature::selectAction( AbstractEventDispatcher * , int x, int y )
|
||||
{
|
||||
if (rubberbandIsAlive())
|
||||
{
|
||||
bool eventHandled = false;
|
||||
QPointF scenePos(pixel2ScenePosition(x,y));
|
||||
|
||||
if (_baseInternal->buttonProxyActive(scenePos)) return false;
|
||||
|
||||
_baseInternal->_lastClickPosition = scenePos;
|
||||
|
||||
RubberbandHandle * handlePtr = pickHandle(x,y);
|
||||
if (handlePtr)
|
||||
{
|
||||
handlePtr->setSelection();
|
||||
enableSelectedState();
|
||||
eventHandled = true;
|
||||
}
|
||||
|
||||
if (!isEnabledSelectedState())
|
||||
{
|
||||
if (isEnabledConstructionState())
|
||||
{
|
||||
if (!buttonProxyActive(scenePos))
|
||||
{
|
||||
RubberbandPointHandle * handlePtr = new RubberbandPointHandle( _internal->_mapView, _internal->_mapScene, scenePos );
|
||||
|
||||
_internal->_handleList.append( SituationMap::RefPointer<RubberbandHandle>(handlePtr) );
|
||||
handlePtr->setSelection();
|
||||
enableSelectedState();
|
||||
eventHandled = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (eventHandled)
|
||||
{
|
||||
update();
|
||||
deactivateButtons();
|
||||
}
|
||||
|
||||
|
||||
return eventHandled;
|
||||
}
|
||||
return false;
|
||||
} /* RubberbandPointFeature::selectAction */
|
||||
|
||||
|
||||
|
||||
bool RubberbandPointFeature::setCoordinateAction( AbstractEventDispatcher * causer, int x, int y )
|
||||
{
|
||||
if ((rubberbandIsAlive()) && (_internal->_mapView) && (_internal->_mapScene))
|
||||
{
|
||||
bool eventHandled = false;
|
||||
QPointF scenePos(pixel2ScenePosition(x,y));
|
||||
|
||||
Rubberband::_internal->_lastClickPosition = scenePos;
|
||||
|
||||
if (isEnabledSelectedState())
|
||||
{
|
||||
if (_baseInternal->buttonProxyActive(scenePos)) return false;
|
||||
for (auto handle : qAsConst(_internal->_handleList))
|
||||
{
|
||||
RubberbandPointHandle * handlePointPtr = dynamic_cast<RubberbandPointHandle*>(handle.get());
|
||||
if ((handlePointPtr) && (handlePointPtr->isSelected()))
|
||||
{
|
||||
handlePointPtr->setSelection(false);
|
||||
handlePointPtr->moveCoordinate( scenePos - _baseInternal->_lastClickPosition );
|
||||
eventHandled = true;
|
||||
}
|
||||
}
|
||||
disenableSelectedState();
|
||||
disenableMultiSelectedState();
|
||||
}
|
||||
else if (_baseInternal->buttonProxyActive(scenePos)) return false;
|
||||
|
||||
if (eventHandled) update();
|
||||
|
||||
if ((isEnabledConstructionState()) && (_internal->_handleList.size() >= static_cast<int>(_maximalPointCount)))
|
||||
{
|
||||
completeStateAction( causer, x, y );
|
||||
eventHandled = true;
|
||||
}
|
||||
return eventHandled;
|
||||
}
|
||||
return false;
|
||||
} /* RubberbandPointFeature::setCoordinateAction */
|
||||
|
||||
|
||||
bool RubberbandPointFeature::moveAction( AbstractEventDispatcher*, int x, int y )
|
||||
{
|
||||
adjustConnectedPreviewPixmap(x,y);
|
||||
|
||||
if (rubberbandIsAlive())
|
||||
{
|
||||
if (!isEnabledMultiSelectedState()) deSelectHandles();
|
||||
|
||||
RubberbandHandle * handlePtr = pickHandle(x,y);
|
||||
if (handlePtr)
|
||||
{
|
||||
handlePtr->setSelection();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
} /* RubberbandPointFeature::moveAction */
|
||||
|
||||
|
||||
bool RubberbandPointFeature::movePickedAction( AbstractEventDispatcher*, int x, int y )
|
||||
{
|
||||
adjustConnectedPreviewPixmap(x,y);
|
||||
|
||||
if ((rubberbandIsAlive()) && (_internal->_mapView) && (_internal->_mapScene))
|
||||
{
|
||||
if (isEnabledSelectedState())
|
||||
{
|
||||
QPointF scenePos(pixel2ScenePosition(x,y));
|
||||
QPointF deltaMove(scenePos-_baseInternal->_lastClickPosition);
|
||||
|
||||
_baseInternal->_lastClickPosition = scenePos;
|
||||
|
||||
bool eventHandled = false;
|
||||
|
||||
for (auto handle : qAsConst(_internal->_handleList))
|
||||
{
|
||||
RubberbandPointHandle * handlePointPtr = dynamic_cast<RubberbandPointHandle*>(handle.get());
|
||||
if ((handlePointPtr) && (handlePointPtr->isSelected()))
|
||||
{
|
||||
handlePointPtr->moveCoordinate( deltaMove );
|
||||
eventHandled = true;
|
||||
}
|
||||
}
|
||||
if (eventHandled) update();
|
||||
}
|
||||
return false;
|
||||
}
|
||||
return false;
|
||||
} /* RubberbandPointFeature::movePickedAction */
|
||||
|
||||
|
||||
bool RubberbandPointFeature::contextMenuAction( AbstractEventDispatcher*, int , int )
|
||||
{
|
||||
return rubberbandIsAlive();
|
||||
} /* RubberbandPointFeature::contextMenuAction */
|
||||
|
||||
|
||||
bool RubberbandPointFeature::completeStateAction( AbstractEventDispatcher * causer, int x, int y )
|
||||
{
|
||||
if (!_internal->_handleList.empty())
|
||||
{
|
||||
return applyAndEndAction(causer,x,y);
|
||||
}
|
||||
return false;
|
||||
} /* RubberbandPointFeature::completeStateAction */
|
||||
|
||||
|
||||
bool RubberbandPointFeature::undoAction( AbstractEventDispatcher*, int , int )
|
||||
{
|
||||
if (rubberbandIsAlive())
|
||||
{
|
||||
if (!_internal->_handleList.empty())
|
||||
{
|
||||
_internal->_handleList.pop_back();
|
||||
update();
|
||||
activateButtons();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
} /* RubberbandPointFeature::undoAction */
|
||||
|
||||
|
||||
bool RubberbandPointFeature::deleteAction(AbstractEventDispatcher*, int x, int y)
|
||||
{
|
||||
if ((rubberbandIsAlive()) && (_internal->_mapView) && (_internal->_mapScene))
|
||||
{
|
||||
if ((_internal->_handleList.size() > 1) && (isEnabledSelectedState()))
|
||||
{
|
||||
QPointF scenePosition = pixel2ScenePosition(x,y);
|
||||
QList<SituationMap::RefPointer<RubberbandHandle>>::iterator handleIter = _internal->_handleList.begin();
|
||||
|
||||
while (handleIter != _internal->_handleList.end())
|
||||
{
|
||||
if (handleIter->get()->isPositionInside(scenePosition))
|
||||
{
|
||||
handleIter = _internal->_handleList.erase(handleIter);
|
||||
continue;
|
||||
}
|
||||
++handleIter;
|
||||
}
|
||||
update();
|
||||
activateButtons();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
} /* RubberbandPointFeature::deleteAction */
|
||||
|
||||
|
||||
} } /* namespace SituationMap::RB */
|
||||
@@ -0,0 +1,99 @@
|
||||
/**
|
||||
**
|
||||
** @RDE_HEADER@
|
||||
** Definition of rubberband class to define point feature geoemtry
|
||||
** $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
|
||||
**
|
||||
** -----------------------------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <limits>
|
||||
|
||||
#include "rubberband.h"
|
||||
|
||||
|
||||
namespace SituationMap { namespace RB
|
||||
{
|
||||
|
||||
/**
|
||||
@class RubberbandPointFeature rubberband_point_feature.h
|
||||
@brief Implementation of a rubberband to input single coodinates for building point features
|
||||
@see Rubberband
|
||||
*/
|
||||
class SITUATIONMAP_EXPORT RubberbandPointFeature : public Rubberband
|
||||
{
|
||||
Q_OBJECT
|
||||
/**
|
||||
@name Construction & Destruction
|
||||
@{
|
||||
*/
|
||||
|
||||
friend class RubberbandFactory;
|
||||
friend class RubberbandPointCluster;
|
||||
|
||||
explicit RubberbandPointFeature( SituationMap::Map * map, QObject * parent = nullptr, bool isActive = true );
|
||||
|
||||
public:
|
||||
~RubberbandPointFeature();
|
||||
/** @} */
|
||||
|
||||
bool selectAction ( AbstractEventDispatcher * causer, int x, int y ) override;
|
||||
bool setCoordinateAction ( AbstractEventDispatcher * causer, int x, int y ) override;
|
||||
bool moveAction ( AbstractEventDispatcher * causer, int x, int y ) override;
|
||||
bool movePickedAction ( AbstractEventDispatcher * causer, int x, int y ) override;
|
||||
bool contextMenuAction ( AbstractEventDispatcher * causer, int x, int y ) override;
|
||||
bool completeStateAction ( AbstractEventDispatcher * causer, int x, int y ) override;
|
||||
bool deleteAction ( AbstractEventDispatcher * causer, int x, int y ) override;
|
||||
bool undoAction ( AbstractEventDispatcher * causer, int x, int y ) override;
|
||||
|
||||
|
||||
/**
|
||||
Defines the maximum number of coordinates to input. Default is 1
|
||||
*/
|
||||
inline void maximumPointCount(unsigned int n) { _maximalPointCount = (n > 0) ? n : std::numeric_limits<unsigned int>::max(); }
|
||||
|
||||
/**
|
||||
Returns the setting for maximum number of coordinates to input.
|
||||
*/
|
||||
inline unsigned int getMaximumPointCount() { return _maximalPointCount; }
|
||||
|
||||
|
||||
QVector<QPointF> coordinateVector( CoordinateSystem cs = CoordinateSystem::Geo ) const override;
|
||||
QVector<QPointF> coordinateVectorPixel() const;
|
||||
|
||||
QPointF singleCoordinate( unsigned int idx = 0, CoordinateSystem cs = CoordinateSystem::Geo ) const override;
|
||||
|
||||
void setCoordinateVector( const QVector<QPointF> & coordinateVector, CoordinateSystem cs = CoordinateSystem::Geo ) override;
|
||||
|
||||
protected:
|
||||
|
||||
virtual bool buttonProxyActive( const QPointF & scenePos) const { Q_UNUSED(scenePos); return false; }
|
||||
|
||||
|
||||
unsigned int _maximalPointCount;
|
||||
|
||||
|
||||
}; /* RubberbandPointFeature */
|
||||
|
||||
} } /* namespace SituationMap::RB */
|
||||
@@ -0,0 +1,272 @@
|
||||
/**
|
||||
**
|
||||
** @RDE_HEADER@
|
||||
** Implementation of rubberband class to define point feature geometry in 3d
|
||||
** $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 <limits>
|
||||
|
||||
#include "rubberband_point_feature_3d.h"
|
||||
#include "rubberband_base_internal.h"
|
||||
|
||||
#include <Map/map.h>
|
||||
#include <Map/layer_factory.h>
|
||||
|
||||
#include <MapImpl/map_impl.h>
|
||||
#include <MapImpl/coordinate_translation.h>
|
||||
#include <MapImpl/screen_to_location_helper.h>
|
||||
|
||||
#include <GraphicalObjects/graphical_object_picture_marker.h>
|
||||
|
||||
#include <QtCore/QPoint>
|
||||
|
||||
|
||||
namespace SituationMap { namespace RB
|
||||
{
|
||||
|
||||
struct RubberbandPointFeature3D::InternalData
|
||||
{
|
||||
QPoint m_screenCordinate = QPoint(std::numeric_limits<int>::min(),std::numeric_limits<int>::min());
|
||||
Point3D m_position;
|
||||
GraphicalObjectPictureMarker * m_marker = nullptr;
|
||||
ScreenToLocationHelper * m_screenToMap = nullptr;
|
||||
AbstractEventDispatcher * m_causer = nullptr;
|
||||
bool m_modifyPosition = false;
|
||||
bool m_positionReady = false;
|
||||
|
||||
InternalData() = default;
|
||||
|
||||
~InternalData()
|
||||
{
|
||||
delete m_marker;
|
||||
delete m_screenToMap;
|
||||
}
|
||||
}; // RubberbandPointFeature3D::InternalData
|
||||
|
||||
|
||||
RubberbandPointFeature3D::RubberbandPointFeature3D( SituationMap::Map * map, QObject * parent, bool isActive )
|
||||
: Rubberband3D(map,parent,isActive)
|
||||
, _internal( new RubberbandPointFeature3D::InternalData() )
|
||||
{
|
||||
MapImpl *mapImpl = static_cast<MapImpl*>(_baseInternal->_map.data());
|
||||
Esri::ArcGISRuntime::SceneGraphicsView *view = mapImpl->getEsriSceneGraphicsView();
|
||||
|
||||
_internal->m_screenToMap = new ScreenToLocationHelper(view);
|
||||
connect( _internal->m_screenToMap, &ScreenToLocationHelper::mouseScenePositionChanged, this, &RubberbandPointFeature3D::onMapPosition );
|
||||
|
||||
} // RubberbandPointFeature3D::RubberbandPointFeature3D( SituationMap::Map * map, QObject * parent = nullptr, bool isActive )
|
||||
|
||||
|
||||
RubberbandPointFeature3D::~RubberbandPointFeature3D()
|
||||
{
|
||||
delete _internal;
|
||||
_internal = nullptr;
|
||||
} // RubberbandPointFeature3D::~RubberbandPointFeature3D()
|
||||
|
||||
|
||||
void RubberbandPointFeature3D::enableModificationState()
|
||||
{
|
||||
_internal->m_modifyPosition = true;
|
||||
_internal->m_positionReady = true;
|
||||
} // void RubberbandPointFeature3D::enableModificationState()
|
||||
|
||||
|
||||
void RubberbandPointFeature3D::onMapPosition(const Point3D &mapCoordinate)
|
||||
{
|
||||
if (qIsNaN(mapCoordinate.x())) return; // illegal map position
|
||||
if (qIsNaN(mapCoordinate.y())) return;
|
||||
|
||||
_internal->m_position = mapCoordinate;
|
||||
|
||||
if (nullptr == _internal->m_marker)
|
||||
{
|
||||
MapImpl *mapImpl = static_cast<MapImpl*>(_baseInternal->_map.data());
|
||||
Esri::ArcGISRuntime::SceneGraphicsView *view = mapImpl->getEsriSceneGraphicsView();
|
||||
Esri::ArcGISRuntime::GraphicsOverlay *graphicsLayer = mapImpl->getGraphicsLayer(mapImpl->layerFactory().rubberbandLayer());
|
||||
|
||||
if (nullptr == view) return;
|
||||
|
||||
_internal->m_marker = new GraphicalObjectPictureMarker( view, graphicsLayer, QStringLiteral("RubberbandPointFeature3D"), INVALID_MAP_ID );
|
||||
|
||||
_internal->m_marker->setImage(markerImage());
|
||||
}
|
||||
_internal->m_marker->setOrigin( mapCoordinate );
|
||||
|
||||
update();
|
||||
|
||||
if (_internal->m_causer)
|
||||
{
|
||||
_internal->m_positionReady = true;
|
||||
completeStateAction(_internal->m_causer,_internal->m_screenCordinate.x(), _internal->m_screenCordinate.y());
|
||||
}
|
||||
} // void RubberbandPointFeature3D::onMapPosition(const QPointF &mapCoordinate)
|
||||
|
||||
|
||||
bool RubberbandPointFeature3D::selectAction(AbstractEventDispatcher *, int x, int y)
|
||||
{
|
||||
if (rubberbandIsAlive())
|
||||
{
|
||||
if (nullptr ==_internal->m_causer)
|
||||
{
|
||||
_internal->m_screenCordinate = QPoint(x,y);
|
||||
_internal->m_screenToMap->screenToLocation(x,y);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
} // bool RubberbandPointFeature3D::selectAction(AbstractEventDispatcher *, int x, int y)
|
||||
|
||||
|
||||
bool RubberbandPointFeature3D::setCoordinateAction(AbstractEventDispatcher * causer, int x, int y)
|
||||
{
|
||||
if (rubberbandIsAlive())
|
||||
{
|
||||
_internal->m_causer = (_internal->m_modifyPosition) ? nullptr : causer;
|
||||
_internal->m_screenCordinate = QPoint(x,y);
|
||||
_internal->m_screenToMap->screenToLocation(x,y);
|
||||
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
} // bool RubberbandPointFeature3D::setCoordinateAction(AbstractEventDispatcher * causer, int x, int y)
|
||||
|
||||
|
||||
bool RubberbandPointFeature3D::movePickedAction(AbstractEventDispatcher *, int x, int y)
|
||||
{
|
||||
if (rubberbandIsAlive())
|
||||
{
|
||||
if (nullptr == _internal->m_causer)
|
||||
{
|
||||
_internal->m_screenCordinate = QPoint(x,y);
|
||||
_internal->m_screenToMap->screenToLocation(x,y);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
} // bool RubberbandPointFeature3D::movePickedAction(AbstractEventDispatcher *, int x, int y)
|
||||
|
||||
|
||||
bool RubberbandPointFeature3D::moveAction(AbstractEventDispatcher*,int,int)
|
||||
{
|
||||
if (rubberbandIsAlive())
|
||||
{
|
||||
}
|
||||
return false;
|
||||
} // bool RubberbandPointFeature3D::moveAction(AbstractEventDispatcher*,int,int)
|
||||
|
||||
|
||||
|
||||
bool RubberbandPointFeature3D::completeStateAction ( AbstractEventDispatcher * causer, int x, int y )
|
||||
{
|
||||
if (coordinateCount() > 0)
|
||||
{
|
||||
return applyAndEndAction(causer,x,y);
|
||||
}
|
||||
return false;
|
||||
} // bool RubberbandPointFeature3D::completeStateAction ( AbstractEventDispatcher * causer, int x, int y )
|
||||
|
||||
|
||||
bool RubberbandPointFeature3D::contextMenuAction ( AbstractEventDispatcher*,int,int ) { return rubberbandIsAlive(); }
|
||||
bool RubberbandPointFeature3D::deleteAction ( AbstractEventDispatcher*,int,int ) { return rubberbandIsAlive(); }
|
||||
bool RubberbandPointFeature3D::undoAction ( AbstractEventDispatcher*,int,int ) { return rubberbandIsAlive(); }
|
||||
|
||||
|
||||
unsigned int RubberbandPointFeature3D::coordinateCount() const
|
||||
{
|
||||
return (_internal->m_positionReady) ? 1 : 0;
|
||||
} // unsigned int RubberbandPointFeature3D::coordinateCount() const
|
||||
|
||||
|
||||
void RubberbandPointFeature3D::update()
|
||||
{
|
||||
if (_internal->m_marker) _internal->m_marker->updateView();
|
||||
externalUpdate();
|
||||
} // RubberbandPointFeature3D::update()
|
||||
|
||||
|
||||
QVector<QPointF> RubberbandPointFeature3D::coordinateVector( CoordinateSystem cs ) const
|
||||
{
|
||||
if (coordinateCount() > 0)
|
||||
{
|
||||
const QPointF &geoPos = projectCoordinateFromMap( cs, _internal->m_position.toPointF() );
|
||||
return QVector<QPointF>() << geoPos;
|
||||
}
|
||||
return QVector<QPointF>();
|
||||
} // QVector<QPointF> RubberbandPointFeature3D::coordinateVector( CoordinateSystem cs ) const
|
||||
|
||||
|
||||
QPointF RubberbandPointFeature3D::singleCoordinate( unsigned int idx, CoordinateSystem cs ) const
|
||||
{
|
||||
Q_UNUSED(idx);
|
||||
if (coordinateCount() > 0)
|
||||
{
|
||||
return coordinateVector(cs).value(0);
|
||||
}
|
||||
return QPointF();
|
||||
} // QPointF RubberbandPointFeature3D::singleCoordinate( unsigned int idx, CoordinateSystem cs ) const
|
||||
|
||||
|
||||
void RubberbandPointFeature3D::setCoordinateVector( const QVector<QPointF> & coordinateVector, CoordinateSystem cs )
|
||||
{
|
||||
if (coordinateVector.size() > 0)
|
||||
{
|
||||
const QPointF &mapPos = projectCoordinateToMap(cs,coordinateVector[0]);
|
||||
onMapPosition( Point3D::fromQPointF(mapPos) );
|
||||
}
|
||||
} // void RubberbandPointFeature3D::setCoordinateVector( const QVector<QPointF> & coordinateVector, CoordinateSystem cs )
|
||||
|
||||
|
||||
void RubberbandPointFeature3D::setCoordinateVector(const QVector<Point3D> & coordinateVector, CoordinateSystem cs )
|
||||
{
|
||||
if (coordinateVector.size() > 0)
|
||||
{
|
||||
const QPointF &mapPos = projectCoordinateToMap(cs,coordinateVector[0].toPointF());
|
||||
_internal->m_position = Point3D(mapPos.x(),mapPos.y(),coordinateVector[0].z());
|
||||
}
|
||||
} // void RubberbandPointFeature3D::setCoordinateVector(const QVector<Point3D> & coordinateVector, CoordinateSystem cs )
|
||||
|
||||
|
||||
QVector<Point3D> RubberbandPointFeature3D::coordinateVector3D( CoordinateSystem cs ) const
|
||||
{
|
||||
if (coordinateCount() > 0)
|
||||
{
|
||||
const QPointF &geoPos = projectCoordinateFromMap( cs, _internal->m_position.toPointF() );
|
||||
return QVector<Point3D>() << Point3D(geoPos.x(),geoPos.y(),_internal->m_position.z());
|
||||
}
|
||||
return QVector<Point3D>();
|
||||
} // QVector<Point3D> RubberbandPointFeature3D::coordinateVector3D( CoordinateSystem cs ) const
|
||||
|
||||
|
||||
Point3D RubberbandPointFeature3D::singleCoordinate3D(unsigned int idx , CoordinateSystem cs) const
|
||||
{
|
||||
Q_UNUSED(idx);
|
||||
if (coordinateCount() > 0)
|
||||
{
|
||||
return coordinateVector3D(cs).value(0);
|
||||
}
|
||||
return Point3D();
|
||||
} // Point3D RubberbandPointFeature3D::singleCoordinate3D(unsigned int idx, CoordinateSystem cs) const
|
||||
|
||||
} } /* namespace SituationMap::RB */
|
||||
@@ -0,0 +1,104 @@
|
||||
/**
|
||||
**
|
||||
** @RDE_HEADER@
|
||||
** Definition of rubberband class to define point feature geometry in 3d
|
||||
** $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
|
||||
**
|
||||
** -----------------------------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "rubberband_3d.h"
|
||||
|
||||
|
||||
namespace SituationMap { namespace RB
|
||||
{
|
||||
|
||||
/**
|
||||
@class RubberbandPointFeature rubberband_point_feature.h
|
||||
@brief Implementation of a rubberband to input single coodinates for building point features
|
||||
@see Rubberband
|
||||
*/
|
||||
class SITUATIONMAP_EXPORT RubberbandPointFeature3D : public Rubberband3D
|
||||
{
|
||||
Q_OBJECT
|
||||
/**
|
||||
@name Construction & Destruction
|
||||
@{
|
||||
*/
|
||||
|
||||
friend class RubberbandFactory;
|
||||
|
||||
explicit RubberbandPointFeature3D( SituationMap::Map * map, QObject * parent = nullptr, bool isActive = true );
|
||||
|
||||
public:
|
||||
|
||||
~RubberbandPointFeature3D();
|
||||
/** @} */
|
||||
|
||||
bool selectAction ( AbstractEventDispatcher * causer, int x, int y ) override;
|
||||
bool setCoordinateAction ( AbstractEventDispatcher * causer, int x, int y ) override;
|
||||
bool moveAction ( AbstractEventDispatcher * causer, int x, int y ) override;
|
||||
bool movePickedAction ( AbstractEventDispatcher * causer, int x, int y ) override;
|
||||
bool contextMenuAction ( AbstractEventDispatcher * causer, int x, int y ) override;
|
||||
bool completeStateAction ( AbstractEventDispatcher * causer, int x, int y ) override;
|
||||
bool deleteAction ( AbstractEventDispatcher * causer, int x, int y ) override;
|
||||
bool undoAction ( AbstractEventDispatcher * causer, int x, int y ) override;
|
||||
|
||||
|
||||
unsigned int coordinateCount() const override;
|
||||
|
||||
QVector<QPointF> coordinateVector( CoordinateSystem cs = CoordinateSystem::Geo ) const override;
|
||||
|
||||
QPointF singleCoordinate( unsigned int idx = 0, CoordinateSystem cs = CoordinateSystem::Geo ) const override;
|
||||
|
||||
void setCoordinateVector( const QVector<QPointF> & coordinateVector, CoordinateSystem cs = CoordinateSystem::Geo ) override;
|
||||
|
||||
Point3D singleCoordinate3D( unsigned int idx = 0, CoordinateSystem cs = CoordinateSystem::Geo ) const override;
|
||||
QVector<Point3D> coordinateVector3D( CoordinateSystem cs = CoordinateSystem::Geo ) const override;
|
||||
|
||||
void setCoordinateVector( const QVector<Point3D> & coordinateVector, CoordinateSystem cs = CoordinateSystem::Geo ) override;
|
||||
|
||||
void enableModificationState();
|
||||
|
||||
protected:
|
||||
|
||||
virtual bool buttonProxyActive( const QPointF & scenePos) const { Q_UNUSED(scenePos); return false; }
|
||||
|
||||
void update() override;
|
||||
|
||||
/*
|
||||
Forward declaration of internal container class for member variables. The derived classes of Rubberband
|
||||
often have also a declaration of InternalData for there own internal members.
|
||||
*/
|
||||
struct InternalData;
|
||||
|
||||
InternalData * _internal;
|
||||
|
||||
protected slots:
|
||||
|
||||
void onMapPosition( const Point3D &mapCoordinate );
|
||||
|
||||
}; /* RubberbandPointFeature3D */
|
||||
|
||||
} } /* namespace SituationMap::RB */
|
||||
@@ -0,0 +1,390 @@
|
||||
|
||||
/**
|
||||
**
|
||||
** @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_point_handle.h"
|
||||
|
||||
#include <MathUtils/math_const.h>
|
||||
|
||||
#include <arcgis/MapGraphicsView.h>
|
||||
|
||||
#include <QtWidgets/QGraphicsScene>
|
||||
#include <QtWidgets/QGraphicsEllipseItem>
|
||||
|
||||
namespace SituationMap { namespace RB
|
||||
{
|
||||
|
||||
RubberbandPointHandle::RubberbandPointHandle( Esri::ArcGISRuntime::MapGraphicsView * mapView
|
||||
, QGraphicsScene * scene
|
||||
, const QPointF & scenePosition )
|
||||
: RubberbandHandle(mapView,scene)
|
||||
, _pointSymbol(nullptr)
|
||||
, _coordinate( mapView, scenePosition )
|
||||
, _sceneOffset(0,0)
|
||||
, _iconPixmap(nullptr)
|
||||
, _boundingRect(nullptr)
|
||||
{
|
||||
zBufferPlane( ZBufferPlane::PointHandle );
|
||||
buildHandle( scenePosition );
|
||||
} /* RubberbandPointHandle::RubberbandPointHandle */
|
||||
|
||||
|
||||
RubberbandPointHandle::RubberbandPointHandle( Esri::ArcGISRuntime::MapGraphicsView * mapView
|
||||
, QGraphicsScene * scene
|
||||
, const Esri::ArcGISRuntime::Point & mapCoordinate )
|
||||
: RubberbandHandle(mapView,scene)
|
||||
, _pointSymbol(nullptr)
|
||||
, _coordinate( mapView, mapCoordinate )
|
||||
, _sceneOffset(0,0)
|
||||
, _iconPixmap(nullptr)
|
||||
, _boundingRect(nullptr)
|
||||
{
|
||||
zBufferPlane( ZBufferPlane::PointHandle );
|
||||
buildHandle( _coordinate._sceneCoordinate );
|
||||
} /* RubberbandPointHandle::RubberbandPointHandle */
|
||||
|
||||
|
||||
RubberbandPointHandle::RubberbandPointHandle( Esri::ArcGISRuntime::MapGraphicsView * mapView
|
||||
, QGraphicsScene * scene
|
||||
, const QPointF & scenePosition
|
||||
, const QPixmap & icon )
|
||||
: RubberbandHandle(mapView,scene)
|
||||
, _pointSymbol(nullptr)
|
||||
, _coordinate( mapView, scenePosition )
|
||||
, _sceneOffset(0,0)
|
||||
, _iconPixmap( new QPixmap(icon) )
|
||||
, _boundingRect(nullptr)
|
||||
{
|
||||
zBufferPlane( ZBufferPlane::PointHandle );
|
||||
buildHandle( scenePosition );
|
||||
} /* RubberbandPointHandle::RubberbandPointHandle */
|
||||
|
||||
|
||||
RubberbandPointHandle::RubberbandPointHandle( Esri::ArcGISRuntime::MapGraphicsView * mapView
|
||||
, QGraphicsScene * scene
|
||||
, const Esri::ArcGISRuntime::Point & mapCoordinate
|
||||
, const QPixmap & icon )
|
||||
: RubberbandHandle(mapView,scene)
|
||||
, _pointSymbol(nullptr)
|
||||
, _coordinate( mapView, mapCoordinate )
|
||||
, _sceneOffset(0,0)
|
||||
, _iconPixmap( new QPixmap(icon) )
|
||||
, _boundingRect(nullptr)
|
||||
{
|
||||
zBufferPlane( ZBufferPlane::PointHandle );
|
||||
buildHandle( _coordinate._sceneCoordinate );
|
||||
} /* RubberbandPointHandle::RubberbandPointHandle */
|
||||
|
||||
|
||||
void RubberbandPointHandle::setIcon( const QPixmap & icon )
|
||||
{
|
||||
if (_iconPixmap == nullptr)
|
||||
{
|
||||
_iconPixmap = new QPixmap(icon);
|
||||
if (_pointSymbol)
|
||||
{
|
||||
_scene->removeItem(_pointSymbol);
|
||||
delete _pointSymbol;
|
||||
_pointSymbol = nullptr;
|
||||
}
|
||||
buildHandle( _coordinate._sceneCoordinate );
|
||||
return;
|
||||
}
|
||||
|
||||
*_iconPixmap = icon;
|
||||
|
||||
QGraphicsPixmapItem * iconItem = static_cast<QGraphicsPixmapItem*>( _pointSymbol);
|
||||
if (iconItem)
|
||||
{
|
||||
iconItem->setPixmap( *_iconPixmap );
|
||||
QRectF bbox = iconItem->boundingRect();
|
||||
bbox.moveCenter( _coordinate._sceneCoordinate );
|
||||
if (_boundingRect) _boundingRect->setRect(bbox);
|
||||
}
|
||||
else buildHandle( _coordinate._sceneCoordinate );
|
||||
} /* RubberbandPointHandle::setIcon */
|
||||
|
||||
|
||||
void RubberbandPointHandle::buildHandle( const QPointF & scenePosition )
|
||||
{
|
||||
if (_scene != nullptr)
|
||||
{
|
||||
if (_iconPixmap != nullptr)
|
||||
{
|
||||
if (_iconPixmap->isNull())
|
||||
{
|
||||
delete _iconPixmap;
|
||||
_iconPixmap = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
if (_iconPixmap == nullptr)
|
||||
{
|
||||
QGraphicsEllipseItem * kuller = new QGraphicsEllipseItem();
|
||||
|
||||
_pointSymbol = kuller;
|
||||
|
||||
if (_pointSymbol != nullptr)
|
||||
{
|
||||
_scene -> addItem( _pointSymbol );
|
||||
|
||||
kuller -> setPos( scenePosition+_sceneOffset );
|
||||
kuller -> setRect( -qreal(_pickingRatio), -qreal(_pickingRatio), qreal(2*_pickingRatio), qreal(2*_pickingRatio) );
|
||||
kuller -> setZValue( _zBufferValue );
|
||||
|
||||
kuller -> setCacheMode(QGraphicsItem::CacheMode::NoCache, QSize(_pickingRatio*2,_pickingRatio*2) );
|
||||
kuller -> setFlags( QGraphicsItem::ItemIgnoresTransformations );
|
||||
kuller -> setVisible( _isVisible );
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
QGraphicsPixmapItem * icon = new QGraphicsPixmapItem(*_iconPixmap);
|
||||
|
||||
_pointSymbol = icon;
|
||||
|
||||
if (_pointSymbol != nullptr)
|
||||
{
|
||||
_scene -> addItem( _pointSymbol );
|
||||
|
||||
qreal xOff = -(_iconPixmap->width() * 0.5);
|
||||
qreal yOff = -(_iconPixmap->height() * 0.5);
|
||||
|
||||
icon -> setPos( scenePosition+_sceneOffset );
|
||||
icon -> setZValue( _zBufferValue );
|
||||
icon -> setFlags( QGraphicsItem::ItemIgnoresTransformations );
|
||||
icon -> setVisible( _isVisible );
|
||||
icon -> setOffset( xOff, yOff );
|
||||
icon -> setShapeMode( QGraphicsPixmapItem::BoundingRectShape );
|
||||
|
||||
QRectF bbox = icon->boundingRect();
|
||||
bbox.moveCenter( scenePosition );
|
||||
|
||||
_boundingRect = new QGraphicsRectItem( bbox );
|
||||
_boundingRect -> setZValue(_zBufferValue-1);
|
||||
_boundingRect -> setVisible( _isVisible );
|
||||
|
||||
_scene -> addItem( _boundingRect );
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
} /* RubberbandPointHandle::buildHandle */
|
||||
|
||||
|
||||
RubberbandPointHandle::~RubberbandPointHandle()
|
||||
{
|
||||
delete _iconPixmap;
|
||||
if (_scene)
|
||||
{
|
||||
|
||||
if (nullptr != _boundingRect)
|
||||
{
|
||||
_scene->removeItem(_boundingRect);
|
||||
delete _boundingRect;
|
||||
}
|
||||
|
||||
if (nullptr != _pointSymbol)
|
||||
{
|
||||
_scene->removeItem(_pointSymbol);
|
||||
delete _pointSymbol;
|
||||
}
|
||||
}
|
||||
|
||||
_pointSymbol = nullptr;
|
||||
_iconPixmap = nullptr;
|
||||
_boundingRect = nullptr;
|
||||
|
||||
} /* RubberbandHandle::~Rubberbandhandle */
|
||||
|
||||
|
||||
QPointF RubberbandPointHandle::getRotatedSceneOffset() const
|
||||
{
|
||||
auto rotate = [](const QPointF & p, qreal sinA, qreal cosA) -> QPointF { return QPointF(p.x()*cosA+p.y()*sinA,p.y()*cosA-p.x()*sinA); };
|
||||
|
||||
qreal mapRotatePhi = _mapView->mapRotation() * MathConst::pi / 180.0;
|
||||
|
||||
qreal sinMap = sin(mapRotatePhi);
|
||||
qreal cosMap = cos(mapRotatePhi);
|
||||
|
||||
return rotate( _sceneOffset, sinMap, cosMap );
|
||||
} /* RubberbandPointHandle::getRotatedSceneOffset */
|
||||
|
||||
|
||||
void RubberbandPointHandle::adjustCoordinates()
|
||||
{
|
||||
const QPointF & rotatedSceneOffset = getRotatedSceneOffset();
|
||||
|
||||
if (_iconPixmap == nullptr)
|
||||
{
|
||||
static_cast<QGraphicsEllipseItem*>(_pointSymbol)->setPos(_coordinate.mapToScene(_mapView)+rotatedSceneOffset);
|
||||
}
|
||||
else
|
||||
{
|
||||
QGraphicsPixmapItem * icon = static_cast<QGraphicsPixmapItem*>( _pointSymbol);
|
||||
|
||||
const QPointF & scenePosition = _coordinate.mapToScene(_mapView);
|
||||
icon -> setPos( scenePosition+rotatedSceneOffset );
|
||||
|
||||
QRectF bbox = icon->boundingRect();
|
||||
bbox.moveCenter( scenePosition+rotatedSceneOffset );
|
||||
_boundingRect->setRect(bbox);
|
||||
}
|
||||
|
||||
DEBUG_LOG(_logger) << LOGFUNCTION << " map-coordinate = " << QString::number(_coordinate._mapCoordinate.x(),'f',15)
|
||||
<< " ; " << QString::number(_coordinate._mapCoordinate.y(),'f',15)
|
||||
<< " scene-coordinate = " << _coordinate._sceneCoordinate.x() << " ; " << _coordinate._sceneCoordinate.y();
|
||||
emit adjusted();
|
||||
} /* RubberbandPointHandle::onDo_adjustCoordinates */
|
||||
|
||||
|
||||
void RubberbandPointHandle::adjustWindow( const QRectF& )
|
||||
{
|
||||
onDo_adjustCoordinates();
|
||||
} /* RubberbandPointHandle::onDo_adjustWindow */
|
||||
|
||||
|
||||
void RubberbandPointHandle::updateGraphic()
|
||||
{
|
||||
if (_pointSymbol)
|
||||
{
|
||||
if (_pointSymbol != nullptr)
|
||||
{
|
||||
if (_iconPixmap == nullptr)
|
||||
{
|
||||
QGraphicsEllipseItem * kuller = static_cast<QGraphicsEllipseItem*>( _pointSymbol);
|
||||
|
||||
kuller -> setPen( QPen(_drawColor) );
|
||||
|
||||
QRadialGradient gradient(0, 0, _pickingRatio, 0, 0);
|
||||
QColor gradientColor = (_isSelected) ? _selectionColor : _fillColor;
|
||||
|
||||
gradient.setColorAt( 0, gradientColor);
|
||||
gradient.setColorAt( 1, QColor(gradientColor.red(), gradientColor.green(), gradientColor.blue(), 0) );
|
||||
kuller -> setBrush( QBrush(gradient) );
|
||||
kuller -> setVisible( _isVisible );
|
||||
}
|
||||
else
|
||||
{
|
||||
QGraphicsPixmapItem * icon = static_cast<QGraphicsPixmapItem*>( _pointSymbol);
|
||||
|
||||
_boundingRect -> setPen( QPen(_drawColor) );
|
||||
const QColor &backColor = (_isSelected) ? _selectionColor : _fillColor;
|
||||
_boundingRect -> setBrush( QBrush(backColor) );
|
||||
_boundingRect -> setVisible( _isVisible );
|
||||
icon -> setVisible( _isVisible );
|
||||
}
|
||||
}
|
||||
}
|
||||
} /* RubberbandPointHandle::updateGraphic */
|
||||
|
||||
|
||||
void RubberbandPointHandle::updateCoordinate(const QPointF & scenePosition)
|
||||
{
|
||||
const QPointF & rotatedSceneOffset = getRotatedSceneOffset();
|
||||
|
||||
_coordinate.updateSceneCoordinate( _mapView, scenePosition );
|
||||
|
||||
if (_pointSymbol != nullptr)
|
||||
{
|
||||
if (_iconPixmap == nullptr)
|
||||
{
|
||||
QGraphicsEllipseItem * kuller = static_cast<QGraphicsEllipseItem*>( _pointSymbol);
|
||||
kuller -> setPos( scenePosition+rotatedSceneOffset );
|
||||
}
|
||||
else
|
||||
{
|
||||
QGraphicsPixmapItem * icon = static_cast<QGraphicsPixmapItem*>( _pointSymbol);
|
||||
icon -> setPos( scenePosition+rotatedSceneOffset );
|
||||
|
||||
QRectF bbox = icon->boundingRect();
|
||||
bbox.moveCenter( scenePosition+rotatedSceneOffset );
|
||||
|
||||
_boundingRect->setRect(bbox);
|
||||
}
|
||||
}
|
||||
} /* RubberbandPointHandle::updateCoordinate */
|
||||
|
||||
|
||||
void RubberbandPointHandle::updateCoordinate()
|
||||
{
|
||||
const QPointF & rotatedSceneOffset = getRotatedSceneOffset();
|
||||
|
||||
if (_pointSymbol != nullptr)
|
||||
{
|
||||
if (_iconPixmap == nullptr)
|
||||
{
|
||||
QGraphicsEllipseItem * kuller = static_cast<QGraphicsEllipseItem*>( _pointSymbol);
|
||||
kuller -> setPos( _coordinate._sceneCoordinate+rotatedSceneOffset );
|
||||
}
|
||||
else
|
||||
{
|
||||
QGraphicsPixmapItem * icon = static_cast<QGraphicsPixmapItem*>( _pointSymbol);
|
||||
icon -> setPos( _coordinate._sceneCoordinate+rotatedSceneOffset );
|
||||
|
||||
QRectF bbox = icon->boundingRect();
|
||||
|
||||
bbox.moveCenter( _coordinate._sceneCoordinate+rotatedSceneOffset );
|
||||
_boundingRect->setRect(bbox);
|
||||
}
|
||||
}
|
||||
} /* RubberbandPointHandle::updateCoordinate */
|
||||
|
||||
|
||||
void RubberbandPointHandle::moveCoordinate(const QPointF & sceneDelta)
|
||||
{
|
||||
_coordinate.updateSceneCoordinate( _mapView, _coordinate._sceneCoordinate+sceneDelta );
|
||||
updateCoordinate();
|
||||
} /* RubberbandPointHandle::moveCoordinate */
|
||||
|
||||
|
||||
void RubberbandPointHandle::setCoordinate(const RubberbandHandle::RubberbandCoordinate & p)
|
||||
{
|
||||
_coordinate = p;
|
||||
updateCoordinate();
|
||||
} /* RubberbandPointHandle::setCoordinate */
|
||||
|
||||
|
||||
RubberbandHandle::RubberbandCoordinate RubberbandPointHandle::getCoordinate() const { return _coordinate; }
|
||||
|
||||
QPointF RubberbandPointHandle::getPixelCoordinate() const
|
||||
{
|
||||
return _coordinate._sceneCoordinate;
|
||||
}
|
||||
|
||||
|
||||
bool RubberbandPointHandle::isPositionInside( const QPointF & scenePosition ) const
|
||||
{
|
||||
if (_pointSymbol)
|
||||
{
|
||||
return _pointSymbol->contains( _coordinate._sceneCoordinate+getRotatedSceneOffset() - scenePosition );
|
||||
}
|
||||
return false;
|
||||
} /* RubberbandPointHandle::isPositionInside */
|
||||
|
||||
} } /* namespace SituationMap::RB */
|
||||
@@ -0,0 +1,114 @@
|
||||
/**
|
||||
**
|
||||
** @RDE_HEADER@
|
||||
** Definition 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
|
||||
**
|
||||
** -----------------------------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <QtCore/QPointF>
|
||||
|
||||
#include "rubberband_handle.h"
|
||||
|
||||
class QGraphicsItem;
|
||||
class QGraphicsScene;
|
||||
|
||||
namespace SituationMap { namespace RB
|
||||
{
|
||||
|
||||
/**
|
||||
@class RubberbandPointHandle rubberband_point_handle.h
|
||||
@brief Implementation of a point handle for rubberband internal use.
|
||||
@see RubberbandHandle
|
||||
*/
|
||||
class RubberbandPointHandle : public RubberbandHandle
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
|
||||
/**
|
||||
@name Construction & Destruction
|
||||
@{
|
||||
*/
|
||||
RubberbandPointHandle( Esri::ArcGISRuntime::MapGraphicsView*
|
||||
, QGraphicsScene*
|
||||
, const QPointF & scenePosition );
|
||||
|
||||
RubberbandPointHandle( Esri::ArcGISRuntime::MapGraphicsView*
|
||||
, QGraphicsScene*
|
||||
, const Esri::ArcGISRuntime::Point & mapCoordinate );
|
||||
|
||||
RubberbandPointHandle( Esri::ArcGISRuntime::MapGraphicsView*
|
||||
, QGraphicsScene*
|
||||
, const QPointF & scenePosition
|
||||
, const QPixmap & icon );
|
||||
|
||||
RubberbandPointHandle( Esri::ArcGISRuntime::MapGraphicsView*
|
||||
, QGraphicsScene*
|
||||
, const Esri::ArcGISRuntime::Point & mapCoordinate
|
||||
, const QPixmap & icon );
|
||||
|
||||
~RubberbandPointHandle();
|
||||
/** @} */
|
||||
|
||||
void setIcon( const QPixmap & icon );
|
||||
|
||||
bool isPositionInside( const QPointF & scenePosition ) const override;
|
||||
virtual void updateCoordinate( const QPointF & scenePosition );
|
||||
virtual void moveCoordinate( const QPointF & sceneDelta );
|
||||
|
||||
virtual void setCoordinate( const RubberbandCoordinate & );
|
||||
virtual RubberbandCoordinate getCoordinate() const;
|
||||
|
||||
QPointF getPixelCoordinate() const;
|
||||
|
||||
inline void setSceneOffset(const QPointF & offset) { _sceneOffset = offset; }
|
||||
|
||||
protected:
|
||||
|
||||
QGraphicsItem * _pointSymbol;
|
||||
RubberbandCoordinate _coordinate;
|
||||
QPointF _sceneOffset;
|
||||
QPixmap * _iconPixmap;
|
||||
QGraphicsRectItem * _boundingRect;
|
||||
|
||||
void updateGraphic() override;
|
||||
|
||||
virtual void updateCoordinate();
|
||||
|
||||
void adjustCoordinates() override;
|
||||
void adjustWindow( const QRectF & ) override;
|
||||
|
||||
private:
|
||||
|
||||
QPointF getRotatedSceneOffset() const;
|
||||
|
||||
void buildHandle( const QPointF & scenePosition );
|
||||
|
||||
|
||||
|
||||
}; /* RubberbandPointHandle */
|
||||
|
||||
} } /* namespace SituationMap::RB */
|
||||
@@ -0,0 +1,318 @@
|
||||
/**
|
||||
**
|
||||
** @RDE_HEADER@
|
||||
** Definition of rubberband class to define multi point feature geometry with an additional width coordinate
|
||||
** $Id$
|
||||
** $HeadURL$
|
||||
** $Author$
|
||||
**
|
||||
** -----------------------------------------------------------------------------------------------
|
||||
**
|
||||
** Hardware-Environment: Intel-PC
|
||||
** Software-Environment: Linux, Windows 7, Qt 5.7. ArcGISRuntimeQt 100
|
||||
**
|
||||
** Language ........: C++ 11
|
||||
**
|
||||
** -----------------------------------------------------------------------------------------------
|
||||
**
|
||||
** Author ...........: Jörg Turla, SPD G, Tel. 3132
|
||||
**
|
||||
** -----------------------------------------------------------------------------------------------
|
||||
**
|
||||
** Notes .........:
|
||||
**
|
||||
** 7.12.2016, JT : First edition for use with Qt5
|
||||
**
|
||||
** -----------------------------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
#include "rubberband_polyline_width.h"
|
||||
#include "rubberband_point_handle.h"
|
||||
|
||||
#include "rubberband_internal.h"
|
||||
#include "rubberband_base_internal.h"
|
||||
|
||||
#include <cmath>
|
||||
|
||||
#include <arcgis/Map.h>
|
||||
|
||||
|
||||
|
||||
namespace SituationMap { namespace RB
|
||||
{
|
||||
|
||||
struct RubberbandPolylineWidth::InternalData
|
||||
{
|
||||
SituationMap::RefPointer<RubberbandPointHandle> _widthItem;
|
||||
}; /* RubberbandPolylineWidth::InternalData*/
|
||||
|
||||
|
||||
RubberbandPolylineWidth::RubberbandPolylineWidth( SituationMap::Map * map, QObject * parent )
|
||||
: RubberbandMultiPointFeature(map,true,parent), _internal( new InternalData() )
|
||||
{
|
||||
} /* RubberbandPolylineWidth::RubberbandPolylineWidth */
|
||||
|
||||
|
||||
RubberbandPolylineWidth::~RubberbandPolylineWidth()
|
||||
{
|
||||
delete _internal;
|
||||
} /* RubberbandPolylineWidth::~RubberbandPolylineWidth */
|
||||
|
||||
|
||||
void RubberbandPolylineWidth::buildWidthItem(const QPointF & mapPos1, const QPointF & mapPos2) const
|
||||
{
|
||||
double dx = mapPos2.x() - mapPos1.x();
|
||||
double dy = mapPos2.y() - mapPos1.y();
|
||||
QPointF handleMapPos = mapPos1 + QPointF(dx,dy)*0.35 + QPointF(dy,dx)*0.35;
|
||||
|
||||
setUpWidthItem(handleMapPos);
|
||||
} /* RubberbandPolylineWidth::buildWidthItem */
|
||||
|
||||
|
||||
void RubberbandPolylineWidth::setUpWidthItem(const QPointF & mapPos) const
|
||||
{
|
||||
RubberbandHandle::RubberbandCoordinate coordinate( Rubberband::_internal->_mapView, convert(mapPos,Rubberband::_internal->_mapView->map()->spatialReference()) );
|
||||
|
||||
_internal->_widthItem = new RubberbandPointHandle(Rubberband::_internal->_mapView, Rubberband::_internal->_mapScene, coordinate._sceneCoordinate);
|
||||
} /* RubberbandPolylineWidth::setUpWidthItem */
|
||||
|
||||
|
||||
QVector<QPointF> RubberbandPolylineWidth::coordinateVector( CoordinateSystem cs ) const
|
||||
{
|
||||
QVector<QPointF> polylineCoords = RubberbandMultiPointFeature::coordinateVector(cs);
|
||||
if (polylineCoords.size() > 1)
|
||||
{
|
||||
if (_internal->_widthItem == nullptr)
|
||||
{
|
||||
RubberbandPointHandle * pointHandle1Ptr = static_cast<RubberbandPointHandle*>(Rubberband::_internal->_handleList[0].get());
|
||||
RubberbandPointHandle * pointHandle2Ptr = static_cast<RubberbandPointHandle*>(Rubberband::_internal->_handleList[1].get());
|
||||
Esri::ArcGISRuntime::Point p1 = pointHandle1Ptr->getCoordinate()._mapCoordinate;
|
||||
Esri::ArcGISRuntime::Point p2 = pointHandle2Ptr->getCoordinate()._mapCoordinate;
|
||||
|
||||
buildWidthItem( QPointF(p1.x(),p1.y()), QPointF(p2.x(),p2.y()) );
|
||||
|
||||
}
|
||||
polylineCoords += projectCoordinateFromMap(cs, _internal->_widthItem->getCoordinate()._mapCoordinate);
|
||||
}
|
||||
return polylineCoords;
|
||||
} /* RubberbandPolylineWidth::coordinateVector */
|
||||
|
||||
|
||||
QPointF RubberbandPolylineWidth::singleCoordinate( unsigned int idx, CoordinateSystem cs ) const
|
||||
{
|
||||
if (static_cast<unsigned int>(Rubberband::_internal->_handleList.size()) == idx)
|
||||
{
|
||||
return projectCoordinateFromMap(cs, _internal->_widthItem->getCoordinate()._mapCoordinate);
|
||||
}
|
||||
return RubberbandMultiPointFeature::singleCoordinate(idx, cs);
|
||||
} /* RubberbandPolylineWidth::singleCoordinate */
|
||||
|
||||
|
||||
void RubberbandPolylineWidth::setCoordinateVector( const QVector<QPointF> & coordinateVector, CoordinateSystem cs )
|
||||
{
|
||||
if (coordinateVector.size() > 2)
|
||||
{
|
||||
QVector<QPointF> lineCoords = coordinateVector;
|
||||
setUpWidthItem( projectCoordinateToMap(cs, lineCoords.last()) );
|
||||
lineCoords.removeLast();
|
||||
RubberbandMultiPointFeature::setCoordinateVector(lineCoords, cs);
|
||||
|
||||
return;
|
||||
}
|
||||
if (coordinateVector.size() == 2)
|
||||
{
|
||||
const QPointF & mapP1 = projectCoordinateToMap(cs, coordinateVector[0]);
|
||||
const QPointF & mapP2 = projectCoordinateToMap(cs, coordinateVector[1]);
|
||||
|
||||
buildWidthItem(mapP1, mapP2);
|
||||
}
|
||||
RubberbandMultiPointFeature::setCoordinateVector(coordinateVector,cs);
|
||||
} /* RubberbandPolylineWidth::setCoordinateVector */
|
||||
|
||||
|
||||
bool RubberbandPolylineWidth::selectAction( AbstractEventDispatcher * causer, int x, int y )
|
||||
{
|
||||
if (rubberbandIsAlive() && (nullptr != _internal->_widthItem.get()))
|
||||
{
|
||||
_internal->_widthItem->setSelection(false);
|
||||
QPointF scenePos(pixel2ScenePosition(x, y));
|
||||
if (_baseInternal->buttonProxyActive(scenePos)) return false;
|
||||
if (_internal->_widthItem->isPositionInside(scenePos))
|
||||
{
|
||||
_internal->_widthItem->setSelection();
|
||||
_baseInternal->_lastClickPosition = scenePos;
|
||||
update();
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return RubberbandMultiPointFeature::selectAction(causer,x,y);
|
||||
} /* RubberbandPolylineWidth::selectAction */
|
||||
|
||||
|
||||
bool RubberbandPolylineWidth::setCoordinateAction( AbstractEventDispatcher * causer, int x, int y )
|
||||
{
|
||||
if (rubberbandIsAlive() && (nullptr != _internal->_widthItem.get()))
|
||||
{
|
||||
if (_internal->_widthItem->isSelected())
|
||||
{
|
||||
QPointF scenePos(pixel2ScenePosition(x, y));
|
||||
QPointF deltaMove = scenePos - _baseInternal->_lastClickPosition;
|
||||
|
||||
_internal->_widthItem->setSelection(false);
|
||||
_internal->_widthItem->moveCoordinate(deltaMove);
|
||||
update();
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return RubberbandMultiPointFeature::setCoordinateAction(causer, x, y);
|
||||
} /* RubberbandPolylineWidth::setCoordinateAction */
|
||||
|
||||
|
||||
bool RubberbandPolylineWidth::movePickedAction( AbstractEventDispatcher * causer, int x, int y )
|
||||
{
|
||||
if (rubberbandIsAlive() && (nullptr != _internal->_widthItem.get()))
|
||||
{
|
||||
if (_internal->_widthItem->isSelected())
|
||||
{
|
||||
adjustConnectedPreviewPixmap(x, y);
|
||||
|
||||
QPointF scenePos(pixel2ScenePosition(x, y));
|
||||
QPointF deltaMove = scenePos - _baseInternal->_lastClickPosition;
|
||||
_baseInternal->_lastClickPosition = scenePos;
|
||||
|
||||
_internal->_widthItem->moveCoordinate(deltaMove);
|
||||
update();
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
RubberbandPointHandle * handlePoint1Ptr = dynamic_cast<RubberbandPointHandle*>(Rubberband::_internal->_handleList[0].get());
|
||||
RubberbandPointHandle * handlePoint2Ptr = dynamic_cast<RubberbandPointHandle*>(Rubberband::_internal->_handleList[1].get());
|
||||
|
||||
if (handlePoint1Ptr && handlePoint2Ptr)
|
||||
{
|
||||
const RubberbandDrawable::RubberbandCoordinate & loc1Start = handlePoint1Ptr->getCoordinate();
|
||||
const RubberbandDrawable::RubberbandCoordinate & loc2Start = handlePoint2Ptr->getCoordinate();
|
||||
|
||||
bool ret = RubberbandMultiPointFeature::movePickedAction(causer, x, y);
|
||||
|
||||
const RubberbandDrawable::RubberbandCoordinate & loc1End = handlePoint1Ptr->getCoordinate();
|
||||
const RubberbandDrawable::RubberbandCoordinate & loc2End = handlePoint2Ptr->getCoordinate();
|
||||
|
||||
QPointF deltaMove1 = loc1End._sceneCoordinate - loc1Start._sceneCoordinate;
|
||||
QPointF deltaMove2 = loc2End._sceneCoordinate - loc2Start._sceneCoordinate;
|
||||
|
||||
|
||||
if ((fabs(deltaMove1.x()) >= 1) || (fabs(deltaMove1.y()) >= 1) || (fabs(deltaMove2.x()) >= 1) || (fabs(deltaMove2.y()) >= 1))
|
||||
{
|
||||
/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
*
|
||||
* First or second point have been moved. Now recalculate the coordinate of the width handle point as follows:
|
||||
* The width handle "C" and the first two coordinates ("A","B") are providing a triangle:
|
||||
* B
|
||||
* / \
|
||||
* / \
|
||||
* /sinB \
|
||||
* / cosB \
|
||||
* / \
|
||||
* / \
|
||||
* c / \ a
|
||||
* / \
|
||||
* / \
|
||||
* / \
|
||||
* / \
|
||||
* / sinA sinC \
|
||||
* / cosA cosC \
|
||||
* A ------------------------- C
|
||||
* b
|
||||
* If the coordinates of "A" or "B" are changed, try to keep the ratio of angles and sides of the triangle constant. For this
|
||||
* use some trigonometric identities.
|
||||
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
|
||||
|
||||
auto rotate = []( const QPointF & p, qreal sinPhi, qreal cosPhi ) -> QPointF
|
||||
{
|
||||
return QPointF( p.x()*cosPhi - p.y()*sinPhi, p.y()*cosPhi + p.x()*sinPhi );
|
||||
};
|
||||
|
||||
QPointF A = loc2Start._sceneCoordinate;
|
||||
QPointF B = loc1Start._sceneCoordinate;
|
||||
QPointF C = _internal->_widthItem->getCoordinate()._sceneCoordinate;
|
||||
|
||||
qreal a = QLineF(B,C).length(); // side length of triangle
|
||||
qreal b = QLineF(A,C).length();
|
||||
qreal c = QLineF(A,B).length();
|
||||
qreal cosA = (b*b+c*c-a*a)/(b*c*2); // cosin rule
|
||||
qreal cosB = (a*a+c*c-b*b)/(a*c*2);
|
||||
qreal cosC = (a*a+b*b-c*c)/(a*b*2);
|
||||
qreal sinA = sqrt(1-cosA*cosA); // pythagorean trigonometric identity
|
||||
qreal sinB = sqrt(1-cosB*cosB);
|
||||
qreal sinC = sqrt(1-cosC*cosC);
|
||||
|
||||
// now we have all angle of the triangle, set A and B to the new coordinates ...
|
||||
|
||||
A = loc2End._sceneCoordinate;
|
||||
B = loc1End._sceneCoordinate;
|
||||
|
||||
// ... and calculate the coordinate of C with the same ratio of angles as before ...
|
||||
|
||||
QPointF AB = B-A;
|
||||
|
||||
// c = QLineF(QPointF(0,0),AB).length();
|
||||
|
||||
if (sinC != 0.0)
|
||||
{
|
||||
// ... rotate AB and scale it to the right length
|
||||
C = A + rotate(AB,sinA,cosA) * sinB / sinC;
|
||||
|
||||
// the RubberbandPointHandle dosn't has a set to set scene coordinate. Using the moveCoordinate methode instead.
|
||||
|
||||
_internal->_widthItem->moveCoordinate( C - _internal->_widthItem->getCoordinate()._sceneCoordinate );
|
||||
}
|
||||
// else could only happen when the triangle is degenrated to a line
|
||||
update();
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
}
|
||||
return RubberbandMultiPointFeature::movePickedAction(causer, x, y);
|
||||
} /* RubberbandPolylineWidth::movePickedAction */
|
||||
|
||||
|
||||
bool RubberbandPolylineWidth::moveAction( AbstractEventDispatcher * causer, int x, int y )
|
||||
{
|
||||
if (rubberbandIsAlive() && (nullptr != _internal->_widthItem.get()))
|
||||
{
|
||||
QPointF scenePos(pixel2ScenePosition(x, y));
|
||||
_internal->_widthItem->setSelection( _internal->_widthItem->isPositionInside(scenePos) );
|
||||
}
|
||||
return RubberbandMultiPointFeature::moveAction( causer, x, y);
|
||||
|
||||
} /* RubberbandPolylineWidth::moveAction */
|
||||
|
||||
|
||||
void RubberbandPolylineWidth::update()
|
||||
{
|
||||
if ((_internal->_widthItem.get() == nullptr) && (Rubberband::_internal->_handleList.size() > 1))
|
||||
{
|
||||
RubberbandPointHandle * pointHandle1Ptr = static_cast<RubberbandPointHandle*>(Rubberband::_internal->_handleList[0].get());
|
||||
RubberbandPointHandle * pointHandle2Ptr = static_cast<RubberbandPointHandle*>(Rubberband::_internal->_handleList[1].get());
|
||||
Esri::ArcGISRuntime::Point p1 = pointHandle1Ptr->getCoordinate()._mapCoordinate;
|
||||
Esri::ArcGISRuntime::Point p2 = pointHandle2Ptr->getCoordinate()._mapCoordinate;
|
||||
|
||||
buildWidthItem(QPointF(p1.x(), p1.y()), QPointF(p2.x(), p2.y()));
|
||||
}
|
||||
|
||||
if (_internal->_widthItem)
|
||||
{
|
||||
Rubberband::_internal->_handleList += static_cast<SituationMap::RefPointer<RubberbandHandle>>(_internal->_widthItem);
|
||||
RubberbandMultiPointFeature::update();
|
||||
Rubberband::_internal->_handleList.removeLast();
|
||||
}
|
||||
else RubberbandMultiPointFeature::update();
|
||||
|
||||
} /* RubberbandPolylineWidth::update */
|
||||
|
||||
|
||||
|
||||
} } /* namespace SituationMap::RB */
|
||||
@@ -0,0 +1,88 @@
|
||||
/**
|
||||
**
|
||||
** @RDE_HEADER@
|
||||
** Definition of rubberband class to define multi point feature geometry with an additional width coordinate
|
||||
** $Id$
|
||||
** $HeadURL$
|
||||
** $Author$
|
||||
**
|
||||
** -----------------------------------------------------------------------------------------------
|
||||
**
|
||||
** Hardware-Environment: Intel-PC
|
||||
** Software-Environment: Linux, Windows 7, Qt 5.7. ArcGISRuntimeQt 100
|
||||
**
|
||||
** Language ........: C++ 11
|
||||
**
|
||||
** -----------------------------------------------------------------------------------------------
|
||||
**
|
||||
** Author ...........: Jörg Turla, SPD G, Tel. 3132
|
||||
**
|
||||
** -----------------------------------------------------------------------------------------------
|
||||
**
|
||||
** Notes .........:
|
||||
**
|
||||
** 7.12.2016, JT : First edition for use with Qt5
|
||||
**
|
||||
** -----------------------------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "rubberband_multi_point_feature.h"
|
||||
|
||||
|
||||
namespace SituationMap { namespace RB
|
||||
{
|
||||
|
||||
class RubberbandLineHandle;
|
||||
class RubberbandFrameHandle;
|
||||
|
||||
/**
|
||||
@class RubberbandPolylineWidth rubberband_smooth_line.h
|
||||
@brief Implementation of a multi point feature rubberband with rounded edges.
|
||||
@see RubberbandFactory, Rubberband, RubberbandMultiPointFeature
|
||||
|
||||
*/
|
||||
class SITUATIONMAP_EXPORT RubberbandPolylineWidth : public RubberbandMultiPointFeature
|
||||
{
|
||||
Q_OBJECT
|
||||
/**
|
||||
@name Construction & Destruction
|
||||
@{
|
||||
*/
|
||||
|
||||
friend class RubberbandFactory;
|
||||
|
||||
explicit RubberbandPolylineWidth( SituationMap::Map * map, QObject * parent = nullptr );
|
||||
|
||||
public:
|
||||
|
||||
virtual ~RubberbandPolylineWidth();
|
||||
/** @} */
|
||||
|
||||
virtual QVector<QPointF> coordinateVector( CoordinateSystem cs = CoordinateSystem::Geo ) const override;
|
||||
virtual QPointF singleCoordinate( unsigned int idx = 0, CoordinateSystem cs = CoordinateSystem::Geo ) const override;
|
||||
|
||||
virtual void setCoordinateVector( const QVector<QPointF> &, CoordinateSystem cs = CoordinateSystem::Geo ) override;
|
||||
|
||||
bool selectAction ( AbstractEventDispatcher * causer, int x, int y ) override;
|
||||
bool setCoordinateAction( AbstractEventDispatcher * causer, int x, int y ) override;
|
||||
bool movePickedAction ( AbstractEventDispatcher * causer, int x, int y ) override;
|
||||
bool moveAction ( AbstractEventDispatcher * causer, int x, int y ) override;
|
||||
|
||||
protected:
|
||||
/*
|
||||
Forward declaration of InternalData to hold private member variables. Becareful the base class Rubberband
|
||||
has similary a class for internal data member with name "InternalData". Don't be confused it is not the same.
|
||||
*/
|
||||
struct InternalData;
|
||||
|
||||
InternalData * _internal;
|
||||
|
||||
void update() override;
|
||||
|
||||
void buildWidthItem(const QPointF & mapPos1, const QPointF & mapPos2) const;
|
||||
void setUpWidthItem(const QPointF & mapPos) const;
|
||||
}; /* RubberbandSmoothLine */
|
||||
|
||||
} } /* namespace SituationMap::RB */
|
||||
+1913
File diff suppressed because it is too large.
Load diff
+274
@@ -0,0 +1,274 @@
|
||||
/**
|
||||
**
|
||||
** @RDE_HEADER@
|
||||
** Definition of rubberband class to define point feature geoemtry
|
||||
** $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 .........:
|
||||
**
|
||||
** 17.06.2015, JT : First edition for use with Qt5
|
||||
**
|
||||
** -----------------------------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "rubberband.h"
|
||||
|
||||
#include <MathUtils/matrix2d.h>
|
||||
|
||||
|
||||
namespace SituationMap { namespace RB
|
||||
{
|
||||
|
||||
class RubberbandPointHandle;
|
||||
|
||||
/**
|
||||
@class RubberbandRectangle rubberband_rectangle.h
|
||||
@brief Implementation of a rectangle rubberband
|
||||
@see Rubberband
|
||||
*/
|
||||
class SITUATIONMAP_EXPORT RubberbandRectangle : public Rubberband
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
/**
|
||||
@name Construction & Destruction
|
||||
@}
|
||||
*/
|
||||
|
||||
friend class RubberbandFactory;
|
||||
friend class RubberbandEllipse;
|
||||
friend class RubberbandTransform;
|
||||
|
||||
explicit RubberbandRectangle( SituationMap::Map * map, QObject * parent = nullptr );
|
||||
|
||||
public:
|
||||
|
||||
~RubberbandRectangle();
|
||||
/** @} */
|
||||
|
||||
bool selectAction ( AbstractEventDispatcher * causer, int x, int y ) override;
|
||||
bool multiSelectActionPress ( AbstractEventDispatcher * causer, int x, int y ) override;
|
||||
bool multiSelectActionRelease( AbstractEventDispatcher * causer, int x, int y ) override;
|
||||
bool setCoordinateAction ( AbstractEventDispatcher * causer, int x, int y ) override;
|
||||
bool moveAction ( AbstractEventDispatcher * causer, int x, int y ) override;
|
||||
bool movePickedAction ( AbstractEventDispatcher * causer, int x, int y ) override;
|
||||
bool contextMenuAction ( AbstractEventDispatcher * causer, int x, int y ) override;
|
||||
bool completeStateAction ( AbstractEventDispatcher * causer, int x, int y ) override;
|
||||
bool deleteAction ( AbstractEventDispatcher * causer, int x, int y ) override;
|
||||
bool undoAction ( AbstractEventDispatcher * causer, int x, int y ) override;
|
||||
|
||||
|
||||
/**
|
||||
@see rectangleVerticies
|
||||
*/
|
||||
bool coordinatesAreValid() const override { return rectangleIsValid(); }
|
||||
/**
|
||||
* @brief Get 4 verticies of rectangle
|
||||
*/
|
||||
QVector<QPointF> coordinateVector( CoordinateSystem cs = CoordinateSystem::Geo ) const override;
|
||||
|
||||
/**
|
||||
* @brief Get center point of rectangle, see methode centerPoint
|
||||
*/
|
||||
QPointF singleCoordinate( unsigned int idx = 0, CoordinateSystem cs = CoordinateSystem::Geo ) const override;
|
||||
|
||||
/**
|
||||
* @brief Set 4 verticies of rectangle
|
||||
*/
|
||||
void setCoordinateVector( const QVector<QPointF> &, CoordinateSystem cs = CoordinateSystem::Geo ) override;
|
||||
|
||||
|
||||
/**
|
||||
* @brief Returns center point of rectangle
|
||||
*/
|
||||
QPointF centerPoint( CoordinateSystem cs = CoordinateSystem::Geo ) const;
|
||||
|
||||
/**
|
||||
* @brief Sets center point of rectangle
|
||||
*/
|
||||
void centerPoint(const QPointF ¢erPoint, CoordinateSystem cs = CoordinateSystem::Geo );
|
||||
|
||||
/**
|
||||
* @brief Get 4 verticies of rectangle
|
||||
*/
|
||||
QVector<QPointF> rectangleVerticies( CoordinateSystem cs = CoordinateSystem::Geo ) const;
|
||||
|
||||
/**
|
||||
* @brief Set 4 verticies of rectangle
|
||||
*/
|
||||
void rectangleVerticies( const QVector<QPointF> &, CoordinateSystem cs = CoordinateSystem::Geo );
|
||||
|
||||
/**
|
||||
* @brief Returns true if a valid rectangle has been set with method \c rectangleVerticies
|
||||
* The rectangle rubberband is expecting input coordinates defining a rectangle in map coordinate system. Otherwise
|
||||
* a similar as possible rectangle is used for rubberbanding and the coordinates returned by \c coordinateVector()
|
||||
* will be different from input coordinates.
|
||||
*/
|
||||
bool rectangleIsValid() const;
|
||||
|
||||
/**
|
||||
* @brief Pass back the rectangle parameter
|
||||
* For convenience some times it would be an asset to get the parameter like center, width, height and rotation. This
|
||||
* function pass back these parameter. A coordinate transformation or projection will \b not be done. All values are related to
|
||||
* the coordinate system of the map.
|
||||
* <b>Warning, if the map coordinate system doesn't use the same geographical projection as the simulation coordinate system
|
||||
* the returned parameter may be all wrong.</b>
|
||||
*
|
||||
* @param center Center point of the rectangle in map coordinates.
|
||||
* @param width Width of the rectangle.
|
||||
* @param height Height of the rectangle.
|
||||
* @param direction Normalized direction vector related to width axis.
|
||||
*/
|
||||
void rectangleParameter( QPointF & center, qreal & width, qreal & height, QPointF & direction, CoordinateSystem cs = CoordinateSystem::Geo );
|
||||
|
||||
/**
|
||||
* @brief Build rectangle from rectangle parameter
|
||||
* For convenience some times it would be an asset to initialize a rectangle rubberband from rectangle the parameter like width, height and rotation.
|
||||
* A coordinate transformation or projection will \b not be done. All values are related to the coordinate system of the map.
|
||||
* <b>Warning, if the map coordinate system doesn't use the same geographical projection as the simulation coordinate system all parameter may be wrong.</b>
|
||||
*
|
||||
* @param center Center of the rectangle in \b cs coordinate.
|
||||
* @param width Width of the rectangle.
|
||||
* @param height Height of the rectangle.
|
||||
* @param direction Normalized direction vector related to width axis.
|
||||
* @param cs Coordinate System.
|
||||
*/
|
||||
void buildFromRectangleParamter( const QPointF & center, qreal width, qreal height, const QPointF & direction, CoordinateSystem cs = CoordinateSystem::Geo );
|
||||
|
||||
/**
|
||||
* @brief Build rectangle relative to the bottom left corner
|
||||
* For convenience some times it would be an asset to initialize a rectangle rubberband from rectangle the parameter like width, height and rotation.
|
||||
* A coordinate transformation or projection will \b not be done. All values are related to the coordinate system of the map.
|
||||
* <b>Warning, if the map coordinate system doesn't use the same geographical projection as the simulation coordinate system all parameter may be wrong.</b>
|
||||
*
|
||||
* @param bottomLeft Bottom left corner of the rectangle in \b cs coordinates.
|
||||
* @param width Width of the rectangle.
|
||||
* @param height Height of the rectangle.
|
||||
* @param direction Normalized direction vector related to width axis.
|
||||
* @param cs Coordinate System.
|
||||
*/
|
||||
void buildRectangleRelativeToBottomLeftCorner( const QPointF & bottomLeft, qreal width, qreal height, const QPointF & direction, CoordinateSystem cs = CoordinateSystem::Geo );
|
||||
|
||||
|
||||
/**
|
||||
* @brief If set to true only quadratic rectangles can be created.
|
||||
*/
|
||||
void constrainQuadratic( bool on );
|
||||
|
||||
/**
|
||||
* @brief Returns the setting for quadratic constrain.
|
||||
*/
|
||||
bool constrainQuadratic() const;
|
||||
|
||||
/**
|
||||
* @brief If set to true the rectangle can not be rotated.
|
||||
*/
|
||||
void constrainOrthogonal( bool on );
|
||||
|
||||
/**
|
||||
* @brief Returns the setting fpr orthogonsl constrain.
|
||||
*/
|
||||
bool constrainOrthogonal() const;
|
||||
|
||||
|
||||
/**
|
||||
@name Setting Constrains for Width and Height
|
||||
To define a constrain value a postive values has to be assigned. Negative values will reset the constrain setting to undefined state.
|
||||
@{
|
||||
*/
|
||||
void minWidth ( qreal x );
|
||||
void maxWidth ( qreal x );
|
||||
void minHeight( qreal x );
|
||||
void maxHeight( qreal x );
|
||||
/** @} */
|
||||
|
||||
|
||||
protected:
|
||||
|
||||
/*
|
||||
Forward declaration of InternalData to hold private member variables. Becareful the base class Rubberband
|
||||
has similary a class for internal data member with name "InternalData". Don't be confused it is not the same.
|
||||
*/
|
||||
struct InternalData;
|
||||
|
||||
InternalData * _internal;
|
||||
bool _rectangleIsValid;
|
||||
|
||||
/*
|
||||
Coordinate matrix to describe the change of coordinates of the last user input
|
||||
*/
|
||||
MathUtils::Matrix2D _lastCoordinateChange;
|
||||
|
||||
|
||||
/*
|
||||
ModificationMode is used internally to restrict input for special purposes. It will be defined
|
||||
by derived class
|
||||
*/
|
||||
enum class ModificationMode
|
||||
{
|
||||
NoneRestriction,
|
||||
NoneRotation,
|
||||
TranslationOnly,
|
||||
ScalingOnly,
|
||||
RotationOnly
|
||||
};
|
||||
|
||||
void setModificationMode( ModificationMode );
|
||||
|
||||
|
||||
void activateButtons() override;
|
||||
void constructHandles();
|
||||
void updateHandles( const QPointF & scenePos, QPointF deltaMove );
|
||||
|
||||
bool adjustLine( QPointF & deltaMove, bool & constrainsComplied );
|
||||
void adjustNeighbouringPoints( RubberbandPointHandle * handlePointPtr, unsigned int handleIdx, QPointF deltaMove );
|
||||
|
||||
bool checkMinMaxConstrains(const QPointF & vertexScene, QPointF & deltaMovePtr );
|
||||
bool checkMinMaxConstrains(const QPointF & vertexScene, bool isVertical );
|
||||
|
||||
bool constrainsSatisfied( RubberbandPointHandle * handlePointPtr, unsigned int handleIdx, QPointF & deltaMove, bool & constrainsComplied );
|
||||
|
||||
void useDottedLineHandles( bool on = true );
|
||||
|
||||
void update() override;
|
||||
|
||||
QPointF getSceneCenter() const;
|
||||
qreal getSceneWidth() const;
|
||||
qreal getSceneHeight() const;
|
||||
|
||||
QPointF getCenter() const;
|
||||
qreal getWidth() const;
|
||||
qreal getHeight() const;
|
||||
|
||||
void getSceneRotation( qreal & sinA, qreal & cosA ) const;
|
||||
void getMapRotation ( qreal & sinA, qreal & cosA ) const;
|
||||
|
||||
void buildTmpConstructionPath(const QPointF & start, const QPointF & end, QVector<QPointF> & path, QPointF & sceneCenter, qreal & sceneWidth, qreal & sceneHeight );
|
||||
|
||||
virtual void buildTmpConstruction( SituationMap::RefPointer<RubberbandDrawable> & tmpGraphic, QPointF & start, QPointF & end );
|
||||
virtual void getTmpConstructionParameter( const QPointF & start, const QPointF & end, QPointF & sceneCenter, qreal & sceneWidth, qreal & sceneHeight );
|
||||
|
||||
private:
|
||||
|
||||
void setButtonPosition();
|
||||
|
||||
}; /* RubberbandRectangle */
|
||||
|
||||
} } /* namespace SituationMap::RB */
|
||||
@@ -0,0 +1,93 @@
|
||||
/**
|
||||
**
|
||||
** @RDE_HEADER@
|
||||
** Definition of rubberband class to define multi point feature geometry
|
||||
** $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 .........:
|
||||
**
|
||||
** 17.06.2015, JT : First edition for use with Qt5
|
||||
**
|
||||
** -----------------------------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
#include "rubberband_smooth_line.h"
|
||||
#include "rubberband_point_handle.h"
|
||||
|
||||
#include "drawable_smooth_path.h"
|
||||
|
||||
#include "rubberband_internal.h"
|
||||
|
||||
|
||||
namespace SituationMap { namespace RB
|
||||
{
|
||||
|
||||
struct RubberbandSmoothLine::InternalData
|
||||
{
|
||||
SituationMap::RefPointer<DrawableSmoothPath> _smoothLineItem;
|
||||
}; /* RubberbandSmoothLine::InternalData*/
|
||||
|
||||
|
||||
RubberbandSmoothLine::RubberbandSmoothLine( SituationMap::Map * map, QObject * parent )
|
||||
: RubberbandMultiPointFeature(map,true,parent), _internal( new InternalData() )
|
||||
{
|
||||
} /* RubberbandSmoothLine::RubberbandSmoothLine */
|
||||
|
||||
RubberbandSmoothLine::~RubberbandSmoothLine()
|
||||
{
|
||||
delete _internal;
|
||||
} /* RubberbandSmoothLine::~RubberbandSmoothLine */
|
||||
|
||||
|
||||
void RubberbandSmoothLine::update()
|
||||
{
|
||||
QVector<RubberbandDrawable::RubberbandCoordinate> vertexVector;
|
||||
|
||||
vertexVector.reserve( Rubberband::_internal->_handleList.size() );
|
||||
|
||||
for (auto handle : qAsConst(Rubberband::_internal->_handleList))
|
||||
{
|
||||
RubberbandPointHandle * pointHandlePtr = dynamic_cast<RubberbandPointHandle*>(handle.get());
|
||||
|
||||
if (pointHandlePtr)
|
||||
{
|
||||
vertexVector.append( pointHandlePtr -> getCoordinate() );
|
||||
}
|
||||
}
|
||||
if (vertexVector.size() > 2)
|
||||
{
|
||||
if (!_internal->_smoothLineItem)
|
||||
{
|
||||
_internal->_smoothLineItem = new DrawableSmoothPath( Rubberband::_internal->_mapView );
|
||||
}
|
||||
|
||||
_internal->_smoothLineItem -> enableClosedLine( isClosedEnabled() );
|
||||
_internal->_smoothLineItem -> setDrawColor( _drawColor );
|
||||
_internal->_smoothLineItem -> setFillColor( _fillColor );
|
||||
_internal->_smoothLineItem -> setVisibility( true );
|
||||
_internal->_smoothLineItem -> setPath( vertexVector );
|
||||
}
|
||||
else if (_internal->_smoothLineItem) _internal->_smoothLineItem->setVisibility( false );
|
||||
|
||||
RubberbandMultiPointFeature::update();
|
||||
|
||||
} /* RubberbandSmoothLine::update */
|
||||
|
||||
|
||||
|
||||
} } /* namespace SituationMap::RB */
|
||||
@@ -0,0 +1,72 @@
|
||||
/**
|
||||
**
|
||||
** @RDE_HEADER@
|
||||
** Definition of rubberband class to define multi point feature geoemtry with rounded edges
|
||||
** $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 .........:
|
||||
**
|
||||
** 17.06.2015, JT : First edition for use with Qt5
|
||||
**
|
||||
** -----------------------------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "rubberband_multi_point_feature.h"
|
||||
|
||||
|
||||
namespace SituationMap { namespace RB
|
||||
{
|
||||
/**
|
||||
@class RubberbandSmoothLine rubberband_smooth_line.h
|
||||
@brief Implementation of a multi point feature rubberband with rounded edges.
|
||||
@see RubberbandFactory, Rubberband, RubberbandMultiPointFeature
|
||||
|
||||
*/
|
||||
class SITUATIONMAP_EXPORT RubberbandSmoothLine : public RubberbandMultiPointFeature
|
||||
{
|
||||
Q_OBJECT
|
||||
/**
|
||||
@name Construction & Destruction
|
||||
@{
|
||||
*/
|
||||
|
||||
friend class RubberbandFactory;
|
||||
|
||||
explicit RubberbandSmoothLine( SituationMap::Map * map, QObject * parent = nullptr );
|
||||
|
||||
public:
|
||||
|
||||
~RubberbandSmoothLine();
|
||||
/** @} */
|
||||
|
||||
protected:
|
||||
/*
|
||||
Forward declaration of InternalData to hold private member variables. Becareful the base class Rubberband
|
||||
has similary a class for internal data member with name "InternalData". Don't be confused it is not the same.
|
||||
*/
|
||||
struct InternalData;
|
||||
|
||||
InternalData * _internal;
|
||||
|
||||
void update() override;
|
||||
|
||||
}; /* RubberbandSmoothLine */
|
||||
|
||||
} } /* namespace SituationMap::RB */
|
||||
@@ -0,0 +1,572 @@
|
||||
|
||||
/**
|
||||
**
|
||||
** @RDE_HEADER@
|
||||
** Implementation of rubberband class to edit states of point objects
|
||||
** $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 .........:
|
||||
**
|
||||
** 19.10.2015, JT : First edition for use with Qt5
|
||||
**
|
||||
** -----------------------------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
#include "rubberband_state_select.h"
|
||||
#include "rubberband_point_handle.h"
|
||||
#include "rubberband_drawable.h"
|
||||
#include "rubberband_handle_proxy.h"
|
||||
#include "rubberband_factory.h"
|
||||
|
||||
#include "rubberband_internal.h"
|
||||
#include "rubberband_base_internal.h"
|
||||
|
||||
|
||||
#include <arcgis/Map.h>
|
||||
#include <arcgis/MapGraphicsView.h>
|
||||
|
||||
#include <QtGui/QCursor>
|
||||
#include <QtWidgets/QPushButton>
|
||||
#include <QtWidgets/QHBoxLayout>
|
||||
#include <QtWidgets/QMenu>
|
||||
|
||||
#include "polygon.xpm"
|
||||
|
||||
|
||||
namespace SituationMap { namespace RB
|
||||
{
|
||||
|
||||
struct RubberbandStateSelect::InternalData
|
||||
{
|
||||
Q_DISABLE_COPY(InternalData)
|
||||
|
||||
InternalData() : _logger(getLogger("RubberbandStateSelect"))
|
||||
{}
|
||||
|
||||
~InternalData()
|
||||
{
|
||||
delete _stateMenu;
|
||||
}
|
||||
|
||||
QVector<State> _states;
|
||||
QVector<StateItem> _items;
|
||||
QList<SituationMap::RefPointer<RubberbandHandle>> _stateMenuSelectedHandleList;
|
||||
LOGGER_T _logger;
|
||||
|
||||
const State * getStateFromValue( int stateValue ) const
|
||||
{
|
||||
for (const State &state : _states)
|
||||
{
|
||||
if (state.value() == stateValue) return &state;
|
||||
}
|
||||
return nullptr;
|
||||
} /* getStateFromValue */
|
||||
|
||||
const State * getStateFromItem( const StateItem & item ) const { return getStateFromValue(item.stateValue()); }
|
||||
|
||||
static QPixmap * _polygonIcon;
|
||||
|
||||
QPushButton * _polygonButton = nullptr;
|
||||
QMenu * _stateMenu = nullptr;
|
||||
bool _stateMenuIsActive = false;
|
||||
|
||||
}; /* RubberbandMultiPointFeature::InternalData */
|
||||
|
||||
|
||||
QPixmap * RubberbandStateSelect::InternalData::_polygonIcon = nullptr;
|
||||
|
||||
void RubberbandStateSelect::setIconPolygon(const QPixmap & icon)
|
||||
{
|
||||
if (InternalData::_polygonIcon == nullptr) InternalData::_polygonIcon = new QPixmap(icon);
|
||||
else *InternalData::_polygonIcon = icon;
|
||||
} /* RubberbandStateSelect::setIconPolygon */
|
||||
|
||||
|
||||
RubberbandStateSelect::RubberbandStateSelect( SituationMap::Map * map, QObject * parent )
|
||||
: Rubberband(map,parent), _internal(new InternalData())
|
||||
{
|
||||
delete RubberbandBase::_baseInternal->_undoButton;
|
||||
RubberbandBase::_baseInternal->_undoButton = nullptr;
|
||||
|
||||
_internal->_polygonButton = new QPushButton( (InternalData::_polygonIcon) ? *InternalData::_polygonIcon : QPixmap(polygon_xpm), QString(), RubberbandBase::_baseInternal->_buttonBox );
|
||||
|
||||
RubberbandBase::_baseInternal->_buttonLayout->insertWidget( 0, _internal->_polygonButton );
|
||||
|
||||
connect( _internal->_polygonButton, &QPushButton::clicked, this, &RubberbandStateSelect::onDo_areaSelectionBegin );
|
||||
|
||||
// Check Quartz
|
||||
connect( Rubberband::_internal->_mapView.data(), &Esri::ArcGISRuntime::MapGraphicsView::viewpointChanged,
|
||||
this, &RubberbandStateSelect::onDo_updateButtonFixCoordinates );
|
||||
connect( Rubberband::_internal->_mapView.data(), &Esri::ArcGISRuntime::MapGraphicsView::rectChanged ,
|
||||
this, &RubberbandStateSelect::onDo_updateButtonFixCoordinates );
|
||||
|
||||
|
||||
setFixedButtonBoxPosition(QPoint(5,5));
|
||||
|
||||
} /* RubberbandStateSelect::RubberbandStateSelect */
|
||||
|
||||
|
||||
bool RubberbandStateSelect::setStateItems( const QVector<State> & stateVector
|
||||
, const QVector<StateItem> & itemVector
|
||||
, CoordinateSystem cs )
|
||||
{
|
||||
if (stateVector.size() < 2) return false;
|
||||
if (itemVector.isEmpty()) return false;
|
||||
|
||||
// check for all states are valid
|
||||
for (const State & state : qAsConst(_internal->_states))
|
||||
{
|
||||
if (!state.isValid())
|
||||
return false;
|
||||
}
|
||||
|
||||
bool ok = true;
|
||||
|
||||
_internal -> _states = stateVector;
|
||||
_internal -> _items = itemVector;
|
||||
|
||||
for (QVector<StateItem>::iterator it = _internal->_items.begin(); it != _internal->_items.end(); ++it)
|
||||
{
|
||||
if (it->isValid())
|
||||
{
|
||||
const State * statePtr = _internal->getStateFromItem( *it );
|
||||
|
||||
if (statePtr == nullptr)
|
||||
{
|
||||
ok = false;
|
||||
statePtr = & _internal->_states.first();
|
||||
}
|
||||
|
||||
const QPointF &mapPos = projectCoordinateToMap( cs, it->coordinate() );
|
||||
|
||||
Esri::ArcGISRuntime::Point mapCoordinate( mapPos.x(), mapPos.y(), Rubberband::_internal->_mapView->map()->spatialReference() );
|
||||
RubberbandPointHandle * handlePtr = new RubberbandPointHandle( Rubberband::_internal->_mapView
|
||||
, Rubberband::_internal->_mapScene
|
||||
, mapCoordinate
|
||||
, statePtr->icon() );
|
||||
if (handlePtr)
|
||||
{
|
||||
handlePtr->setSelection(false);
|
||||
handlePtr->setUserData( &(*it) );
|
||||
Rubberband::_internal->_handleList.append( SituationMap::RefPointer<RubberbandHandle>(handlePtr) );
|
||||
}
|
||||
}
|
||||
else ok = false;
|
||||
}
|
||||
update();
|
||||
activateButtons();
|
||||
buildStateMenu();
|
||||
return ok;
|
||||
} /* RubberbandStateSelect::setStateItems */
|
||||
|
||||
|
||||
const QVector<RubberbandStateSelect::StateItem> & RubberbandStateSelect::stateItems() const
|
||||
{
|
||||
return _internal->_items;
|
||||
} /* RubberbandStateSelect::stateItems */
|
||||
|
||||
|
||||
void RubberbandStateSelect::activateButtons()
|
||||
{
|
||||
_baseInternal->_hasUndoButton = false;
|
||||
_baseInternal->_applyIsPossible = (!Rubberband::_internal->_handleList.isEmpty());
|
||||
_baseInternal->_undoIsPossible = false;
|
||||
Rubberband::activateButtons();
|
||||
} /* RubberbandStateSelect::activateButton */
|
||||
|
||||
|
||||
void RubberbandStateSelect::toggleState( RubberbandPointHandle * handlePtr )
|
||||
{
|
||||
if (_internal->_states.size() < 2) return;
|
||||
if (handlePtr == nullptr) return;
|
||||
|
||||
StateItem * itemPtr = static_cast<StateItem*>(handlePtr->userData());
|
||||
|
||||
if (itemPtr == nullptr) return;
|
||||
|
||||
if (_internal->_states.size() == 2)
|
||||
{
|
||||
const State * statePtr = _internal -> getStateFromItem( *itemPtr );
|
||||
|
||||
if (statePtr != nullptr)
|
||||
{
|
||||
if (statePtr == &_internal->_states.first()) statePtr = &_internal->_states.last();
|
||||
else statePtr = &_internal->_states.first();
|
||||
}
|
||||
else statePtr = &_internal->_states.first();
|
||||
|
||||
itemPtr->_stateValue = statePtr->value();
|
||||
handlePtr->setIcon( statePtr->icon() );
|
||||
}
|
||||
|
||||
} /* RubberbandStateSelect::toggleState */
|
||||
|
||||
|
||||
void RubberbandStateSelect::setState( RubberbandPointHandle * handlePtr, int stateValue )
|
||||
{
|
||||
if (handlePtr == nullptr) return;
|
||||
|
||||
const State * statePtr = _internal -> getStateFromValue(stateValue);
|
||||
StateItem * itemPtr = static_cast<StateItem*>(handlePtr->userData());
|
||||
|
||||
if (itemPtr == nullptr) return;
|
||||
if (statePtr == nullptr) return;
|
||||
|
||||
itemPtr->_stateValue = stateValue;
|
||||
handlePtr->setIcon( statePtr->icon() );
|
||||
|
||||
} /* RubberbandStateSelect::setState */
|
||||
|
||||
|
||||
void RubberbandStateSelect::buildStateMenu()
|
||||
{
|
||||
if (_internal->_states.isEmpty()) return;
|
||||
|
||||
_internal->_stateMenu = new QMenu();
|
||||
|
||||
for (const State & state : qAsConst(_internal->_states))
|
||||
{
|
||||
QAction * action = _internal->_stateMenu->addAction( state.icon(), state.description() );
|
||||
action -> setData( state.value() );
|
||||
|
||||
connect( action, &QAction::triggered, this, &RubberbandStateSelect::onDo_setState );
|
||||
}
|
||||
|
||||
connect( _internal->_stateMenu, &QMenu::aboutToShow, this, [this]()
|
||||
{
|
||||
this->_internal->_stateMenuSelectedHandleList.clear();
|
||||
|
||||
_baseInternal->_buttonBox->setDisabled(true);
|
||||
for (auto handle : qAsConst(Rubberband::_internal->_handleList))
|
||||
{
|
||||
if (handle->isSelected())
|
||||
{
|
||||
this->_internal->_stateMenuSelectedHandleList << handle;
|
||||
}
|
||||
}
|
||||
} );
|
||||
|
||||
connect( _internal->_stateMenu, &QMenu::aboutToHide, this, [this]()
|
||||
{
|
||||
_baseInternal->_buttonBox->setEnabled(true);
|
||||
deSelectHandles();
|
||||
} );
|
||||
|
||||
} /* RubberbandStateSelect::buildStateMenu */
|
||||
|
||||
|
||||
void RubberbandStateSelect::onDo_setState(bool)
|
||||
{
|
||||
QAction * action = (QAction*) sender();
|
||||
|
||||
if (action == nullptr) return;
|
||||
|
||||
int stateValue = action->data().toInt();
|
||||
|
||||
for (auto handle : qAsConst(_internal->_stateMenuSelectedHandleList))
|
||||
setState( dynamic_cast<RubberbandPointHandle*>(handle.get()), stateValue );
|
||||
|
||||
_internal -> _stateMenuSelectedHandleList.clear();
|
||||
_internal -> _stateMenuIsActive = false;
|
||||
|
||||
update();
|
||||
|
||||
} /* RubberbandStateSelect::onDo_setState */
|
||||
|
||||
|
||||
void RubberbandStateSelect::chooseStateMenu()
|
||||
{
|
||||
// popup a window with states the user can choose
|
||||
_internal->_stateMenu->popup( QCursor::pos() );
|
||||
_internal -> _stateMenuIsActive = true;
|
||||
} /* RubberbandStateSelect::chooseStateMenu */
|
||||
|
||||
|
||||
bool RubberbandStateSelect::selectAction( AbstractEventDispatcher*, int x, int y )
|
||||
{
|
||||
DEBUG_LOG(_internal->_logger) << LOGFUNCTION << x << " ; " << y;
|
||||
|
||||
_internal->_stateMenuSelectedHandleList.clear();
|
||||
|
||||
if (rubberbandIsAlive())
|
||||
{
|
||||
if (_internal->_stateMenuIsActive) return true;
|
||||
|
||||
QPointF scenePos(pixel2ScenePosition(x,y));
|
||||
|
||||
if (_baseInternal->buttonProxyActive(scenePos)) return false;
|
||||
|
||||
RubberbandHandle * handlePtr = pickHandle(x,y);
|
||||
|
||||
if (handlePtr)
|
||||
{
|
||||
handlePtr->setSelection();
|
||||
enableSelectedState();
|
||||
|
||||
update();
|
||||
deactivateButtons();
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
} /* RubberbandStateSelect::selectAction */
|
||||
|
||||
|
||||
bool RubberbandStateSelect::multiSelectActionPress(AbstractEventDispatcher*, int x, int y)
|
||||
{
|
||||
DEBUG_LOG(_internal->_logger) << LOGFUNCTION << x << " ; " << y;
|
||||
|
||||
if (rubberbandIsAlive())
|
||||
{
|
||||
if (_internal -> _stateMenuIsActive) return true;
|
||||
|
||||
RubberbandHandle * handlePtr = pickHandle(x,y);
|
||||
|
||||
if (handlePtr)
|
||||
{
|
||||
handlePtr->setSelection();
|
||||
enableSelectedState();
|
||||
enableMultiSelectedState();
|
||||
|
||||
update();
|
||||
deactivateButtons();
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
} /* RubberbandStateSelect::multiSelectActionPress */
|
||||
|
||||
|
||||
bool RubberbandStateSelect::multiSelectActionRelease( AbstractEventDispatcher*, int, int )
|
||||
{
|
||||
return false;
|
||||
} /* RubberbandStateSelect::multiSelectActionRelease */
|
||||
|
||||
|
||||
bool RubberbandStateSelect::setCoordinateAction( AbstractEventDispatcher * causer, int x, int y )
|
||||
{
|
||||
DEBUG_LOG(_internal->_logger) << LOGFUNCTION << x << " ; " << y;
|
||||
|
||||
if (rubberbandIsAlive())
|
||||
{
|
||||
Rubberband::_internal->_lastClickPosition = pixel2ScenePosition(x,y);
|
||||
|
||||
if (_internal->_stateMenuIsActive)
|
||||
{
|
||||
_internal -> _stateMenuIsActive = false;
|
||||
disenableSelectedState();
|
||||
disenableMultiSelectedState();
|
||||
activateButtons();
|
||||
return true;
|
||||
}
|
||||
|
||||
if (isEnabledSelectedState())
|
||||
{
|
||||
bool handlePicked = (pickHandle(x,y) != nullptr);
|
||||
bool toggleMode = (_internal->_states.size() == 2);
|
||||
bool eventHandled = false;
|
||||
|
||||
if (!toggleMode)
|
||||
{
|
||||
disenableSelectedState();
|
||||
disenableMultiSelectedState();
|
||||
|
||||
chooseStateMenu();
|
||||
return true;
|
||||
}
|
||||
for (auto handle : qAsConst(Rubberband::_internal->_handleList))
|
||||
{
|
||||
RubberbandPointHandle * handlePointPtr = dynamic_cast<RubberbandPointHandle*>(handle.get());
|
||||
if ((handlePointPtr) && (handlePointPtr->isSelected()))
|
||||
{
|
||||
handlePointPtr->setSelection(false);
|
||||
if ((handlePicked) && (toggleMode)) toggleState( handlePointPtr );
|
||||
eventHandled = true;
|
||||
}
|
||||
}
|
||||
|
||||
disenableSelectedState();
|
||||
disenableMultiSelectedState();
|
||||
activateButtons();
|
||||
return eventHandled;
|
||||
}
|
||||
else Rubberband::setCoordinateAction(causer,x,y);
|
||||
}
|
||||
return false;
|
||||
} /* RubberbandStateSelect::setCoordinateAction */
|
||||
|
||||
|
||||
bool RubberbandStateSelect::moveAction(AbstractEventDispatcher*, int x, int y)
|
||||
{
|
||||
DEBUG_LOG(_internal->_logger) << LOGFUNCTION << x << " ; " << y;
|
||||
|
||||
if (rubberbandIsAlive())
|
||||
{
|
||||
if (_internal -> _stateMenuIsActive) return false;
|
||||
|
||||
bool eventHandled = false;
|
||||
|
||||
QPointF scenePosition(pixel2ScenePosition(x,y));
|
||||
|
||||
if (_baseInternal->buttonProxyActive(scenePosition)) return false;
|
||||
|
||||
if (Rubberband::_internal->_mapView != nullptr)
|
||||
{
|
||||
if (!isEnabledMultiSelectedState()) deSelectHandles();
|
||||
|
||||
RubberbandHandle * handlePtr = pickHandle(x,y);
|
||||
if (handlePtr != nullptr)
|
||||
{
|
||||
handlePtr->setSelection();
|
||||
eventHandled = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (eventHandled) update();
|
||||
}
|
||||
return false;
|
||||
} /* RubberbandStateSelect::moveAction */
|
||||
|
||||
|
||||
bool RubberbandStateSelect::movePickedAction(AbstractEventDispatcher * causer, int x, int y )
|
||||
{
|
||||
DEBUG_LOG(_internal->_logger) << LOGFUNCTION << x << " ; " << y;
|
||||
|
||||
Rubberband::movePickedAction(causer,x,y);
|
||||
return false; // isEnabledSelectedState() || _internal->_stateMenuIsActive;
|
||||
} /* RubberbandStateSelect::movePickedAction */
|
||||
|
||||
|
||||
bool RubberbandStateSelect::contextMenuAction( AbstractEventDispatcher*, int, int )
|
||||
{
|
||||
if (!_internal -> _stateMenuIsActive) chooseStateMenu();
|
||||
return true;
|
||||
} /* RubberbandStateSelect::contextMenuAction */
|
||||
|
||||
|
||||
void RubberbandStateSelect::onDo_areaSelectionBegin()
|
||||
{
|
||||
bool mRbands = _baseInternal->_map->rubberbandFactory().allowMultipleRubberbands();
|
||||
_baseInternal->_map->rubberbandFactory().allowMultipleRubberbands(true);
|
||||
{
|
||||
RB::RubberbandMultiPointFeature * selectionRB = _baseInternal->_map->rubberbandFactory().create<RB::RubberbandMultiPointFeature>(this);
|
||||
|
||||
if (selectionRB == nullptr)
|
||||
{
|
||||
qWarning() << LOGFUNCTION << "Creating rubberband multi points feature failed";
|
||||
}
|
||||
else
|
||||
{
|
||||
selectionRB->setAutoDelete(true); // when finished rubberband will commit suicide
|
||||
selectionRB->setDrawColor( QColor(255,0,0,255) );
|
||||
selectionRB->setFillColor( QColor( 0,0,0,100) );
|
||||
|
||||
selectionRB -> enableClosed( true );
|
||||
selectionRB -> enableFinishAfterConstruction( true );
|
||||
|
||||
selectionRB -> setFixedButtonBoxPosition(QPoint(15,15));
|
||||
|
||||
QObject::connect( selectionRB, &RB::Rubberband::apply, this, &RubberbandStateSelect::onDo_areaSelectionApply );
|
||||
QObject::connect( selectionRB, &RB::Rubberband::abort, this, &RubberbandStateSelect::onDo_areaSelectionAbort );
|
||||
|
||||
RubberbandBase::_baseInternal->_buttonBox->setDisabled(true);
|
||||
}
|
||||
}
|
||||
_baseInternal->_map->rubberbandFactory().allowMultipleRubberbands( mRbands );
|
||||
} /* RubberbandStateSelect::onDo_areaSelectionBegin */
|
||||
|
||||
|
||||
void RubberbandStateSelect::onDo_areaSelectionApply( RubberbandBase * selectionRB )
|
||||
{
|
||||
RubberbandBase::_baseInternal->_buttonBox->setEnabled(true);
|
||||
if (selectionRB)
|
||||
{
|
||||
QVector<QPointF> polygonVertexList = selectionRB->coordinateVector( CoordinateSystem::Map );
|
||||
|
||||
// Looking for all handle which are inside polygon and select
|
||||
|
||||
unsigned int hitCounter = 0;
|
||||
|
||||
for (auto handle : qAsConst(Rubberband::_internal->_handleList))
|
||||
{
|
||||
RubberbandPointHandle * handlePointPtr = dynamic_cast<RubberbandPointHandle*>(handle.get());
|
||||
if (handlePointPtr)
|
||||
{
|
||||
const Esri::ArcGISRuntime::Point &v = handlePointPtr->getCoordinate()._mapCoordinate;
|
||||
bool inside = false;
|
||||
int nvert = polygonVertexList.size();
|
||||
|
||||
for (int i = 0, j = nvert-1; i < nvert; j = i++)
|
||||
{
|
||||
const QPointF & vertex_i = polygonVertexList[i];
|
||||
const QPointF & vertex_j = polygonVertexList[j];
|
||||
|
||||
if ((vertex_i.y()>v.y()) != (vertex_j.y()>v.y()))
|
||||
{
|
||||
if (v.x() < (vertex_j.x() - vertex_i.x()) * (v.y() - vertex_i.y()) / (vertex_j.y() - vertex_i.y()) + vertex_i.x())
|
||||
{
|
||||
inside = !inside;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (inside)
|
||||
{
|
||||
hitCounter++;
|
||||
handlePointPtr->setSelection();
|
||||
}
|
||||
}
|
||||
}
|
||||
if (hitCounter > 0)
|
||||
{
|
||||
if (_internal->_states.size() == 2)
|
||||
{
|
||||
for (auto handle : qAsConst(Rubberband::_internal->_handleList))
|
||||
{
|
||||
if (!handle->isSelected()) continue;
|
||||
handle->setSelection(false);
|
||||
toggleState( dynamic_cast<RubberbandPointHandle*>(handle.get()) );
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
chooseStateMenu();
|
||||
// ????? enableMultiSelectedState();
|
||||
}
|
||||
}
|
||||
}
|
||||
} /* RubberbandStateSelect::onDo_areaSelectionApply */
|
||||
|
||||
|
||||
void RubberbandStateSelect::onDo_areaSelectionAbort( RubberbandBase * )
|
||||
{
|
||||
_baseInternal->_buttonBox->setEnabled(true);
|
||||
/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
* Really nothing else to do here?
|
||||
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
|
||||
} /* RubberbandStateSelect::onDo_areaSelectionAbort */
|
||||
|
||||
|
||||
void RubberbandStateSelect::update()
|
||||
{
|
||||
Rubberband::update();
|
||||
|
||||
onDo_updateButtonFixCoordinates();
|
||||
|
||||
} /* RubberbandPointCluster::update */
|
||||
|
||||
} } /* namespace SituationMap::RB */
|
||||
@@ -0,0 +1,180 @@
|
||||
/**
|
||||
**
|
||||
** @RDE_HEADER@
|
||||
** Definition of rubberband class to edit states of point objects
|
||||
** $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 .........:
|
||||
**
|
||||
** 18.06.2015, JT : First edition for use with Qt5
|
||||
**
|
||||
** -----------------------------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "rubberband.h"
|
||||
|
||||
|
||||
namespace SituationMap { namespace RB
|
||||
{
|
||||
class RubberbandPointHandle;
|
||||
|
||||
|
||||
/**
|
||||
@class RubberbandPointCluster rubberband_point_cluster.h
|
||||
@brief Implementation of a rubberband to input single coodinates for building point feature clusters
|
||||
@see Rubberband, RubberbandPointFeature
|
||||
*/
|
||||
class SITUATIONMAP_EXPORT RubberbandStateSelect : public Rubberband
|
||||
{
|
||||
Q_OBJECT
|
||||
/**
|
||||
@name Construction & Destruction
|
||||
@{
|
||||
*/
|
||||
|
||||
friend class RubberbandFactory;
|
||||
|
||||
explicit RubberbandStateSelect( SituationMap::Map * map, QObject * parent = nullptr );
|
||||
|
||||
public:
|
||||
|
||||
class State
|
||||
{
|
||||
public:
|
||||
State() = default;
|
||||
State(int value, const QString & description, const QPixmap & icon)
|
||||
: _description(description), _icon(icon), _value(value), _valid(true)
|
||||
{
|
||||
}
|
||||
|
||||
inline bool isValid() const { return _valid; }
|
||||
inline int value() const { return _value; }
|
||||
inline const QString & description() const { return _description; }
|
||||
inline const QPixmap & icon() const { return _icon; }
|
||||
|
||||
protected:
|
||||
|
||||
QString _description;
|
||||
QPixmap _icon;
|
||||
int _value = 0;
|
||||
bool _valid = false;
|
||||
|
||||
}; /* State */
|
||||
|
||||
|
||||
class StateItem
|
||||
{
|
||||
friend class RubberbandStateSelect;
|
||||
|
||||
public:
|
||||
|
||||
StateItem() : _valid(false), _id(0), _description(), _coordinate(), _stateValue(0) {;}
|
||||
|
||||
StateItem( quint32 id, const QString &description, const QPointF & coordinate, int stateValue )
|
||||
: _valid(true), _id(id), _description(description), _coordinate(coordinate), _stateValue(stateValue)
|
||||
{
|
||||
} /* StateItem */
|
||||
|
||||
~StateItem() = default;
|
||||
|
||||
StateItem(const StateItem &) = default;
|
||||
StateItem & operator = (const StateItem &) = default;
|
||||
|
||||
inline bool isValid() const { return _valid; }
|
||||
inline quint32 id() const { return _id; }
|
||||
inline const QPointF & coordinate() const { return _coordinate; }
|
||||
inline int stateValue() const { return _stateValue; }
|
||||
|
||||
protected:
|
||||
|
||||
bool _valid;
|
||||
quint32 _id;
|
||||
QString _description;
|
||||
QPointF _coordinate;
|
||||
int _stateValue;
|
||||
|
||||
}; /* StateItem */
|
||||
|
||||
|
||||
virtual ~RubberbandStateSelect() = default;
|
||||
|
||||
RubberbandStateSelect(const RubberbandStateSelect &) = delete;
|
||||
RubberbandStateSelect & operator = (const RubberbandStateSelect &) = delete;
|
||||
/** @} */
|
||||
|
||||
bool selectAction ( AbstractEventDispatcher * causer, int x, int y ) override;
|
||||
bool multiSelectActionPress ( AbstractEventDispatcher * causer, int x, int y ) override;
|
||||
bool multiSelectActionRelease( AbstractEventDispatcher * causer, int x, int y ) override;
|
||||
bool setCoordinateAction ( AbstractEventDispatcher * causer, int x, int y ) override;
|
||||
bool moveAction ( AbstractEventDispatcher * causer, int x, int y ) override;
|
||||
bool movePickedAction ( AbstractEventDispatcher * causer, int x, int y ) override;
|
||||
bool contextMenuAction ( AbstractEventDispatcher * causer, int x, int y ) override;
|
||||
bool undoAction ( AbstractEventDispatcher * causer, int x, int y ) override { return contextMenuAction(causer,x,y); }
|
||||
|
||||
bool setStateItems( const QVector<State> & stateVector,
|
||||
const QVector<StateItem> & itemVector,
|
||||
CoordinateSystem cs = CoordinateSystem::Geo );
|
||||
|
||||
const QVector<StateItem> & stateItems() const;
|
||||
|
||||
static void setIconPolygon( const QPixmap & );
|
||||
|
||||
protected:
|
||||
|
||||
/*
|
||||
Forward declaration of InternalData to hold private member variables. Becareful the base class Rubberband
|
||||
has similary a class for internal data member with name "InternalData". Don't be confused it is not the same.
|
||||
*/
|
||||
struct InternalData;
|
||||
|
||||
InternalData * _internal;
|
||||
|
||||
void activateButtons() override;
|
||||
|
||||
void update() override;
|
||||
|
||||
void applyButtonClicked() override { applyAndEndAction( _windowEventDispatcher, 0.0, 0.0 ); }
|
||||
|
||||
void buildStateMenu();
|
||||
void chooseStateMenu();
|
||||
|
||||
void toggleState( RubberbandPointHandle * handlePtr );
|
||||
void setState( RubberbandPointHandle * handlePtr, int stateValue );
|
||||
|
||||
|
||||
|
||||
protected slots:
|
||||
|
||||
void onDo_areaSelectionBegin();
|
||||
void onDo_areaSelectionApply( RubberbandBase* );
|
||||
void onDo_areaSelectionAbort( RubberbandBase* );
|
||||
|
||||
void onDo_setState( bool );
|
||||
|
||||
private:
|
||||
|
||||
void setCoordinateVector(const QVector<QPointF> &, CoordinateSystem ) override {}
|
||||
|
||||
QVector<QPointF> coordinateVector( CoordinateSystem ) const override { return QVector<QPointF>(); }
|
||||
QPointF singleCoordinate( unsigned int, CoordinateSystem ) const override { return QPointF(); }
|
||||
|
||||
}; /* RubberbandStateSelect */
|
||||
|
||||
} } /* namespace SituationMap::RB */
|
||||
@@ -0,0 +1,92 @@
|
||||
|
||||
/**
|
||||
**
|
||||
** @RDE_HEADER@
|
||||
** Implementation of rubberband class to define moving transforms
|
||||
** $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 .........:
|
||||
**
|
||||
** 07.04.2015, JT : First edition for use with Qt5
|
||||
**
|
||||
** -----------------------------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
#include "rubberband_transform.h"
|
||||
|
||||
#include "rubberband_internal.h"
|
||||
|
||||
#include <MathUtils/math_const.h>
|
||||
|
||||
|
||||
namespace SituationMap { namespace RB
|
||||
{
|
||||
|
||||
struct RubberbandTransform::InternalData
|
||||
{
|
||||
Q_DISABLE_COPY(InternalData)
|
||||
MathUtils::Matrix2D _transformCoordinates;
|
||||
LOGGER_T _logger;
|
||||
|
||||
InternalData()
|
||||
: _transformCoordinates()
|
||||
, _logger(getLogger("RubberbandTransform"))
|
||||
{
|
||||
} /* InternalData */
|
||||
}; /* RubberbandTransform::InternalData */
|
||||
|
||||
|
||||
|
||||
|
||||
RubberbandTransform::RubberbandTransform( SituationMap::Map * map, QObject * parent )
|
||||
: RubberbandRectangle(map,parent)
|
||||
, _internal(new InternalData())
|
||||
{
|
||||
} /* RubberbandTransform::RubberbandTransform */
|
||||
|
||||
|
||||
RubberbandTransform::~RubberbandTransform()
|
||||
{
|
||||
delete _internal;
|
||||
_internal = nullptr;
|
||||
} /* RubberbandTransform::~RubberbandTransform */
|
||||
|
||||
|
||||
const MathUtils::Matrix2D & RubberbandTransform::transformMatrix() const { return _internal->_transformCoordinates; }
|
||||
|
||||
|
||||
void RubberbandTransform::update()
|
||||
{
|
||||
/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
* It is importent here to call RubberbandRectangle::update(); first to do an update, because
|
||||
* in other case the RubberbandRectangle::_lastCoordinateChange variable will have wrong values.
|
||||
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
|
||||
RubberbandRectangle::update();
|
||||
|
||||
if (!_lastCoordinateChange.isIdentity())
|
||||
{
|
||||
_internal->_transformCoordinates = _lastCoordinateChange * _internal->_transformCoordinates;
|
||||
}
|
||||
|
||||
emit updatePreview( this, _lastCoordinateChange );
|
||||
|
||||
_lastCoordinateChange.setToIdentity(); // reset matrix
|
||||
|
||||
} /* RubberbandTransform::update */
|
||||
|
||||
} } /* namespace SituationMap::RB */
|
||||
@@ -0,0 +1,99 @@
|
||||
/**
|
||||
**
|
||||
** @RDE_HEADER@
|
||||
** Definition of rubberband class to define moving, scale and rotating transforms
|
||||
** $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 .........:
|
||||
**
|
||||
** 22.06.2016, JT : First edition for use with Qt5
|
||||
**
|
||||
** -----------------------------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "rubberband_rectangle.h"
|
||||
|
||||
namespace SituationMap { namespace RB
|
||||
{
|
||||
|
||||
/**
|
||||
@class RubberbandTransform rubberband_transform.h
|
||||
@brief Implementation of a rubberband to move, scale and rotate features
|
||||
@see Rubberband
|
||||
*/
|
||||
class SITUATIONMAP_EXPORT RubberbandTransform : public RubberbandRectangle
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
friend class RubberbandFactory;
|
||||
|
||||
friend class RubberbandTransformMove;
|
||||
friend class RubberbandTransformRotate;
|
||||
friend class RubberbandTransformScale;
|
||||
|
||||
|
||||
/**
|
||||
@name Construction & Destruction
|
||||
@}
|
||||
*/
|
||||
|
||||
explicit RubberbandTransform( SituationMap::Map * map, QObject * parent = nullptr );
|
||||
|
||||
public:
|
||||
|
||||
~RubberbandTransform();
|
||||
/** @} */
|
||||
|
||||
/**
|
||||
Provides the transformation matrix
|
||||
*/
|
||||
const MathUtils::Matrix2D & transformMatrix() const;
|
||||
|
||||
signals:
|
||||
|
||||
/**
|
||||
The updatePreview signal is emitted before the rubbberband itself will be redrawn. Connecting this signal can be
|
||||
used to draw an preview e.g in case of transform rubberbands.
|
||||
|
||||
@param rbnd pointer to this Rubberband
|
||||
@param mat transformation matrix to transform features for preview
|
||||
@see Rubberband
|
||||
*/
|
||||
void updatePreview( Rubberband * rbnd, const MathUtils::Matrix2D & mat );
|
||||
|
||||
protected:
|
||||
|
||||
/*
|
||||
Forward declaration of InternalData to hold private member variables. Becareful the base class Rubberband
|
||||
has similary a class for internal data member with name "InternalData". Don't be confused it is not the same.
|
||||
*/
|
||||
struct InternalData;
|
||||
|
||||
InternalData * _internal;
|
||||
|
||||
void update() override;
|
||||
|
||||
private:
|
||||
|
||||
void setButtonPosition();
|
||||
|
||||
}; /* RubberbandTransform */
|
||||
|
||||
} } /* namespace SituationMap::RB */
|
||||
@@ -0,0 +1,48 @@
|
||||
|
||||
/**
|
||||
**
|
||||
** @RDE_HEADER@
|
||||
** Implementation of rubberband class to define moving transforms
|
||||
** $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 .........:
|
||||
**
|
||||
** 07.04.2015, JT : First edition for use with Qt5
|
||||
**
|
||||
** -----------------------------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
#include "rubberband_transform_move.h"
|
||||
|
||||
namespace SituationMap { namespace RB
|
||||
{
|
||||
|
||||
RubberbandTransformMove::RubberbandTransformMove( SituationMap::Map * map, QObject * parent )
|
||||
: RubberbandTransform(map,parent)
|
||||
{
|
||||
setModificationMode( ModificationMode::TranslationOnly );
|
||||
} /* RubberbandTransformMove::RubberbandTransformMove */
|
||||
|
||||
|
||||
QPointF RubberbandTransformMove::translationVector() const
|
||||
{
|
||||
const MathUtils::Matrix2D & M = transformMatrix();
|
||||
return QPointF(M(0,2),M(1,2));
|
||||
} /* RubberbandTransformMove::translationVector() const */
|
||||
|
||||
} } /* namespace SituationMap::RB */
|
||||
@@ -0,0 +1,67 @@
|
||||
/**
|
||||
**
|
||||
** @RDE_HEADER@
|
||||
** Definition of rubberband class to define moving transforms
|
||||
** $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 .........:
|
||||
**
|
||||
** 17.06.2015, JT : First edition for use with Qt5
|
||||
**
|
||||
** -----------------------------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "rubberband_transform.h"
|
||||
|
||||
|
||||
namespace SituationMap { namespace RB
|
||||
{
|
||||
|
||||
class RubberbandPointHandle;
|
||||
|
||||
/**
|
||||
@class RubberbandTransformMove rubberband_transform_move.h
|
||||
@brief Implementation of a rubberband to move features
|
||||
@see Rubberband, RubberbandRectangle, RubberbandTransform
|
||||
*/
|
||||
class SITUATIONMAP_EXPORT RubberbandTransformMove : public RubberbandTransform
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
friend class RubberbandFactory;
|
||||
|
||||
/**
|
||||
@name Construction & Destruction
|
||||
@}
|
||||
*/
|
||||
|
||||
explicit RubberbandTransformMove( SituationMap::Map * map, QObject * parent = nullptr );
|
||||
|
||||
/**
|
||||
Returns vector of translation
|
||||
*/
|
||||
QPointF translationVector() const;
|
||||
|
||||
public:
|
||||
/** @} */
|
||||
|
||||
}; /* RubberbandTransformMove */
|
||||
|
||||
} } /* namespace SituationMap::RB */
|
||||
@@ -0,0 +1,62 @@
|
||||
/**
|
||||
**
|
||||
** @RDE_HEADER@
|
||||
** Implementation of rubberband class to define rotating transforms
|
||||
** $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 .........:
|
||||
**
|
||||
** 07.04.2015, JT : First edition for use with Qt5
|
||||
**
|
||||
** -----------------------------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
#include "rubberband_transform_rotate.h"
|
||||
|
||||
#include <MathUtils/simple_helper.h>
|
||||
|
||||
|
||||
namespace SituationMap { namespace RB
|
||||
{
|
||||
|
||||
|
||||
RubberbandTransformRotate::RubberbandTransformRotate( SituationMap::Map * map, QObject * parent )
|
||||
: RubberbandTransform(map,parent)
|
||||
{
|
||||
setModificationMode( ModificationMode::RotationOnly );
|
||||
} /* RubberbandTransformRotate::RubberbandTransformRotate */
|
||||
|
||||
qreal RubberbandTransformRotate::rotationSin() const
|
||||
{
|
||||
return transformMatrix()(0,1);
|
||||
} // RubberbandTransformRotate::rotationSin
|
||||
|
||||
|
||||
qreal RubberbandTransformRotate::rotationCos() const
|
||||
{
|
||||
return transformMatrix()(0,0);
|
||||
} // RubberbandTransformRotate::rotationCos
|
||||
|
||||
|
||||
qreal RubberbandTransformRotate::rotationAngle() const
|
||||
{
|
||||
return MathUtils::getMathAngle(rotationSin(),rotationCos());
|
||||
} // RubberbandTransformRotate::rotationAngle
|
||||
|
||||
|
||||
} } /* namespace SituationMap::RB */
|
||||
@@ -0,0 +1,77 @@
|
||||
/**
|
||||
**
|
||||
** @RDE_HEADER@
|
||||
** Definition of rubberband class to define moving transformation
|
||||
** $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 .........:
|
||||
**
|
||||
** 07.04.2016, JT : First edition for use with Qt5
|
||||
**
|
||||
** -----------------------------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "rubberband_transform.h"
|
||||
|
||||
|
||||
namespace SituationMap { namespace RB
|
||||
{
|
||||
|
||||
class RubberbandPointHandle;
|
||||
|
||||
/**
|
||||
@class RubberbandTransformRotate rubberband_transform_rotate.h
|
||||
@brief Implementation of a rubberband to rotate features
|
||||
@see Rubberband
|
||||
*/
|
||||
class SITUATIONMAP_EXPORT RubberbandTransformRotate : public RubberbandTransform
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
friend class RubberbandFactory;
|
||||
|
||||
/**
|
||||
@name Construction & Destruction
|
||||
@}
|
||||
*/
|
||||
|
||||
explicit RubberbandTransformRotate( SituationMap::Map * map, QObject * parent );
|
||||
|
||||
public:
|
||||
/** @} */
|
||||
|
||||
/**
|
||||
Returns sinus of rotation angle
|
||||
*/
|
||||
qreal rotationSin() const;
|
||||
|
||||
/**
|
||||
Return cosinus of roation angle
|
||||
*/
|
||||
qreal rotationCos() const;
|
||||
|
||||
/**
|
||||
Return rotation angle (math.) in radians
|
||||
*/
|
||||
qreal rotationAngle() const;
|
||||
|
||||
}; /* RubberbandTransformRotate */
|
||||
|
||||
} } /* namespace SituationMap::RB */
|
||||
@@ -0,0 +1,47 @@
|
||||
/**
|
||||
**
|
||||
** @RDE_HEADER@
|
||||
** Implementation of rubberband class to define scaling transforms
|
||||
** $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 .........:
|
||||
**
|
||||
** 07.04.2015, JT : First edition for use with Qt5
|
||||
**
|
||||
** -----------------------------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
#include "rubberband_transform_scale.h"
|
||||
|
||||
|
||||
namespace SituationMap { namespace RB
|
||||
{
|
||||
|
||||
|
||||
|
||||
RubberbandTransformScale::RubberbandTransformScale( SituationMap::Map * map, QObject * parent )
|
||||
: RubberbandTransform(map,parent)
|
||||
{
|
||||
setModificationMode( ModificationMode::ScalingOnly );
|
||||
} /* RubberbandTransformScale::RubberbandTransformScale */
|
||||
|
||||
|
||||
qreal RubberbandTransformScale::scaleX() const { return transformMatrix()(0,0); }
|
||||
qreal RubberbandTransformScale::scaleY() const { return transformMatrix()(1,1); }
|
||||
|
||||
} } /* namespace SituationMap::RB */
|
||||
@@ -0,0 +1,64 @@
|
||||
/**
|
||||
**
|
||||
** @RDE_HEADER@
|
||||
** Definition of rubberband class to define scaling transformation
|
||||
** $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 .........:
|
||||
**
|
||||
** 07.04.2016, JT : First edition for use with Qt5
|
||||
**
|
||||
** -----------------------------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "rubberband_transform.h"
|
||||
|
||||
|
||||
namespace SituationMap { namespace RB
|
||||
{
|
||||
|
||||
/**
|
||||
@class RubberbandTransformScale rubberband_transform_scale.h
|
||||
@brief Implementation of a rubberband to scale features
|
||||
@see Rubberband
|
||||
*/
|
||||
class SITUATIONMAP_EXPORT RubberbandTransformScale : public RubberbandTransform
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
friend class RubberbandFactory;
|
||||
|
||||
/**
|
||||
@name Construction & Destruction
|
||||
@}
|
||||
*/
|
||||
|
||||
explicit RubberbandTransformScale( SituationMap::Map * map, QObject * parent = nullptr );
|
||||
|
||||
public:
|
||||
/** @} */
|
||||
|
||||
|
||||
qreal scaleX() const; /**< Returns scaling factor in x direction */
|
||||
qreal scaleY() const; /**< Returns scaling factor in y direction */
|
||||
|
||||
}; /* RubberbandTransformRotate */
|
||||
|
||||
} } /* namespace SituationMap::RB */
|
||||
+32
@@ -0,0 +1,32 @@
|
||||
/* XPM */
|
||||
static const char *sphere_pattern_xpm[] = {
|
||||
"16 16 13 1",
|
||||
" c None",
|
||||
". c #FFFFFF",
|
||||
"+ c #F8F8F8",
|
||||
"@ c #DCDCDC",
|
||||
"# c #BFBFBF",
|
||||
"$ c #E3E3E3",
|
||||
"% c #929292",
|
||||
"& c #6C6C6C",
|
||||
"* c #484848",
|
||||
"= c #393939",
|
||||
"- c #F3F3F3",
|
||||
"; c #B5B5B5",
|
||||
"> c #0A0A0A",
|
||||
" ...... ",
|
||||
" .....+.... ",
|
||||
" ..@++++++... ",
|
||||
" ..#$++....++.. ",
|
||||
" .%#$+.......+. ",
|
||||
"..%#$........+..",
|
||||
".&%#@........+..",
|
||||
".*%%#$........+.",
|
||||
".=&%##@-.....+-.",
|
||||
".=*&%##@$--++-@.",
|
||||
".;=*&%##@@$$@@#.",
|
||||
" .>==&%%######. ",
|
||||
" ..>>==&&%%%%.. ",
|
||||
" ..>>>>==*=.. ",
|
||||
" ..;>>>>;.. ",
|
||||
" ...... "};
|
||||
@@ -0,0 +1,88 @@
|
||||
|
||||
/**
|
||||
**
|
||||
** @RDE_HEADER@
|
||||
** Implementation of preview for tactical symbols
|
||||
** $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 "transient_tactical_symbol.h"
|
||||
|
||||
#include <Map/situation_map_types.h>
|
||||
#include <MapImpl/sidc_symbol_impl.h>
|
||||
#include <MapImpl/layer_factory_impl.h>
|
||||
|
||||
|
||||
namespace SituationMap { namespace RB
|
||||
{
|
||||
|
||||
TransientTacticalSymbol::TransientTacticalSymbol( MapImpl * mapImpl, const QString & sidc )
|
||||
{
|
||||
QString layerIdent;
|
||||
if (mapImpl)
|
||||
{
|
||||
layerIdent = mapImpl->layerFactoryImpl().rubberbandLayer();
|
||||
}
|
||||
|
||||
if (layerIdent.isEmpty())
|
||||
{
|
||||
qWarning() << LOGFUNCTION << "not layername found";
|
||||
}
|
||||
|
||||
_tacticalRubberbandObj = new SidcSymbolImpl( sidc, QStringLiteral("TransientTacticalSymbol:sidc=%1").arg(sidc) );
|
||||
_tacticalRubberbandObj -> init( mapImpl, layerIdent );
|
||||
//_tacticalRubberbandObj -> setDrawOrder( 2000 );
|
||||
|
||||
} /* PreviewTaticalSymbol::PreviewTaticalSymbol */
|
||||
|
||||
TransientTacticalSymbol::~TransientTacticalSymbol()
|
||||
{
|
||||
delete _tacticalRubberbandObj;
|
||||
} /* TransientTacticalSymbol::~TransientTacticalSymbol */
|
||||
|
||||
|
||||
void TransientTacticalSymbol::update(const QVector<RubberbandDrawable::RubberbandCoordinate> & coordinateVector)
|
||||
{
|
||||
PositionCont controlPoints;
|
||||
controlPoints.reserve(coordinateVector.size());
|
||||
|
||||
for (const RubberbandDrawable::RubberbandCoordinate &pos : coordinateVector)
|
||||
{
|
||||
const Esri::ArcGISRuntime::Point & p = pos._mapCoordinate;
|
||||
|
||||
controlPoints.append(Point3D(p.x(), p.y(), p.z()));
|
||||
}
|
||||
_tacticalRubberbandObj -> setPositionsTranslated( controlPoints );
|
||||
try
|
||||
{
|
||||
_tacticalRubberbandObj -> updateView();
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
qWarning() << LOGFUNCTION << "Exception from TacticalAppearance::updateView() catched!!!!";
|
||||
}
|
||||
} /* TransientTacticalSymbol::update */
|
||||
|
||||
|
||||
} } /* namespace SituationMap::RB */
|
||||
@@ -0,0 +1,79 @@
|
||||
/**
|
||||
**
|
||||
** @RDE_HEADER@
|
||||
** Definition of tansient tactical symbols while rubberband input is done.
|
||||
** $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 .........:
|
||||
**
|
||||
** 01.09.2015, JT : First edition for use with Qt5
|
||||
**
|
||||
** -----------------------------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "rubberband_drawable.h"
|
||||
|
||||
#include <MapImpl/map_impl.h>
|
||||
#include <Common/referenced.h>
|
||||
|
||||
#include <QtCore/QObject>
|
||||
|
||||
namespace SituationMap { class SidcSymbolImpl; }
|
||||
|
||||
namespace SituationMap { namespace RB
|
||||
{
|
||||
|
||||
/**
|
||||
@class TransientTacticalSymbol transient_tactical_symbol.h
|
||||
The class \c TransientTacticalSymbol a map object of type RubberbandObjectImpl to display a tactical symbol
|
||||
transiently while rubberband input is done. The tactical symbol is defined by a \a sidc code which is passed
|
||||
to the ctor as second parameter.
|
||||
|
||||
@see RubberbandObjectImpl
|
||||
*/
|
||||
class TransientTacticalSymbol : public QObject, public SituationMap::Referenced
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
|
||||
|
||||
/**
|
||||
@name Construction & Destruction
|
||||
@{
|
||||
*/
|
||||
explicit TransientTacticalSymbol( MapImpl *, const QString & sidc );
|
||||
virtual ~TransientTacticalSymbol();
|
||||
|
||||
TransientTacticalSymbol(const TransientTacticalSymbol &) = delete;
|
||||
TransientTacticalSymbol & operator = (const TransientTacticalSymbol &) = delete;
|
||||
/** @} */
|
||||
|
||||
virtual void update( const QVector<RubberbandDrawable::RubberbandCoordinate> & coordinateVector );
|
||||
|
||||
protected:
|
||||
|
||||
SidcSymbolImpl * _tacticalRubberbandObj;
|
||||
|
||||
protected slots:
|
||||
|
||||
|
||||
}; /* TransientTacticalSymbol */
|
||||
|
||||
} } /* namespace SituationMap::RB */
|
||||
Executable
+134
@@ -0,0 +1,134 @@
|
||||
/* XPM */
|
||||
static const char * undo_xpm[] = {
|
||||
"24 24 107 2",
|
||||
" c None",
|
||||
". c #BEAD52",
|
||||
"+ c #D4C15C",
|
||||
"@ c #CCBA59",
|
||||
"# c #A49546",
|
||||
"$ c #F7E16A",
|
||||
"% c #FEE65E",
|
||||
"& c #FEE350",
|
||||
"* c #FEE248",
|
||||
"= c #FEE34C",
|
||||
"- c #FEE662",
|
||||
"; c #DAC75E",
|
||||
"> c #CBBA57",
|
||||
", c #FDE456",
|
||||
"' c #FCDE32",
|
||||
") c #FCDD2D",
|
||||
"! c #FCE143",
|
||||
"~ c #E5D15F",
|
||||
"{ c #C1B152",
|
||||
"] c #FBE047",
|
||||
"^ c #FADB2B",
|
||||
"/ c #FADE3C",
|
||||
"( c #BBAB4F",
|
||||
"_ c #94873F",
|
||||
": c #F9DF49",
|
||||
"< c #F8D929",
|
||||
"[ c #F5DC4B",
|
||||
"} c #EFD751",
|
||||
"| c #F6D627",
|
||||
"1 c #EACC25",
|
||||
"2 c #E3C524",
|
||||
"3 c #F1D226",
|
||||
"4 c #F6D72A",
|
||||
"5 c #AA9A46",
|
||||
"6 c #BAAA4B",
|
||||
"7 c #F3D52B",
|
||||
"8 c #F3D424",
|
||||
"9 c #E1C421",
|
||||
"0 c #C0A81C",
|
||||
"a c #D3BD43",
|
||||
"b c #EBD242",
|
||||
"c c #F1D122",
|
||||
"d c #D3B71E",
|
||||
"e c #B29B19",
|
||||
"f c #E7CB37",
|
||||
"g c #97893C",
|
||||
"h c #EECF25",
|
||||
"i c #EECE1F",
|
||||
"j c #E7C81E",
|
||||
"k c #D8BB1C",
|
||||
"l c #ECCE28",
|
||||
"m c #CDB741",
|
||||
"n c #EBCC1C",
|
||||
"o c #EBCD1F",
|
||||
"p c #CBB84D",
|
||||
"q c #DCC857",
|
||||
"r c #B5A447",
|
||||
"s c #E6CA31",
|
||||
"t c #E8C919",
|
||||
"u c #D0B416",
|
||||
"v c #DFC118",
|
||||
"w c #E8CA26",
|
||||
"x c #EACF3B",
|
||||
"y c #ECD552",
|
||||
"z c #E3CE59",
|
||||
"A c #CAB74F",
|
||||
"B c #E6C71C",
|
||||
"C c #E6C617",
|
||||
"D c #BEA51A",
|
||||
"E c #D3B513",
|
||||
"F c #E3C314",
|
||||
"G c #E4C51D",
|
||||
"H c #E6CA2E",
|
||||
"I c #DBBC13",
|
||||
"J c #917F20",
|
||||
"K c #917E15",
|
||||
"L c #E0C011",
|
||||
"M c #DDBF17",
|
||||
"N c #C0AE49",
|
||||
"O c #D8BA0E",
|
||||
"P c #DDBE0E",
|
||||
"Q c #DEBF12",
|
||||
"R c #E1C62C",
|
||||
"S c #E5CE4A",
|
||||
"T c #D3BF4F",
|
||||
"U c #928436",
|
||||
"V c #AC930E",
|
||||
"W c #DBBB0C",
|
||||
"X c #DEC01D",
|
||||
"Y c #E2C93D",
|
||||
"Z c #CCB84B",
|
||||
"` c #D7B809",
|
||||
" . c #D8B909",
|
||||
".. c #CCAF09",
|
||||
"+. c #BDA107",
|
||||
"@. c #D6B607",
|
||||
"#. c #CFB007",
|
||||
"$. c #897504",
|
||||
"%. c #D4B405",
|
||||
"&. c #D0B105",
|
||||
"*. c #978004",
|
||||
"=. c #C9AA03",
|
||||
"-. c #D2B203",
|
||||
";. c #D0B003",
|
||||
">. c #A48B03",
|
||||
",. c #968109",
|
||||
"'. c #AD9301",
|
||||
" ",
|
||||
" ",
|
||||
" . + @ ",
|
||||
" # $ % & * = - ; ",
|
||||
" > , ' ) ) ) ) ) ! ~ ",
|
||||
" { ] ^ ^ ^ ^ ^ ^ ^ ^ / ( ",
|
||||
" _ : < < < < < < < < < < [ ",
|
||||
" } | | | | | | 1 2 3 | | 4 5 ",
|
||||
" 6 7 8 8 8 8 9 0 8 8 a ",
|
||||
" b c c c c d e c f ",
|
||||
" g h i i i j k l ",
|
||||
" m n n n n o ",
|
||||
" p q r s t t t u v ",
|
||||
" w x y z A B C C C D ",
|
||||
" E F F G H F F F I J ",
|
||||
" K L L L L L L L M N ",
|
||||
" O P P P P P P Q R S T U ",
|
||||
" V W W W W W W W W W X Y Z ",
|
||||
" ` . . . . . . . ... ",
|
||||
" +.@.@.@.@.@.@.#.$. ",
|
||||
" %.%.%.%.&.*. ",
|
||||
" =.-.;.>. ",
|
||||
" ,.'. ",
|
||||
" "};
|
||||
+84
@@ -0,0 +1,84 @@
|
||||
/* XPM */
|
||||
static const char * winkelIcon_xpm[] = {
|
||||
"40 40 41 1",
|
||||
" c None",
|
||||
". c #250075",
|
||||
"+ c #250074",
|
||||
"@ c #260074",
|
||||
"# c #250073",
|
||||
"$ c #240072",
|
||||
"% c #250071",
|
||||
"& c #22006F",
|
||||
"* c #24006E",
|
||||
"= c #280078",
|
||||
"- c #290076",
|
||||
"; c #270076",
|
||||
"> c #240073",
|
||||
", c #250072",
|
||||
"' c #240071",
|
||||
") c #240070",
|
||||
"! c #23006E",
|
||||
"~ c #23006D",
|
||||
"{ c #22006D",
|
||||
"] c #23006C",
|
||||
"^ c #21006D",
|
||||
"/ c #270075",
|
||||
"( c #230073",
|
||||
"_ c #24006F",
|
||||
": c #22006E",
|
||||
"< c #22006C",
|
||||
"[ c #240075",
|
||||
"} c #260075",
|
||||
"| c #230070",
|
||||
"1 c #24006C",
|
||||
"2 c #230072",
|
||||
"3 c #260073",
|
||||
"4 c #23006F",
|
||||
"5 c #230071",
|
||||
"6 c #24006D",
|
||||
"7 c #210064",
|
||||
"8 c #210066",
|
||||
"9 c #200065",
|
||||
"0 c #210065",
|
||||
"a c #200063",
|
||||
"b c #1D0062",
|
||||
" ",
|
||||
" ",
|
||||
" ",
|
||||
" ",
|
||||
" ",
|
||||
" ",
|
||||
" ",
|
||||
" .++ ",
|
||||
" @+#+$%&* ",
|
||||
" =-;#>,')!~{]^ ",
|
||||
" .;/>(>)_:~~~<~< ",
|
||||
" [}###'|&:~<<~~1!* ",
|
||||
" .2$3'')4::{~~~~~^ ",
|
||||
" $%'5' 4{6<~~~~_ ",
|
||||
" 4)| <~~~~! ",
|
||||
" :~~~!~ ",
|
||||
" 4{~~~< ",
|
||||
" ~~~~{_ ",
|
||||
" ~~~6~ ",
|
||||
" ~~~~: ",
|
||||
" ]~~{~! ",
|
||||
" ~~~{~ ",
|
||||
" ~~~]! ",
|
||||
" ~~~~:| ",
|
||||
" {<~~~! ",
|
||||
" ~~~~!~ ",
|
||||
" <~~~~! ",
|
||||
" :{{<~~~*] ",
|
||||
" !::]1!{{{{<~{~~~~]! ",
|
||||
" ^64~~]!~~~<~~~~~*6{ ",
|
||||
" {!&!]~~~~~~~<]~*~ ",
|
||||
" :*]~~~~~~~<_< ",
|
||||
" 7890009ab ",
|
||||
" ",
|
||||
" ",
|
||||
" ",
|
||||
" ",
|
||||
" ",
|
||||
" ",
|
||||
" "};
|
||||
Reference in new issue
Block a user