Medical Imaging Interaction Toolkit  2016.11.0
Medical Imaging Interaction Toolkit
mitkPlanarCircle.cpp
Go to the documentation of this file.
1 /*===================================================================
2 
3 The Medical Imaging Interaction Toolkit (MITK)
4 
5 Copyright (c) German Cancer Research Center,
6 Division of Medical and Biological Informatics.
7 All rights reserved.
8 
9 This software is distributed WITHOUT ANY WARRANTY; without
10 even the implied warranty of MERCHANTABILITY or FITNESS FOR
11 A PARTICULAR PURPOSE.
12 
13 See LICENSE.txt or http://www.mitk.org for details.
14 
15 ===================================================================*/
16 
17 #include "mitkPlanarCircle.h"
18 #include "mitkPlaneGeometry.h"
19 
20 #include "mitkProperties.h"
21 
23  : FEATURE_ID_RADIUS(this->AddFeature("Radius", "mm")),
24  FEATURE_ID_DIAMETER(this->AddFeature("Diameter", "mm")),
25  FEATURE_ID_AREA(this->AddFeature("Area", "mm2")),
26  m_MinRadius(0),
27  m_MaxRadius(100),
28  m_MinMaxRadiusContraintsActive(false)
29 {
30  // Circle has two control points
32  this->SetNumberOfPolyLines(1);
33  this->SetProperty("closed", mitk::BoolProperty::New(true));
34 }
35 
36 bool mitk::PlanarCircle::SetControlPoint(unsigned int index, const Point2D &point, bool /*createIfDoesNotExist*/)
37 {
38  // moving center point
39  if (index == 0)
40  {
41  const Point2D &centerPoint = GetControlPoint(0);
42  Point2D boundaryPoint = GetControlPoint(1);
43  const vnl_vector<ScalarType> vec = (point.GetVnlVector() - centerPoint.GetVnlVector());
44 
45  boundaryPoint[0] += vec[0];
46  boundaryPoint[1] += vec[1];
48  PlanarFigure::SetControlPoint(1, boundaryPoint);
49  return true;
50  }
51  else if (index == 1)
52  {
53  PlanarFigure::SetControlPoint(index, point);
54  return true;
55  }
56  return false;
57 }
58 
60 {
61  if (this->GetPlaneGeometry() == nullptr)
62  {
63  return point;
64  }
65 
66  Point2D indexPoint;
67  this->GetPlaneGeometry()->WorldToIndex(point, indexPoint);
68 
69  const BoundingBox::BoundsArrayType bounds = this->GetPlaneGeometry()->GetBounds();
70  if (indexPoint[0] < bounds[0])
71  {
72  indexPoint[0] = bounds[0];
73  }
74  if (indexPoint[0] > bounds[1])
75  {
76  indexPoint[0] = bounds[1];
77  }
78  if (indexPoint[1] < bounds[2])
79  {
80  indexPoint[1] = bounds[2];
81  }
82  if (indexPoint[1] > bounds[3])
83  {
84  indexPoint[1] = bounds[3];
85  }
86 
87  Point2D constrainedPoint;
88  this->GetPlaneGeometry()->IndexToWorld(indexPoint, constrainedPoint);
89 
90  if (m_MinMaxRadiusContraintsActive)
91  {
92  if (index != 0)
93  {
94  const Point2D &centerPoint = this->GetControlPoint(0);
95  const double euclideanDinstanceFromCenterToPoint1 = centerPoint.EuclideanDistanceTo(point);
96 
97  Vector2D vectorProjectedPoint = point - centerPoint;
98  vectorProjectedPoint.Normalize();
99 
100  if (euclideanDinstanceFromCenterToPoint1 > m_MaxRadius)
101  {
102  vectorProjectedPoint *= m_MaxRadius;
103  constrainedPoint = centerPoint;
104  constrainedPoint += vectorProjectedPoint;
105  }
106  else if (euclideanDinstanceFromCenterToPoint1 < m_MinRadius)
107  {
108  vectorProjectedPoint *= m_MinRadius;
109  constrainedPoint = centerPoint;
110  constrainedPoint += vectorProjectedPoint;
111  }
112  }
113  }
114 
115  return constrainedPoint;
116 }
117 
119 {
120  // TODO: start circle at specified boundary point...
121 
122  // clear the PolyLine-Contrainer, it will be reconstructed soon enough...
123  this->ClearPolyLines();
124 
125  const Point2D &centerPoint = GetControlPoint(0);
126  const Point2D &boundaryPoint = GetControlPoint(1);
127 
128  const double radius = centerPoint.EuclideanDistanceTo(boundaryPoint);
129 
130  // Generate poly-line with 64 segments
131  for (int t = 0; t < 64; ++t)
132  {
133  const double alpha = (double)t * vnl_math::pi / 32.0;
134 
135  // construct the new polyline point ...
136  Point2D polyLinePoint;
137  polyLinePoint[0] = centerPoint[0] + radius * cos(alpha);
138  polyLinePoint[1] = centerPoint[1] + radius * sin(alpha);
139 
140  // ... and append it to the PolyLine.
141  // No extending supported here, so we can set the index of the PolyLineElement to '0'
142  this->AppendPointToPolyLine(0, polyLinePoint);
143  }
144 }
145 
146 void mitk::PlanarCircle::GenerateHelperPolyLine(double /*mmPerDisplayUnit*/, unsigned int /*displayHeight*/)
147 {
148  // A circle does not require a helper object
149 }
150 
152 {
153  // Calculate circle radius and area
154  const Point3D &p0 = this->GetWorldControlPoint(0);
155  const Point3D &p1 = this->GetWorldControlPoint(1);
156 
157  const double radius = p0.EuclideanDistanceTo(p1);
158  const double area = vnl_math::pi * radius * radius;
159 
160  this->SetQuantity(FEATURE_ID_RADIUS, radius);
161  this->SetQuantity(FEATURE_ID_DIAMETER, 2 * radius);
162  this->SetQuantity(FEATURE_ID_AREA, area);
163 }
164 
165 void mitk::PlanarCircle::PrintSelf(std::ostream &os, itk::Indent indent) const
166 {
167  Superclass::PrintSelf(os, indent);
168 }
169 
171 {
172  if (m_SelectedControlPoint < 0)
173  {
174  m_SelectedControlPoint = 1;
175  }
176 
177  return this->SetControlPoint(m_SelectedControlPoint, point, false);
178 }
179 
180 bool mitk::PlanarCircle::Equals(const PlanarFigure &other) const
181 {
182  const mitk::PlanarCircle *otherCircle = dynamic_cast<const mitk::PlanarCircle *>(&other);
183  if (otherCircle)
184  {
185  return Superclass::Equals(other);
186  }
187  else
188  {
189  return false;
190  }
191 }
virtual Point2D ApplyControlPointConstraints(unsigned int index, const Point2D &point) override
Spatially constrain control points of second (orthogonal) line.
void ResetNumberOfControlPoints(int numberOfControlPoints)
Set the initial number of control points of the planar figure.
virtual void GeneratePolyLine() override
Generates the poly-line representation of the planar figure.
bool SetControlPoint(unsigned int index, const Point2D &point, bool createIfDoesNotExist=false) override
Place figure in its minimal configuration (a point at least) onto the given 2D geometry.
virtual bool SetCurrentControlPoint(const Point2D &point) override
static Pointer New()
void SetProperty(const char *propertyKey, BaseProperty *property)
virtual void EvaluateFeaturesInternal() override
Calculates feature quantities of the planar figure.
virtual void PrintSelf(std::ostream &os, itk::Indent indent) const override
void SetNumberOfPolyLines(unsigned int numberOfPolyLines)
defines the number of PolyLines that will be available
virtual bool Equals(const mitk::PlanarFigure &other) const override
Compare two PlanarFigure objects Note: all subclasses have to implement the method on their own...
virtual bool SetControlPoint(unsigned int index, const Point2D &point, bool createIfDoesNotExist=false)
Base-class for geometric planar (2D) figures, such as lines, circles, rectangles, polygons...
Implementation of PlanarFigure representing a circle through two control points.
virtual void GenerateHelperPolyLine(double mmPerDisplayUnit, unsigned int displayHeight) override
Generates the poly-lines that should be drawn the same size regardless of zoom.
BoundingBoxType::BoundsArrayType BoundsArrayType