Commit cc20cb41 authored by Ell's avatar Ell

app: add gimp_transform_polygon()

gimp_transform_polygon() transforms an (open or closed) polygon by
a GimpMatrix3, performing clipping to the near plane, to avoid
erroneously transforming points behind the camera.
parent 7dfe81f1
......@@ -27,6 +27,7 @@
#define EPSILON 1e-6
#define NEAR_Z 0.02
void
......@@ -506,3 +507,79 @@ gimp_transform_polygon_is_convex (gdouble x1,
return (z1 * z2 > 0) && (z3 * z4 > 0);
}
void
gimp_transform_polygon (const GimpMatrix3 *matrix,
const GimpVector2 *vertices,
gint n_vertices,
gboolean closed,
GimpVector2 *t_vertices,
gint *n_t_vertices)
{
GimpVector3 curr;
gboolean curr_visible;
gint i;
g_return_if_fail (matrix != NULL);
g_return_if_fail (vertices != NULL);
g_return_if_fail (n_vertices >= 0);
g_return_if_fail (t_vertices != NULL);
g_return_if_fail (n_t_vertices != NULL);
*n_t_vertices = 0;
if (n_vertices == 0)
return;
curr.x = matrix->coeff[0][0] * vertices[0].x +
matrix->coeff[0][1] * vertices[0].y +
matrix->coeff[0][2];
curr.y = matrix->coeff[1][0] * vertices[0].x +
matrix->coeff[1][1] * vertices[0].y +
matrix->coeff[1][2];
curr.z = matrix->coeff[2][0] * vertices[0].x +
matrix->coeff[2][1] * vertices[0].y +
matrix->coeff[2][2];
curr_visible = (curr.z >= NEAR_Z);
for (i = 0; i < n_vertices; i++)
{
if (curr_visible)
{
t_vertices[(*n_t_vertices)++] = (GimpVector2) { curr.x / curr.z,
curr.y / curr.z };
}
if (i < n_vertices - 1 || closed)
{
GimpVector3 next;
gboolean next_visible;
gint j = (i + 1) % n_vertices;
next.x = matrix->coeff[0][0] * vertices[j].x +
matrix->coeff[0][1] * vertices[j].y +
matrix->coeff[0][2];
next.y = matrix->coeff[1][0] * vertices[j].x +
matrix->coeff[1][1] * vertices[j].y +
matrix->coeff[1][2];
next.z = matrix->coeff[2][0] * vertices[j].x +
matrix->coeff[2][1] * vertices[j].y +
matrix->coeff[2][2];
next_visible = (next.z >= NEAR_Z);
if (next_visible != curr_visible)
{
gdouble ratio = (curr.z - NEAR_Z) / (curr.z - next.z);
t_vertices[(*n_t_vertices)++] =
(GimpVector2) { (curr.x + (next.x - curr.x) * ratio) / NEAR_Z,
(curr.y + (next.y - curr.y) * ratio) / NEAR_Z };
}
curr = next;
curr_visible = next_visible;
}
}
}
......@@ -98,5 +98,12 @@ gboolean gimp_transform_polygon_is_convex (gdouble x1,
gdouble x4,
gdouble y4);
void gimp_transform_polygon (const GimpMatrix3 *matrix,
const GimpVector2 *vertices,
gint n_vertices,
gboolean closed,
GimpVector2 *t_vertices,
gint *n_t_vertices);
#endif /* __GIMP_TRANSFORM_UTILS_H__ */
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment