xref: /potrace-1.14/src/trans.c (revision b3fce824)
1 /* Copyright (C) 2001-2017 Peter Selinger.
2    This file is part of Potrace. It is free software and it is covered
3    by the GNU General Public License. See the file COPYING for details. */
4 
5 /* calculations with coordinate transformations and bounding boxes */
6 
7 #ifdef HAVE_CONFIG_H
8 #include <config.h>
9 #endif
10 
11 #include <math.h>
12 #include <string.h>
13 
14 #include "trans.h"
15 #include "bbox.h"
16 
17 /* rotate the coordinate system counterclockwise by alpha degrees. The
18    new bounding box will be the smallest box containing the rotated
19    old bounding box */
trans_rotate(trans_t * r,double alpha)20 void trans_rotate(trans_t *r, double alpha) {
21   double s, c, x0, x1, y0, y1, o0, o1;
22   trans_t t_struct;
23   trans_t *t = &t_struct;
24 
25   memcpy(t, r, sizeof(trans_t));
26 
27   s = sin(alpha/180*M_PI);
28   c = cos(alpha/180*M_PI);
29 
30   /* apply the transformation matrix to the sides of the bounding box */
31   x0 = c * t->bb[0];
32   x1 = s * t->bb[0];
33   y0 = -s * t->bb[1];
34   y1 = c * t->bb[1];
35 
36   /* determine new bounding box, and origin of old bb within new bb */
37   r->bb[0] = fabs(x0) + fabs(y0);
38   r->bb[1] = fabs(x1) + fabs(y1);
39   o0 = - min(x0,0) - min(y0,0);
40   o1 = - min(x1,0) - min(y1,0);
41 
42   r->orig[0] = o0 + c * t->orig[0] - s * t->orig[1];
43   r->orig[1] = o1 + s * t->orig[0] + c * t->orig[1];
44   r->x[0] = c * t->x[0] - s * t->x[1];
45   r->x[1] = s * t->x[0] + c * t->x[1];
46   r->y[0] = c * t->y[0] - s * t->y[1];
47   r->y[1] = s * t->y[0] + c * t->y[1];
48 }
49 
50 /* return the standard cartesian coordinate system for an w x h rectangle. */
trans_from_rect(trans_t * r,double w,double h)51 void trans_from_rect(trans_t *r, double w, double h) {
52   r->bb[0] = w;
53   r->bb[1] = h;
54   r->orig[0] = 0.0;
55   r->orig[1] = 0.0;
56   r->x[0] = 1.0;
57   r->x[1] = 0.0;
58   r->y[0] = 0.0;
59   r->y[1] = 1.0;
60   r->scalex = 1.0;
61   r->scaley = 1.0;
62 }
63 
64 /* rescale the coordinate system r by factor sc >= 0. */
trans_rescale(trans_t * r,double sc)65 void trans_rescale(trans_t *r, double sc) {
66   r->bb[0] *= sc;
67   r->bb[1] *= sc;
68   r->orig[0] *= sc;
69   r->orig[1] *= sc;
70   r->x[0] *= sc;
71   r->x[1] *= sc;
72   r->y[0] *= sc;
73   r->y[1] *= sc;
74   r->scalex *= sc;
75   r->scaley *= sc;
76 }
77 
78 /* rescale the coordinate system to size w x h */
trans_scale_to_size(trans_t * r,double w,double h)79 void trans_scale_to_size(trans_t *r, double w, double h) {
80   double xsc = w/r->bb[0];
81   double ysc = h/r->bb[1];
82 
83   r->bb[0] = w;
84   r->bb[1] = h;
85   r->orig[0] *= xsc;
86   r->orig[1] *= ysc;
87   r->x[0] *= xsc;
88   r->x[1] *= ysc;
89   r->y[0] *= xsc;
90   r->y[1] *= ysc;
91   r->scalex *= xsc;
92   r->scaley *= ysc;
93 
94   if (w<0) {
95     r->orig[0] -= w;
96     r->bb[0] = -w;
97   }
98   if (h<0) {
99     r->orig[1] -= h;
100     r->bb[1] = -h;
101   }
102 }
103 
104 /* adjust the bounding box to the actual vector outline */
trans_tighten(trans_t * r,potrace_path_t * plist)105 void trans_tighten(trans_t *r, potrace_path_t *plist) {
106   interval_t i;
107   dpoint_t dir;
108   int j;
109 
110   /* if pathlist is empty, do nothing */
111   if (!plist) {
112     return;
113   }
114 
115   for (j=0; j<2; j++) {
116     dir.x = r->x[j];
117     dir.y = r->y[j];
118     path_limits(plist, dir, &i);
119     if (i.min == i.max) {
120       /* make the extent non-zero to avoid later division by zero errors */
121       i.max = i.min+0.5;
122       i.min = i.min-0.5;
123     }
124     r->bb[j] = i.max - i.min;
125     r->orig[j] = -i.min;
126   }
127 }
128