21 #include <vtkCellArray.h>
22 #include <vtkPoints.h>
23 #include <vtkPolyData.h>
24 #include <vtkPolyDataNormals.h>
25 #include <vtkSmartPointer.h>
34 auto polyLineEnd = polyLine.cend();
36 for (
auto polyLineIter = polyLine.cbegin(); polyLineIter != polyLineEnd; ++polyLineIter)
38 centerPoint[0] +=
static_cast<mitk::Point2D>(*polyLineIter)[0];
39 centerPoint[1] +=
static_cast<mitk::Point2D>(*polyLineIter)[1];
42 const size_t numPoints = polyLine.size();
44 centerPoint[0] /= numPoints;
45 centerPoint[1] /= numPoints;
59 for (
size_t i = 0; i < numPolyLines; ++i)
63 centerPoint[0] += polyLineCenterPoint[0];
64 centerPoint[1] += polyLineCenterPoint[1];
67 centerPoint[0] /= numPolyLines;
68 centerPoint[1] /= numPolyLines;
77 const mitk::Point2D point2d = centerPoint2d + bendDirection2d;
80 planeGeometry->
Map(point2d, point3d);
83 planeGeometry->
Map(centerPoint2d, centerPoint3d);
86 bendDirection3d.Normalize();
88 return bendDirection3d;
92 : m_Length(1), m_NumberOfSegments(1), m_TwistAngle(0), m_BendAngle(0), m_FlipDirection(false), m_FlipNormals(false)
94 m_BendDirection[0] = 0;
95 m_BendDirection[1] = 0;
97 this->SetNumberOfRequiredInputs(1);
98 this->SetNumberOfRequiredOutputs(1);
110 typedef PolyLine::const_iterator PolyLineConstIter;
113 mitkThrow() <<
"Length is not positive!";
115 if (m_NumberOfSegments == 0)
116 mitkThrow() <<
"Number of segments is zero!";
118 if (m_BendAngle != 0 && m_BendDirection[0] == 0 && m_BendDirection[1] == 0)
119 mitkThrow() <<
"Bend direction is zero-length vector!";
123 if (input ==
nullptr)
124 mitkThrow() <<
"Primary input is not a planar figure!";
128 if (numPolyLines == 0)
129 mitkThrow() <<
"Primary input does not contain any poly lines!";
133 if (planeGeometry ==
nullptr)
134 mitkThrow() <<
"Could not get plane geometry from primary input!";
137 planeNormal.Normalize();
142 planeGeometry->
Map(centerPoint2d, centerPoint3d);
147 const ScalarType radius = m_Length * (360 / m_BendAngle) / (2 * vnl_math::pi);
148 const Vector3D scaledBendDirection3d = bendDirection3d * radius;
150 Vector3D bendAxis = itk::CrossProduct(planeNormal, bendDirection3d);
151 bendAxis.Normalize();
155 vtkIdType baseIndex = 0;
157 for (
size_t i = 0; i < numPolyLines; ++i)
160 const size_t numPoints = polyLine.size();
163 mitkThrow() <<
"Poly line " << i <<
" of primary input consists of less than two points!";
165 std::vector<mitk::Point3D> crossSection;
167 PolyLineConstIter polyLineEnd = polyLine.end();
169 for (PolyLineConstIter polyLineIter = polyLine.begin(); polyLineIter != polyLineEnd; ++polyLineIter)
172 planeGeometry->
Map(*polyLineIter, point);
173 crossSection.push_back(point);
176 const ScalarType segmentLength = m_Length / m_NumberOfSegments;
177 Vector3D translation = planeNormal * segmentLength;
179 const bool bend = std::abs(m_BendAngle) >
mitk::eps;
180 const bool twist = std::abs(m_TwistAngle) >
mitk::eps;
182 const ScalarType twistAngle = twist ? m_TwistAngle / m_NumberOfSegments * vnl_math::pi / 180 : 0;
184 ScalarType bendAngle = bend ? m_BendAngle / m_NumberOfSegments * vnl_math::pi / 180 : 0;
192 for (
size_t k = 0; k < numPoints; ++k)
193 points->InsertNextPoint(crossSection[k].GetDataPointer());
195 for (
size_t j = 1; j <= m_NumberOfSegments; ++j)
200 transform->Translate(centerPoint3d.GetVectorFromOrigin(),
true);
204 transform->Translate(scaledBendDirection3d,
true);
205 transform->Rotate3D(bendAxis, bendAngle * j,
true);
206 transform->Translate(-scaledBendDirection3d,
true);
210 transform->Translate(translation * j,
true);
214 transform->Rotate3D(planeNormal, twistAngle * j,
true);
217 transform->Translate(-centerPoint3d.GetVectorFromOrigin(),
true);
219 for (
size_t k = 0; k < numPoints; ++k)
221 const mitk::Point3D transformedPoint = transform->TransformPoint(crossSection[k]);
222 points->InsertNextPoint(transformedPoint.GetDataPointer());
226 for (
size_t j = 0; j < m_NumberOfSegments; ++j)
228 for (
size_t k = 1; k < numPoints; ++k)
231 cell[0] = baseIndex + j * numPoints + (k - 1);
232 cell[1] = baseIndex + (j + 1) * numPoints + (k - 1);
233 cell[2] = baseIndex + j * numPoints + k;
235 cells->InsertNextCell(3, cell);
238 cell[1] = baseIndex + (j + 1) * numPoints + k;
240 cells->InsertNextCell(3, cell);
243 if (input->
IsClosed() && numPoints > 2)
246 cell[0] = baseIndex + j * numPoints + (numPoints - 1);
247 cell[1] = baseIndex + (j + 1) * numPoints + (numPoints - 1);
248 cell[2] = baseIndex + j * numPoints;
250 cells->InsertNextCell(3, cell);
253 cell[1] = baseIndex + (j + 1) * numPoints;
255 cells->InsertNextCell(3, cell);
259 baseIndex += points->GetNumberOfPoints();
263 polyData->SetPoints(points);
264 polyData->SetPolys(cells);
267 polyDataNormals->SetFlipNormals(m_FlipNormals);
268 polyDataNormals->SetInputData(polyData);
269 polyDataNormals->SplittingOff();
271 polyDataNormals->Update();
273 Surface *output =
static_cast<Surface *
>(this->GetPrimaryOutput());
283 return idx == 0 ?
Surface::New().GetPointer() :
nullptr;
288 return this->IsIndexedOutputName(name) ? this->MakeOutput(this->MakeIndexFromOutputName(name)) :
nullptr;
293 Superclass::PrintSelf(os, indent);
295 os << indent <<
"Length: " << m_Length << std::endl;
296 os << indent <<
"Number of Segments: " << m_NumberOfSegments << std::endl;
297 os << indent <<
"Twist Angle: " << m_TwistAngle << std::endl;
298 os << indent <<
"Bend Angle: " << m_BendAngle << std::endl;
299 os << indent <<
"Bend Direction: " << m_BendDirection << std::endl;
300 os << indent <<
"Flip Normals: " << m_FlipNormals << std::endl;
305 this->SetPrimaryInput(planarFigure);
310 return static_cast<Surface *
>(this->GetPrimaryOutput());
Class for storing surfaces (vtkPolyData).
itk::SmartPointer< Self > Pointer
virtual bool Map(const mitk::Point3D &pt3d_mm, mitk::Point2D &pt2d_mm) const
Project a 3D point given in mm (pt3d_mm) onto the 2D geometry. The result is a 2D point in mm (pt2d_m...
Vector3D GetNormal() const
Normal of the plane.
Vector< ScalarType, 3 > Vector3D
virtual void SetVtkPolyData(vtkPolyData *polydata, unsigned int t=0)
MITKCORE_EXPORT const ScalarType eps
Describes a two-dimensional, rectangular plane.
static itkEventMacro(BoundingShapeInteractionEvent, itk::AnyEvent) class MITKBOUNDINGSHAPE_EXPORT BoundingShapeInteractor Pointer New()
Basic interaction methods for mitk::GeometryData.