mirror of https://github.com/GNOME/gimp.git
transformtool: rotate handles along with frame
This commit is contained in:
parent
e83b40982f
commit
b11a705203
|
@ -300,22 +300,50 @@ gimp_canvas_handle_draw (GimpCanvasItem *item,
|
|||
cairo_t *cr)
|
||||
{
|
||||
GimpCanvasHandlePrivate *private = GET_PRIVATE (item);
|
||||
gdouble x, y;
|
||||
gdouble x, y, tx, ty;
|
||||
|
||||
gimp_canvas_handle_transform (item, shell, &x, &y);
|
||||
gimp_display_shell_transform_xy_f (shell,
|
||||
private->x, private->y,
|
||||
&tx, &ty);
|
||||
|
||||
switch (private->type)
|
||||
{
|
||||
case GIMP_HANDLE_SQUARE:
|
||||
cairo_rectangle (cr, x, y, private->width - 1.0, private->height - 1.0);
|
||||
|
||||
_gimp_canvas_item_stroke (item, cr);
|
||||
break;
|
||||
|
||||
case GIMP_HANDLE_FILLED_SQUARE:
|
||||
cairo_rectangle (cr, x - 0.5, y - 0.5, private->width, private->height);
|
||||
case GIMP_HANDLE_DIAMOND:
|
||||
case GIMP_HANDLE_FILLED_DIAMOND:
|
||||
cairo_save (cr);
|
||||
cairo_translate (cr, tx, ty);
|
||||
cairo_rotate (cr, private->start_angle);
|
||||
cairo_translate (cr, -tx, -ty);
|
||||
|
||||
_gimp_canvas_item_fill (item, cr);
|
||||
switch (private->type)
|
||||
{
|
||||
case GIMP_HANDLE_SQUARE:
|
||||
cairo_rectangle (cr, x, y, private->width - 1.0, private->height - 1.0);
|
||||
_gimp_canvas_item_stroke (item, cr);
|
||||
break;
|
||||
case GIMP_HANDLE_FILLED_SQUARE:
|
||||
cairo_rectangle (cr, x - 0.5, y - 0.5, private->width, private->height);
|
||||
_gimp_canvas_item_fill (item, cr);
|
||||
break;
|
||||
case GIMP_HANDLE_DIAMOND:
|
||||
case GIMP_HANDLE_FILLED_DIAMOND:
|
||||
cairo_move_to (cr, x, y - (gdouble) private->height / 2.0);
|
||||
cairo_line_to (cr, x + (gdouble) private->width / 2.0, y);
|
||||
cairo_line_to (cr, x, y + (gdouble) private->height / 2.0);
|
||||
cairo_line_to (cr, x - (gdouble) private->width / 2.0, y);
|
||||
cairo_line_to (cr, x, y - (gdouble) private->height / 2.0);
|
||||
if (private->type == GIMP_HANDLE_DIAMOND)
|
||||
_gimp_canvas_item_stroke (item, cr);
|
||||
else
|
||||
_gimp_canvas_item_fill (item, cr);
|
||||
break;
|
||||
default:
|
||||
g_assert_not_reached ();
|
||||
}
|
||||
cairo_restore (cr);
|
||||
break;
|
||||
|
||||
case GIMP_HANDLE_CIRCLE:
|
||||
|
@ -346,20 +374,6 @@ gimp_canvas_handle_draw (GimpCanvasItem *item,
|
|||
_gimp_canvas_item_stroke (item, cr);
|
||||
break;
|
||||
|
||||
case GIMP_HANDLE_DIAMOND:
|
||||
case GIMP_HANDLE_FILLED_DIAMOND:
|
||||
cairo_move_to (cr, x, y - (gdouble) private->height / 2.0);
|
||||
cairo_line_to (cr, x + (gdouble) private->width / 2.0, y);
|
||||
cairo_line_to (cr, x, y + (gdouble) private->height / 2.0);
|
||||
cairo_line_to (cr, x - (gdouble) private->width / 2.0, y);
|
||||
cairo_line_to (cr, x, y - (gdouble) private->height / 2.0);
|
||||
|
||||
if (private->type == GIMP_HANDLE_DIAMOND)
|
||||
_gimp_canvas_item_stroke (item, cr);
|
||||
else
|
||||
_gimp_canvas_item_fill (item, cr);
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
@ -372,6 +386,7 @@ gimp_canvas_handle_get_extents (GimpCanvasItem *item,
|
|||
GimpCanvasHandlePrivate *private = GET_PRIVATE (item);
|
||||
cairo_rectangle_int_t rectangle;
|
||||
gdouble x, y;
|
||||
gdouble w, h;
|
||||
|
||||
gimp_canvas_handle_transform (item, shell, &x, &y);
|
||||
|
||||
|
@ -379,10 +394,12 @@ gimp_canvas_handle_get_extents (GimpCanvasItem *item,
|
|||
{
|
||||
case GIMP_HANDLE_SQUARE:
|
||||
case GIMP_HANDLE_FILLED_SQUARE:
|
||||
rectangle.x = x - 1.5;
|
||||
rectangle.y = y - 1.5;
|
||||
rectangle.width = private->width + 3.0;
|
||||
rectangle.height = private->height + 3.0;
|
||||
w = private->width * (sqrt(2) - 1) / 2;
|
||||
h = private->height * (sqrt(2) - 1) / 2;
|
||||
rectangle.x = x - 1.5 - w;
|
||||
rectangle.y = y - 1.5 - h;
|
||||
rectangle.width = private->width + 3.0 + w * 2;
|
||||
rectangle.height = private->height + 3.0 + h * 2;
|
||||
break;
|
||||
|
||||
case GIMP_HANDLE_CIRCLE:
|
||||
|
@ -411,20 +428,33 @@ gimp_canvas_handle_hit (GimpCanvasItem *item,
|
|||
{
|
||||
GimpCanvasHandlePrivate *private = GET_PRIVATE (item);
|
||||
gdouble handle_tx, handle_ty;
|
||||
gdouble tx, ty;
|
||||
gdouble mx, my, tx, ty, mmx, mmy;
|
||||
gdouble diamond_offset_x = 0.0, diamond_offset_y = 0.0;
|
||||
gdouble angle = -private->start_angle;
|
||||
|
||||
gimp_canvas_handle_transform (item, shell, &handle_tx, &handle_ty);
|
||||
|
||||
gimp_display_shell_transform_xy_f (shell,
|
||||
x, y,
|
||||
&tx, &ty);
|
||||
&mx, &my);
|
||||
|
||||
switch (private->type)
|
||||
{
|
||||
case GIMP_HANDLE_DIAMOND:
|
||||
case GIMP_HANDLE_FILLED_DIAMOND:
|
||||
angle -= G_PI / 4.0;
|
||||
diamond_offset_x = private->width / 2.0;
|
||||
diamond_offset_y = private->height / 2.0;
|
||||
case GIMP_HANDLE_SQUARE:
|
||||
case GIMP_HANDLE_FILLED_SQUARE:
|
||||
return (tx == CLAMP (tx, handle_tx, handle_tx + private->width) &&
|
||||
ty == CLAMP (ty, handle_ty, handle_ty + private->height));
|
||||
gimp_display_shell_transform_xy_f (shell,
|
||||
private->x, private->y,
|
||||
&tx, &ty);
|
||||
mmx = mx - tx; mmy = my - ty;
|
||||
mx = cos (angle) * mmx - sin (angle) * mmy + tx + diamond_offset_x;
|
||||
my = sin (angle) * mmx + cos (angle) * mmy + ty + diamond_offset_y;
|
||||
return mx > handle_tx && mx < handle_tx + private->width &&
|
||||
my > handle_ty && my < handle_ty + private->height;
|
||||
|
||||
case GIMP_HANDLE_CIRCLE:
|
||||
case GIMP_HANDLE_FILLED_CIRCLE:
|
||||
|
@ -437,14 +467,9 @@ gimp_canvas_handle_hit (GimpCanvasItem *item,
|
|||
|
||||
width /= 2;
|
||||
|
||||
return ((SQR (handle_tx - tx) + SQR (handle_ty - ty)) < SQR (width));
|
||||
return ((SQR (handle_tx - mx) + SQR (handle_ty - my)) < SQR (width));
|
||||
}
|
||||
|
||||
case GIMP_HANDLE_DIAMOND:
|
||||
case GIMP_HANDLE_FILLED_DIAMOND:
|
||||
return ((ABS (handle_tx - tx) + ABS (handle_ty - ty)) < ABS (private->width));
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
|
|
@ -39,6 +39,7 @@
|
|||
#include "widgets/gimphelp-ids.h"
|
||||
|
||||
#include "display/gimpcanvasgroup.h"
|
||||
#include "display/gimpcanvashandle.h"
|
||||
#include "display/gimpdisplay.h"
|
||||
#include "display/gimpdisplayshell.h"
|
||||
#include "display/gimpdisplayshell-transform.h"
|
||||
|
@ -136,6 +137,164 @@ gimp_unified_transform_tool_init (GimpUnifiedTransformTool *unified_tool)
|
|||
tr_tool->use_handles = TRUE;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
transform_is_convex (GimpVector2 *pos)
|
||||
{
|
||||
return gimp_transform_polygon_is_convex (pos[0].x, pos[0].y,
|
||||
pos[1].x, pos[1].y,
|
||||
pos[2].x, pos[2].y,
|
||||
pos[3].x, pos[3].y);
|
||||
}
|
||||
|
||||
static inline gdouble
|
||||
dotprod (GimpVector2 a,
|
||||
GimpVector2 b)
|
||||
{
|
||||
return a.x * b.x + a.y * b.y;
|
||||
}
|
||||
|
||||
static inline gdouble norm (GimpVector2 a)
|
||||
{
|
||||
return sqrt (dotprod (a, a));
|
||||
}
|
||||
|
||||
static inline GimpVector2
|
||||
vectorsubtract (GimpVector2 a,
|
||||
GimpVector2 b)
|
||||
{
|
||||
GimpVector2 c;
|
||||
|
||||
c.x = a.x - b.x;
|
||||
c.y = a.y - b.y;
|
||||
|
||||
return c;
|
||||
}
|
||||
|
||||
static inline GimpVector2
|
||||
vectoradd (GimpVector2 a,
|
||||
GimpVector2 b)
|
||||
{
|
||||
GimpVector2 c;
|
||||
|
||||
c.x = a.x + b.x;
|
||||
c.y = a.y + b.y;
|
||||
|
||||
return c;
|
||||
}
|
||||
|
||||
static inline GimpVector2
|
||||
scalemult (GimpVector2 a,
|
||||
gdouble b)
|
||||
{
|
||||
GimpVector2 c;
|
||||
|
||||
c.x = a.x * b;
|
||||
c.y = a.y * b;
|
||||
|
||||
return c;
|
||||
}
|
||||
|
||||
static inline GimpVector2
|
||||
vectorproject (GimpVector2 a,
|
||||
GimpVector2 b)
|
||||
{
|
||||
return scalemult (b, dotprod (a, b) / dotprod (b, b));
|
||||
}
|
||||
|
||||
/* finds the clockwise angle between the vectors given, 0-2π */
|
||||
static inline gdouble
|
||||
calcangle (GimpVector2 a,
|
||||
GimpVector2 b)
|
||||
{
|
||||
gdouble angle, angle2;
|
||||
gdouble length = norm (a) * norm (b);
|
||||
|
||||
angle = acos (dotprod (a, b)/length);
|
||||
angle2 = b.y;
|
||||
b.y = -b.x;
|
||||
b.x = angle2;
|
||||
angle2 = acos (dotprod (a, b)/length);
|
||||
|
||||
return ((angle2 > G_PI/2.) ? angle : 2*G_PI-angle);
|
||||
}
|
||||
|
||||
static inline GimpVector2
|
||||
rotate2d (GimpVector2 p,
|
||||
gdouble angle)
|
||||
{
|
||||
GimpVector2 ret;
|
||||
|
||||
ret.x = cos (angle) * p.x-sin (angle) * p.y;
|
||||
ret.y = sin (angle) * p.x+cos (angle) * p.y;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static inline GimpVector2
|
||||
lineintersect (GimpVector2 p1, GimpVector2 p2,
|
||||
GimpVector2 q1, GimpVector2 q2)
|
||||
{
|
||||
gdouble denom, u;
|
||||
GimpVector2 p;
|
||||
|
||||
denom = (q2.y - q1.y) * (p2.x - p1.x) - (q2.x - q1.x) * (p2.y - p1.y);
|
||||
if (denom == 0.0)
|
||||
{
|
||||
p.x = (p1.x + p2.x + q1.x + q2.x) / 4;
|
||||
p.y = (p1.y + p2.y + q1.y + q2.y) / 4;
|
||||
}
|
||||
else
|
||||
{
|
||||
u = (q2.x - q1.x) * (p1.y - q1.y) - (q2.y - q1.y) * (p1.x - q1.x);
|
||||
u /= denom;
|
||||
|
||||
p.x = p1.x + u * (p2.x - p1.x);
|
||||
p.y = p1.y + u * (p2.y - p1.y);
|
||||
}
|
||||
|
||||
return p;
|
||||
}
|
||||
|
||||
static inline GimpVector2
|
||||
getpivotdelta (GimpTransformTool *tr_tool,
|
||||
GimpVector2 *oldpos,
|
||||
GimpVector2 *newpos,
|
||||
GimpVector2 pivot)
|
||||
{
|
||||
GimpMatrix3 transform_before, transform_after;
|
||||
GimpVector2 delta;
|
||||
|
||||
gimp_matrix3_identity (&transform_before);
|
||||
gimp_matrix3_identity (&transform_after);
|
||||
|
||||
gimp_transform_matrix_perspective (&transform_before,
|
||||
tr_tool->x1,
|
||||
tr_tool->y1,
|
||||
tr_tool->x2 - tr_tool->x1,
|
||||
tr_tool->y2 - tr_tool->y1,
|
||||
oldpos[0].x, oldpos[0].y,
|
||||
oldpos[1].x, oldpos[1].y,
|
||||
oldpos[2].x, oldpos[2].y,
|
||||
oldpos[3].x, oldpos[3].y);
|
||||
gimp_transform_matrix_perspective (&transform_after,
|
||||
tr_tool->x1,
|
||||
tr_tool->y1,
|
||||
tr_tool->x2 - tr_tool->x1,
|
||||
tr_tool->y2 - tr_tool->y1,
|
||||
newpos[0].x, newpos[0].y,
|
||||
newpos[1].x, newpos[1].y,
|
||||
newpos[2].x, newpos[2].y,
|
||||
newpos[3].x, newpos[3].y);
|
||||
gimp_matrix3_invert (&transform_before);
|
||||
gimp_matrix3_mult (&transform_after, &transform_before);
|
||||
gimp_matrix3_transform_point (&transform_before,
|
||||
pivot.x, pivot.y, &delta.x, &delta.y);
|
||||
|
||||
delta = vectorsubtract (delta, pivot);
|
||||
|
||||
return delta;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
point_is_inside_polygon (gint n, gdouble *x, gdouble *y, gdouble px, gdouble py)
|
||||
{
|
||||
|
@ -309,65 +468,85 @@ gimp_unified_transform_tool_draw_gui (GimpTransformTool *tr_tool,
|
|||
GimpDrawTool *draw_tool = GIMP_DRAW_TOOL (tr_tool);
|
||||
GimpCanvasGroup *stroke_group;
|
||||
gint d, i;
|
||||
gdouble tx[] = { tr_tool->tx1, tr_tool->tx2,
|
||||
tr_tool->tx3, tr_tool->tx4 },
|
||||
ty[] = { tr_tool->ty1, tr_tool->ty2,
|
||||
tr_tool->ty3, tr_tool->ty4 };
|
||||
gdouble angle[8];
|
||||
GimpVector2 o[] = { { .x = tr_tool->tx1, .y = tr_tool->ty1 },
|
||||
{ .x = tr_tool->tx2, .y = tr_tool->ty2 },
|
||||
{ .x = tr_tool->tx3, .y = tr_tool->ty3 },
|
||||
{ .x = tr_tool->tx4, .y = tr_tool->ty4 } },
|
||||
t[] = { o[0], o[1], o[2], o[3] },
|
||||
right = { .x = 1.0, .y = 0.0 },
|
||||
up = { .x = 0.0, .y = 1.0 };
|
||||
|
||||
angle[0] = calcangle (vectorsubtract (o[0], o[1]), right);
|
||||
angle[1] = calcangle (vectorsubtract (o[2], o[3]), right);
|
||||
angle[2] = calcangle (vectorsubtract (o[3], o[1]), up);
|
||||
angle[3] = calcangle (vectorsubtract (o[2], o[0]), up);
|
||||
|
||||
angle[4] = angle[0] + angle[3];
|
||||
angle[5] = angle[0] + angle[2];
|
||||
angle[6] = angle[1] + angle[3];
|
||||
angle[7] = angle[1] + angle[2];
|
||||
|
||||
for (i = 0; i < 4; i++)
|
||||
{
|
||||
GimpCanvasItem *h;
|
||||
|
||||
/* draw the scale handles */
|
||||
tr_tool->handles[TRANSFORM_HANDLE_NW + i] =
|
||||
gimp_draw_tool_add_handle (draw_tool,
|
||||
GIMP_HANDLE_SQUARE,
|
||||
tx[i], ty[i],
|
||||
handle_w * 1.5, handle_h * 1.5,
|
||||
GIMP_HANDLE_ANCHOR_CENTER);
|
||||
h = gimp_draw_tool_add_handle (draw_tool,
|
||||
GIMP_HANDLE_SQUARE,
|
||||
t[i].x, t[i].y,
|
||||
handle_w * 1.5, handle_h * 1.5,
|
||||
GIMP_HANDLE_ANCHOR_CENTER);
|
||||
gimp_canvas_handle_set_angles (h, angle[i + 4] / 2.0, 0.0);
|
||||
tr_tool->handles[TRANSFORM_HANDLE_NW + i] = h;
|
||||
|
||||
/* draw the perspective handles */
|
||||
tr_tool->handles[TRANSFORM_HANDLE_NW_P + i] =
|
||||
gimp_draw_tool_add_handle (draw_tool,
|
||||
GIMP_HANDLE_SQUARE,
|
||||
tx[i], ty[i],
|
||||
handle_w * 0.8, handle_h * 0.8,
|
||||
GIMP_HANDLE_ANCHOR_CENTER);
|
||||
h = gimp_draw_tool_add_handle (draw_tool,
|
||||
GIMP_HANDLE_SQUARE,
|
||||
t[i].x, t[i].y,
|
||||
handle_w * 0.8, handle_h * 0.8,
|
||||
GIMP_HANDLE_ANCHOR_CENTER);
|
||||
gimp_canvas_handle_set_angles (h, angle[i + 4] / 2.0, 0.0);
|
||||
tr_tool->handles[TRANSFORM_HANDLE_NW_P + i] = h;
|
||||
}
|
||||
|
||||
/* draw the side handles */
|
||||
tx[0] = (tr_tool->tx1 + tr_tool->tx2) / 2.0;
|
||||
ty[0] = (tr_tool->ty1 + tr_tool->ty2) / 2.0;
|
||||
tx[1] = (tr_tool->tx3 + tr_tool->tx4) / 2.0;
|
||||
ty[1] = (tr_tool->ty3 + tr_tool->ty4) / 2.0;
|
||||
tx[2] = (tr_tool->tx2 + tr_tool->tx4) / 2.0;
|
||||
ty[2] = (tr_tool->ty2 + tr_tool->ty4) / 2.0;
|
||||
tx[3] = (tr_tool->tx3 + tr_tool->tx1) / 2.0;
|
||||
ty[3] = (tr_tool->ty3 + tr_tool->ty1) / 2.0;
|
||||
t[0] = scalemult (vectoradd (o[0], o[1]), 0.5);
|
||||
t[1] = scalemult (vectoradd (o[2], o[3]), 0.5);
|
||||
t[2] = scalemult (vectoradd (o[1], o[3]), 0.5);
|
||||
t[3] = scalemult (vectoradd (o[2], o[0]), 0.5);
|
||||
|
||||
for (i = 0; i < 4; i++)
|
||||
tr_tool->handles[TRANSFORM_HANDLE_N + i] =
|
||||
gimp_draw_tool_add_handle (draw_tool,
|
||||
GIMP_HANDLE_SQUARE,
|
||||
tx[i], ty[i],
|
||||
handle_w, handle_h,
|
||||
GIMP_HANDLE_ANCHOR_CENTER);
|
||||
{
|
||||
GimpCanvasItem *h;
|
||||
|
||||
h = gimp_draw_tool_add_handle (draw_tool,
|
||||
GIMP_HANDLE_SQUARE,
|
||||
t[i].x, t[i].y,
|
||||
handle_w, handle_h,
|
||||
GIMP_HANDLE_ANCHOR_CENTER);
|
||||
gimp_canvas_handle_set_angles (h, angle[i], 0.0);
|
||||
tr_tool->handles[TRANSFORM_HANDLE_N + i] = h;
|
||||
}
|
||||
|
||||
/* draw the shear handles */
|
||||
tx[0] = (tr_tool->tx1 * 1.0 + tr_tool->tx2 * 3.0) / 4.0;
|
||||
ty[0] = (tr_tool->ty1 * 1.0 + tr_tool->ty2 * 3.0) / 4.0;
|
||||
tx[1] = (tr_tool->tx3 * 3.0 + tr_tool->tx4 * 1.0) / 4.0;
|
||||
ty[1] = (tr_tool->ty3 * 3.0 + tr_tool->ty4 * 1.0) / 4.0;
|
||||
tx[2] = (tr_tool->tx2 * 1.0 + tr_tool->tx4 * 3.0) / 4.0;
|
||||
ty[2] = (tr_tool->ty2 * 1.0 + tr_tool->ty4 * 3.0) / 4.0;
|
||||
tx[3] = (tr_tool->tx3 * 3.0 + tr_tool->tx1 * 1.0) / 4.0;
|
||||
ty[3] = (tr_tool->ty3 * 3.0 + tr_tool->ty1 * 1.0) / 4.0;
|
||||
t[0] = scalemult (vectoradd ( o[0] , scalemult (o[1], 3.0)), 0.25);
|
||||
t[1] = scalemult (vectoradd (scalemult (o[2], 3.0), o[3] ), 0.25);
|
||||
t[2] = scalemult (vectoradd ( o[1] , scalemult (o[3], 3.0)), 0.25);
|
||||
t[3] = scalemult (vectoradd (scalemult (o[2], 3.0), o[0] ), 0.25);
|
||||
|
||||
for (i = 0; i < 4; i++)
|
||||
tr_tool->handles[TRANSFORM_HANDLE_N_S + i] =
|
||||
gimp_draw_tool_add_handle (draw_tool,
|
||||
GIMP_HANDLE_FILLED_DIAMOND,
|
||||
tx[i], ty[i],
|
||||
handle_w, handle_h,
|
||||
GIMP_HANDLE_ANCHOR_CENTER);
|
||||
{
|
||||
GimpCanvasItem *h;
|
||||
|
||||
h = gimp_draw_tool_add_handle (draw_tool,
|
||||
GIMP_HANDLE_FILLED_DIAMOND,
|
||||
t[i].x, t[i].y,
|
||||
handle_w, handle_h,
|
||||
GIMP_HANDLE_ANCHOR_CENTER);
|
||||
gimp_canvas_handle_set_angles (h, angle[i], 0.0);
|
||||
tr_tool->handles[TRANSFORM_HANDLE_N_S + i] = h;
|
||||
}
|
||||
|
||||
/* draw the rotation center axis handle */
|
||||
d = MIN (handle_w, handle_h);
|
||||
|
@ -473,164 +652,6 @@ gimp_unified_transform_tool_prepare (GimpTransformTool *tr_tool)
|
|||
tr_tool->trans_info[Y3] = (gdouble) tr_tool->y2;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
transform_is_convex (GimpVector2 *pos)
|
||||
{
|
||||
return gimp_transform_polygon_is_convex (pos[0].x, pos[0].y,
|
||||
pos[1].x, pos[1].y,
|
||||
pos[2].x, pos[2].y,
|
||||
pos[3].x, pos[3].y);
|
||||
}
|
||||
|
||||
static inline gdouble
|
||||
dotprod (GimpVector2 a,
|
||||
GimpVector2 b)
|
||||
{
|
||||
return a.x * b.x + a.y * b.y;
|
||||
}
|
||||
|
||||
static inline gdouble norm (GimpVector2 a)
|
||||
{
|
||||
return sqrt (dotprod (a, a));
|
||||
}
|
||||
|
||||
static inline GimpVector2
|
||||
vectorsubtract (GimpVector2 a,
|
||||
GimpVector2 b)
|
||||
{
|
||||
GimpVector2 c;
|
||||
|
||||
c.x = a.x - b.x;
|
||||
c.y = a.y - b.y;
|
||||
|
||||
return c;
|
||||
}
|
||||
|
||||
static inline GimpVector2
|
||||
vectoradd (GimpVector2 a,
|
||||
GimpVector2 b)
|
||||
{
|
||||
GimpVector2 c;
|
||||
|
||||
c.x = a.x + b.x;
|
||||
c.y = a.y + b.y;
|
||||
|
||||
return c;
|
||||
}
|
||||
|
||||
static inline GimpVector2
|
||||
scalemult (GimpVector2 a,
|
||||
gdouble b)
|
||||
{
|
||||
GimpVector2 c;
|
||||
|
||||
c.x = a.x * b;
|
||||
c.y = a.y * b;
|
||||
|
||||
return c;
|
||||
}
|
||||
|
||||
static inline GimpVector2
|
||||
vectorproject (GimpVector2 a,
|
||||
GimpVector2 b)
|
||||
{
|
||||
return scalemult (b, dotprod (a, b) / dotprod (b, b));
|
||||
}
|
||||
|
||||
/* finds the clockwise angle between the vectors given, 0-2π */
|
||||
static inline gdouble
|
||||
calcangle (GimpVector2 a,
|
||||
GimpVector2 b)
|
||||
{
|
||||
gdouble angle, angle2;
|
||||
gdouble length = norm (a) * norm (b);
|
||||
|
||||
angle = acos (dotprod (a, b)/length);
|
||||
angle2 = b.y;
|
||||
b.y = -b.x;
|
||||
b.x = angle2;
|
||||
angle2 = acos (dotprod (a, b)/length);
|
||||
|
||||
return ((angle2 > G_PI/2.) ? angle : 2*G_PI-angle);
|
||||
}
|
||||
|
||||
static inline GimpVector2
|
||||
rotate2d (GimpVector2 p,
|
||||
gdouble angle)
|
||||
{
|
||||
GimpVector2 ret;
|
||||
|
||||
ret.x = cos (angle) * p.x-sin (angle) * p.y;
|
||||
ret.y = sin (angle) * p.x+cos (angle) * p.y;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static inline GimpVector2
|
||||
lineintersect (GimpVector2 p1, GimpVector2 p2,
|
||||
GimpVector2 q1, GimpVector2 q2)
|
||||
{
|
||||
gdouble denom, u;
|
||||
GimpVector2 p;
|
||||
|
||||
denom = (q2.y - q1.y) * (p2.x - p1.x) - (q2.x - q1.x) * (p2.y - p1.y);
|
||||
if (denom == 0.0)
|
||||
{
|
||||
p.x = (p1.x + p2.x + q1.x + q2.x) / 4;
|
||||
p.y = (p1.y + p2.y + q1.y + q2.y) / 4;
|
||||
}
|
||||
else
|
||||
{
|
||||
u = (q2.x - q1.x) * (p1.y - q1.y) - (q2.y - q1.y) * (p1.x - q1.x);
|
||||
u /= denom;
|
||||
|
||||
p.x = p1.x + u * (p2.x - p1.x);
|
||||
p.y = p1.y + u * (p2.y - p1.y);
|
||||
}
|
||||
|
||||
return p;
|
||||
}
|
||||
|
||||
static inline GimpVector2
|
||||
getpivotdelta (GimpTransformTool *tr_tool,
|
||||
GimpVector2 *oldpos,
|
||||
GimpVector2 *newpos,
|
||||
GimpVector2 pivot)
|
||||
{
|
||||
GimpMatrix3 transform_before, transform_after;
|
||||
GimpVector2 delta;
|
||||
|
||||
gimp_matrix3_identity (&transform_before);
|
||||
gimp_matrix3_identity (&transform_after);
|
||||
|
||||
gimp_transform_matrix_perspective (&transform_before,
|
||||
tr_tool->x1,
|
||||
tr_tool->y1,
|
||||
tr_tool->x2 - tr_tool->x1,
|
||||
tr_tool->y2 - tr_tool->y1,
|
||||
oldpos[0].x, oldpos[0].y,
|
||||
oldpos[1].x, oldpos[1].y,
|
||||
oldpos[2].x, oldpos[2].y,
|
||||
oldpos[3].x, oldpos[3].y);
|
||||
gimp_transform_matrix_perspective (&transform_after,
|
||||
tr_tool->x1,
|
||||
tr_tool->y1,
|
||||
tr_tool->x2 - tr_tool->x1,
|
||||
tr_tool->y2 - tr_tool->y1,
|
||||
newpos[0].x, newpos[0].y,
|
||||
newpos[1].x, newpos[1].y,
|
||||
newpos[2].x, newpos[2].y,
|
||||
newpos[3].x, newpos[3].y);
|
||||
gimp_matrix3_invert (&transform_before);
|
||||
gimp_matrix3_mult (&transform_after, &transform_before);
|
||||
gimp_matrix3_transform_point (&transform_before,
|
||||
pivot.x, pivot.y, &delta.x, &delta.y);
|
||||
|
||||
delta = vectorsubtract (delta, pivot);
|
||||
|
||||
return delta;
|
||||
}
|
||||
|
||||
static void
|
||||
gimp_unified_transform_tool_motion (GimpTransformTool *transform_tool)
|
||||
{
|
||||
|
|
Loading…
Reference in New Issue