File indexing completed on 2024-12-22 04:04:15

0001 /* Copyright (C) 2001-2019 Peter Selinger.
0002    This file is part of Potrace. It is free software and it is covered
0003    by the GNU General Public License. See the file COPYING for details. */
0004 
0005 /* calculations with coordinate transformations and bounding boxes */
0006 
0007 #ifdef HAVE_CONFIG_H
0008 #include <config.h>
0009 #endif
0010 
0011 #include <math.h>
0012 #include <string.h>
0013 
0014 #include "trans.h"
0015 #include "bbox.h"
0016 
0017 /* rotate the coordinate system counterclockwise by alpha degrees. The
0018    new bounding box will be the smallest box containing the rotated
0019    old bounding box */
0020 void trans_rotate(trans_t *r, double alpha) {
0021   double s, c, x0, x1, y0, y1, o0, o1;
0022   trans_t t_struct;
0023   trans_t *t = &t_struct;
0024 
0025   memcpy(t, r, sizeof(trans_t));
0026 
0027   s = sin(alpha/180*M_PI);
0028   c = cos(alpha/180*M_PI);
0029 
0030   /* apply the transformation matrix to the sides of the bounding box */
0031   x0 = c * t->bb[0];
0032   x1 = s * t->bb[0];
0033   y0 = -s * t->bb[1];
0034   y1 = c * t->bb[1];
0035 
0036   /* determine new bounding box, and origin of old bb within new bb */
0037   r->bb[0] = fabs(x0) + fabs(y0);
0038   r->bb[1] = fabs(x1) + fabs(y1);
0039   o0 = - min(x0,0) - min(y0,0);
0040   o1 = - min(x1,0) - min(y1,0);
0041 
0042   r->orig[0] = o0 + c * t->orig[0] - s * t->orig[1];
0043   r->orig[1] = o1 + s * t->orig[0] + c * t->orig[1];
0044   r->x[0] = c * t->x[0] - s * t->x[1];
0045   r->x[1] = s * t->x[0] + c * t->x[1];
0046   r->y[0] = c * t->y[0] - s * t->y[1];
0047   r->y[1] = s * t->y[0] + c * t->y[1];
0048 }
0049 
0050 /* return the standard cartesian coordinate system for an w x h rectangle. */
0051 void trans_from_rect(trans_t *r, double w, double h) {
0052   r->bb[0] = w;
0053   r->bb[1] = h;
0054   r->orig[0] = 0.0;
0055   r->orig[1] = 0.0;
0056   r->x[0] = 1.0;
0057   r->x[1] = 0.0;
0058   r->y[0] = 0.0;
0059   r->y[1] = 1.0;
0060   r->scalex = 1.0;
0061   r->scaley = 1.0;
0062 }
0063 
0064 /* rescale the coordinate system r by factor sc >= 0. */
0065 void trans_rescale(trans_t *r, double sc) {
0066   r->bb[0] *= sc;
0067   r->bb[1] *= sc;
0068   r->orig[0] *= sc;
0069   r->orig[1] *= sc;
0070   r->x[0] *= sc;
0071   r->x[1] *= sc;
0072   r->y[0] *= sc;
0073   r->y[1] *= sc;
0074   r->scalex *= sc;
0075   r->scaley *= sc;
0076 }
0077 
0078 /* rescale the coordinate system to size w x h */
0079 void trans_scale_to_size(trans_t *r, double w, double h) {
0080   double xsc = w/r->bb[0];
0081   double ysc = h/r->bb[1];
0082 
0083   r->bb[0] = w;
0084   r->bb[1] = h;
0085   r->orig[0] *= xsc;
0086   r->orig[1] *= ysc;
0087   r->x[0] *= xsc;
0088   r->x[1] *= ysc;
0089   r->y[0] *= xsc;
0090   r->y[1] *= ysc;
0091   r->scalex *= xsc;
0092   r->scaley *= ysc;
0093   
0094   if (w<0) {
0095     r->orig[0] -= w;
0096     r->bb[0] = -w;
0097   }
0098   if (h<0) {
0099     r->orig[1] -= h;
0100     r->bb[1] = -h;
0101   }
0102 }
0103 
0104 /* adjust the bounding box to the actual vector outline */
0105 void trans_tighten(trans_t *r, potrace_path_t *plist) {
0106   interval_t i;
0107   dpoint_t dir;
0108   int j;
0109   
0110   /* if pathlist is empty, do nothing */
0111   if (!plist) {
0112     return;
0113   }
0114 
0115   for (j=0; j<2; j++) {
0116     dir.x = r->x[j];
0117     dir.y = r->y[j];
0118     path_limits(plist, dir, &i);
0119     if (i.min == i.max) {
0120       /* make the extent non-zero to avoid later division by zero errors */
0121       i.max = i.min+0.5;
0122       i.min = i.min-0.5;
0123     }
0124     r->bb[j] = i.max - i.min;
0125     r->orig[j] = -i.min;
0126   }
0127 }