/*virtual*/ void Circle::Draw(Painter * painter)
{
- if (state == OSSelected)
+ if (state == OSSelected || hitCircle || hitCenter)
painter->SetPen(QPen(Qt::red, 2.0, Qt::DotLine));
else
painter->SetPen(QPen(Qt::black, 1.0, Qt::SolidLine));
-// if (draggingHandle1)
- if (state == OSSelected)
+ if (state == OSSelected || hitCenter)
painter->DrawEllipse(position, 4.0, 4.0);
-// if (draggingHandle2)
-// if (state == OSSelected)
-// painter->drawEllipse(QPointF(endpoint.x, endpoint.y), 4.0, 4.0);
if (state == OSSelected && dragging)
painter->DrawEllipse(oldPoint, 4.0, 4.0);
/*virtual*/ bool Circle::Collided(Vector point)
{
+ // We can assume this, since this is a mouse down event here.
objectWasDragged = false;
+ HitTest(point);
+
+// objectWasDragged = false;
Vector v1 = position - point;
if (state == OSInactive)
/*virtual*/ void Circle::PointerMoved(Vector point)
{
+ // Hit test tells us what we hit (if anything) through boolean variables. It
+ // also tells us whether or not the state changed.
+ needUpdate = HitTest(point);
+
objectWasDragged = true;
if (dragging)
oldPoint = point;
needUpdate = true;
}*/
- else
- needUpdate = false;
+// else
+// needUpdate = false;
}
/*virtual*/ void Circle::PointerReleased(void)
return needUpdate;
}
#endif
+
+bool Circle::HitTest(Point point)
+{
+ SaveState();
+
+ hitCenter = hitCircle = false;
+
+#if 0
+ Vector lineSegment = endpoint - position;
+ Vector v1 = point - position;
+ Vector v2 = point - endpoint;
+ double parameterizedPoint = lineSegment.Dot(v1) / lineSegment.Magnitude(), distance;
+
+ // Geometric interpretation:
+ // The parameterized point on the vector lineSegment is where the perpendicular
+ // intersects lineSegment. If pp < 0, then the perpendicular lies beyond the 1st
+ // endpoint. If pp > length of ls, then the perpendicular lies beyond the 2nd endpoint.
+
+ if (parameterizedPoint < 0.0)
+ distance = v1.Magnitude();
+ else if (parameterizedPoint > lineSegment.Magnitude())
+ distance = v2.Magnitude();
+ else
+ // distance = ?Det?(ls, v1) / |ls|
+ distance = fabs((lineSegment.x * v1.y - v1.x * lineSegment.y) / lineSegment.Magnitude());
+
+ // Geometric interpretation of the above:
+ // If the segment endpoints are s and e, and the point is p, then the test
+ // for the perpendicular intercepting the segment is equivalent to insisting
+ // that the two dot products {s-e}.{s-p} and {e-s}.{e-p} are both non-negative.
+ // Perpendicular distance from the point to the segment is computed by first
+ // computing the area of the triangle the three points form, then dividing by
+ // the length of the segment. Distances are done just by the Pythagorean
+ // theorem. Twice the area of the triangle formed by three points is the
+ // determinant of the following matrix:
+ //
+ // sx sy 1 0 0 1 0 0 0
+ // ex ey 1 ==> ex ey 1 ==> ex ey 0
+ // px py 1 px py 1 px py 0
+ //
+ // By translating the start point to the origin, and subtracting row 1 from
+ // all other rows, we end up with the matrix on the right which greatly
+ // simplifies the calculation of the determinant.
+
+//How do we determine distance here? Especially if zoomed in or out???
+#warning "!!! Distances tested for may not be valid if zoomed in or out !!!"
+ if (v1.Magnitude() < 8.0)
+ hitPoint1 = true;
+ else if (v2.Magnitude() < 8.0)
+ hitPoint2 = true;
+ else if (distance < 5.0)
+ hitLine = true;
+#else
+ Vector v1 = position - point;
+//How to translate this into pixels from Document space???
+//Maybe we need to pass a scaling factor in here from the caller? That would make sense, as
+//the caller knows about the zoom factor and all that good kinda crap
+ if (v1.Magnitude() < 10.0)
+ hitCenter = true;
+ else if ((v1.Magnitude() < radius + 2.0) && (v1.Magnitude() > radius - 2.0))
+ hitCircle = true;
+#endif
+
+ return StateChanged();
+}
+
+void Circle::SaveState(void)
+{
+ oldHitCenter = hitCenter;
+ oldHitCircle = hitCircle;
+}
+
+bool Circle::StateChanged(void)
+{
+ if ((hitCenter != oldHitCenter) || (hitCircle != oldHitCircle))
+ return true;
+
+ return false;
+}
qtPainter.setRenderHint(QPainter::Antialiasing);
Painter::screenSize = Vector(size().width(), size().height());
+ Painter::zoom = 2.0; // 200% zoom
#if 0
#if 0
painter.translate(QPoint(-offsetX, size.height() - (-offsetY)));
{
if (event->button() == Qt::LeftButton)
{
- QPoint pt = GetAdjustedMousePosition(event);
- Vector point(pt.x(), pt.y());
+// QPoint pt = GetAdjustedMousePosition(event);
+// Vector point(pt.x(), pt.y());
+ Vector point = Painter::QtToCartesianCoords(Vector(event->x(), event->y()));
collided = document.Collided(point);
void DrawingView::mouseMoveEvent(QMouseEvent * event)
{
- QPoint pt = GetAdjustedMousePosition(event);
- Vector point(pt.x(), pt.y());
+// QPoint pt = GetAdjustedMousePosition(event);
+// Vector point(pt.x(), pt.y());
+ Vector point = Painter::QtToCartesianCoords(Vector(event->x(), event->y()));
// Grid processing...
#if 1
return Vector((v.x - origin.x) * zoom, screenSize.y - ((v.y - origin.y) * zoom));
}
-Vector Painter::QtCoordsToCartesian(Vector v)
+Vector Painter::QtToCartesianCoords(Vector v)
{
// Convert screen location, with inverted Y-axis coordinates, to regular
// Cartesian coordinates at the current zoom level.
void Painter::DrawAngledText(Vector center, double angle, QString text)
{
+ // Strategy: Since Qt doesn't have any rotated text drawing functions,
+ // we instead translate the origin to the center of the text to be drawn and
+ // then rotate the frame to the desired angle.
center = CartesianToQtCoords(center);
// We may need this stuff... If dimension text is large enough.
// int textHeight = QFontMetrics(painter->font()).height();
QRectF textBox(-100, -100, 200, 200); // x, y, w, h; x/y = upper left corner
- // Some things to note here: if angle > 90 degrees, then we need to take the negative
- // of the angle for our text.
- painter->save();
- painter->translate(center.x, center.y);
// This is in pixels. Might not render correctly at all zoom levels.
// Need to figure out if dimensions are always rendered at one size regardless of zoom,
// or if they have a definite size, and are thus zoomable.
// If zoomable, this is incorrect:
int yOffset = -12;
- //Fix text so it isn't upside down...
+ // Fix text so it isn't upside down...
if ((angle > PI * 0.5) && (angle < PI * 1.5))
{
angle += PI;
}
textBox.translate(0, yOffset);
- // Angles are backwards in the Qt coord system...
+ painter->save();
+ painter->translate(center.x, center.y);
+ // Angles are backwards in the Qt coord system, so we flip ours...
painter->rotate(-angle * RADIANS_TO_DEGREES);
painter->drawText(textBox, Qt::AlignCenter, text);
painter->restore();