[dia] Standard - Arc: movable center point
- From: Hans Breuer <hans src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [dia] Standard - Arc: movable center point
- Date: Fri, 8 Jul 2011 17:19:32 +0000 (UTC)
commit c6d7f13d0bcb51ced9fb9251260e99353c8177e5
Author: Hans Breuer <hans breuer org>
Date: Fri Jul 1 19:04:56 2011 +0200
Standard - Arc: movable center point
allows to create 'perfect' arcs (e.g. 90Â) with grid snapping on.
objects/standard/arc.c | 46 ++++++++++++++++++++++++++++++++++++++++++----
1 files changed, 42 insertions(+), 4 deletions(-)
---
diff --git a/objects/standard/arc.c b/objects/standard/arc.c
index 9900c07..dfc11f3 100644
--- a/objects/standard/arc.c
+++ b/objects/standard/arc.c
@@ -268,8 +268,9 @@ arc_update_handles(Arc *arc)
middle_pos->x -= arc->curve_distance*dy/dist;
middle_pos->y += arc->curve_distance*dx/dist;
}
- /* just mirroring the center position */
+ /* just update it from the calculated position */
arc->center_handle.pos = arc->center;
+
}
static real
@@ -327,6 +328,22 @@ arc_find_radial(const Arc *arc, const Point *to, Point *best)
}
+static gboolean
+point_projection_is_between (const Point *c,
+ const Point *a,
+ const Point *b)
+{
+ real len = distance_point_point (a, b);
+ real r;
+
+ if (len > 0) {
+ real r = ((a->y - c->y) * (a->y - b->y) - (a->x - c->x) * (b->x - a->x)) / (len * len);
+ return (r >= 0 && r <= 1.0);
+ }
+ /* identity of three points ? */
+ return (c->x == a->x && c->y == a->y);
+}
+
static ObjectChange*
arc_move_handle(Arc *arc, Handle *handle,
Point *to, ConnectionPoint *cp,
@@ -346,7 +363,7 @@ arc_move_handle(Arc *arc, Handle *handle,
} else if (handle->id == HANDLE_CENTER) {
p1 = &arc->connection.endpoints[0];
p2 = &arc->connection.endpoints[1];
- /* TODO: special movement, e.g. change the radius */
+ /* special movement, let the center point snap to grid */
} else {
p1 = &arc->middle_handle.pos;
p2 = &arc->connection.endpoints[(handle == (&arc->connection.endpoint_handles[0])) ? 1 : 0];
@@ -361,7 +378,28 @@ arc_move_handle(Arc *arc, Handle *handle,
arc->curve_distance = arc_compute_curve_distance(arc, &arc->connection.endpoints[0], &arc->connection.endpoints[1], to);
TRACE(printf("curve_dist: %.2f \n",arc->curve_distance));
} else if (handle->id == HANDLE_CENTER) {
- /* we can move the handle only on the line through center and middle */
+ /* We can move the handle only on the line through center and middle
+ * Intersecting chord theorem says a*a=b*c
+ * with a = dist(p1,p2)/2
+ * b = curve_distance
+ * c = 2*radius-b or c = r + d
+ * with Pythagoras r^2 = d^2 + a^2
+ * d = sqrt(r^2-a^2)
+ */
+ Point p0 = arc->connection.endpoints[0];
+ Point p1 = arc->connection.endpoints[1];
+ Point p2 = { (p0.x + p1.x) / 2.0, (p0.y + p1.y) / 2.0 };
+ real a = distance_point_point (&p0, &p1)/2.0;
+ real r = ( distance_point_point (&p0, to) + distance_point_point (&p1, to)) / 2.0;
+ real d = sqrt(r*r-a*a);
+ real cd;
+ /* If the new point lies between midpoint and the chords center the angles is >180,
+ * so c is smaller than r */
+ if (point_projection_is_between (to, &arc->middle_handle.pos, &p2))
+ d = -d;
+ cd = a*a / (r+d);
+ /* the sign of curve_distance, i.e. if the arc angle is clockwise, does not change */
+ arc->curve_distance = (arc->curve_distance > 0) ? cd : -cd;
} else {
Point best;
TRACE(printf("Modifiers: %d \n",modifiers));
@@ -632,7 +670,7 @@ _arc_setup_handles(Arc *arc)
obj->handles[3] = &arc->center_handle;
arc->center_handle.id = HANDLE_CENTER;
- arc->center_handle.type = HANDLE_NON_MOVABLE;
+ arc->center_handle.type = HANDLE_MINOR_CONTROL;
arc->center_handle.connect_type = HANDLE_NONCONNECTABLE;
arc->center_handle.connected_to = NULL;
}
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]