Index: trunk/src/obj_common.c =================================================================== --- trunk/src/obj_common.c (revision 19572) +++ trunk/src/obj_common.c (revision 19573) @@ -226,3 +226,86 @@ return 0; } } + +static void mmult(pcb_xform_mx_t dst, const pcb_xform_mx_t src) +{ + pcb_xform_mx_t tmp; + + tmp[0] = dst[0] * src[0] + dst[1] * src[3] + dst[2] * src[6]; + tmp[1] = dst[0] * src[1] + dst[1] * src[4] + dst[2] * src[7]; + tmp[2] = dst[0] * src[2] + dst[1] * src[5] + dst[2] * src[8]; + + tmp[3] = dst[3] * src[0] + dst[4] * src[3] + dst[5] * src[6]; + tmp[4] = dst[3] * src[1] + dst[4] * src[4] + dst[5] * src[7]; + tmp[5] = dst[3] * src[2] + dst[4] * src[5] + dst[5] * src[8]; + + tmp[6] = dst[6] * src[0] + dst[7] * src[3] + dst[8] * src[6]; + tmp[7] = dst[6] * src[1] + dst[7] * src[4] + dst[8] * src[7]; + tmp[8] = dst[6] * src[2] + dst[7] * src[5] + dst[8] * src[8]; + + memcpy(dst, tmp, sizeof(tmp)); +} + +void pcb_xform_mx_rotate(pcb_xform_mx_t mx, double deg) +{ + pcb_xform_mx_t tr; + + deg /= PCB_RAD_TO_DEG; + + tr[0] = cos(deg); + tr[1] = sin(deg); + tr[2] = 0; + + tr[3] = -sin(deg); + tr[4] = cos(deg); + tr[5] = 0; + + tr[6] = 0; + tr[7] = 0; + tr[8] = 1; + + mmult(mx, tr); +} + +void pcb_xform_mx_translate(pcb_xform_mx_t mx, double xt, double yt) +{ + pcb_xform_mx_t tr; + + tr[0] = 1; + tr[1] = 0; + tr[2] = xt; + + tr[3] = 0; + tr[4] = 1; + tr[5] = yt; + + tr[6] = 0; + tr[7] = 0; + tr[8] = 1; + + mmult(mx, tr); +} + +void pcb_xform_mx_scale(pcb_xform_mx_t mx, double sx, double sy) +{ + pcb_xform_mx_t tr; + + tr[0] = sx; + tr[1] = 0; + tr[2] = 0; + + tr[3] = 0; + tr[4] = sy; + tr[5] = 0; + + tr[6] = 0; + tr[7] = 0; + tr[8] = 1; + + mmult(mx, tr); +} + +void pcb_xform_mx_mirrorx(pcb_xform_mx_t mx) +{ + pcb_xform_mx_scale(mx, 0, -1); +} Index: trunk/src/obj_common.h =================================================================== --- trunk/src/obj_common.h (revision 19572) +++ trunk/src/obj_common.h (revision 19573) @@ -92,6 +92,9 @@ pcb_coord_t X2, Y2; /* and lower right corner */ }; +typedef double pcb_xform_mx_t[9]; +#define PCB_XFORM_MX_IDENT {1,0,0, 0,1,0, 0,0,1} + typedef struct pcb_xform_s { /* generic object transformation */ pcb_coord_t bloat; /* if non-zero, bloat (positive) or shrink (negative) by this value */ } pcb_xform_t; @@ -106,6 +109,15 @@ } while(0) #define pcb_xform_is_nop(src) ((src)->bloat == 0) +/* Standard 2d matrix transformation using mx as pcb_xform_mx_t */ +#define pcb_xform_x(mx, x_in, y_in) ((double)(x_in) * mx[0] + (double)(y_in) * mx[1] + mx[2]) +#define pcb_xform_y(mx, x_in, y_in) ((double)(x_in) * mx[3] + (double)(y_in) * mx[4] + mx[5]) + +void pcb_xform_mx_rotate(pcb_xform_mx_t mx, double deg); +void pcb_xform_mx_translate(pcb_xform_mx_t mx, double xt, double yt); +void pcb_xform_mx_scale(pcb_xform_mx_t mx, double st, double sy); +void pcb_xform_mx_mirrorx(pcb_xform_mx_t mx); /* mirror over the x axis (flip y coords) */ + /* Return the user readable name of an object type in a string; never NULL */ const char *pcb_obj_type_name(pcb_objtype_t type);