pcb 4.1.1
An interactive printed circuit board layout editor.

box.h

Go to the documentation of this file.
00001 
00039 #ifndef PCB_BOX_H
00040 #define PCB_BOX_H
00041 
00042 #include <assert.h>
00043 #include "global.h"
00044 
00045 #include "misc.h"
00046 
00047 typedef enum
00048 { NORTH = 0, EAST = 1, SOUTH = 2, WEST = 3, NE = 4, SE = 5, SW = 6, NW =
00049     7, ALL = 8 } direction_t;
00050 
00056 #define ROTATEBOX_CW(box) { Coord t;\
00057     t = (box).X1; (box).X1 = -(box).Y2; (box).Y2 = (box).X2;\
00058     (box).X2 = -(box).Y1; (box).Y1 = t;\
00059 }
00060 #define ROTATEBOX_TO_NORTH(box, dir) do { Coord t;\
00061   switch(dir) {\
00062   case EAST: \
00063    t = (box).X1; (box).X1 = (box).Y1; (box).Y1 = -(box).X2;\
00064    (box).X2 = (box).Y2; (box).Y2 = -t; break;\
00065   case SOUTH: \
00066    t = (box).X1; (box).X1 = -(box).X2; (box).X2 = -t;\
00067    t = (box).Y1; (box).Y1 = -(box).Y2; (box).Y2 = -t; break;\
00068   case WEST: \
00069    t = (box).X1; (box).X1 = -(box).Y2; (box).Y2 = (box).X2;\
00070    (box).X2 = -(box).Y1; (box).Y1 = t; break;\
00071   case NORTH: break;\
00072   default: assert(0);\
00073   }\
00074   } while (0)
00075 #define ROTATEBOX_FROM_NORTH(box, dir) do { Coord t;\
00076   switch(dir) {\
00077   case WEST: \
00078    t = (box).X1; (box).X1 = (box).Y1; (box).Y1 = -(box).X2;\
00079    (box).X2 = (box).Y2; (box).Y2 = -t; break;\
00080   case SOUTH: \
00081    t = (box).X1; (box).X1 = -(box).X2; (box).X2 = -t;\
00082    t = (box).Y1; (box).Y1 = -(box).Y2; (box).Y2 = -t; break;\
00083   case EAST: \
00084    t = (box).X1; (box).X1 = -(box).Y2; (box).Y2 = (box).X2;\
00085    (box).X2 = -(box).Y1; (box).Y1 = t; break;\
00086   case NORTH: break;\
00087   default: assert(0);\
00088   }\
00089   } while (0)
00090 
00091 /* to avoid overflow, we calculate centers this way */
00092 #define CENTER_X(b) ((b).X1 + ((b).X2 - (b).X1)/2)
00093 #define CENTER_Y(b) ((b).Y1 + ((b).Y2 - (b).Y1)/2)
00094 /* some useful box utilities. */
00095 
00096 typedef struct cheap_point
00097 {
00098   Coord X, Y;
00099 } CheapPointType;
00100 
00101 
00102 /* note that boxes are closed on top and left and open on bottom and right. */
00103 /* this means that top-left corner is in box, *but bottom-right corner is
00104  * not*.  */
00105 static inline bool
00106 point_in_box (const BoxType * box, Coord X, Coord Y)
00107 {
00108   return (X >= box->X1) && (Y >= box->Y1) && (X < box->X2) && (Y < box->Y2);
00109 }
00110 
00111 static inline bool
00112 point_in_closed_box (const BoxType * box, Coord X, Coord Y)
00113 {
00114   return (X >= box->X1) && (Y >= box->Y1) && (X <= box->X2) && (Y <= box->Y2);
00115 }
00116 
00117 static inline bool
00118 box_is_good (const BoxType * b)
00119 {
00120   return (b->X1 < b->X2) && (b->Y1 < b->Y2);
00121 }
00122 
00123 static inline bool
00124 box_intersect (const BoxType * a, const BoxType * b)
00125 {
00126   return
00127     (a->X1 < b->X2) && (b->X1 < a->X2) && (a->Y1 < b->Y2) && (b->Y1 < a->Y2);
00128 }
00129 
00130 static inline CheapPointType
00131 closest_point_in_box (const CheapPointType * from, const BoxType * box)
00132 {
00133   CheapPointType r;
00134   assert (box->X1 < box->X2 && box->Y1 < box->Y2);
00135   r.X =
00136     (from->X < box->X1) ? box->X1 : (from->X >
00137                                      box->X2 - 1) ? box->X2 - 1 : from->X;
00138   r.Y =
00139     (from->Y < box->Y1) ? box->Y1 : (from->Y >
00140                                      box->Y2 - 1) ? box->Y2 - 1 : from->Y;
00141   assert (point_in_box (box, r.X, r.Y));
00142   return r;
00143 }
00144 
00145 static inline bool
00146 box_in_box (const BoxType * outer, const BoxType * inner)
00147 {
00148   return
00149     (outer->X1 <= inner->X1) && (inner->X2 <= outer->X2) &&
00150     (outer->Y1 <= inner->Y1) && (inner->Y2 <= outer->Y2);
00151 }
00152 
00153 static inline BoxType
00154 clip_box (const BoxType * box, const BoxType * clipbox)
00155 {
00156   BoxType r;
00157   assert (box_intersect (box, clipbox));
00158   r.X1 = MAX (box->X1, clipbox->X1);
00159   r.X2 = MIN (box->X2, clipbox->X2);
00160   r.Y1 = MAX (box->Y1, clipbox->Y1);
00161   r.Y2 = MIN (box->Y2, clipbox->Y2);
00162   assert (box_in_box (clipbox, &r));
00163   return r;
00164 }
00165 
00166 static inline BoxType
00167 shrink_box (const BoxType * box, Coord amount)
00168 {
00169   BoxType r = *box;
00170   r.X1 += amount;
00171   r.Y1 += amount;
00172   r.X2 -= amount;
00173   r.Y2 -= amount;
00174   return r;
00175 }
00176 
00177 static inline BoxType
00178 bloat_box (const BoxType * box, Coord amount)
00179 {
00180   return shrink_box (box, -amount);
00181 }
00182 
00187 static inline BoxType
00188 box_center (const BoxType * box)
00189 {
00190   BoxType r;
00191   r.X1 = box->X1 + (box->X2 - box->X1)/2;
00192   r.X2 = r.X1 + 1;
00193   r.Y1 = box->Y1 + (box->Y2 - box->Y1)/2;
00194   r.Y2 = r.Y1 + 1;
00195   return r;
00196 }
00197 
00202 static inline BoxType
00203 box_corner (const BoxType * box)
00204 {
00205   BoxType r;
00206   r.X1 = box->X1;
00207   r.X2 = r.X1 + 1;
00208   r.Y1 = box->Y1;
00209   r.Y2 = r.Y1 + 1;
00210   return r;
00211 }
00212 
00216 static inline BoxType
00217 point_box (Coord X, Coord Y)
00218 {
00219   BoxType r;
00220   r.X1 = X;
00221   r.X2 = X + 1;
00222   r.Y1 = Y;
00223   r.Y2 = Y + 1;
00224   return r;
00225 }
00226 
00230 static inline void
00231 close_box (BoxType * r)
00232 {
00233   r->X2++;
00234   r->Y2++;
00235 }
00236 
00245 static inline double
00246 dist2_to_box (const CheapPointType * p, const BoxType * b)
00247 {
00248   CheapPointType r = closest_point_in_box (p, b);
00249   return Distance (r.X, r.Y, p->X, p->Y);
00250 }
00251 
00252 #endif /* __BOX_H_INCLUDED__ */