diff options
Diffstat (limited to 'libart_lgpl/art_svp_intersect.c')
-rw-r--r-- | libart_lgpl/art_svp_intersect.c | 239 |
1 files changed, 102 insertions, 137 deletions
diff --git a/libart_lgpl/art_svp_intersect.c b/libart_lgpl/art_svp_intersect.c index 470c16e7ff..f79216c13a 100644 --- a/libart_lgpl/art_svp_intersect.c +++ b/libart_lgpl/art_svp_intersect.c @@ -35,8 +35,6 @@ should not be necessary. */ #define CHEAP_SANITYCHECK -#define noVERBOSE - #include "art_misc.h" /* A priority queue - perhaps move to a separate file if it becomes @@ -48,15 +46,15 @@ typedef struct _ArtPriQ ArtPriQ; typedef struct _ArtPriPoint ArtPriPoint; struct _ArtPriQ { - int n_items; - int n_items_max; + gint n_items; + gint n_items_max; ArtPriPoint **items; }; struct _ArtPriPoint { - double x; - double y; - void *user_data; + gdouble x; + gdouble y; + gpointer user_data; }; static ArtPriQ * @@ -89,10 +87,10 @@ art_pri_empty (ArtPriQ *pq) http://www.cs.rutgers.edu/~chvatal/notes/pq.html#heap */ static void -art_pri_bubble_up (ArtPriQ *pq, int vacant, ArtPriPoint *missing) +art_pri_bubble_up (ArtPriQ *pq, gint vacant, ArtPriPoint *missing) { ArtPriPoint **items = pq->items; - int parent; + gint parent; parent = (vacant - 1) >> 1; while (vacant > 0 && (missing->y < items[parent]->y || @@ -120,8 +118,8 @@ static void art_pri_sift_down_from_root (ArtPriQ *pq, ArtPriPoint *missing) { ArtPriPoint **items = pq->items; - int vacant = 0, child = 2; - int n = pq->n_items; + gint vacant = 0, child = 2; + gint n = pq->n_items; while (child < n) { @@ -157,10 +155,10 @@ art_pri_choose (ArtPriQ *pq) static ArtPriPoint * art_pri_choose (ArtPriQ *pq) { - int i; - int best = 0; - double best_x, best_y; - double y; + gint i; + gint best = 0; + gdouble best_x, best_y; + gdouble y; ArtPriPoint *result; if (pq->n_items == 0) @@ -201,9 +199,9 @@ art_pri_insert (ArtPriQ *pq, ArtPriPoint *point) #include <stdio.h> static double -double_rand (double lo, double hi, int quant) +double_rand (gdouble lo, gdouble hi, gint quant) { - int tmp = rand () / (RAND_MAX * (1.0 / quant)) + 0.5; + gint tmp = rand () / (RAND_MAX * (1.0 / quant)) + 0.5; return lo + tmp * ((hi - lo) / quant); } @@ -256,14 +254,14 @@ art_pri_pt_pool_free (ArtPriPtPool *pool) art_free (pool); } -int -main (int argc, char **argv) +gint +main (gint argc, gchar **argv) { ArtPriPtPool *pool = art_pri_pt_pool_new (); ArtPriQ *pq; - int i, j; - const int n_iter = 1; - const int pq_size = 100; + gint i, j; + const gint n_iter = 1; + const gint pq_size = 100; for (j = 0; j < n_iter; j++) { @@ -274,7 +272,7 @@ main (int argc, char **argv) ArtPriPoint *pt = art_pri_pt_alloc (pool); pt->x = double_rand (0, 1, 100); pt->y = double_rand (0, 1, 100); - pt->user_data = (void *)i; + pt->user_data = (gpointer)i; art_pri_insert (pq, pt); } @@ -282,7 +280,7 @@ main (int argc, char **argv) { ArtPriPoint *pt = art_pri_choose (pq); if (n_iter == 1) - printf ("(%g, %g), %d\n", pt->x, pt->y, (int)pt->user_data); + printf ("(%g, %g), %d\n", pt->x, pt->y, (gint)pt->user_data); art_pri_pt_free (pool, pt); } @@ -307,21 +305,21 @@ struct _ArtSvpWriterRewind { ArtSvpWriter super; ArtWindRule rule; ArtSVP *svp; - int n_segs_max; - int *n_points_max; + gint n_segs_max; + gint *n_points_max; }; -static int -art_svp_writer_rewind_add_segment (ArtSvpWriter *self, int wind_left, - int delta_wind, double x, double y) +static gint +art_svp_writer_rewind_add_segment (ArtSvpWriter *self, gint wind_left, + gint delta_wind, gdouble x, gdouble y) { ArtSvpWriterRewind *swr = (ArtSvpWriterRewind *)self; ArtSVP *svp; ArtSVPSeg *seg; art_boolean left_filled, right_filled; - int wind_right = wind_left + delta_wind; - int seg_num; - const int init_n_points_max = 4; + gint wind_right = wind_left + delta_wind; + gint seg_num; + const gint init_n_points_max = 4; switch (swr->rule) { @@ -377,12 +375,12 @@ art_svp_writer_rewind_add_segment (ArtSvpWriter *self, int wind_left, } static void -art_svp_writer_rewind_add_point (ArtSvpWriter *self, int seg_id, - double x, double y) +art_svp_writer_rewind_add_point (ArtSvpWriter *self, gint seg_id, + gdouble x, gdouble y) { ArtSvpWriterRewind *swr = (ArtSvpWriterRewind *)self; ArtSVPSeg *seg; - int n_points; + gint n_points; if (seg_id < 0) /* omitted segment */ @@ -402,7 +400,7 @@ art_svp_writer_rewind_add_point (ArtSvpWriter *self, int seg_id, } static void -art_svp_writer_rewind_close_segment (ArtSvpWriter *self, int seg_id) +art_svp_writer_rewind_close_segment (ArtSvpWriter *self, gint seg_id) { /* Not needed for this simple implementation. A potential future optimization is to merge segments that can be merged safely. */ @@ -443,7 +441,7 @@ art_svp_writer_rewind_new (ArtWindRule rule) result->rule = rule; result->n_segs_max = 16; - result->svp = art_alloc (sizeof(ArtSVP) + + result->svp = art_alloc (sizeof(ArtSVP) + (result->n_segs_max - 1) * sizeof(ArtSVPSeg)); result->svp->n_segs = 0; result->n_points_max = art_new (int, result->n_segs_max); @@ -474,28 +472,28 @@ typedef struct _ArtActiveSeg ArtActiveSeg; #define ART_ACTIVE_FLAGS_IN_HORIZ 16 struct _ArtActiveSeg { - int flags; - int wind_left, delta_wind; + gint flags; + gint wind_left, delta_wind; ArtActiveSeg *left, *right; /* doubly linked list structure */ const ArtSVPSeg *in_seg; - int in_curs; + gint in_curs; - double x[2]; - double y0, y1; - double a, b, c; /* line equation; ax+by+c = 0 for the line, a^2 + b^2 = 1, + gdouble x[2]; + gdouble y0, y1; + gdouble a, b, c; /* line equation; ax+by+c = 0 for the line, a^2 + b^2 = 1, and a>0 */ /* bottom point and intersection point stack */ - int n_stack; - int n_stack_max; + gint n_stack; + gint n_stack_max; ArtPoint *stack; /* horiz commit list */ ArtActiveSeg *horiz_left, *horiz_right; - double horiz_x; - int horiz_delta_wind; - int seg_id; + gdouble horiz_x; + gint horiz_delta_wind; + gint seg_id; }; typedef struct _ArtIntersectCtx ArtIntersectCtx; @@ -508,12 +506,12 @@ struct _ArtIntersectCtx { ArtActiveSeg *active_head; - double y; + gdouble y; ArtActiveSeg *horiz_first; ArtActiveSeg *horiz_last; /* segment index of next input segment to be added to pri q */ - int in_curs; + gint in_curs; }; #define EPSILON_A 1e-5 /* Threshold for breaking lines at point insertions */ @@ -532,10 +530,10 @@ static void art_svp_intersect_setup_seg (ArtActiveSeg *seg, ArtPriPoint *pri_pt) { const ArtSVPSeg *in_seg = seg->in_seg; - int in_curs = seg->in_curs++; - double x0, y0, x1, y1; - double dx, dy, s; - double a, b, r2; + gint in_curs = seg->in_curs++; + gdouble x0, y0, x1, y1; + gdouble dx, dy, s; + gdouble a, b, r2; x0 = in_seg->points[in_curs].x; y0 = in_seg->points[in_curs].y; @@ -582,7 +580,6 @@ art_svp_intersect_add_horiz (ArtIntersectCtx *ctx, ArtActiveSeg *seg) ArtActiveSeg *place; ArtActiveSeg *place_right = NULL; - #ifdef CHEAP_SANITYCHECK if (seg->flags & ART_ACTIVE_FLAGS_IN_HORIZ) { @@ -611,10 +608,10 @@ art_svp_intersect_add_horiz (ArtIntersectCtx *ctx, ArtActiveSeg *seg) static void art_svp_intersect_push_pt (ArtIntersectCtx *ctx, ArtActiveSeg *seg, - double x, double y) + gdouble x, gdouble y) { ArtPriPoint *pri_pt; - int n_stack = seg->n_stack; + gint n_stack = seg->n_stack; if (n_stack == seg->n_stack_max) art_expand (seg->stack, ArtPoint, seg->n_stack_max); @@ -647,12 +644,12 @@ typedef enum { */ static double art_svp_intersect_break (ArtIntersectCtx *ctx, ArtActiveSeg *seg, - double x_ref, double y, ArtBreakFlags break_flags) + gdouble x_ref, gdouble y, ArtBreakFlags break_flags) { - double x0, y0, x1, y1; + gdouble x0, y0, x1, y1; const ArtSVPSeg *in_seg = seg->in_seg; - int in_curs = seg->in_curs; - double x; + gint in_curs = seg->in_curs; + gdouble x; x0 = in_seg->points[in_curs - 1].x; y0 = in_seg->points[in_curs - 1].y; @@ -691,22 +688,22 @@ art_svp_intersect_break (ArtIntersectCtx *ctx, ArtActiveSeg *seg, * NULL if the new point is leftmost. **/ static ArtActiveSeg * -art_svp_intersect_add_point (ArtIntersectCtx *ctx, double x, double y, +art_svp_intersect_add_point (ArtIntersectCtx *ctx, gdouble x, gdouble y, ArtActiveSeg *seg, ArtBreakFlags break_flags) { ArtActiveSeg *left, *right; - double x_min = x, x_max = x; + gdouble x_min = x, x_max = x; art_boolean left_live, right_live; - double d; - double new_x; + gdouble d; + gdouble new_x; ArtActiveSeg *test, *result = NULL; - double x_test; + gdouble x_test; left = seg; if (left == NULL) right = ctx->active_head; else - right = left->right; + right = left->right; left_live = (break_flags & ART_BREAK_LEFT) && (left != NULL); right_live = (break_flags & ART_BREAK_RIGHT) && (right != NULL); while (left_live || right_live) @@ -834,16 +831,15 @@ art_svp_intersect_test_cross (ArtIntersectCtx *ctx, ArtActiveSeg *left_seg, ArtActiveSeg *right_seg, ArtBreakFlags break_flags) { - double left_x0, left_y0, left_x1; - double left_y1 = left_seg->y1; - double right_y1 = right_seg->y1; - double d; + gdouble left_x0, left_y0, left_x1; + gdouble left_y1 = left_seg->y1; + gdouble right_y1 = right_seg->y1; + gdouble d; const ArtSVPSeg *in_seg; - int in_curs; - double d0, d1, t; - double x, y; /* intersection point */ - + gint in_curs; + gdouble d0, d1, t; + gdouble x, y; /* intersection point */ if (left_seg->y0 == right_seg->y0 && left_seg->x[0] == right_seg->x[0]) { @@ -855,7 +851,7 @@ art_svp_intersect_test_cross (ArtIntersectCtx *ctx, if (left_y1 < right_y1) { /* Test left (x1, y1) against right segment */ - double left_x1 = left_seg->x[1]; + gdouble left_x1 = left_seg->x[1]; if (left_x1 < right_seg->x[(right_seg->flags & ART_ACTIVE_FLAGS_BNEG) ^ 1] || @@ -867,7 +863,7 @@ art_svp_intersect_test_cross (ArtIntersectCtx *ctx, else if (d < EPSILON_A) { /* I'm unsure about the break flags here. */ - double right_x1 = art_svp_intersect_break (ctx, right_seg, + gdouble right_x1 = art_svp_intersect_break (ctx, right_seg, left_x1, left_y1, ART_BREAK_RIGHT); if (left_x1 <= right_x1) @@ -877,7 +873,7 @@ art_svp_intersect_test_cross (ArtIntersectCtx *ctx, else if (left_y1 > right_y1) { /* Test right (x1, y1) against left segment */ - double right_x1 = right_seg->x[1]; + gdouble right_x1 = right_seg->x[1]; if (right_x1 > left_seg->x[left_seg->flags & ART_ACTIVE_FLAGS_BNEG] || right_y1 == left_seg->y0) @@ -888,7 +884,7 @@ art_svp_intersect_test_cross (ArtIntersectCtx *ctx, else if (d > -EPSILON_A) { /* See above regarding break flags. */ - double left_x1 = art_svp_intersect_break (ctx, left_seg, + gdouble left_x1 = art_svp_intersect_break (ctx, left_seg, right_x1, right_y1, ART_BREAK_LEFT); if (left_x1 <= right_x1) @@ -897,8 +893,8 @@ art_svp_intersect_test_cross (ArtIntersectCtx *ctx, } else /* left_y1 == right_y1 */ { - double left_x1 = left_seg->x[1]; - double right_x1 = right_seg->x[1]; + gdouble left_x1 = left_seg->x[1]; + gdouble right_x1 = right_seg->x[1]; if (left_x1 <= right_x1) return ART_FALSE; @@ -910,7 +906,7 @@ art_svp_intersect_test_cross (ArtIntersectCtx *ctx, if (left_y1 < right_y1) { /* Test left (x1, y1) against right segment */ - double left_x1 = left_seg->x[1]; + gdouble left_x1 = left_seg->x[1]; if (left_x1 < right_seg->x[(right_seg->flags & ART_ACTIVE_FLAGS_BNEG) ^ 1] || @@ -921,7 +917,7 @@ art_svp_intersect_test_cross (ArtIntersectCtx *ctx, return ART_FALSE; else if (d < EPSILON_A) { - double right_x1 = art_svp_intersect_break (ctx, right_seg, + gdouble right_x1 = art_svp_intersect_break (ctx, right_seg, left_x1, left_y1, ART_BREAK_RIGHT); if (left_x1 <= right_x1) @@ -931,7 +927,7 @@ art_svp_intersect_test_cross (ArtIntersectCtx *ctx, else if (left_y1 > right_y1) { /* Test right (x1, y1) against left segment */ - double right_x1 = right_seg->x[1]; + gdouble right_x1 = right_seg->x[1]; if (right_x1 > left_seg->x[left_seg->flags & ART_ACTIVE_FLAGS_BNEG] || right_y1 == left_seg->y0) @@ -941,7 +937,7 @@ art_svp_intersect_test_cross (ArtIntersectCtx *ctx, return ART_FALSE; else if (d > -EPSILON_A) { - double left_x1 = art_svp_intersect_break (ctx, left_seg, + gdouble left_x1 = art_svp_intersect_break (ctx, left_seg, right_x1, right_y1, ART_BREAK_LEFT); if (left_x1 <= right_x1) @@ -949,9 +945,9 @@ art_svp_intersect_test_cross (ArtIntersectCtx *ctx, } } else /* left_y1 == right_y1 */ - { - double left_x1 = left_seg->x[1]; - double right_x1 = right_seg->x[1]; + { + gdouble left_x1 = left_seg->x[1]; + gdouble right_x1 = right_seg->x[1]; if (left_x1 <= right_x1) return ART_FALSE; @@ -1168,7 +1164,7 @@ art_svp_intersect_insert_cross (ArtIntersectCtx *ctx, **/ static void art_svp_intersect_horiz (ArtIntersectCtx *ctx, ArtActiveSeg *seg, - double x0, double x1) + gdouble x0, gdouble x1) { ArtActiveSeg *hs; @@ -1209,7 +1205,7 @@ art_svp_intersect_horiz (ArtIntersectCtx *ctx, ArtActiveSeg *seg, for (left = seg->left; left != NULL; left = seg->left) { - int left_bneg = left->flags & ART_ACTIVE_FLAGS_BNEG; + gint left_bneg = left->flags & ART_ACTIVE_FLAGS_BNEG; if (left->x[left_bneg] <= x1) break; @@ -1236,7 +1232,7 @@ art_svp_intersect_horiz (ArtIntersectCtx *ctx, ArtActiveSeg *seg, for (right = seg->right; right != NULL; right = seg->right) { - int right_bneg = right->flags & ART_ACTIVE_FLAGS_BNEG; + gint right_bneg = right->flags & ART_ACTIVE_FLAGS_BNEG; if (right->x[right_bneg ^ 1] >= x1) break; @@ -1291,7 +1287,7 @@ static void art_svp_intersect_process_intersection (ArtIntersectCtx *ctx, ArtActiveSeg *seg) { - int n_stack = --seg->n_stack; + gint n_stack = --seg->n_stack; seg->x[1] = seg->stack[n_stack - 1].x; seg->y1 = seg->stack[n_stack - 1].y; seg->x[0] = seg->stack[n_stack].x; @@ -1305,7 +1301,7 @@ art_svp_intersect_advance_cursor (ArtIntersectCtx *ctx, ArtActiveSeg *seg, ArtPriPoint *pri_pt) { const ArtSVPSeg *in_seg = seg->in_seg; - int in_curs = seg->in_curs; + gint in_curs = seg->in_curs; ArtSvpWriter *swr = seg->flags & ART_ACTIVE_FLAGS_OUT ? ctx->out : NULL; if (swr != NULL) @@ -1342,7 +1338,7 @@ art_svp_intersect_add_seg (ArtIntersectCtx *ctx, const ArtSVPSeg *in_seg) { ArtActiveSeg *seg = art_new (ArtActiveSeg, 1); ArtActiveSeg *test; - double x0, y0; + gdouble x0, y0; ArtActiveSeg *beg_range; ArtActiveSeg *last = NULL; ArtActiveSeg *left, *right; @@ -1356,7 +1352,7 @@ art_svp_intersect_add_seg (ArtIntersectCtx *ctx, const ArtSVPSeg *in_seg) seg->stack = art_new (ArtPoint, seg->n_stack_max); seg->horiz_delta_wind = 0; - + seg->wind_left = 0; pri_pt->user_data = seg; @@ -1372,8 +1368,8 @@ art_svp_intersect_add_seg (ArtIntersectCtx *ctx, const ArtSVPSeg *in_seg) beg_range = NULL; for (test = ctx->active_head; test != NULL; test = test->right) { - double d; - int test_bneg = test->flags & ART_ACTIVE_FLAGS_BNEG; + gdouble d; + gint test_bneg = test->flags & ART_ACTIVE_FLAGS_BNEG; if (x0 < test->x[test_bneg]) { @@ -1386,7 +1382,8 @@ art_svp_intersect_add_seg (ArtIntersectCtx *ctx, const ArtSVPSeg *in_seg) last = test; } - left = art_svp_intersect_add_point (ctx, x0, y0, last, ART_BREAK_LEFT | ART_BREAK_RIGHT); + left = art_svp_intersect_add_point (ctx, x0, y0, last, + ART_BREAK_LEFT | ART_BREAK_RIGHT); seg->left = left; if (left == NULL) { @@ -1408,35 +1405,6 @@ art_svp_intersect_add_seg (ArtIntersectCtx *ctx, const ArtSVPSeg *in_seg) art_svp_intersect_insert_line (ctx, seg); } -#ifdef SANITYCHECK -static void -art_svp_intersect_sanitycheck_winding (ArtIntersectCtx *ctx) -{ -#if 0 - /* At this point, we seem to be getting false positives, so it's - turned off for now. */ - - ArtActiveSeg *seg; - int winding_number = 0; - - for (seg = ctx->active_head; seg != NULL; seg = seg->right) - { - /* Check winding number consistency. */ - if (seg->flags & ART_ACTIVE_FLAGS_OUT) - { - if (winding_number != seg->wind_left) - art_warn ("*** art_svp_intersect_sanitycheck_winding: seg %lx has wind_left of %d, expected %d\n", - (unsigned long) seg, seg->wind_left, winding_number); - winding_number = seg->wind_left + seg->delta_wind; - } - } - if (winding_number != 0) - art_warn ("*** art_svp_intersect_sanitycheck_winding: non-balanced winding number %d\n", - winding_number); -#endif -} -#endif - /** * art_svp_intersect_horiz_commit: Commit points in horiz list to output. * @ctx: Intersection context. @@ -1457,22 +1425,22 @@ static void art_svp_intersect_horiz_commit (ArtIntersectCtx *ctx) { ArtActiveSeg *seg; - int winding_number = 0; /* initialization just to avoid warning */ - int horiz_wind = 0; - double last_x = 0; /* initialization just to avoid warning */ + gint winding_number = 0; /* initialization just to avoid warning */ + gint horiz_wind = 0; + gdouble last_x = 0; /* initialization just to avoid warning */ /* Output points to svp writer. */ for (seg = ctx->horiz_first; seg != NULL;) { /* Find a cluster with common horiz_x, */ ArtActiveSeg *curs; - double x = seg->horiz_x; + gdouble x = seg->horiz_x; /* Generate any horizontal segments. */ if (horiz_wind != 0) { ArtSvpWriter *swr = ctx->out; - int seg_id; + gint seg_id; seg_id = swr->add_segment (swr, winding_number, horiz_wind, last_x, ctx->y); @@ -1552,9 +1520,6 @@ art_svp_intersect_horiz_commit (ArtIntersectCtx *ctx) } ctx->horiz_first = NULL; ctx->horiz_last = NULL; -#ifdef SANITYCHECK - art_svp_intersect_sanitycheck_winding (ctx); -#endif } #ifdef SANITYCHECK @@ -1563,7 +1528,7 @@ art_svp_intersect_sanitycheck (ArtIntersectCtx *ctx) { ArtActiveSeg *seg; ArtActiveSeg *last = NULL; - double d; + gdouble d; for (seg = ctx->active_head; seg != NULL; seg = seg->right) { @@ -1687,7 +1652,7 @@ art_svp_intersector (const ArtSVP *in, ArtSvpWriter *out) } else { - int n_stack = seg->n_stack; + gint n_stack = seg->n_stack; if (n_stack > 1) { |