Engauge Digitizer  2
 All Classes Files Functions Variables Enumerations Enumerator Friends Pages
mmsubs.cpp
1 #include "mmsubs.h"
2 #include <QImage>
3 #include <QPointF>
4 #include <qmath.h>
5 
6 const double PI = 3.1415926535;
7 
8 double angleBetweenVectors (const QPointF &v1,
9  const QPointF &v2)
10 {
11  double v1Mag = qSqrt (v1.x() * v1.x() + v1.y() * v1.y());
12  double v2Mag = qSqrt (v2.x() * v2.x() + v2.y() * v2.y());
13 
14  double angle = 0;
15  if ((v1Mag > 0) || (v2Mag > 0)) {
16 
17  double cosArg = (v1.x() * v2.x() + v1.y() * v2.y()) / (v1Mag * v2Mag);
18  cosArg = qMin (qMax (cosArg, -1.0), 1.0);
19  angle = qAcos (cosArg);
20  }
21 
22  return angle;
23 }
24 
25 double angleFromVectorToVector (const QPointF &vFrom,
26  const QPointF &vTo)
27 {
28  double angleFrom = qAtan2 (vFrom.y(), vFrom.x());
29  double angleTo = qAtan2 (vTo.y() , vTo.x());
30 
31  // Rotate both angles to put from vector along x axis. Note that angleFrom-angleFrom is zero,
32  // and angleTo-angleFrom is -pi to +pi radians
33  double angleSeparation = angleTo - angleFrom;
34 
35  while (angleSeparation < -1.0 * PI) {
36  angleSeparation += 2.0 * PI;
37  }
38  while (angleSeparation > PI) {
39  angleSeparation -= 2.0 * PI;
40  }
41 
42  return angleSeparation;
43 }
44 
45 QRgb pixelRGB(const QImage &image, int x, int y)
46 {
47  switch (image.depth())
48  {
49  case 1:
50  return pixelRGB1(image, x, y);
51  case 8:
52  return pixelRGB8(image, x, y);
53  default:
54  return pixelRGB32(image, x, y);
55  }
56 }
57 
58 QRgb pixelRGB1(const QImage &image1Bit, int x, int y)
59 {
60  unsigned int bit;
61  if (image1Bit.format () == QImage::Format_MonoLSB) {
62  bit = *(image1Bit.scanLine (y) + (x >> 3)) & (1 << (x & 7));
63  } else {
64  bit = *(image1Bit.scanLine (y) + (x >> 3)) & (1 << (7 - (x & 7)));
65  }
66 
67  unsigned int tableIndex = ((bit == 0) ? 0 : 1);
68  return image1Bit.color(tableIndex);
69 }
70 
71 QRgb pixelRGB8(const QImage &image8Bit, int x, int y)
72 {
73  unsigned int tableIndex = *(image8Bit.scanLine(y) + x);
74  return image8Bit.color(tableIndex);
75 }
76 
77 QRgb pixelRGB32(const QImage &image32Bit, int x, int y)
78 {
79  unsigned int* p = (unsigned int *) image32Bit.scanLine(y) + x;
80  return *p;
81 }
82 
83 void projectPointOntoLine(double xToProject,
84  double yToProject,
85  double xStart,
86  double yStart,
87  double xStop,
88  double yStop,
89  double *xProjection,
90  double *yProjection,
91  double *projectedDistanceOutsideLine,
92  double *distanceToLine)
93 {
94  double s;
95  if (qAbs (yStart - yStop) > qAbs (xStart - xStop)) {
96 
97  // More vertical than horizontal. Compute slope and intercept of y=slope*x+yintercept line through (xToProject, yToProject)
98  double slope = (xStop - xStart) / (yStart - yStop);
99  double yintercept = yToProject - slope * xToProject;
100 
101  // Intersect projected point line (slope-intercept form) with start-stop line (parametric form x=(1-s)*x1+s*x2, y=(1-s)*y1+s*y2)
102  s = (slope * xStart + yintercept - yStart) /
103  (yStop - yStart + slope * (xStart - xStop));
104 
105  } else {
106 
107  // More horizontal than vertical. Compute slope and intercept of x=slope*y+xintercept line through (xToProject, yToProject)
108  double slope = (yStop - yStart) / (xStart - xStop);
109  double xintercept = xToProject - slope * yToProject;
110 
111  // Intersect projected point line (slope-intercept form) with start-stop line (parametric form x=(1-s)*x1+s*x2, y=(1-s)*y1+s*y2)
112  s = (slope * yStart + xintercept - xStart) /
113  (xStop - xStart + slope * (yStart - yStop));
114 
115  }
116 
117  *xProjection = (1.0 - s) * xStart + s * xStop;
118  *yProjection = (1.0 - s) * yStart + s * yStop;
119 
120  if (s < 0) {
121 
122  *projectedDistanceOutsideLine = qSqrt ((*xProjection - xStart) * (*xProjection - xStart) +
123  (*yProjection - yStart) * (*yProjection - yStart));
124  *distanceToLine = qSqrt ((xToProject - xStart) * (xToProject - xStart) +
125  (yToProject - yStart) * (yToProject - yStart));
126 
127  // Bring projection point to inside line
128  *xProjection = xStart;
129  *yProjection = yStart;
130 
131  } else if (s > 1) {
132 
133  *projectedDistanceOutsideLine = qSqrt ((*xProjection - xStop) * (*xProjection - xStop) +
134  (*yProjection - yStop) * (*yProjection - yStop));
135  *distanceToLine = qSqrt ((xToProject - xStop) * (xToProject - xStop) +
136  (yToProject - yStop) * (yToProject - yStop));
137 
138  // Bring projection point to inside line
139  *xProjection = xStop;
140  *yProjection = yStop;
141 
142  } else {
143 
144  *distanceToLine = qSqrt ((xToProject - *xProjection) * (xToProject - *xProjection) +
145  (yToProject - *yProjection) * (yToProject - *yProjection));
146 
147  // Projected point is aleady inside line
148  *projectedDistanceOutsideLine = 0.0;
149 
150  }
151 }
152 
153 void setPixelRGB(QImage &image, int x, int y, QRgb q)
154 {
155  switch (image.depth())
156  {
157  case 1:
158  setPixelRGB1(image, x, y, q);
159  return;
160  case 8:
161  setPixelRGB8(image, x, y, q);
162  return;
163  case 32:
164  setPixelRGB32(image, x, y, q);
165  return;
166  }
167 }
168 
169 void setPixelRGB1(QImage &image1Bit, int x, int y, QRgb q)
170 {
171  for (int index = 0; index < image1Bit.colorCount(); index++) {
172  if (q == image1Bit.color(index))
173  {
174  if (image1Bit.format () == QImage::Format_MonoLSB)
175  {
176  *(image1Bit.scanLine (y) + (x >> 3)) &= ~(1 << (x & 7));
177  if (index > 0)
178  *(image1Bit.scanLine (y) + (x >> 3)) |= index << (x & 7);
179  }
180  else
181  {
182  *(image1Bit.scanLine (y) + (x >> 3)) &= ~(1 << (7 - (x & 7)));
183  if (index > 0)
184  *(image1Bit.scanLine (y) + (x >> 3)) |= index << (7 - (x & 7));
185  }
186  return;
187  }
188  }
189 }
190 
191 void setPixelRGB8(QImage &image8Bit, int x, int y, QRgb q)
192 {
193  for (int index = 0; index < image8Bit.colorCount(); index++) {
194  if (q == image8Bit.color(index))
195  {
196  *(image8Bit.scanLine(y) + x) = index;
197  return;
198  }
199  }
200 }
201 
202 void setPixelRGB32(QImage &image32Bit, int x, int y, QRgb q)
203 {
204  int* p = (int *)image32Bit.scanLine(y) + x;
205  *p = q;
206 }