summaryrefslogtreecommitdiff
path: root/Build/source/libs/potrace/potrace-src/src/trans.c
blob: 287808bb0b865cac86a64c3ee062de0759c913da (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
/* Copyright (C) 2001-2017 Peter Selinger.
   This file is part of Potrace. It is free software and it is covered
   by the GNU General Public License. See the file COPYING for details. */

/* calculations with coordinate transformations and bounding boxes */

#ifdef HAVE_CONFIG_H
#include <config.h>
#endif

#include <math.h>
#include <string.h>

#include "trans.h"
#include "bbox.h"

/* rotate the coordinate system counterclockwise by alpha degrees. The
   new bounding box will be the smallest box containing the rotated
   old bounding box */
void trans_rotate(trans_t *r, double alpha) {
  double s, c, x0, x1, y0, y1, o0, o1;
  trans_t t_struct;
  trans_t *t = &t_struct;

  memcpy(t, r, sizeof(trans_t));

  s = sin(alpha/180*M_PI);
  c = cos(alpha/180*M_PI);

  /* apply the transformation matrix to the sides of the bounding box */
  x0 = c * t->bb[0];
  x1 = s * t->bb[0];
  y0 = -s * t->bb[1];
  y1 = c * t->bb[1];

  /* determine new bounding box, and origin of old bb within new bb */
  r->bb[0] = fabs(x0) + fabs(y0);
  r->bb[1] = fabs(x1) + fabs(y1);
  o0 = - min(x0,0) - min(y0,0);
  o1 = - min(x1,0) - min(y1,0);

  r->orig[0] = o0 + c * t->orig[0] - s * t->orig[1];
  r->orig[1] = o1 + s * t->orig[0] + c * t->orig[1];
  r->x[0] = c * t->x[0] - s * t->x[1];
  r->x[1] = s * t->x[0] + c * t->x[1];
  r->y[0] = c * t->y[0] - s * t->y[1];
  r->y[1] = s * t->y[0] + c * t->y[1];
}

/* return the standard cartesian coordinate system for an w x h rectangle. */
void trans_from_rect(trans_t *r, double w, double h) {
  r->bb[0] = w;
  r->bb[1] = h;
  r->orig[0] = 0.0;
  r->orig[1] = 0.0;
  r->x[0] = 1.0;
  r->x[1] = 0.0;
  r->y[0] = 0.0;
  r->y[1] = 1.0;
  r->scalex = 1.0;
  r->scaley = 1.0;
}

/* rescale the coordinate system r by factor sc >= 0. */
void trans_rescale(trans_t *r, double sc) {
  r->bb[0] *= sc;
  r->bb[1] *= sc;
  r->orig[0] *= sc;
  r->orig[1] *= sc;
  r->x[0] *= sc;
  r->x[1] *= sc;
  r->y[0] *= sc;
  r->y[1] *= sc;
  r->scalex *= sc;
  r->scaley *= sc;
}

/* rescale the coordinate system to size w x h */
void trans_scale_to_size(trans_t *r, double w, double h) {
  double xsc = w/r->bb[0];
  double ysc = h/r->bb[1];

  r->bb[0] = w;
  r->bb[1] = h;
  r->orig[0] *= xsc;
  r->orig[1] *= ysc;
  r->x[0] *= xsc;
  r->x[1] *= ysc;
  r->y[0] *= xsc;
  r->y[1] *= ysc;
  r->scalex *= xsc;
  r->scaley *= ysc;
  
  if (w<0) {
    r->orig[0] -= w;
    r->bb[0] = -w;
  }
  if (h<0) {
    r->orig[1] -= h;
    r->bb[1] = -h;
  }
}

/* adjust the bounding box to the actual vector outline */
void trans_tighten(trans_t *r, potrace_path_t *plist) {
  interval_t i;
  dpoint_t dir;
  int j;
  
  /* if pathlist is empty, do nothing */
  if (!plist) {
    return;
  }

  for (j=0; j<2; j++) {
    dir.x = r->x[j];
    dir.y = r->y[j];
    path_limits(plist, dir, &i);
    if (i.min == i.max) {
      /* make the extent non-zero to avoid later division by zero errors */
      i.max = i.min+0.5;
      i.min = i.min-0.5;
    }
    r->bb[j] = i.max - i.min;
    r->orig[j] = -i.min;
  }
}