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
7#include "DataKey.h"
8#include "EngaugeAssert.h"
9#include "EnumsToQt.h"
10#include "GraphicsItemType.h"
11#include "GuidelineEllipse.h"
12#include "GuidelineFormat.h"
13#include "Guidelines.h"
15#include "Logger.h"
16#include <QGraphicsEllipseItem>
17#include <QGraphicsScene>
18#include <QGraphicsSceneMouseEvent>
19#include <QLineF>
20#include <qmath.h>
21#include <QMouseEvent>
22#include <QPen>
23#include <QWidget>
24#include "ZValues.h"
25
27 Guidelines &guidelines,
29 const QString &identifier) :
30 GuidelineAbstract (scene)
31{
32 LOG4CPP_DEBUG_S ((*mainCat)) << "GuidelineEllipse::GuidelineEllipse identifier=" << identifier.toLatin1().data();
33
34 // Create context after all virtual methods have been created. The transition
35 // into the initial state will position the line if it was created by a button press
37 guidelines,
39
42
43 scene.addItem (this);
44}
45
49
51 Qt::ItemSelectionMode mode) const
52{
53 const double RATIO = 1000.0; // Ratio of many pixels to few pixels, for preventing divide by zero
54 bool collides = false;
55
56 if (QGraphicsEllipseItem::collidesWithPath (path,
57 mode)) {
58
59 // Slow test to not count interior region
60
62
63 // Bounding box of ellipse
64 double a = rect().width() / 2.0;
65 double b = rect().height() / 2.0;
66
67 // Loop through points in path polygon
68 QPolygonF poly = path.toFillPolygon();
69 QPolygonF::const_iterator itr;
70 for (itr = poly.begin(); (itr != poly.end()) && !collides; itr++) {
71
72 // This point is for the ellipse that has already been rotated to be aligned with axes
73 const QPointF &pointAligned = *itr;
74
75 // Project point onto ellipse. The projection is assumed to be the closest ellipse portion to that point.
76 // 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
77 double xGot = pointAligned.x();
78 double yGot = pointAligned.y();
79 double rGot = qSqrt (xGot * xGot + yGot * yGot);
80 if (rGot * RATIO > qAbs (xGot) || rGot * RATIO > qAbs (yGot)) {
81
82 // Check for divide by zero passed so keep going
83 double cTheta = xGot / rGot;
84 double sTheta = yGot / rGot;
85 double rProjected = qSqrt (1.0 / (cTheta * cTheta / a / a + sTheta * sTheta / b / b));
86 double xProjected = rProjected * cTheta;
87 double yProjected = rProjected * sTheta;
88
89 // Distance to projection
90 double distance = qSqrt ((xProjected - xGot) * (xProjected - xGot) +
91 (yProjected - yGot) * (yProjected - yGot));
92
93 if (distance < guidelineFormat.lineWidthHover()) {
94
95 // This will make the loop exit immediately for speed
96 collides = true;
97 }
98 }
99 }
100 }
101
102 return collides;
103}
104
109
111{
112 return QGraphicsEllipseItem::isSelected ();
113}
114
115QGraphicsItem::GraphicsItemFlags GuidelineEllipse::graphicsItemFlags () const
116{
117 return QGraphicsEllipseItem::flags ();
118}
119
121{
123
124 QGraphicsEllipseItem::hoverEnterEvent (event);
125}
126
128{
130
131 QGraphicsEllipseItem::hoverLeaveEvent (event);
132}
133
135{
136 return data (DATA_KEY_IDENTIFIER).toString ();
137}
138
140{
141 handleMouseMoveEvent (event->scenePos ());
142
143 QGraphicsEllipseItem::mouseMoveEvent (event);
144}
145
147{
148 LOG4CPP_DEBUG_S ((*mainCat)) << "GuidelineEllipse::mousePressEvent";
149
150 QGraphicsEllipseItem::mousePressEvent (event);
151
152 handleMousePressEvent (event->scenePos ());
153
154 context()->handleMousePress(event->scenePos());
155}
156
158{
159 LOG4CPP_DEBUG_S ((*mainCat)) << "GuidelineEllipse::mouseReleaseEvent";
160
161 handleMouseReleaseEvent (event->scenePos());
162
163 QGraphicsEllipseItem::mouseReleaseEvent (event);
164}
165
169{
170 if (context()->doPaint ()) {
171
172 QGraphicsEllipseItem::paint (painter,
173 option,
174 widget);
175 }
176}
177
178void GuidelineEllipse::removeFromScene (QGraphicsScene *scene)
179{
180 LOG4CPP_DEBUG_S ((*mainCat)) << "GuidelineLine::removeFromScene identifier="
181 << identifier().toLatin1().data();
182
183 scene->removeItem (this);
184}
185
187{
188 QGraphicsEllipseItem::setAcceptHoverEvents (accept);
189}
190
191void GuidelineEllipse::setGraphicsItemFlags (QGraphicsItem::GraphicsItemFlags flags)
192{
193 QGraphicsEllipseItem::setFlags (flags);
194}
195
197{
198 // Noop
199}
200
202 double lineWidth)
203{
204 QBrush brush (color);
205
206 setPen (QPen (brush,
207 lineWidth));
208}
209
211{
212 QGraphicsEllipseItem::setVisible (visible);
213}
214
216{
217 QGraphicsEllipseItem::setZValue (z);
218}
219
221{
222 // Apply color to brush and pen defined in setGraphicsItemPen.
223
224 QPen p = QGraphicsEllipseItem::pen();
225 QBrush br = p.brush();
226 double alphaF = br.color().alphaF();
227 double lineWidth = p.width ();
228
229 QColor color = ColorPaletteToQColor (context()->color());
230 color.setAlphaF (alphaF);
231
232 setGraphicsItemPen (color,
233 lineWidth);
234}
235
237{
238 // Convert single graph coordinate, which is range, into screen point pair,
239 // then update with the screen point
240 updateGeometry (context ()->convertGraphCoordinateToScreenPoint (valueGraph));
241}
242
244{
245 LOG4CPP_INFO_S ((*mainCat)) << "GuidelineEllipse::updateGeometry scale=" << scale()
246 << " rotation(deg)=" << rotation();
247
249
250 QPointF posCenter = ellipseParameters.posCenter();
251
252 double a = ellipseParameters.a();
253 double b = ellipseParameters.b();
254
255 setRect (QRectF (- QPointF (a, b),
256 + QPointF (a, b)));
257
258 // Rotate. Originally the rectangle was centered at posCenter, the rotation center
259 // was set using setTransformOriginPoint to posCenter, but the resulting shape was not right
261 setPos (posCenter);
262
263 // Save the graph value for later
264 QPointF posGraph;
266 posGraph);
267 context()->setPosCursorGraph (posGraph);
268}
@ DATA_KEY_GRAPHICS_ITEM_TYPE
‍Unique identifier for QGraphicsItem object
Definition DataKey.h:15
@ DATA_KEY_IDENTIFIER
Definition DataKey.h:14
const int INNER_RADIUS_MIN
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
Parameters that define an ellipse about the specified center, at the specified angle from alignment w...
QPointF posCenter() const
Get method for center.
This class is a special case of the standard QGraphicsLineItem for guidelines, and serves as the base...
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.
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.
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.
GuidelineEllipse(QGraphicsScene &scene, Guidelines &guidelines, GuidelineState guidelineStateInitial, const QString &identifier)
Single constructor.
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.
This class centralizes the formatting information (color, line width, alpha) for the Guidelines.
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
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