Medical Imaging Interaction Toolkit  2018.4.99-389bf124
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 (DKFZ)
6 All rights reserved.
7 
8 Use of this source code is governed by a 3-clause BSD license that can be
9 found in the LICENSE file.
10 
11 ============================================================================*/
12 
13 #include "mitkPlanarCircle.h"
14 #include "mitkPlaneGeometry.h"
15 
16 #include "mitkProperties.h"
17 
19  : FEATURE_ID_RADIUS(this->AddFeature("Radius", "mm")),
20  FEATURE_ID_DIAMETER(this->AddFeature("Diameter", "mm")),
21  FEATURE_ID_AREA(this->AddFeature("Area", "mm2")),
22  m_MinRadius(0),
23  m_MaxRadius(100),
24  m_MinMaxRadiusContraintsActive(false),
25  m_RadiusFixed(false)
26 {
27  // Circle has two control points
29  this->SetNumberOfPolyLines(1);
30  this->SetProperty("closed", mitk::BoolProperty::New(true));
31 }
32 
34  : FEATURE_ID_RADIUS(this->AddFeature("Radius", "mm")),
35  FEATURE_ID_DIAMETER(this->AddFeature("Diameter", "mm")),
36  FEATURE_ID_AREA(this->AddFeature("Area", "mm2")),
37  m_MinRadius(fixedRadius),
38  m_MaxRadius(100),
40  m_RadiusFixed(true)
41 {
42  // Fixed Circle has 1 control points
44  this->SetNumberOfPolyLines(1);
45  this->SetProperty("closed", mitk::BoolProperty::New(true));
46 }
47 
48 bool mitk::PlanarCircle::SetControlPoint(unsigned int index, const Point2D &point, bool /*createIfDoesNotExist*/)
49 {
50  // moving center point
51  if (index == 0)
52  {
53  const Point2D &centerPoint = GetControlPoint(0);
54  if (!m_RadiusFixed)
55  {
56  Point2D boundaryPoint = GetControlPoint(1);
57  const vnl_vector<ScalarType> vec = (point.GetVnlVector() - centerPoint.GetVnlVector());
58 
59  boundaryPoint[0] += vec[0];
60  boundaryPoint[1] += vec[1];
61  PlanarFigure::SetControlPoint(1, boundaryPoint);
62  }
64  return true;
65  }
66  else if (index == 1)
67  {
68  PlanarFigure::SetControlPoint(index, point);
69  return true;
70  }
71  return false;
72 }
73 
75 {
76  if (this->GetPlaneGeometry() == nullptr)
77  {
78  return point;
79  }
80 
81  Point2D indexPoint;
82  this->GetPlaneGeometry()->WorldToIndex(point, indexPoint);
83 
85  if (indexPoint[0] < bounds[0])
86  {
87  indexPoint[0] = bounds[0];
88  }
89  if (indexPoint[0] > bounds[1])
90  {
91  indexPoint[0] = bounds[1];
92  }
93  if (indexPoint[1] < bounds[2])
94  {
95  indexPoint[1] = bounds[2];
96  }
97  if (indexPoint[1] > bounds[3])
98  {
99  indexPoint[1] = bounds[3];
100  }
101 
102  Point2D constrainedPoint;
103  this->GetPlaneGeometry()->IndexToWorld(indexPoint, constrainedPoint);
104 
106  {
107  if (index != 0)
108  {
109  const Point2D &centerPoint = this->GetControlPoint(0);
110  const double euclideanDinstanceFromCenterToPoint1 = centerPoint.EuclideanDistanceTo(point);
111 
112  Vector2D vectorProjectedPoint = point - centerPoint;
113  vectorProjectedPoint.Normalize();
114 
115  if (euclideanDinstanceFromCenterToPoint1 > m_MaxRadius)
116  {
117  vectorProjectedPoint *= m_MaxRadius;
118  constrainedPoint = centerPoint;
119  constrainedPoint += vectorProjectedPoint;
120  }
121  else if (euclideanDinstanceFromCenterToPoint1 < m_MinRadius)
122  {
123  vectorProjectedPoint *= m_MinRadius;
124  constrainedPoint = centerPoint;
125  constrainedPoint += vectorProjectedPoint;
126  }
127  }
128  }
129 
130  return constrainedPoint;
131 }
132 
134 {
135  // TODO: start circle at specified boundary point...
136 
137  // clear the PolyLine-Contrainer, it will be reconstructed soon enough...
138  this->ClearPolyLines();
139 
140  const Point2D &centerPoint = GetControlPoint(0);
141 
142  double radius = m_MinRadius;
143 
144  if (!m_RadiusFixed)
145  {
146  const Point2D &boundaryPoint = GetControlPoint(1);
147  radius = centerPoint.EuclideanDistanceTo(boundaryPoint);
148  }
149 
150  // Generate poly-line with 64 segments
151  for (int t = 0; t < 64; ++t)
152  {
153  const double alpha = (double)t * vnl_math::pi / 32.0;
154 
155  // construct the new polyline point ...
156  Point2D polyLinePoint;
157  polyLinePoint[0] = centerPoint[0] + radius * cos(alpha);
158  polyLinePoint[1] = centerPoint[1] + radius * sin(alpha);
159 
160  // ... and append it to the PolyLine.
161  // No extending supported here, so we can set the index of the PolyLineElement to '0'
162  this->AppendPointToPolyLine(0, polyLinePoint);
163  }
164 }
165 
166 void mitk::PlanarCircle::GenerateHelperPolyLine(double /*mmPerDisplayUnit*/, unsigned int /*displayHeight*/)
167 {
168  // A circle does not require a helper object
169 }
170 
172 {
173  // Calculate circle radius and area
174  const Point3D &p0 = this->GetWorldControlPoint(0);
175  double radius = m_MinRadius;
176 
177  if (!m_RadiusFixed)
178  {
179  const Point3D &p1 = this->GetWorldControlPoint(1);
180  radius = p0.EuclideanDistanceTo(p1);
181  }
182 
183  const double area = vnl_math::pi * radius * radius;
184 
185  this->SetQuantity(FEATURE_ID_RADIUS, radius);
186  this->SetQuantity(FEATURE_ID_DIAMETER, 2 * radius);
187  this->SetQuantity(FEATURE_ID_AREA, area);
188 }
189 
190 void mitk::PlanarCircle::PrintSelf(std::ostream &os, itk::Indent indent) const
191 {
192  Superclass::PrintSelf(os, indent);
193 }
194 
196 {
197  if (m_SelectedControlPoint < 0)
198  {
200  }
201 
202  return this->SetControlPoint(m_SelectedControlPoint, point, false);
203 }
204 
205 bool mitk::PlanarCircle::Equals(const PlanarFigure &other) const
206 {
207  const auto *otherCircle = dynamic_cast<const mitk::PlanarCircle *>(&other);
208  if (otherCircle)
209  {
210  return Superclass::Equals(other);
211  }
212  else
213  {
214  return false;
215  }
216 }
Point2D ApplyControlPointConstraints(unsigned int index, const Point2D &point) override
Spatially constrain control points of second (orthogonal) line.
Point2D GetControlPoint(unsigned int index) const
Returns specified control point in 2D world coordinates.
virtual const PlaneGeometry * GetPlaneGeometry() const
Returns (previously set) 2D geometry of this figure.
virtual unsigned int AddFeature(const char *featureName, const char *unitName)
Point3D GetWorldControlPoint(unsigned int index) const
Returns specified control point in world coordinates.
void ResetNumberOfControlPoints(int numberOfControlPoints)
Set the initial number of control points of the planar figure.
const unsigned int FEATURE_ID_DIAMETER
virtual void IndexToWorld(const Point2D &pt_units, Point2D &pt_mm) const
void GeneratePolyLine() override
Generates the poly-line representation of the planar figure.
void SetProperty(const std::string &propertyKey, BaseProperty *property, const std::string &contextName="", bool fallBackOnDefaultContext=false) override
Add new or change existent property.
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.
const unsigned int FEATURE_ID_RADIUS
bool SetCurrentControlPoint(const Point2D &point) override
static Pointer New()
void SetQuantity(unsigned int index, double quantity)
virtual void WorldToIndex(const Point2D &pt_mm, Point2D &pt_units) const
void EvaluateFeaturesInternal() override
Calculates feature quantities of the planar figure.
void PrintSelf(std::ostream &os, itk::Indent indent) const override
void AppendPointToPolyLine(unsigned int index, PolyLineElement element)
Append a point to the PolyLine # index.
void SetNumberOfPolyLines(unsigned int numberOfPolyLines)
defines the number of PolyLines that will be available
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 either through two control points or by one cont...
void GenerateHelperPolyLine(double mmPerDisplayUnit, unsigned int displayHeight) override
Generates the poly-lines that should be drawn the same size regardless of zoom.
const unsigned int FEATURE_ID_AREA
const BoundsArrayType GetBounds() const
void ClearPolyLines()
clears the list of PolyLines. Call before re-calculating a new Polyline.
BoundingBoxType::BoundsArrayType BoundsArrayType