Main Page | Data Structures | Directories | File List | Data Fields | Globals

bresenham.c

Go to the documentation of this file.
00001 
00019 /* This file is part of tclSadie.
00020 
00021    tclSadie is free software; you can redistribute it and/or modify it
00022    under the terms of the GNU General Public License as published by
00023    the Free Software Foundation; either version 2 of the License, or
00024    (at your option) any later version.
00025 
00026    tclSadie is distributed in the hope that it will be useful, but
00027    WITHOUT ANY WARRANTY; without even the implied warranty of
00028    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00029    General Public License for more details.
00030 
00031    You should have received a copy of the GNU General Public License
00032    along with tclSadie; if not, write to the Free Software Foundation,
00033    Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.  */
00034 
00035 #if HAVE_CONFIG_H
00036 #include <config.h>
00037 #endif /* HAVE_CONFIG_H */
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 /* WITH_DMALLOC */
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 

Generated on Fri Jul 8 14:55:00 2005 for tclSadie by  doxygen 1.4.2