SMIL  1.0.4
DImageDraw.h
1 /*
2  * Copyright (c) 2011-2016, Matthieu FAESSEL and ARMINES
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions are met:
7  *
8  * * Redistributions of source code must retain the above copyright
9  * notice, this list of conditions and the following disclaimer.
10  * * Redistributions in binary form must reproduce the above copyright
11  * notice, this list of conditions and the following disclaimer in the
12  * documentation and/or other materials provided with the distribution.
13  * * Neither the name of Matthieu FAESSEL, or ARMINES nor the
14  * names of its contributors may be used to endorse or promote products
15  * derived from this software without specific prior written permission.
16  *
17  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS IS''
18  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS AND CONTRIBUTORS BE
21  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
22  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
23  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
24  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
25  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
26  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
27  * POSSIBILITY OF SUCH DAMAGE.
28  */
29 
30 #ifndef _D_IMAGE_DRAW_H
31 #define _D_IMAGE_DRAW_H
32 
33 #include <vector>
34 #include <algorithm>
35 
36 #include "Core/include/DCommon.h"
37 #include "Core/include/DBaseObject.h"
38 
39 namespace smil
40 {
62  inline vector<IntPoint> bresenhamPoints(int p1x, int p1y, int p2x, int p2y,
63  int xMax = 0, int yMax = 0)
64  {
65  vector<IntPoint> points;
66  int F, x, y;
67 
68  bool swapped = false;
69  if (p1x > p2x) // Swap points if p1 is on the right of p2
70  {
71  swap(p1x, p2x);
72  swap(p1y, p2y);
73  swapped = true;
74  }
75 
76  // Handle trivial cases separately for algorithm speed up.
77  // Trivial case 1: m = +/-INF (Vertical line)
78  if (p1x == p2x) {
79  if (p1y > p2y) // Swap y-coordinates if p1 is above p2
80  {
81  swap(p1y, p2y);
82  }
83 
84  x = p1x;
85  y = p1y;
86  if ((xMax == 0) || (x >= 0 && x < xMax))
87  while (y <= p2y) {
88  points.push_back(IntPoint(x, y, 0));
89  y++;
90  }
91  return points;
92  }
93  // Trivial case 2: m = 0 (Horizontal line)
94  else if (p1y == p2y) {
95  x = p1x;
96  y = p1y;
97 
98  if ((yMax == 0) || (y >= 0 && y < yMax))
99  while (x <= p2x) {
100  points.push_back(IntPoint(x, y, 0));
101  x++;
102  }
103  return points;
104  }
105 
106  int dy = p2y - p1y; // y-increment from p1 to p2
107  int dx = p2x - p1x; // x-increment from p1 to p2
108  int dx2 = (dx << 1); // dx << 1 == 2*dx
109  int dy2 = 2 * dy; // dy can be negative, prefer * over <<
110  int dy2_minus_dx2 = dy2 - dx2; // precompute constant for speed up
111  int dy2_plus_dx2 = dy2 + dx2;
112 
113  if (dy >= 0) // m >= 0
114  {
115  // Case 1: 0 <= m <= 1 (Original case)
116  if (dy <= dx) {
117  F = dy2 - dx; // initial F
118 
119  x = p1x;
120  y = p1y;
121  while (x <= p2x) {
122  if ((xMax == 0) || (x >= 0 && x < xMax && y >= 0 && y < yMax))
123  points.push_back(IntPoint(x, y, 0));
124  if (F <= 0) {
125  F += dy2;
126  } else {
127  y++;
128  F += dy2_minus_dx2;
129  }
130  x++;
131  }
132  }
133  // Case 2: 1 < m < INF (Mirror about y=x line
134  // replace all dy by dx and dx by dy)
135  else {
136  F = dx2 - dy; // initial F
137 
138  y = p1y;
139  x = p1x;
140  while (y <= p2y) {
141  if ((xMax == 0) || (x >= 0 && x < xMax && y >= 0 && y < yMax))
142  points.push_back(IntPoint(x, y, 0));
143  if (F <= 0) {
144  F += dx2;
145  } else {
146  x++;
147  F -= dy2_minus_dx2;
148  }
149  y++;
150  }
151  }
152  } else // m < 0
153  {
154  // Case 3: -1 <= m < 0 (Mirror about x-axis, replace all dy by -dy)
155  if (dx >= -dy) {
156  F = -dy2 - dx; // initial F
157 
158  x = p1x;
159  y = p1y;
160  while (x <= p2x) {
161  if ((xMax == 0) || (x >= 0 && x < xMax && y >= 0 && y < yMax))
162  points.push_back(IntPoint(x, y, 0));
163  if (F <= 0) {
164  F -= dy2;
165  } else {
166  y--;
167  F -= dy2_plus_dx2;
168  }
169  x++;
170  }
171  }
172  // Case 4: -INF < m < -1 (Mirror about x-axis and mirror
173  // about y=x line, replace all dx by -dy and dy by dx)
174  else {
175  F = dx2 + dy; // initial F
176 
177  y = p1y;
178  x = p1x;
179  while (y >= p2y) {
180  if ((xMax == 0) || (x >= 0 && x < xMax && y >= 0 && y < yMax))
181  points.push_back(IntPoint(x, y, 0));
182  if (F <= 0) {
183  F += dx2;
184  } else {
185  x++;
186  F += dy2_plus_dx2;
187  }
188  y--;
189  }
190  }
191  }
192  // If input points have been swapped, reverse the vector
193  if (swapped)
194  std::reverse(points.begin(), points.end());
195  return points;
196  }
197 
211  vector<IntPoint> bresenhamLine(int p1x, int p1y, int p2x, int p2y);
212 
224  class Bresenham : public BaseObject
225  {
226  public:
234  Bresenham(const IntPoint &pi, const IntPoint &pf)
235  : BaseObject("Bresenham"), pi(pi), pf(pf)
236  {
237  doBresenham3D(pi.x, pi.y, pi.z, pf.x, pf.y, pf.z);
238  }
239 
246  Bresenham(const IntPoint &pf)
247  : BaseObject("Bresenham"), pi(IntPoint(0, 0, 0)), pf(pf)
248  {
249  doBresenham3D(pi.x, pi.y, pi.z, pf.x, pf.y, pf.z);
250  }
251 
259  Bresenham(int xi, int yi, int zi, int xf, int yf, int zf)
260  : BaseObject("Bresenham")
261  {
262  pi.x = xi;
263  pi.y = yi;
264  pi.z = zi;
265  pf.x = xf;
266  pf.y = yf;
267  pf.z = zf;
268 
269  doBresenham3D(xi, yi, zi, xf, yf, zf);
270  }
271 
279  Bresenham(int xi, int yi, int xf, int yf) : BaseObject("Bresenham Line")
280  {
281  pi.x = xi;
282  pi.y = yi;
283  pi.z = 0;
284  pf.x = xf;
285  pf.y = yf;
286  pf.z = 0;
287 
288  doBresenham3D(xi, yi, 0, xf, yf, 0);
289  }
290 
296  vector<IntPoint> getPoints() const
297  {
298  return pts;
299  }
300 
307  {
308  if (i < pts.size())
309  return pts[i];
310  return IntPoint(0, 0, 0);
311  }
312 
317  size_t nbPoints()
318  {
319  return pts.size();
320  }
321 
327  double length()
328  {
329  return std::sqrt(std::pow(pf.x - pi.x, 2) + std::pow(pf.y - pi.y, 2) +
330  std::pow(pf.z - pi.z, 2));
331  }
332 
333  void printSelf(ostream &os = std::cout, string indent = "")
334  {
335  os << indent << "Bresenham Line" << endl;
336  os << indent << "Class : " << className << endl;
337  // os << indent << "Name : " << name << endl;
338 
339  for (UINT i = 0; i < pts.size(); i++)
340  os << indent << "#" << i + 1 << "\t: (" << pts[i].x << "," << pts[i].y
341  << "," << pts[i].z << ")" << endl;
342  }
343 
344  private:
345  IntPoint pi;
346  IntPoint pf;
347 
348  vector<IntPoint> pts;
349 
350  void addPoint(IntPoint &p)
351  {
352  pts.push_back(p);
353  }
354 
355  void doBresenham3D(int x1, int y1, int z1, int x2, int y2, int z2)
356  {
357  int dx, dy, dz;
358  int dx2, dy2, dz2;
359 
360  int xInc, yInc, zInc;
361  int xLen, yLen, zLen;
362 
363  IntPoint pt(x1, y1, z1);
364 
365  dx = x2 - x1;
366  dy = y2 - y1;
367  dz = z2 - z1;
368 
369  xInc = (dx < 0) ? -1 : 1;
370  xLen = abs(dx);
371 
372  yInc = (dy < 0) ? -1 : 1;
373  yLen = abs(dy);
374 
375  zInc = (dz < 0) ? -1 : 1;
376  zLen = abs(dz);
377 
378  dx2 = 2 * xLen;
379  dy2 = 2 * yLen;
380  dz2 = 2 * zLen;
381 
382  if ((xLen >= yLen) && (xLen >= zLen)) {
383  int err_1 = dy2 - xLen;
384  int err_2 = dz2 - xLen;
385  for (int i = 0; i < xLen; i++) {
386  addPoint(pt);
387  if (err_1 > 0) {
388  pt.y += yInc;
389  err_1 -= dx2;
390  }
391  if (err_2 > 0) {
392  pt.z += zInc;
393  err_2 -= dx2;
394  }
395  err_1 += dy2;
396  err_2 += dz2;
397  pt.x += xInc;
398  }
399  addPoint(pt);
400  return;
401  }
402 
403  if ((yLen >= xLen) && (yLen >= zLen)) {
404  int err_1 = dx2 - yLen;
405  int err_2 = dz2 - yLen;
406  for (int i = 0; i < yLen; i++) {
407  addPoint(pt);
408  if (err_1 > 0) {
409  pt.x += xInc;
410  err_1 -= dy2;
411  }
412  if (err_2 > 0) {
413  pt.z += zInc;
414  err_2 -= dy2;
415  }
416  err_1 += dx2;
417  err_2 += dz2;
418  pt.y += yInc;
419  }
420  addPoint(pt);
421  return;
422  }
423 
424  if ((zLen >= xLen) && (zLen >= yLen)) {
425  int err_1 = dy2 - zLen;
426  int err_2 = dx2 - zLen;
427  for (int i = 0; i < zLen; i++) {
428  addPoint(pt);
429  if (err_1 > 0) {
430  pt.y += yInc;
431  err_1 -= dz2;
432  }
433  if (err_2 > 0) {
434  pt.x += xInc;
435  err_2 -= dz2;
436  }
437  err_1 += dy2;
438  err_2 += dx2;
439  pt.z += zInc;
440  }
441  addPoint(pt);
442  return;
443  }
444  }
445  };
446 
449 } // namespace smil
450 
451 #endif // _D_IMAGE_DRAW_H
Base Smil Object.
Definition: DBaseObject.h:52
Bresenham Class.
Definition: DImageDraw.h:225
double length()
length() - length of the line (Euclidean distance between extremities)
Definition: DImageDraw.h:327
vector< IntPoint > getPoints() const
getPoints() - access a vector with the points of the line
Definition: DImageDraw.h:296
Bresenham(int xi, int yi, int zi, int xf, int yf, int zf)
Constructor : build a 3D line defined by the coordinates of extremities.
Definition: DImageDraw.h:259
Bresenham(int xi, int yi, int xf, int yf)
Constructor : build a 2D line defined by the coordinates of extremities.
Definition: DImageDraw.h:279
Bresenham(const IntPoint &pf)
Constructor : build a line (2D or 3D) with extremities the origin and pf
Definition: DImageDraw.h:246
Bresenham(const IntPoint &pi, const IntPoint &pf)
Constructor : build a line (2D or 3D) with extremities pi and pf
Definition: DImageDraw.h:234
size_t nbPoints()
nbPoints() - the number of pixels in the line
Definition: DImageDraw.h:317
IntPoint getPoint(UINT i)
getPoint() -
Definition: DImageDraw.h:306
RES_T sqrt(const Image< T1 > &imIn, Image< T2 > &imOut)
sqrt() - square root of an image
Definition: DImageArith.hpp:926
RES_T pow(const Image< T1 > &imIn, Image< T2 > &imOut, double exponent=2)
pow() - power of an image
Definition: DImageArith.hpp:905
Point< int > IntPoint
IntPoint.
Definition: DCommon.h:212
vector< IntPoint > bresenhamPoints(int p1x, int p1y, int p2x, int p2y, int xMax=0, int yMax=0)
Find intermediate points forming a line between two end points, using the Bresenham Line Draw Algorit...
Definition: DImageDraw.h:62
vector< IntPoint > bresenhamLine(int p1x, int p1y, int p2x, int p2y)
Find intermediate points forming a line between two end points, using the Bresenham Line Draw Algorit...
Definition: DDraw.cpp:42