00001
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035 #if HAVE_CONFIG_H
00036 #include <config.h>
00037 #endif
00038 #include <sadie.h>
00039 #include <math.h>
00040 #include "logerr.h"
00041 #include "bresenham.h"
00042 #if WITH_DMALLOC
00043 #include <dmalloc.h>
00044 #endif
00045
00047 typedef int64_t bcoord_t;
00048
00050 typedef bcoord_t (* coord_accessorp_t) (bresenham_linep_t bline);
00051
00053 typedef void (* point_iteratorp_t) (bresenham_linep_t bline);
00054
00056 struct Bpoint
00057 {
00058 bcoord_t x;
00059 bcoord_t y;
00060 };
00061
00063 struct Bresenham_line
00064 {
00065 struct Bpoint first;
00066 struct Bpoint current;
00067 struct Bpoint last;
00068 int past_the_end;
00069 bcoord_t epsilon;
00070 bcoord_t delta_x;
00071 bcoord_t delta_y;
00072 coord_accessorp_t get_col;
00073 coord_accessorp_t get_row;
00074 point_iteratorp_t next_pt;
00075 };
00076
00083 static void
00084 next_positive (bresenham_linep_t bline)
00085 {
00086 logerr_assert (LOGERR_DEBUG, LOGERR_FUNC,
00087 ((bline != NULL) && (bline->current.x < bline->last.x)));
00088 bline->epsilon += bline->delta_y;
00089 if ((2 * bline->epsilon) >= bline->delta_x)
00090 {
00091 bline->epsilon -= bline->delta_x;
00092 (bline->current.y)++;
00093 }
00094 (bline->current.x)++;
00095 }
00096
00103 static void
00104 next_negative (bresenham_linep_t bline)
00105 {
00106 logerr_assert (LOGERR_DEBUG, LOGERR_FUNC,
00107 ((bline != NULL) && (bline->current.x < bline->last.x)));
00108 bline->epsilon += bline->delta_y;
00109 if ((2 * bline->epsilon) <= (-bline->delta_x))
00110 {
00111 bline->epsilon += bline->delta_x;
00112 (bline->current.y)--;
00113 }
00114 (bline->current.x)++;
00115 }
00116
00121 static bcoord_t
00122 fetch_x (bresenham_linep_t bline)
00123 {
00124 logerr_assert (LOGERR_DEBUG, LOGERR_FUNC, (bline != NULL));
00125 return bline->current.x;
00126 }
00127
00132 static bcoord_t
00133 fetch_y (bresenham_linep_t bline)
00134 {
00135 logerr_assert (LOGERR_DEBUG, LOGERR_FUNC, (bline != NULL));
00136 return bline->current.y;
00137 }
00138
00143 static bcoord_t
00144 fetch_neg_x (bresenham_linep_t bline)
00145 {
00146 logerr_assert (LOGERR_DEBUG, LOGERR_FUNC, (bline != NULL));
00147 return (2 * bline->first.x - bline->current.x);
00148 }
00149
00171 static bresenham_linep_t
00172 bresenham_from_bcoord (bcoord_t first_col, bcoord_t first_row,
00173 bcoord_t last_col, bcoord_t last_row)
00174 {
00175 bcoord_t delta_row, delta_col, abs_delta_row, abs_delta_col;
00176 bresenham_linep_t bline;
00177 int transposition_needed, reflection_needed;
00178
00179 bline = malloc(sizeof(struct Bresenham_line));
00180 logerr_assert (LOGERR_DEBUG, LOGERR_FUNC, (bline != NULL));
00181 delta_row = last_row - first_row;
00182 delta_col = last_col - first_col;
00183 abs_delta_row = (delta_row >= 0) ? delta_row : (-delta_row);
00184 abs_delta_col = (delta_col >= 0) ? delta_col : (-delta_col);
00185 transposition_needed = (abs_delta_row < abs_delta_col);
00186 reflection_needed = (delta_col < (-delta_row));
00187 if (transposition_needed)
00188 {
00189 bline->first.x = first_col;
00190 bline->first.y = first_row;
00191 }
00192 else
00193 {
00194 bline->first.x = first_row;
00195 bline->first.y = first_col;
00196 }
00197 if (reflection_needed)
00198 {
00199 if (transposition_needed)
00200 {
00201 bline->last.x = first_col - delta_col;
00202 bline->last.y = last_row;
00203 bline->get_row = fetch_y;
00204 bline->get_col = fetch_neg_x;
00205 }
00206 else
00207 {
00208 bline->last.x = first_row - delta_row;
00209 bline->last.y = last_col;
00210 bline->get_row = fetch_neg_x;
00211 bline->get_col = fetch_y;
00212 }
00213 if ((delta_row > 0) || (delta_col > 0))
00214 bline->next_pt = next_positive;
00215 else
00216 bline->next_pt = next_negative;
00217 }
00218 else
00219 {
00220 if (transposition_needed)
00221 {
00222 bline->last.x = last_col;
00223 bline->last.y = last_row;
00224 bline->get_row = fetch_y;
00225 bline->get_col = fetch_x;
00226 }
00227 else
00228 {
00229 bline->last.x = last_row;
00230 bline->last.y = last_col;
00231 bline->get_row = fetch_x;
00232 bline->get_col = fetch_y;
00233 }
00234 if ((delta_row < 0) || (delta_col < 0))
00235 bline->next_pt = next_negative;
00236 else
00237 bline->next_pt = next_positive;
00238 }
00239 bline->delta_x = bline->last.x - bline->first.x;
00240 bline->delta_y = bline->last.y - bline->first.y;
00241 bline->past_the_end = 0;
00242 bline->epsilon = 0;
00243 bline->current = bline->first;
00244 return bline;
00245 }
00246
00259 bresenham_linep_t
00260 bresenham_from_s_coord (int32_t first_col, int32_t first_row,
00261 int32_t last_col, int32_t last_row)
00262 {
00263 return bresenham_from_bcoord (first_col, first_row, last_col, last_row);
00264 }
00265
00278 bresenham_linep_t
00279 bresenham_from_coord (uint32_t first_col, uint32_t first_row,
00280 uint32_t last_col, uint32_t last_row)
00281 {
00282 return bresenham_from_bcoord (first_col, first_row, last_col, last_row);
00283 }
00284
00302 int
00303 bresenham_next (bresenham_linep_t bline, uint32_t * col, uint32_t * row)
00304 {
00305 logerr_assert (LOGERR_DEBUG, LOGERR_FUNC,
00306 (bline && col && row
00307 && bline->get_row && bline->get_col && bline->next_pt));
00308 if (bline->past_the_end)
00309 logerr_debug (LOGERR_FUNC, "iterating off the end of a line");
00310 else
00311 {
00312 *col = (uint32_t) ((*(bline->get_col)) (bline));
00313 *row = (uint32_t) ((*(bline->get_row)) (bline));
00314 bline->past_the_end = ((bline->current.x == bline->last.x)
00315 && (bline->current.y == bline->last.y));
00316 if (!bline->past_the_end)
00317 (*(bline->next_pt)) (bline);
00318 }
00319 return bline->past_the_end;
00320 }
00321
00331 int
00332 bresenham_next_s (bresenham_linep_t bline, int32_t * col, int32_t * row)
00333 {
00334 logerr_assert (LOGERR_DEBUG, LOGERR_FUNC,
00335 (bline && col && row
00336 && bline->get_row && bline->get_col && bline->next_pt));
00337 if (bline->past_the_end)
00338 logerr_debug (LOGERR_FUNC, "iterating off the end of a line");
00339 else
00340 {
00341 *col = (int32_t) ((*(bline->get_col)) (bline));
00342 *row = (int32_t) ((*(bline->get_row)) (bline));
00343 bline->past_the_end = ((bline->current.x == bline->last.x)
00344 && (bline->current.y == bline->last.y));
00345 if (!bline->past_the_end)
00346 (*(bline->next_pt)) (bline);
00347 }
00348 return bline->past_the_end;
00349 }
00350
00358 void
00359 demolish_bresenham (bresenham_linep_t * blinehandle)
00360 {
00361 logerr_assert (LOGERR_CRIT, LOGERR_FUNC,
00362 ((blinehandle != NULL) && (*blinehandle != NULL)));
00363 free (*blinehandle);
00364 *blinehandle = NULL;
00365 }
00366