mirror of
https://gitlab.gnome.org/GNOME/gimp
synced 2024-10-21 12:02:32 +00:00
applied patch from Geert Jordaens that reimplements the algorithm to
2007-06-25 Sven Neumann <sven@gimp.org> * app/core/gimp-transform-resize.c: applied patch from Geert Jordaens that reimplements the algorithm to determine the largest rectangle. Fixes bug #412473. svn path=/trunk/; revision=22834
This commit is contained in:
parent
1cf291e593
commit
7aa01e3120
|
@ -1,3 +1,9 @@
|
|||
2007-06-25 Sven Neumann <sven@gimp.org>
|
||||
|
||||
* app/core/gimp-transform-resize.c: applied patch from Geert
|
||||
Jordaens that reimplements the algorithm to determine the largest
|
||||
rectangle. Fixes bug #412473.
|
||||
|
||||
2007-06-25 Sven Neumann <sven@gimp.org>
|
||||
|
||||
* configure.in: removed extra check for gthread and fold it into
|
||||
|
|
|
@ -36,25 +36,22 @@
|
|||
#else
|
||||
#error "no FINITE() implementation available?!"
|
||||
#endif
|
||||
|
||||
#define EPSILON 0.00000001
|
||||
#define MIN4(a,b,c,d) MIN(MIN((a),(b)),MIN((c),(d)))
|
||||
#define MAX4(a,b,c,d) MAX(MAX((a),(b)),MAX((c),(d)))
|
||||
|
||||
|
||||
typedef struct
|
||||
{
|
||||
gint x, y;
|
||||
gdouble x, y;
|
||||
} Point;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
gint xmin, xmax;
|
||||
gint ymin, ymax;
|
||||
gdouble m, b; /* y = mx + b */
|
||||
gboolean top, right;
|
||||
} Edge;
|
||||
|
||||
|
||||
Point a, b, c, d;
|
||||
gdouble area;
|
||||
gdouble aspect;
|
||||
} Rectangle;
|
||||
|
||||
static void gimp_transform_resize_adjust (gdouble dx1,
|
||||
gdouble dy1,
|
||||
|
@ -82,7 +79,45 @@ static void gimp_transform_resize_crop (gdouble dx1,
|
|||
gint *x2,
|
||||
gint *y2);
|
||||
|
||||
static void add_rectangle (Point points[4],
|
||||
Rectangle *r,
|
||||
Point a,
|
||||
Point b,
|
||||
Point c,
|
||||
Point d);
|
||||
static gboolean intersect (Point a,
|
||||
Point b,
|
||||
Point c,
|
||||
Point d,
|
||||
Point *i);
|
||||
static gboolean intersect_x (Point a,
|
||||
Point b,
|
||||
Point c,
|
||||
Point *i);
|
||||
static gboolean intersect_y (Point a,
|
||||
Point b,
|
||||
Point c,
|
||||
Point *i);
|
||||
static gboolean in_poly (Point points[4],
|
||||
Point p);
|
||||
static gboolean point_on_border (Point points[4],
|
||||
Point p);
|
||||
|
||||
static void find_two_point_rectangle (Rectangle *r,
|
||||
Point points[4],
|
||||
gint p);
|
||||
static void find_three_point_rectangle_corner (Rectangle *r,
|
||||
Point points[4],
|
||||
gint p);
|
||||
static void find_three_point_rectangle (Rectangle *r,
|
||||
Point points[4],
|
||||
gint p);
|
||||
static void find_three_point_rectangle_triangle (Rectangle *r,
|
||||
Point points[4],
|
||||
gint p);
|
||||
static void find_maximum_aspect_rectangle (Rectangle *r,
|
||||
Point points[4],
|
||||
gint p);
|
||||
/*
|
||||
* This function wants to be passed the inverse transformation matrix!!
|
||||
*/
|
||||
|
@ -179,84 +214,6 @@ gimp_transform_resize_adjust (gdouble dx1,
|
|||
*y2 = (gint) ceil (MAX4 (dy1, dy2, dy3, dy4));
|
||||
}
|
||||
|
||||
static void
|
||||
edge_init (Edge *edge,
|
||||
const Point *p,
|
||||
const Point *q)
|
||||
{
|
||||
gdouble den;
|
||||
|
||||
edge->xmin = MIN ((p->x), (q->x));
|
||||
edge->xmax = MAX ((p->x), (q->x));
|
||||
|
||||
edge->ymin = MIN ((p->y), (q->y));
|
||||
edge->ymax = MAX ((p->y), (q->y));
|
||||
|
||||
edge->top = p->x > q->x;
|
||||
edge->right = p->y > q->y;
|
||||
|
||||
den = q->x - p->x;
|
||||
|
||||
if (den == 0)
|
||||
den = 0.001;
|
||||
|
||||
edge->m = ((gdouble) q->y - p->y) / den;
|
||||
edge->b = p->y - edge->m * p->x;
|
||||
}
|
||||
|
||||
static const Edge *
|
||||
find_edge (const Edge *edges,
|
||||
gint x,
|
||||
gboolean top)
|
||||
{
|
||||
const Edge *emax = edges;
|
||||
const Edge *e = edges;
|
||||
gint i;
|
||||
|
||||
for (i = 0; i < 4; i++)
|
||||
{
|
||||
if ((e->xmin == x) && (e->xmax != e->xmin) &&
|
||||
((e->top && top) || (!e->top && !top)))
|
||||
emax = e;
|
||||
|
||||
e++;
|
||||
}
|
||||
|
||||
return emax;
|
||||
}
|
||||
|
||||
/* find largest pixel completely inside;
|
||||
* look through all edges for intersection
|
||||
*/
|
||||
static gint
|
||||
intersect_x (const Edge *edges,
|
||||
gint y)
|
||||
{
|
||||
gdouble x0 = 0;
|
||||
gdouble x1 = 0;
|
||||
gint i;
|
||||
|
||||
for (i = 0; i < 4; i++)
|
||||
if (edges[i].right && edges[i].ymin <= y && edges[i].ymax >= y)
|
||||
{
|
||||
x0 = (y + 0.5 - edges[i].b) / edges[i].m;
|
||||
x1 = (y - 0.5 - edges[i].b) / edges[i].m;
|
||||
}
|
||||
|
||||
return (gint) floor (MIN (x0, x1));
|
||||
}
|
||||
|
||||
static gint
|
||||
intersect_y (const Edge *edge,
|
||||
gint xi)
|
||||
{
|
||||
gdouble yfirst = edge->m * (xi - 0.5) + edge->b;
|
||||
gdouble ylast = edge->m * (xi + 0.5) + edge->b;
|
||||
|
||||
return (gint) (edge->top ?
|
||||
ceil (MAX (yfirst, ylast)) : floor (MIN (yfirst, ylast)));
|
||||
}
|
||||
|
||||
static void
|
||||
gimp_transform_resize_crop (gdouble dx1,
|
||||
gdouble dy1,
|
||||
|
@ -272,24 +229,11 @@ gimp_transform_resize_crop (gdouble dx1,
|
|||
gint *x2,
|
||||
gint *y2)
|
||||
{
|
||||
Point points[4];
|
||||
gint ax, ay;
|
||||
int min;
|
||||
gint tx, ty;
|
||||
|
||||
Edge edges[4];
|
||||
const Point *a;
|
||||
const Point *b;
|
||||
const Edge *top;
|
||||
const Edge *bottom;
|
||||
gint cxmin, cymin;
|
||||
gint cxmax, cymax;
|
||||
Point *xint;
|
||||
|
||||
gint ymin, ymax;
|
||||
gint maxarea = 0;
|
||||
gint xi;
|
||||
gint i;
|
||||
Point points[4];
|
||||
Rectangle r;
|
||||
gint ax, ay, tx, ty;
|
||||
gint i, j;
|
||||
gint min;
|
||||
|
||||
/* fill in the points array */
|
||||
points[0].x = floor (dx1);
|
||||
|
@ -310,6 +254,7 @@ gimp_transform_resize_crop (gdouble dx1,
|
|||
{
|
||||
if (points[i].x < ax)
|
||||
ax = points[i].x;
|
||||
|
||||
if (points[i].y < ay)
|
||||
ay = points[i].y;
|
||||
}
|
||||
|
@ -320,6 +265,8 @@ gimp_transform_resize_crop (gdouble dx1,
|
|||
points[i].y += (-ay) * 2;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* find the convex hull using Jarvis's March as the points are passed
|
||||
* in different orders due to gimp_matrix3_transform_point()
|
||||
*/
|
||||
|
@ -342,9 +289,8 @@ gimp_transform_resize_crop (gdouble dx1,
|
|||
|
||||
for (i = 1; i < 4; i++)
|
||||
{
|
||||
gdouble theta, theta_m = 2 * G_PI;
|
||||
gdouble theta_v = 0;
|
||||
gint j;
|
||||
gdouble theta, theta_m = 2.0 * G_PI;
|
||||
gdouble theta_v = 0;
|
||||
|
||||
min = 3;
|
||||
|
||||
|
@ -352,6 +298,7 @@ gimp_transform_resize_crop (gdouble dx1,
|
|||
{
|
||||
gdouble sy = points[j].y - points[i - 1].y;
|
||||
gdouble sx = points[j].x - points[i - 1].x;
|
||||
|
||||
theta = atan2 (sy, sx);
|
||||
|
||||
if ((theta < theta_m) &&
|
||||
|
@ -376,125 +323,461 @@ gimp_transform_resize_crop (gdouble dx1,
|
|||
|
||||
/* reverse the order of points */
|
||||
|
||||
tx = points[0].x; ty = points[0].y;
|
||||
points[0].x = points[3].x; points[0].y = points[3].y;
|
||||
points[3].x = tx; points[3].y = ty;
|
||||
tx = points[0].x;
|
||||
ty = points[0].y;
|
||||
|
||||
tx = points[1].x; ty = points[1].y;
|
||||
points[1].x = points[2].x; points[1].y = points[2].y;
|
||||
points[2].x = tx; points[2].y = ty;
|
||||
points[0].x = points[3].x;
|
||||
points[0].y = points[3].y;
|
||||
points[3].x = tx;
|
||||
points[3].y = ty;
|
||||
|
||||
tx = points[1].x;
|
||||
ty = points[1].y;
|
||||
|
||||
/* now, find the largest rectangle using the method described in
|
||||
* "Computing the Largest Inscribed Isothetic Rectangle" by
|
||||
* D. Hsu, J. Snoeyink, et al.
|
||||
*/
|
||||
points[1].x = points[2].x;
|
||||
points[1].y = points[2].y;
|
||||
points[2].x = tx;
|
||||
points[2].y = ty;
|
||||
|
||||
/* first create an array of edges */
|
||||
r.a.x = r.a.y = r.b.x = r.b.y = r.c.x = r.c.x = r.d.x = r.d.x = r.area = 0;
|
||||
r.aspect = aspect;
|
||||
|
||||
cxmin = cxmax = points[3].x;
|
||||
cymin = cymax = points[3].y;
|
||||
|
||||
for (i = 0, a = points + 3, b = points; i < 4; i++, a = b, b++)
|
||||
if (aspect != 0)
|
||||
{
|
||||
if (G_UNLIKELY (i == 0))
|
||||
for (i = 0; i < 4; i++)
|
||||
find_maximum_aspect_rectangle (&r, points, i);
|
||||
}
|
||||
else
|
||||
{
|
||||
for (i = 0; i < 4; i++)
|
||||
{
|
||||
cxmin = cxmax = a->x;
|
||||
cymin = cymax = a->y;
|
||||
find_three_point_rectangle (&r, points, i);
|
||||
find_three_point_rectangle_corner (&r, points, i);
|
||||
find_two_point_rectangle (&r, points, i);
|
||||
find_three_point_rectangle_triangle (&r, points, i);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (a->x < cxmin)
|
||||
cxmin = a->x;
|
||||
|
||||
if (a->x > cxmax)
|
||||
cxmax = a->x;
|
||||
|
||||
if (a->y < cymin)
|
||||
cymin = a->y;
|
||||
|
||||
if (a->y > cymax)
|
||||
cymax = a->y;
|
||||
}
|
||||
|
||||
edge_init (edges + i, a, b);
|
||||
}
|
||||
|
||||
xint = g_new (Point, cymax);
|
||||
|
||||
for (i = 0; i < cymax; i++)
|
||||
{
|
||||
xint[i].x = intersect_x (edges, i);
|
||||
xint[i].y = i;
|
||||
}
|
||||
|
||||
top = find_edge (edges, cxmin, TRUE);
|
||||
bottom = find_edge (edges, cxmin, FALSE);
|
||||
|
||||
for (xi = cxmin; xi < cxmax; xi++)
|
||||
{
|
||||
gint ylo, yhi;
|
||||
|
||||
ymin = intersect_y (top, xi);
|
||||
ymax = intersect_y (bottom, xi);
|
||||
|
||||
for (ylo = ymax; ylo > ymin; ylo--)
|
||||
{
|
||||
for (yhi = ymin; yhi < ymax; yhi++)
|
||||
{
|
||||
if (yhi > ylo)
|
||||
{
|
||||
gint xlo, xhi;
|
||||
gint xright;
|
||||
gint height, width, fixed_width;
|
||||
gint area;
|
||||
|
||||
xlo = xint[ylo].x;
|
||||
xhi = xint[yhi].x;
|
||||
|
||||
xright = MIN (xlo, xhi);
|
||||
|
||||
height = yhi - ylo;
|
||||
width = xright - xi;
|
||||
|
||||
if (aspect != 0)
|
||||
{
|
||||
fixed_width = (gint) ceil ((gdouble) height * aspect);
|
||||
|
||||
if (fixed_width <= width)
|
||||
width = fixed_width;
|
||||
else
|
||||
width = 0;
|
||||
}
|
||||
|
||||
area = width * height;
|
||||
|
||||
if (area > maxarea)
|
||||
{
|
||||
maxarea = area;
|
||||
|
||||
*x1 = xi;
|
||||
*y1 = ylo;
|
||||
*x2 = xi + width;
|
||||
*y2 = ylo + height;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (xi == top->xmax)
|
||||
top = find_edge (edges, xi, TRUE);
|
||||
|
||||
if (xi == bottom->xmax)
|
||||
bottom = find_edge (edges, xi, FALSE);
|
||||
}
|
||||
|
||||
g_free (xint);
|
||||
|
||||
/* translate back the vertices */
|
||||
*x1 = floor(r.a.x + 0.5);
|
||||
*y1 = floor(r.a.y + 0.5);
|
||||
*x2 = ceil(r.c.x - 0.5);
|
||||
*y2 = ceil(r.c.y - 0.5);
|
||||
|
||||
*x1 = *x1 - ((-ax) * 2);
|
||||
*y1 = *y1 - ((-ay) * 2);
|
||||
*x2 = *x2 - ((-ax) * 2);
|
||||
*y2 = *y2 - ((-ay) * 2);
|
||||
|
||||
}
|
||||
|
||||
static void
|
||||
find_three_point_rectangle (Rectangle *r,
|
||||
Point points[4],
|
||||
gint p)
|
||||
{
|
||||
Point a = points[p % 4]; /* 0 1 2 3 */
|
||||
Point b = points[(p + 1) % 4]; /* 1 2 3 0 */
|
||||
Point c = points[(p + 2) % 4]; /* 2 3 0 2 */
|
||||
Point d = points[(p + 3) % 4]; /* 3 0 1 1 */
|
||||
Point i1; /* intersection point */
|
||||
Point i2; /* intersection point */
|
||||
Point i3; /* intersection point */
|
||||
|
||||
if (intersect_x (b, c, a, &i1) &&
|
||||
intersect_y (c, d, i1, &i2) &&
|
||||
intersect_x (d, a, i2, &i3))
|
||||
add_rectangle (points, r, i3, i3, i1, i1);
|
||||
|
||||
if (intersect_y (b, c, a, &i1) &&
|
||||
intersect_x (c, d, i1, &i2) &&
|
||||
intersect_y (a, i1, i2, &i3))
|
||||
add_rectangle (points, r, i3, i3, i1, i2);
|
||||
|
||||
if (intersect_x (c, d, a, &i1) &&
|
||||
intersect_y (b, c, i1, &i2) &&
|
||||
intersect_x (a, i1, i2, &i3))
|
||||
add_rectangle (points, r, i3, i3, i1, i2);
|
||||
|
||||
if ( intersect_y (c, d, a, &i1) &&
|
||||
intersect_x (b, c, i1, &i2) &&
|
||||
intersect_y (a, i1, i2, &i3))
|
||||
add_rectangle (points, r, i3, i3, i1, i2);
|
||||
}
|
||||
|
||||
static void
|
||||
find_three_point_rectangle_corner (Rectangle *r,
|
||||
Point points[4],
|
||||
gint p)
|
||||
{
|
||||
Point a = points[p % 4]; /* 0 1 2 3 */
|
||||
Point b = points[(p + 1) % 4]; /* 1 2 3 0 */
|
||||
Point c = points[(p + 2) % 4]; /* 2 3 0 2 */
|
||||
Point d = points[(p + 3) % 4]; /* 3 0 1 1 */
|
||||
Point i1; /* intersection point */
|
||||
Point i2; /* intersection point */
|
||||
|
||||
if (intersect_x (b, c, a , &i1) &&
|
||||
intersect_y (c, d, i1, &i2))
|
||||
add_rectangle (points, r, a, a, i1, i2);
|
||||
|
||||
if (intersect_y (b, c, a , &i1) &&
|
||||
intersect_x (c, d, i1, &i2))
|
||||
add_rectangle (points, r, a, a, i1, i2);
|
||||
|
||||
if (intersect_x (c, d, a , &i1) &&
|
||||
intersect_y (b, c, i1, &i2))
|
||||
add_rectangle (points, r, a, a, i1, i2);
|
||||
|
||||
if (intersect_y (c, d, a , &i1) &&
|
||||
intersect_x (b, c, i1, &i2))
|
||||
add_rectangle (points, r, a, a, i1, i2);
|
||||
}
|
||||
|
||||
static void
|
||||
find_two_point_rectangle (Rectangle *r,
|
||||
Point points[4],
|
||||
gint p)
|
||||
{
|
||||
Point a = points[ p % 4]; /* 0 1 2 3 */
|
||||
Point b = points[(p + 1) % 4]; /* 1 2 3 0 */
|
||||
Point c = points[(p + 2) % 4]; /* 2 3 0 2 */
|
||||
Point d = points[(p + 3) % 4]; /* 2 3 0 2 */
|
||||
Point i1; /* intersection point */
|
||||
Point i2; /* intersection point */
|
||||
Point mid; /* Mid point */
|
||||
|
||||
add_rectangle (points, r, a, a, c, c);
|
||||
add_rectangle (points, r, b, b, d, d);
|
||||
|
||||
if (intersect_x (c, b, a, &i1) &&
|
||||
intersect_y (c, b, a, &i2))
|
||||
{
|
||||
mid.x = ( i1.x + i2.x ) / 2.0;
|
||||
mid.y = ( i1.y + i2.y ) / 2.0;
|
||||
|
||||
add_rectangle (points, r, a, a, mid, mid);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
find_three_point_rectangle_triangle (Rectangle *r,
|
||||
Point points[4],
|
||||
gint p)
|
||||
{
|
||||
Point a = points[p % 4]; /* 0 1 2 3 */
|
||||
Point b = points[(p + 1) % 4]; /* 1 2 3 0 */
|
||||
Point c = points[(p + 2) % 4]; /* 2 3 0 2 */
|
||||
Point d = points[(p + 3) % 4]; /* 3 0 1 1 */
|
||||
Point i1; /* intersection point */
|
||||
Point i2; /* intersection point */
|
||||
Point mid;
|
||||
|
||||
mid.x = (a.x + b.x) / 2.0;
|
||||
mid.y = (a.y + b.y) / 2.0;
|
||||
|
||||
if (intersect_x (b, c, mid, &i1) &&
|
||||
intersect_y (a, d, mid, &i2))
|
||||
add_rectangle (points, r, mid, mid, i1, i2);
|
||||
|
||||
if (intersect_y (b, c, mid, &i1) &&
|
||||
intersect_x (a, d, mid, &i2))
|
||||
add_rectangle (points, r, mid, mid, i1, i2);
|
||||
|
||||
if (intersect_x (a, d, mid, &i1) &&
|
||||
intersect_y (b, c, mid, &i2))
|
||||
add_rectangle (points, r, mid, mid, i1, i2);
|
||||
|
||||
if (intersect_y (a, d, mid, &i1) &&
|
||||
intersect_x (b, c, mid, &i2))
|
||||
add_rectangle (points, r, mid, mid, i1, i2);
|
||||
}
|
||||
|
||||
static void
|
||||
find_maximum_aspect_rectangle (Rectangle *r,
|
||||
Point points[4],
|
||||
gint p)
|
||||
{
|
||||
Point a = points[ p % 4]; /* 0 1 2 3 */
|
||||
Point b = points[(p + 1) % 4]; /* 1 2 3 0 */
|
||||
Point c = points[(p + 2) % 4]; /* 2 3 0 2 */
|
||||
Point d = points[(p + 3) % 4]; /* 2 3 0 2 */
|
||||
Point i1; /* intersection point */
|
||||
Point i2; /* intersection point */
|
||||
Point i3; /* intersection point */
|
||||
|
||||
if (intersect_x (b, c, a, &i1))
|
||||
{
|
||||
i2.x = i1.x + 1.0 * r->aspect;
|
||||
i2.y = i1.y + 1.0;
|
||||
|
||||
if (intersect (d, a, i1, i2, &i3))
|
||||
add_rectangle (points, r, i1, i3, i1, i3);
|
||||
|
||||
if (intersect (a, b, i1, i2, &i3))
|
||||
add_rectangle (points, r, i1, i3, i1, i3);
|
||||
|
||||
if (intersect (c, d, i1, i2, &i3))
|
||||
add_rectangle (points, r, i1, i3, i1, i3);
|
||||
}
|
||||
|
||||
if (intersect_x (b, c, a, &i1))
|
||||
{
|
||||
i2.x = i1.x - 1.0 * r->aspect;
|
||||
i2.y = i1.y + 1.0;
|
||||
|
||||
if (intersect (d, a, i1, i2, &i3))
|
||||
add_rectangle (points, r, i1, i3, i1, i3);
|
||||
|
||||
if (intersect (a, b, i1, i2, &i3))
|
||||
add_rectangle (points, r, i1, i3, i1, i3);
|
||||
|
||||
if (intersect (c, d, i1, i2, &i3))
|
||||
add_rectangle (points, r, i1, i3, i1, i3);
|
||||
}
|
||||
|
||||
if (intersect_x (c, d, a, &i1))
|
||||
{
|
||||
i2.x = i1.x + 1.0 * r->aspect;
|
||||
i2.y = i1.y + 1.0;
|
||||
|
||||
if (intersect (d, a, i1, i2, &i3))
|
||||
add_rectangle (points, r, i1, i3, i1, i3);
|
||||
|
||||
if (intersect (a, b, i1, i2, &i3))
|
||||
add_rectangle (points, r, i1, i3, i1, i3);
|
||||
|
||||
if (intersect (b, c, i1, i2, &i3))
|
||||
add_rectangle (points, r, i1, i3, i1, i3);
|
||||
}
|
||||
|
||||
if (intersect_x (c, d, a, &i1))
|
||||
{
|
||||
i2.x = i1.x - 1.0 * r->aspect;
|
||||
i2.y = i1.y + 1.0;
|
||||
|
||||
if (intersect (d, a, i1, i2, &i3))
|
||||
add_rectangle (points, r, i1, i3, i1, i3);
|
||||
|
||||
if (intersect (a, b, i1, i2, &i3))
|
||||
add_rectangle (points, r, i1, i3, i1, i3);
|
||||
|
||||
if (intersect (b, c, i1, i2, &i3))
|
||||
add_rectangle (points, r, i1, i3, i1, i3);
|
||||
}
|
||||
}
|
||||
|
||||
static gboolean
|
||||
in_poly (Point points[4],
|
||||
Point p)
|
||||
{
|
||||
Point p1, p2;
|
||||
gint counter = 0;
|
||||
gint i;
|
||||
|
||||
p1 = points[0];
|
||||
|
||||
for (i = 1; i <= 4; i++)
|
||||
{
|
||||
p2 = points[i % 4];
|
||||
|
||||
if (p.y > MIN (p1.y, p2.y))
|
||||
{
|
||||
if (p.y <= MAX (p1.y, p2.y))
|
||||
{
|
||||
if (p.x <= MAX (p1.x, p2.x))
|
||||
{
|
||||
if (p1.y != p2.y)
|
||||
{
|
||||
gdouble xinters = ((p.y - p1.y) * (p2.x - p1.x) /
|
||||
(p2.y - p1.y) + p1.x);
|
||||
|
||||
if (p1.x == p2.x || p.x <= xinters)
|
||||
counter++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
p1 = p2;
|
||||
}
|
||||
|
||||
/* border check */
|
||||
if (point_on_border (points, p))
|
||||
return TRUE;
|
||||
|
||||
return (counter % 2 != 0);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
point_on_border (Point points[4],
|
||||
Point p)
|
||||
{
|
||||
gint i;
|
||||
|
||||
for (i = 0; i <= 4; i++)
|
||||
{
|
||||
Point a = points[i % 4];
|
||||
Point b = points[(i + 1) % 4];
|
||||
gdouble a1 = (b.y - a.y);
|
||||
gdouble b1 = (a.x - b.x);
|
||||
gdouble c1 = a1 * a.x + b1 * a.y;
|
||||
gdouble c2 = a1 * p.x + b1 * p.y;
|
||||
|
||||
if (ABS (c1 - c2) < EPSILON &&
|
||||
MIN (a.x, b.x) <= p.x &&
|
||||
MAX (a.x, b.x) >= p.x &&
|
||||
MIN (a.y, b.y) <= p.y &&
|
||||
MAX (a.y, b.y) >= p.y)
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
intersect (Point a,
|
||||
Point b,
|
||||
Point c,
|
||||
Point d,
|
||||
Point *i)
|
||||
{
|
||||
gdouble a1 = (b.y - a.y);
|
||||
gdouble b1 = (a.x - b.x);
|
||||
gdouble c1 = a1 * a.x + b1 * a.y;
|
||||
|
||||
gdouble a2 = (d.y - c.y);
|
||||
gdouble b2 = (c.x - d.x);
|
||||
gdouble c2 = a2 * c.x + b2 * c.y;
|
||||
gdouble det = a1*b2 - a2*b1;
|
||||
|
||||
if (det == 0)
|
||||
return FALSE;
|
||||
|
||||
i->x = (b2*c1 - b1*c2) / det;
|
||||
i->y = (a1*c2 - a2*c1) / det;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
intersect_x (Point a,
|
||||
Point b,
|
||||
Point c,
|
||||
Point *i)
|
||||
{
|
||||
gdouble a1, b1, c1;
|
||||
gdouble a2, b2, c2;
|
||||
gdouble det;
|
||||
Point d = c;
|
||||
|
||||
d.y += 1;
|
||||
a1 = (b.y - a.y);
|
||||
b1 = (a.x - b.x);
|
||||
c1 = a1 * a.x + b1 * a.y;
|
||||
|
||||
a2 = (d.y - c.y);
|
||||
b2 = (c.x - d.x);
|
||||
c2 = a2 * c.x + b2 * c.y;
|
||||
det = a1*b2 - a2*b1;
|
||||
|
||||
if (det == 0)
|
||||
return FALSE;
|
||||
|
||||
i->x = (b2*c1 - b1*c2) / det;
|
||||
i->y = (a1*c2 - a2*c1) / det;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
intersect_y (Point a,
|
||||
Point b,
|
||||
Point c,
|
||||
Point *i)
|
||||
{
|
||||
gdouble a1, b1, c1, a2, b2, c2;
|
||||
gdouble det;
|
||||
Point d = c;
|
||||
|
||||
d.x += 1;
|
||||
|
||||
a1 = (b.y - a.y);
|
||||
b1 = (a.x - b.x);
|
||||
c1 = a1 * a.x + b1 * a.y;
|
||||
|
||||
a2 = (d.y - c.y);
|
||||
b2 = (c.x - d.x);
|
||||
c2 = a2 * c.x + b2 * c.y;
|
||||
det = a1*b2 - a2*b1;
|
||||
|
||||
if (det == 0)
|
||||
return FALSE;
|
||||
|
||||
i->x = (b2*c1 - b1*c2) / det;
|
||||
i->y = (a1*c2 - a2*c1) / det;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static void
|
||||
add_rectangle (Point points[4],
|
||||
Rectangle *r,
|
||||
Point a,
|
||||
Point b,
|
||||
Point c,
|
||||
Point d)
|
||||
{
|
||||
gdouble width;
|
||||
gdouble height;
|
||||
gdouble minx, maxx;
|
||||
gdouble miny, maxy;
|
||||
gint i;
|
||||
|
||||
minx = MIN4(a.x,b.x,c.x,d.x);
|
||||
maxx = MAX4(a.x,b.x,c.x,d.x);
|
||||
miny = MIN4(a.y,b.y,c.y,d.y);
|
||||
maxy = MAX4(a.y,b.y,c.y,d.y);
|
||||
|
||||
a.x = minx;
|
||||
a.y = miny;
|
||||
|
||||
b.x = maxx;
|
||||
b.y = miny;
|
||||
|
||||
c.x = maxx;
|
||||
c.y = maxy;
|
||||
|
||||
d.x = minx;
|
||||
d.y = maxy;
|
||||
|
||||
width = maxx - minx;
|
||||
height = maxy - miny;
|
||||
|
||||
for ( i = 0 ; i < 4 ; i++)
|
||||
{
|
||||
if (in_poly(points, a) &&
|
||||
in_poly(points, b) &&
|
||||
in_poly(points, c) &&
|
||||
in_poly(points, d))
|
||||
{
|
||||
gdouble area = width * height;
|
||||
|
||||
if (r->area <= area)
|
||||
{
|
||||
r->a.x = a.x;
|
||||
r->a.y = a.y;
|
||||
|
||||
r->b.x = b.x;
|
||||
r->b.y = b.y;
|
||||
|
||||
r->c.x = c.x;
|
||||
r->c.y = c.y;
|
||||
|
||||
r->d.x = d.x;
|
||||
r->d.y = d.y;
|
||||
|
||||
r->area = area;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue