Engauge Digitizer 2
Loading...
Searching...
No Matches
GuidelineEllipse.cpp
Go to the documentation of this file.
1/******************************************************************************************************
2 * (C) 2019 markummitchell@github.com. This file is part of Engauge Digitizer, which is released *
3 * under GNU General Public License version 2 (GPLv2) or (at your option) any later version. See file *
4 * LICENSE or go to gnu.org/licenses for details. Distribution requires prior written permission. *
5 ******************************************************************************************************/
6
8#include "CmdMediator.h"
9#include "DataKey.h"
10#include "Document.h"
12#include "EngaugeAssert.h"
13#include "EnumsToQt.h"
14#include "GraphicsItemType.h"
15#include "GuidelineEllipse.h"
16#include "Guidelines.h"
18#include "Logger.h"
19#include <QGraphicsEllipseItem>
20#include <QGraphicsScene>
21#include <QGraphicsSceneMouseEvent>
22#include <QLineF>
23#include <qmath.h>
24#include <QMouseEvent>
25#include <QPen>
26#include <QWidget>
27#include "ZValues.h"
28
30 MainWindow &mainWindow,
31 Guidelines &guidelines,
32 GuidelineState guidelineStateInitial,
33 const QString &identifier) :
35 m_mainWindow (mainWindow)
36{
37 LOG4CPP_DEBUG_S ((*mainCat)) << "GuidelineEllipse::GuidelineEllipse identifier=" << identifier.toLatin1().data();
38
39 // Create context after all virtual methods have been created. The transition
40 // into the initial state will position the line if it was created by a button press
42 mainWindow,
43 guidelines,
44 guidelineStateInitial));
45
47 setData (DATA_KEY_IDENTIFIER, QVariant (identifier));
48
49 scene.addItem (this);
50}
51
55
56bool GuidelineEllipse::collidesWithPath (const QPainterPath &path,
57 Qt::ItemSelectionMode mode) const
58{
59 const double RATIO = 1000.0; // Ratio of many pixels to few pixels, for preventing divide by zero
60 bool collides = false;
61
62 if (QGraphicsEllipseItem::collidesWithPath (path,
63 mode)) {
64
65 // Slow (but fast enough) test to count interior regions
66
67 // Bounding box of ellipse
68 double a = rect().width() / 2.0;
69 double b = rect().height() / 2.0;
70
71 // Loop through points in path polygon
72 QPolygonF poly = path.toFillPolygon();
73 QPolygonF::const_iterator itr;
74 for (itr = poly.begin(); (itr != poly.end()) && !collides; itr++) {
75
76 // This point is for the ellipse that has already been rotated to be aligned with axes
77 const QPointF &pointAligned = *itr;
78
79 // Project point onto ellipse. The projection is assumed to be the closest ellipse portion to that point.
80 // Starting with (x/a)^2+(y/b)^2=1 with x=r cos(Theta) and y=r sin(Theta), we can solve to get r^2 (cT^2/a^2 + sT2/b^2) = 1
81 double xGot = pointAligned.x();
82 double yGot = pointAligned.y();
83 double rGot = qSqrt (xGot * xGot + yGot * yGot);
84 if (rGot * RATIO > qAbs (xGot) || rGot * RATIO > qAbs (yGot)) {
85
86 // Check for divide by zero passed so keep going
87 double cTheta = xGot / rGot;
88 double sTheta = yGot / rGot;
89 double rProjected = qSqrt (1.0 / (cTheta * cTheta / a / a + sTheta * sTheta / b / b));
90 double xProjected = rProjected * cTheta;
91 double yProjected = rProjected * sTheta;
92
93 // Distance to projection
94 double distance = qSqrt ((xProjected - xGot) * (xProjected - xGot) +
95 (yProjected - yGot) * (yProjected - yGot));
96
97 int lineWidthHover = m_mainWindow.cmdMediator ()->document ().modelGuideline ().lineWidthActive ();
98
99 if (distance < lineWidthHover) {
100
101 // This will make the loop exit immediately for speed
102 collides = true;
103 }
104 }
105 }
106 }
107
108 return collides;
109}
110
112{
113 return acceptHoverEvents();
114}
115
117{
118 return QGraphicsEllipseItem::isSelected ();
119}
120
121QGraphicsItem::GraphicsItemFlags GuidelineEllipse::graphicsItemFlags () const
122{
123 return QGraphicsEllipseItem::flags ();
124}
125
126void GuidelineEllipse::hoverEnterEvent(QGraphicsSceneHoverEvent *event)
127{
129
130 QGraphicsEllipseItem::hoverEnterEvent (event);
131}
132
133void GuidelineEllipse::hoverLeaveEvent(QGraphicsSceneHoverEvent *event)
134{
136
137 QGraphicsEllipseItem::hoverLeaveEvent (event);
138}
139
141{
142 return data (DATA_KEY_IDENTIFIER).toString ();
143}
144
145void GuidelineEllipse::mouseMoveEvent (QGraphicsSceneMouseEvent *event)
146{
147 handleMouseMoveEvent (event->scenePos ());
148
149 QGraphicsEllipseItem::mouseMoveEvent (event);
150}
151
152void GuidelineEllipse::mousePressEvent(QGraphicsSceneMouseEvent *event)
153{
154 LOG4CPP_DEBUG_S ((*mainCat)) << "GuidelineEllipse::mousePressEvent";
155
156 QGraphicsEllipseItem::mousePressEvent (event);
157
158 handleMousePressEvent (event->scenePos ());
159
160 context()->handleMousePress(event->scenePos());
161}
162
163void GuidelineEllipse::mouseReleaseEvent (QGraphicsSceneMouseEvent *event)
164{
165 LOG4CPP_DEBUG_S ((*mainCat)) << "GuidelineEllipse::mouseReleaseEvent";
166
167 handleMouseReleaseEvent (event->scenePos());
168
169 QGraphicsEllipseItem::mouseReleaseEvent (event);
170}
171
172void GuidelineEllipse::paint(QPainter *painter,
173 const QStyleOptionGraphicsItem *option,
174 QWidget *widget)
175{
176 if (context()->doPaint ()) {
177
178 QGraphicsEllipseItem::paint (painter,
179 option,
180 widget);
181 }
182}
183
185{
186 LOG4CPP_DEBUG_S ((*mainCat)) << "GuidelineLine::removeFromScene identifier="
187 << identifier().toLatin1().data();
188
189 scene->removeItem (this);
190}
191
193{
194 QGraphicsEllipseItem::setAcceptHoverEvents (accept);
195}
196
197void GuidelineEllipse::setGraphicsItemFlags (QGraphicsItem::GraphicsItemFlags flags)
198{
199 QGraphicsEllipseItem::setFlags (flags);
200}
201
202void GuidelineEllipse::setGraphicsItemLine (const QLineF & /* line */)
203{
204 // Noop
205}
206
207void GuidelineEllipse::setGraphicsItemPen (const QColor &color,
208 double lineWidth)
209{
210 QBrush brush (color);
211
212 setPen (QPen (brush,
213 lineWidth));
214}
215
217{
218 QGraphicsEllipseItem::setVisible (visible);
219}
220
222{
223 QGraphicsEllipseItem::setZValue (z);
224}
225
227{
228 // Apply color to brush and pen defined in setGraphicsItemPen.
229
230 QPen p = QGraphicsEllipseItem::pen();
231 QBrush br = p.brush();
232 double alphaF = br.color().alphaF();
233 double lineWidth = p.width ();
234
235 QColor color = ColorPaletteToQColor (context()->color());
236 color.setAlphaF (alphaF);
237
238 setGraphicsItemPen (color,
239 lineWidth);
240}
241
242void GuidelineEllipse::updateGeometry (double valueGraph)
243{
244 // Convert single graph coordinate, which is range, into screen point pair,
245 // then update with the screen point
246 updateGeometry (context ()->convertGraphCoordinateToScreenPoint (valueGraph));
247}
248
249void GuidelineEllipse::updateGeometry (const QPointF &posScreen)
250{
251 LOG4CPP_INFO_S ((*mainCat)) << "GuidelineEllipse::updateGeometry scale=" << scale()
252 << " rotation(deg)=" << rotation();
253
254 EllipseParameters ellipseParameters = context()->pointToEllipse (posScreen);
255
256 QPointF posCenter = ellipseParameters.posCenter();
257
258 double a = ellipseParameters.a();
259 double b = ellipseParameters.b();
260
261 setRect (QRectF (- QPointF (a, b),
262 + QPointF (a, b)));
263
264 // Rotate. Originally the rectangle was centered at posCenter, the rotation center
265 // was set using setTransformOriginPoint to posCenter, but the resulting shape was not right
266 setRotation (qRadiansToDegrees (ellipseParameters.angleRadians()));
267 setPos (posCenter);
268
269 // Save the graph value for later
270 QPointF posGraph;
272 posGraph);
273 context()->setPosCursorGraph (posGraph);
274
275 CentipedeDebugPolar debugPolar;
276 debugPolar.dumpEllipseGraphicsItem ("GuidelineEllipse::updateGeometry",
277 this);
278}
@ DATA_KEY_GRAPHICS_ITEM_TYPE
Definition DataKey.h:15
@ DATA_KEY_IDENTIFIER
Definition DataKey.h:14
QColor ColorPaletteToQColor(ColorPalette color)
Definition EnumsToQt.cpp:16
@ GRAPHICS_ITEM_TYPE_GUIDELINE
GuidelineState
Set of possible Guideline states. See class Guideline for more information.
log4cpp::Category * mainCat
Definition Logger.cpp:14
Class for collecting and then displaying debug information computed during constant R ellipse calcula...
void dumpEllipseGraphicsItem(const QString &callerMethod, const QGraphicsEllipseItem *ellipse) const
Dump ellipse grahics item.
Parameters that define an ellipse about the specified center, at the specified angle from alignment w...
double angleRadians() const
Get method for angle in radians.
double b() const
Get method for b.
QPointF posCenter() const
Get method for center.
double a() const
Get method for a.
QGraphicsScene & scene()
GraphicsScene that owns this class.
void handleMousePressEvent(const QPointF &posScene)
Forward press event to state machine.
void setContext(GuidelineStateContext *context)
Create state machine after virtual methods of child classes have been defined.
void handleMouseMoveEvent(const QPointF &posScene)
Forward movements to visible Guideline.
void handleMouseReleaseEvent(const QPointF &posScene)
Cleanup after being dragged.
GuidelineStateContext * context()
State machine context owned by this class.
void handleHoverEnterEvent()
Highlight this Guideline upon hover enter.
void handleHoverLeaveEvent()
Unset highlighting triggered by hover enter.
GuidelineAbstract(QGraphicsScene &scene)
Single constructor.
virtual void setGraphicsItemPen(const QColor &color, double lineWidth)
Wrapper for QGraphicsItem::setPen.
virtual void mouseMoveEvent(QGraphicsSceneMouseEvent *event)
Forward movements to visible Guideline.
virtual QString identifier() const
Unique identifier from QGraphicsItem.
virtual void mouseReleaseEvent(QGraphicsSceneMouseEvent *event)
Cleanup after being dragged.
GuidelineEllipse(QGraphicsScene &scene, MainWindow &mainWindow, Guidelines &guidelines, GuidelineState guidelineStateInitial, const QString &identifier)
Single constructor.
virtual void mousePressEvent(QGraphicsSceneMouseEvent *event)
Forward press event to state machine.
virtual void setGraphicsItemFlags(QGraphicsItem::GraphicsItemFlags flags)
Wrapper for QGraphicsItem::setFlags.
virtual void hoverLeaveEvent(QGraphicsSceneHoverEvent *event)
Unset highlighting triggered by hover enter.
virtual void setGraphicsItemAcceptHoverEvents(bool accept)
Wrapper for QGraphicsItem::setAcceptHoverEvents.
virtual void removeFromScene(QGraphicsScene *scene)
Make graphics item remove itself from the scene.
virtual QGraphicsItem::GraphicsItemFlags graphicsItemFlags() const
Wraps QGraphicsItem::flags.
virtual void setGraphicsItemVisible(bool visible)
Wrapper for QGraphicsItem::setVisible.
virtual void updateGeometry(double valueGraph)
Update the geometry so it passes through the specified coordinate value in graph coordinates.
virtual void setGraphicsItemZValue(double z)
Wrapper for QGraphicsItem::setZValue.
virtual void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget=Q_NULLPTR)
Override painting so this disappears when selected. Selected Guidelines are never visible.
virtual void updateColor()
Force a color update.
virtual void setGraphicsItemLine(const QLineF &line)
Wrapper for QGraphicsLineItem::setLine.
virtual bool getGraphicsItemSelected() const
Wrapper for QGraphicsItem::isSelected.
virtual bool collidesWithPath(const QPainterPath &path, Qt::ItemSelectionMode mode=Qt::IntersectsItemShape) const
Override normal QGraphicsEllipseItem collision detection that covers ellipse boundary and entire inte...
virtual void hoverEnterEvent(QGraphicsSceneHoverEvent *event)
Highlight this Guideline upon hover enter.
virtual bool getGraphicsItemAcceptHover() const
Return true if accepting hover events.
Context class for state machine that belongs to the Guideline class.
Transformation transformation() const
Return copy of transformation owned by MainWindow.
void setPosCursorGraph(const QPointF &posGraph)
Pass the current cursor coordinate to the state so it can save the relevant coordinate for later adju...
EllipseParameters pointToEllipse(const QPointF &posScreen) const
Return ellipse representing constant range, that passes through the specified point.
void handleMousePress(const QPointF &posScene)
At the start of dragging, convert the original Guideline into an invisible handle and visible slaved ...
This class contains all Guideline objects.
Definition Guidelines.h:28
Main window consisting of menu, graphics scene, status bar and optional toolbars as a Single Document...
Definition MainWindow.h:95
void transformScreenToRawGraph(const QPointF &coordScreen, QPointF &coordGraph) const
Transform from cartesian pixel screen coordinates to cartesian/polar graph coordinates.
#define LOG4CPP_INFO_S(logger)
Definition convenience.h:18
#define LOG4CPP_DEBUG_S(logger)
Definition convenience.h:20