1/*********************************************************************** 2 * * 3 * $Id: hpgsmatrix.c 298 2006-03-05 18:18:03Z softadm $ 4 * * 5 * hpgs - HPGl Script, a hpgl/2 interpreter, which uses a Postscript * 6 * API for rendering a scene and thus renders to a variety of * 7 * devices and fileformats. * 8 * * 9 * (C) 2004-2006 ev-i Informationstechnologie GmbH http://www.ev-i.at * 10 * * 11 * Author: Wolfgang Glas * 12 * * 13 * hpgs is free software; you can redistribute it and/or * 14 * modify it under the terms of the GNU Lesser General Public * 15 * License as published by the Free Software Foundation; either * 16 * version 2.1 of the License, or (at your option) any later version. * 17 * * 18 * hpgs is distributed in the hope that it will be useful, * 19 * but WITHOUT ANY WARRANTY; without even the implied warranty of * 20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * 21 * Lesser General Public License for more details. * 22 * * 23 * You should have received a copy of the GNU Lesser General Public * 24 * License along with this library; if not, write to the * 25 * Free Software Foundation, Inc., 59 Temple Place, Suite 330, * 26 * Boston, MA 02111-1307 USA * 27 * * 28 *********************************************************************** 29 * * 30 * The implementation of the public API for transformation matrices. * 31 * * 32 ***********************************************************************/ 33 34#include<hpgs.h> 35 36/*! 37 Sets the given matrix to the identity matrix. 38 */ 39void hpgs_matrix_set_identity(hpgs_matrix *m) 40{ 41 m->myx = m->mxy = m->dy = m->dx = 0.0; 42 m->myy = m->mxx = 1.0; 43} 44 45/*! 46 Transforms the given point \c p with the matrix \c m. 47 The result is stored in \c res. 48 The pointers \c p and \c res may point to the same memory location. 49 */ 50void hpgs_matrix_xform(hpgs_point *res, 51 const hpgs_matrix *m, const hpgs_point *p) 52{ 53 double x = m->dx + m->mxx * p->x + m->mxy * p->y; 54 double y = m->dy + m->myx * p->x + m->myy * p->y; 55 res->x = x; 56 res->y = y; 57} 58 59/*! 60 Transforms the given point \c p with the inverse of the matrix \c m. 61 The result is stored in \c res. 62 The pointers \c p and \c res may point to the same memory location. 63 */ 64void hpgs_matrix_ixform(hpgs_point *res, 65 const hpgs_point *p, const hpgs_matrix *m) 66{ 67 double x0 = (p->x - m->dx); 68 double y0 = (p->y - m->dy); 69 70 double det = m->mxx * m->myy - m->mxy * m->myx; 71 72 res->x = (m->myy * x0 - m->mxy * y0)/det; 73 res->y = (m->mxx * y0 - m->myx * x0)/det; 74} 75 76/*! 77 Transforms the given bounding box \c bb with the matrix \c m. 78 The result is the enclosing bounding box of the transformed 79 rectangle of the bounding box and is stored in \c res. 80 The pointers \c bb and \c res may point to the same memory location. 81 */ 82void hpgs_matrix_xform_bbox(hpgs_bbox *res, 83 const hpgs_matrix *m, const hpgs_bbox *bb) 84{ 85 hpgs_point ll = { bb->llx, bb->lly }; 86 hpgs_point ur = { bb->urx, bb->ury }; 87 88 hpgs_point lr = { bb->llx, bb->ury }; 89 hpgs_point ul = { bb->urx, bb->lly }; 90 91 hpgs_matrix_xform(&ll,m,&ll); 92 hpgs_matrix_xform(&ur,m,&ur); 93 94 hpgs_matrix_xform(&lr,m,&lr); 95 hpgs_matrix_xform(&ul,m,&ul); 96 97 res->llx = HPGS_MIN(HPGS_MIN(ll.x,ur.x),HPGS_MIN(lr.x,ul.x)); 98 res->lly = HPGS_MIN(HPGS_MIN(ll.y,ur.y),HPGS_MIN(lr.y,ul.y)); 99 100 res->urx = HPGS_MAX(HPGS_MAX(ll.x,ur.x),HPGS_MAX(lr.x,ul.x)); 101 res->ury = HPGS_MAX(HPGS_MAX(ll.y,ur.y),HPGS_MAX(lr.y,ul.y)); 102} 103 104/*! 105 Transforms the given bounding box \c bb with the the inverse of 106 the matrix \c m. 107 The result is the enclosing bounding box of the transformed 108 rectangle of the bounding box and is stored in \c res. 109 The pointers \c bb and \c res may point to the same memory location. 110 */ 111void hpgs_matrix_ixform_bbox(hpgs_bbox *res, 112 const hpgs_bbox *bb, const hpgs_matrix *m) 113{ 114 hpgs_point ll = { bb->llx, bb->lly }; 115 hpgs_point ur = { bb->urx, bb->ury }; 116 117 hpgs_point lr = { bb->llx, bb->ury }; 118 hpgs_point ul = { bb->urx, bb->lly }; 119 120 hpgs_matrix_ixform(&ll,&ll,m); 121 hpgs_matrix_ixform(&ur,&ur,m); 122 123 hpgs_matrix_ixform(&lr,&lr,m); 124 hpgs_matrix_ixform(&ul,&ul,m); 125 126 res->llx = HPGS_MIN(HPGS_MIN(ll.x,ur.x),HPGS_MIN(lr.x,ul.x)); 127 res->lly = HPGS_MIN(HPGS_MIN(ll.y,ur.y),HPGS_MIN(lr.y,ul.y)); 128 129 res->urx = HPGS_MAX(HPGS_MAX(ll.x,ur.x),HPGS_MAX(lr.x,ul.x)); 130 res->ury = HPGS_MAX(HPGS_MAX(ll.y,ur.y),HPGS_MAX(lr.y,ul.y)); 131} 132 133/*! 134 Transforms the given point \c p with the matrix \c m without 135 applying the translation part of \c m. This is useful in order 136 to transform delta vectors. 137 138 The result is stored in \c res. 139 The pointers \c p and \c res may point to the same memory location. 140 */ 141void hpgs_matrix_scale(hpgs_point *res, 142 const hpgs_matrix *m, const hpgs_point *p) 143{ 144 double x = m->mxx * p->x + m->mxy * p->y; 145 double y = m->myx * p->x + m->myy * p->y; 146 res->x = x; 147 res->y = y; 148} 149 150/*! 151 Transforms the given point \c p with the inverse of the matrix \c m 152 without applying the translation part of \c m. This is useful in order 153 to transform delta vectors. 154 155 The result is stored in \c res. 156 The pointers \c p and \c res may point to the same memory location. 157 */ 158void hpgs_matrix_iscale(hpgs_point *res, 159 const hpgs_point *p, const hpgs_matrix *m) 160{ 161 double x0 = p->x; 162 double y0 = p->y; 163 164 double det = m->mxx * m->myy - m->mxy * m->myx; 165 166 res->x = (m->myy * x0 - m->mxy * y0)/det; 167 res->y = (m->mxx * y0 - m->myx * x0)/det; 168} 169 170/*! 171 Concatenates the given matrices \c a and \c b. 172 The result is stored in \c res. 173 Either of the pointer \c a or \b may point to the same memory location as 174 the pointer \c res. 175 */ 176void hpgs_matrix_concat(hpgs_matrix *res, 177 const hpgs_matrix *a, const hpgs_matrix *b) 178{ 179 // 180 // | 1 0 0 | | 1 0 0 | | 1 0 0 | 181 // | dx mxx mxy | x | Dx Mxx Mxy | = | dx+Dx*mxx+Dy*mxy mxx*Mxx+mxy*Myx mxx*Mxy+mxy*Myy | 182 // | dy myx myy | | Dy Myx Myy | | dy+Dx*myx+Dy*myy myx*Mxx+myy*Myx myx*Mxy+myy*Myy | 183 // 184 double r0,r1,r2,r3; 185 186 r0 = a->dx+b->dx*a->mxx+b->dy*a->mxy; 187 r1 = a->dy+b->dx*a->myx+b->dy*a->myy; 188 189 res->dx = r0; 190 res->dy = r1; 191 192 r0 = a->mxx*b->mxx+a->mxy*b->myx; 193 r1 = a->mxx*b->mxy+a->mxy*b->myy; 194 r2 = a->myx*b->mxx+a->myy*b->myx; 195 r3 = a->myx*b->mxy+a->myy*b->myy; 196 197 res->mxx = r0; 198 res->mxy = r1; 199 res->myx = r2; 200 res->myy = r3; 201} 202 203/*! 204 Inverts the given matrix \c m. 205 The result is stored in \c res. 206 The pointers \c m and \c res may point to the same memory location. 207 */ 208void hpgs_matrix_invert(hpgs_matrix *res, const hpgs_matrix *m) 209{ 210 double det = m->mxx * m->myy - m->mxy * m->myx; 211 212 double tmp = m->mxx/det; 213 res->mxx = m->myy/det; 214 res->myy = tmp; 215 216 res->mxy = -m->mxy/det; 217 res->myx = -m->myx/det; 218 219 double x0 = -m->dx; 220 double y0 = -m->dy; 221 res->dx = x0 * res->mxx + y0 * res->mxy; 222 res->dy = x0 * res->myx + y0 * res->myy; 223} 224