[gimp/soc-2012-unified-transformation: 16/21] transformtool: Make perspective op behave as spec
- From: Mikael Magnusson <mikachu src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gimp/soc-2012-unified-transformation: 16/21] transformtool: Make perspective op behave as spec
- Date: Sat, 16 Jun 2012 12:41:03 +0000 (UTC)
commit eb0870cd8f25a5eda2007956f9190ddd9cb65126
Author: Mikael Magnusson <mikachu src gnome org>
Date: Fri Jun 15 09:11:48 2012 +0200
transformtool: Make perspective op behave as spec
app/tools/gimpunifiedtransformationtool.c | 99 ++++++++++++++++++++++++++++-
1 files changed, 98 insertions(+), 1 deletions(-)
---
diff --git a/app/tools/gimpunifiedtransformationtool.c b/app/tools/gimpunifiedtransformationtool.c
index e134f3d..36a7fda 100644
--- a/app/tools/gimpunifiedtransformationtool.c
+++ b/app/tools/gimpunifiedtransformationtool.c
@@ -710,6 +710,10 @@ static inline GimpVector2 scalemult(GimpVector2 a, gdouble 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, length = norm(a) * norm(b);
@@ -775,6 +779,7 @@ gimp_unified_transformation_tool_motion (GimpTransformTool *transform_tool)
ppivot_x = (*transform_tool->prev_trans_info)[PIVOT_X];
ppivot_y = (*transform_tool->prev_trans_info)[PIVOT_Y];
+ /* move */
if (function == TRANSFORM_HANDLE_CENTER)
{
gdouble dx = transform_tool->curx - transform_tool->mousex;
@@ -808,6 +813,7 @@ gimp_unified_transformation_tool_motion (GimpTransformTool *transform_tool)
return;
}
+ /* rotate */
if (function == TRANSFORM_HANDLE_ROTATION)
{
GimpVector2 m = { .x = transform_tool->curx, .y = transform_tool->cury };
@@ -830,6 +836,7 @@ gimp_unified_transformation_tool_motion (GimpTransformTool *transform_tool)
return;
}
+ /* move rotation axis */
if (function == TRANSFORM_HANDLE_PIVOT)
{
gdouble dx = transform_tool->curx - transform_tool->mousex;
@@ -840,7 +847,7 @@ gimp_unified_transformation_tool_motion (GimpTransformTool *transform_tool)
if (constrain)
{
/* snap to corner points and center */
- gint closest;
+ gint closest = 0;
gdouble closest_dist = G_MAXDOUBLE, dist;
for (i = 0; i < 5; i++)
{
@@ -867,6 +874,96 @@ gimp_unified_transformation_tool_motion (GimpTransformTool *transform_tool)
return;
}
+ if (function == TRANSFORM_HANDLE_NW ||
+ function == TRANSFORM_HANDLE_NE ||
+ function == TRANSFORM_HANDLE_SE ||
+ function == TRANSFORM_HANDLE_SW)
+ {
+ //TODO: scale through corner
+ }
+
+ if (function == TRANSFORM_HANDLE_N ||
+ function == TRANSFORM_HANDLE_E ||
+ function == TRANSFORM_HANDLE_S ||
+ function == TRANSFORM_HANDLE_W)
+ {
+ //TODO: scale through side
+ }
+
+ if (function == TRANSFORM_HANDLE_N_S ||
+ function == TRANSFORM_HANDLE_E_S ||
+ function == TRANSFORM_HANDLE_S_S ||
+ function == TRANSFORM_HANDLE_W_S)
+ {
+ //TODO: shear
+ }
+
+ /* perspective transform */
+ if (function == TRANSFORM_HANDLE_NW_P ||
+ function == TRANSFORM_HANDLE_NE_P ||
+ function == TRANSFORM_HANDLE_SE_P ||
+ function == TRANSFORM_HANDLE_SW_P)
+ {
+ gdouble dx = transform_tool->curx - transform_tool->mousex;
+ gdouble dy = transform_tool->cury - transform_tool->mousey;
+ gint this, left, right, opposite;
+
+ /* 1: northwest, 2: northeast, 3: southwest, 4: southeast */
+ if (function == TRANSFORM_HANDLE_NW_P) {
+ this = 0; left = 1; right = 2; opposite = 3;
+ } else if (function == TRANSFORM_HANDLE_NE_P) {
+ this = 1; left = 3; right = 0; opposite = 2;
+ } else if (function == TRANSFORM_HANDLE_SW_P) {
+ this = 2; left = 0; right = 3; opposite = 1;
+ } else if (function == TRANSFORM_HANDLE_SE_P) {
+ this = 3; left = 2; right = 1; opposite = 0;
+ } else g_assert_not_reached();
+
+ if (constrain)
+ { /* when the constrain transformation constraint is enabled, the
+ translation shall only be either along the side angles of the
+ two sides that run to this corner point, or along the
+ diagonal that runs trough this corner point. */
+
+ GimpVector2 l = { .x = px[left], .y = py[left] };
+ GimpVector2 r = { .x = px[right], .y = py[right] };
+ GimpVector2 o = { .x = px[opposite], .y = py[opposite] };
+ GimpVector2 t = { .x = px[this], .y = py[this] };
+ GimpVector2 p = { .x = dx, .y = dy };
+ GimpVector2 lp, rp, op;
+ gdouble rej_lp, rej_rp, rej_op;
+
+ /* get the vectors along the sides and the diagonal */
+ l = vectorsubtract(t, l);
+ r = vectorsubtract(t, r);
+ o = vectorsubtract(t, o);
+
+ /* project p on l, r and o and see which has the shortest rejection */
+ lp = vectorproject(p, l);
+ rp = vectorproject(p, r);
+ op = vectorproject(p, o);
+
+ rej_lp = norm(vectorsubtract(p, lp));
+ rej_rp = norm(vectorsubtract(p, rp));
+ rej_op = norm(vectorsubtract(p, op));
+
+ if (rej_lp < rej_rp && rej_lp < rej_op)
+ p = lp;
+ else if (rej_rp < rej_op)
+ p = rp;
+ else
+ p = op;
+
+ dx = p.x;
+ dy = p.y;
+ }
+
+ *x[this] = px[this] + dx;
+ *y[this] = py[this] + dy;
+
+ return;
+ }
+
if (options->alternate)
{
gdouble *x0, *x1, *y0, *y1;
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]