Orfeo Toolbox  3.16
itkPolygonSpatialObject.txx
Go to the documentation of this file.
1 /*=========================================================================
2 
3 Program: Insight Segmentation & Registration Toolkit
4 Module: $RCSfile: itkPolygonSpatialObject.txx,v $
5 Language: C++
6 Date: $Date: 2010-07-07 15:53:07 $
7 Version: $Revision: 1.30 $
8 
9 Copyright (c) Insight Software Consortium. All rights reserved.
10 See ITKCopyright.txt or http://www.itk.org/HTML/Copyright.htm for details.
11 
12 This software is distributed WITHOUT ANY WARRANTY; without even
13 the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
14 PURPOSE. See the above copyright notices for more information.
15 
16 =========================================================================*/
17 
18 #ifndef __itkPolygonSpatialObject_txx
19 #define __itkPolygonSpatialObject_txx
20 
22 #include "itkExceptionObject.h"
23 
24 namespace itk
25 {
26 
27 template <unsigned int TDimension >
30 ::Plane() const
31 {
32  if (Self::ObjectDimension == 2)
33  {
34  return Axial;
35  }
36 
38  // local typedef to shut up the compiler...
39 
40  const PointListType & points = this->GetPoints();
41  typename PointListType::const_iterator it = points.begin();
42  typename PointListType::const_iterator itend = points.end();
43  double min[3],max[3]; // x, y, z
44  int i;
45  for(i = 0; i < 3; i++)
46  {
47  max[i] = NumericTraits<double>::NonpositiveMin();
48  min[i] = NumericTraits<double>::max();
49  }
50  while (it != itend)
51  {
52  PointType curpoint = (*it).GetPosition();
53  for(i = 0; i < 3; i++)
54  {
55  if(min[i] > curpoint[i]) min[i] = curpoint[i];
56  if(max[i] < curpoint[i]) max[i] = curpoint[i];
57  }
58  it++;
59  }
60  if(min[0] == max[0] && min[1] != max[1] && min[2] != max[2])
61  {
62  plane = Sagittal;
63  }
64  else if(min[0] != max[0] && min[1] == max[1] && min[2] != max[2])
65  {
66  plane = Coronal;
67  }
68  else if(min[0] != max[0] && min[1] != max[1] && min[2] == max[2])
69  {
70  plane = Axial;
71  }
72  else
73  {
74  plane = Unknown;
75  }
76  return plane;
77 }
78 
79 template <unsigned int TDimension >
80 bool
82 ::IsClosed() const
83 {
84  const PointListType & points = this->GetPoints();
85  typename PointListType::const_iterator it = points.begin();
86  typename PointListType::const_iterator itend = points.end();
87  itend--;
88  return (*it).GetPosition() == (*itend).GetPosition();
89 }
90 
91 template <unsigned int TDimension >
92 unsigned int
95 {
96  return (this->GetPoints()).size();
97 }
98 
99 template <unsigned int TDimension >
102 ::ClosestPoint( const PointType & curPoint ) const
103 {
104  const PointListType &points = this->GetPoints();
105  typename PointListType::const_iterator it = points.begin();
106  typename PointListType::const_iterator itend = points.end();
107  double distance = NumericTraits<double>::max();
108 
109  if(it == itend)
110  {
111  ExceptionObject exception(__FILE__, __LINE__);
112  exception.SetDescription(
113  "PolygonSpatialObject: ClosestPoint called using an empty point list");
114  throw exception;
115  }
116 
117  PointType closestPoint;
118  closestPoint.Fill(0.0);
119  while (it != itend)
120  {
122  = (*it).GetPosition();
123  double curdistance = curpos.EuclideanDistanceTo(curPoint);
124  if(curdistance < distance)
125  {
126  closestPoint = (*it).GetPosition();
127  distance = curdistance;
128  }
129  it++;
130  }
131  return closestPoint;
132 }
133 
134 template <unsigned int TDimension >
135 double
138 {
139  //To find the area of a planar polygon not in the x-y plane, use:
140  //2 A(P) = vcl_abs(N . (sum_{i=0}^{n-1} (v_i x v_{i+1})))
141  //where N is a unit vector normal to the plane. The `.' represents the
142  //dot product operator, the `x' represents the cross product operator,
143  // and vcl_abs() is the absolute value function.
144  double area = 0.0;
145  int numpoints = this->NumberOfPoints();
146  int X, Y;
147  if(numpoints < 3)
148  {
149  return 0;
150  }
151  switch(this->Plane())
152  {
153  case Sagittal:
154  X = 1; Y = 2;
155  break;
156  case Axial:
157  X = 0; Y = 1;
158  break;
159  case Coronal:
160  X = 0; Y = 2;
161  break;
162  default:
163  ExceptionObject exception(__FILE__, __LINE__);
164  exception.SetDescription("File cannot be read");
165  throw exception;
166  }
167  const PointListType & points = this->GetPoints();
168  typename PointListType::const_iterator it = points.begin();
169  PointType start = (*it).GetPosition();
170  for(int i = 0; i < numpoints; i++)
171  {
172  PointType a = (*it).GetPosition();
173  PointType b;
174  it++;
175  if(i == numpoints - 1)
176  {
177  b = start;
178  }
179  else
180  {
181  b = (*it).GetPosition();
182  }
183  //
184  // closed PolygonGroup has first and last points the same
185  if(a == b)
186  {
187  continue;
188  }
189  area += a[X] * b[Y] - a[Y] * b[X];
190  }
191  area *= 0.5;
192  return area < 0.0 ? -area : area;
193 }
194 
195 template <unsigned int TDimension >
196 double
199 {
200  return m_Thickness * this->MeasureArea();
201 }
202 
203 template <unsigned int TDimension >
204 double
207 {
208  double perimeter = 0.0;
209  int numpoints = this->NumberOfPoints();
210  if(numpoints < 3)
211  {
212  return 0;
213  }
214  const PointListType & points = this->GetPoints();
215 
216  typename PointListType::const_iterator it = points.begin();
217 
218  PointType start = (*it).GetPosition();
219  for(int i = 0; i < numpoints; i++)
220  {
221  PointType a = (*it).GetPosition();
222  PointType b;
223  it++;
224  if(i == numpoints - 1)
225  {
226  b = start;
227  }
228  else
229  {
230  b = (*it).GetPosition();
231  }
232  //
233  // closed PolygonGroup has first and last points the same
234  if(a == b)
235  {
236  continue;
237  }
238  double curdistance = a.EuclideanDistanceTo(b);
239  perimeter += curdistance;
240  }
241  return perimeter;
242 }
243 
244 template <unsigned int TDimension >
245 bool
247 ::DeletePoint( const PointType & pointToDelete )
248 {
249 
250  PointListType &points = this->GetPoints();
251  typename PointListType::iterator it = points.begin();
252  typename PointListType::iterator itend = points.end();
253  if(it == itend)
254  {
255  return false;
256  }
257 
258  while (it != itend)
259  {
260  BlobPointType &curPoint = (*it);
262  = curPoint.GetPosition();
263  if(curpos == pointToDelete)
264  {
265  points.erase(it);
266  return true;
267  }
268  it++;
269  }
270  return false;
271 }
272 
273 template <unsigned int TDimension >
274 bool
276 ::AddPoint( const PointType & pointToAdd )
277 {
278  BlobPointType newPoint;
279  newPoint.SetPosition(pointToAdd);
280  this->GetPoints().push_back(newPoint);
281  return true;
282 }
283 
284 template <unsigned int TDimension >
285 bool
287 ::InsertPoint( const PointType & point1, const PointType & pointToAdd )
288 {
289 
290  PointListType &points = this->GetPoints();
291  typename PointListType::iterator it = points.begin();
292  typename PointListType::iterator itend = points.end();
293  if(it == itend)
294  {
295  this->AddPoint(pointToAdd);
296  return true;
297  }
298 
299  while (it != itend)
300  {
301  BlobPointType &curPoint = (*it);
303  = curPoint.GetPosition();
304  if(curpos == point1)
305  {
306  typename PointListType::iterator after = it;
307  after++;
308  BlobPointType newPoint;
309  newPoint.SetPosition(pointToAdd);
310  points.insert(after,1,newPoint);
311  return true;
312  }
313  it++;
314  }
315  return false;
316 }
317 
318 template <unsigned int TDimension >
319 bool
321 ::ReplacePoint( const PointType & oldpoint, const PointType & newPoint )
322 {
323  if (oldpoint == newPoint)
324  {
325  return true;
326  }
327  PointListType &points = this->GetPoints();
328  typename PointListType::iterator it = points.begin();
329  typename PointListType::iterator itend = points.end();
330  if(it == itend)
331  {
332  this->AddPoint(newPoint);
333  return true;
334  }
335 
336  while(it != itend)
337  {
338  BlobPointType &curPoint = (*it);
340  = curPoint.GetPosition();
341  if(curpos == oldpoint)
342  {
343  typename PointListType::iterator after = it;
344  after++;
345  BlobPointType newBlobPoint;
346  newBlobPoint.SetPosition(newPoint);
347  points.insert(after,1,newBlobPoint);
348  points.erase(it);
349  return true;
350  }
351  it++;
352  }
353  return false;
354 }
355 
356 template <unsigned int TDimension >
357 bool
359 ::RemoveSegment( const PointType & startPoint, const PointType & endPoint )
360 {
361  PointListType &points = this->GetPoints();
362  typename PointListType::iterator it = points.begin();
363  typename PointListType::iterator itend = points.end();
364  typename PointListType::iterator first;
365  typename PointListType::iterator last;
366 
367  if(it == itend)
368  {
369  return false;
370  }
371  int foundcount = 0;
372  while(it != itend)
373  {
374  BlobPointType &curPoint = (*it);
376  = curPoint.GetPosition();
377  if(curpos == startPoint)
378  {
379  first = it;
380  foundcount++;
381  }
382  //
383  // make sure you find the start before you find the end
384  else if(foundcount > 0 && curpos == endPoint)
385  {
386  last = it;
387  foundcount++;
388  }
389  if(foundcount == 2)
390  {
391  break;
392  }
393  it++;
394  }
395  if(foundcount != 2)
396  {
397  return false;
398  }
399 
400  points.erase(first,points.erase(last));
401  return true;
402 }
403 
404 template <unsigned int TDimension >
405 bool
407 ::IsInside( const PointType & point) const
408 {
409  return this->IsInside(point, 0, NULL);
410 }
411 
412 template <unsigned int TDimension >
413 bool
415 ::IsInside( const PointType & point,unsigned int ,char * ) const
416 {
417  int numpoints = this->NumberOfPoints();
418  int X, Y;
419  if(numpoints < 3)
420  {
421  return false;
422  }
423  switch( this->Plane() )
424  {
425  case Sagittal:
426  X = 1; Y = 2;
427  break;
428  case Axial:
429  X = 0; Y = 1;
430  break;
431  case Coronal:
432  X = 0; Y = 2;
433  break;
434  default:
435  ExceptionObject exception(__FILE__, __LINE__);
436  exception.SetDescription("non-planar polygon");
437  throw exception;
438  }
439 
440  if( !this->SetInternalInverseTransformToWorldToIndexTransform() )
441  {
442  return false;
443  }
444 
445  PointType transformedPoint =
446  this->GetInternalInverseTransform()->TransformPoint(point);
447 
448  const PointListType & points = this->GetPoints();
449  typename PointListType::const_iterator it = points.begin();
450  typename PointListType::const_iterator itend = points.end();
451  itend--;
452 
453  PointType first = (*it).GetPosition();
454  PointType last = (*itend).GetPosition();
455 
456  // If last point same as first, don't bother with it.
457  if( this->IsClosed() )
458  {
459  numpoints--;
460  }
461 
462  bool oddNodes = false;
463 
464  PointType node1;
465  PointType node2;
466 
467  for(int i = 0; i < numpoints; i++)
468  {
469  node1 = (*it).GetPosition();
470  it++;
471  if(i == numpoints - 1)
472  {
473  node2 = first;
474  }
475  else
476  {
477  node2 = (*it).GetPosition();
478  }
479 
480  const double x = transformedPoint[X];
481  const double y = transformedPoint[Y];
482 
483  if((node1[Y] < y && node2[Y] >= y) ||
484  (node2[Y] < y && node1[Y] >= y))
485  {
486  if( node1[X] + (y - node1[Y])/
487  (node2[Y] - node1[Y]) * (node2[X] - node1[X]) < x )
488  {
489  oddNodes = !oddNodes;
490  }
491  }
492  }
493 
494  return oddNodes;
495 }
496 
497 template <unsigned int TDimension >
498 void
500 ::PrintSelf( std::ostream& os, Indent indent ) const
501 {
502  Superclass::PrintSelf( os, indent );
503  os << indent << m_Thickness << std::endl;
504 }
505 
506 }
507 #endif

Generated at Sat Feb 2 2013 23:59:48 for Orfeo Toolbox with doxygen 1.8.1.1