Seg3D  2.4
Seg3D is a free volume segmentation and processing tool developed by the NIH Center for Integrative Biomedical Computing at the University of Utah Scientific Computing and Imaging (SCI) Institute.
draw.hxx
1 /*
2  For more information, please see: http://software.sci.utah.edu
3 
4  The MIT License
5 
6  Copyright (c) 2016 Scientific Computing and Imaging Institute,
7  University of Utah.
8 
9 
10  Permission is hereby granted, free of charge, to any person obtaining a
11  copy of this software and associated documentation files (the "Software"),
12  to deal in the Software without restriction, including without limitation
13  the rights to use, copy, modify, merge, publish, distribute, sublicense,
14  and/or sell copies of the Software, and to permit persons to whom the
15  Software is furnished to do so, subject to the following conditions:
16 
17  The above copyright notice and this permission notice shall be included
18  in all copies or substantial portions of the Software.
19 
20  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
21  OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
22  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
23  THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
24  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
25  FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
26  DEALINGS IN THE SOFTWARE.
27 */
28 
29 // File : draw.hxx
30 // Author : Pavel A. Koshevoy
31 // Created : 2006/01/04 11:26
32 // Copyright : (C) 2004-2008 University of Utah
33 // Description : Functions for drawing anti-aliased lines using
34 // Xiaolin Wu's line algorithm taken from the wikipedia article
35 // http://en.wikipedia.org/wiki/Xiaolin_Wu's_line_algorithm
36 
37 #ifndef DRAW_HXX_
38 #define DRAW_HXX_
39 
40 
41 // system includes:
42 #include <algorithm>
43 
44 // ITK includes:
45 #include <itkImage.h>
46 
47 
48 namespace wu
49 {
50  //----------------------------------------------------------------
51  // ipart
52  //
53  // return integer part of x
54  inline double ipart(const double & x)
55  {
56  return (x == x) ? x - fmod(x, 1.0) : x;
57  }
58 
59  //----------------------------------------------------------------
60  // round
61  //
62  inline double round(const double & x)
63  {
64  return ipart(x + 0.5);
65  }
66 
67  //----------------------------------------------------------------
68  // fpart
69  //
70  // return fractional part of x
71  inline double fpart(const double & x)
72  {
73  return x - ipart(x);
74  }
75 
76  //----------------------------------------------------------------
77  // rfpart
78  //
79  inline double rfpart(const double & x)
80  {
81  return 1.0 - fpart(x);
82  }
83 
84  //----------------------------------------------------------------
85  // plot_pixel
86  //
87  template <class image_t>
88  void
89  plot_pixel(typename image_t::Pointer & image,
90  const unsigned int & width,
91  const unsigned int & height,
92  const typename image_t::IndexType & index,
93  const double & w,
94  const double & c)
95  {
96  if ((unsigned int)(index[0]) >= width ||
97  (unsigned int)(index[1]) >= height)
98  {
99  return;
100  }
101 
102  typedef typename image_t::PixelType color_t;
103  double o = double(image->GetPixel(index));
104  double n = (1.0 - w) * o + w * c;
105  n = std::max(0.0, std::min(255.0, n));
106  image->SetPixel(index, color_t(n));
107  }
108 
109  //----------------------------------------------------------------
110  // plot_normal
111  //
112  template <class image_t>
113  void
114  plot_normal(typename image_t::Pointer & image,
115  const unsigned int & width,
116  const unsigned int & height,
117  const double & x,
118  const double & y,
119  const double & w,
120  const double & c)
121  {
122  typename image_t::IndexType index;
123  index[0] = (unsigned int)(x);
124  index[1] = (unsigned int)(y);
125  plot_pixel<image_t>(image, width, height, index, w, c);
126  }
127 
128  //----------------------------------------------------------------
129  // plot_swapped
130  //
131  template <class image_t>
132  void
133  plot_swapped(typename image_t::Pointer & image,
134  const unsigned int & width,
135  const unsigned int & height,
136  const double & x,
137  const double & y,
138  const double & w,
139  const double & c)
140  {
141  typename image_t::IndexType index;
142  index[0] = (unsigned int)(y);
143  index[1] = (unsigned int)(x);
144  plot_pixel<image_t>(image, width, height, index, w, c);
145  }
146 
147  //----------------------------------------------------------------
148  // draw_nearly_horizontal_line
149  //
150  // Xiaolin Wu's line algorithm taken from the wikipedia article
151  // http://en.wikipedia.org/wiki/Xiaolin_Wu's_line_algorithm
152  //
153  template <class image_t>
154  void
155  draw_nearly_horizontal_line
156  (typename image_t::Pointer & image,
157  const double & c,
158  double x1,
159  double y1,
160  double x2,
161  double y2,
162  void(*draw_pixel)(typename image_t::Pointer &, // image
163  const unsigned int &, // width
164  const unsigned int &, // height
165  const double &, // x
166  const double &, // y
167  const double &, // weight
168  const double &)) // paint color
169  {
170  typename image_t::SizeType sz =
171  image->GetLargestPossibleRegion().GetSize();
172 
173  // check that x1 < x2
174  if (x2 < x1)
175  {
176  std::swap(x1, x2);
177  std::swap(y1, y2);
178  }
179 
180  double dx = x2 - x1;
181  double dy = y2 - y1;
182  double gradient = dy / dx;
183 
184  // handle first endpoint
185  double xend = round(x1);
186  double yend = y1 + gradient * (xend - x1);
187  double xgap = rfpart(x1 + 0.5);
188  double xpxl1 = xend; // this will be used in the main loop
189  double ypxl1 = ipart(yend);
190  draw_pixel(image, sz[0], sz[1], xpxl1, ypxl1, rfpart(yend) * xgap, c);
191  draw_pixel(image, sz[0], sz[1], xpxl1, ypxl1 + 1, fpart(yend) * xgap, c);
192  double intery = yend + gradient; // first y-intersection for the main loop
193 
194  // handle second endpoint
195  xend = round(x2);
196  yend = y2 + gradient * (xend - x2);
197  xgap = rfpart(x2 - 0.5);
198  double xpxl2 = xend; // this will be used in the main loop
199  double ypxl2 = ipart(yend);
200  draw_pixel(image, sz[0], sz[1], xpxl2, ypxl2, rfpart(yend) * xgap, c);
201  draw_pixel(image, sz[0], sz[1], xpxl2, ypxl2 + 1, fpart(yend) * xgap, c);
202 
203  // main loop
204  for (double x = xpxl1 + 1.0; x <= xpxl2 - 1.0; x += 1.0)
205  {
206  draw_pixel(image, sz[0], sz[1], x, ipart(intery), rfpart(intery), c);
207  draw_pixel(image, sz[0], sz[1], x, ipart(intery) + 1, fpart(intery), c);
208  intery = intery + gradient;
209  }
210  }
211 }
212 
213 //----------------------------------------------------------------
214 // draw_line
215 //
216 template <class image_t>
217 void
218 draw_line(typename image_t::Pointer & image,
219  const typename image_t::PixelType color,
220  double x1,
221  double y1,
222  double x2,
223  double y2)
224 {
225  if (false)
226  {
227  // MSVC++ will not instantiate plot_normal and plot_swapped
228  // unless it sees them called explicitly:
229  wu::plot_normal<image_t>(image, 0, 0, 0.0, 0.0, 0.0, 0.0);
230  wu::plot_swapped<image_t>(image, 0, 0, 0.0, 0.0, 0.0, 0.0);
231  }
232 
233  double dx = fabs(x2 - x1);
234  double dy = fabs(y2 - y1);
235 
236  typename image_t::PointType origin = image->GetOrigin();
237  typename image_t::SpacingType spacing = image->GetSpacing();
238 
239  x1 /= spacing[0];
240  x2 /= spacing[0];
241 
242  y1 /= spacing[1];
243  y2 /= spacing[1];
244 
245  if (dx > dy)
246  {
247  // horizontal line:
248  wu::draw_nearly_horizontal_line<image_t>(image,
249  double(color),
250  x1, y1, x2, y2,
251  wu::plot_normal<image_t>);
252  }
253  else if (dy != 0.0)
254  {
255  // vertical line:
256  wu::draw_nearly_horizontal_line<image_t>(image,
257  double(color),
258  y1, x1, y2, x2,
259  wu::plot_swapped<image_t>);
260  }
261 }
262 
263 //----------------------------------------------------------------
264 // draw_line_rotated
265 //
266 template <class image_t>
267 void
268 draw_line_rotated(typename image_t::Pointer & image,
269  const typename image_t::PixelType color,
270  const double & x1,
271  const double & y1,
272  const double & x2,
273  const double & y2,
274  const double & radians,
275  const double & ox = 0.0,
276  const double & oy = 0.0)
277 {
278  const double ct = ::cos(radians);
279  const double st = ::sin(radians);
280 
281  const double u1 = ox + ct * (x1 - ox) - st * (y1 - oy);
282  const double v1 = oy + ct * (y1 - oy) + st * (x1 - ox);
283 
284  const double u2 = ox + ct * (x2 - ox) - st * (y2 - oy);
285  const double v2 = oy + ct * (y2 - oy) + st * (x2 - ox);
286 
287  draw_line<image_t>(image, color, u1, v1, u2, v2);
288 }
289 
290 
291 #endif // DRAW_HXX_
Definition: draw.hxx:48