17 #include <vtkCellArray.h> 18 #include <vtkPoints.h> 19 #include <vtkPolyData.h> 20 #include <vtkPolyDataNormals.h> 21 #include <vtkSmartPointer.h> 30 auto polyLineEnd = polyLine.cend();
32 for (
auto polyLineIter = polyLine.cbegin(); polyLineIter != polyLineEnd; ++polyLineIter)
34 centerPoint[0] +=
static_cast<mitk::Point2D>(*polyLineIter)[0];
35 centerPoint[1] +=
static_cast<mitk::Point2D>(*polyLineIter)[1];
38 const size_t numPoints = polyLine.size();
40 centerPoint[0] /= numPoints;
41 centerPoint[1] /= numPoints;
55 for (
size_t i = 0; i < numPolyLines; ++i)
59 centerPoint[0] += polyLineCenterPoint[0];
60 centerPoint[1] += polyLineCenterPoint[1];
63 centerPoint[0] /= numPolyLines;
64 centerPoint[1] /= numPolyLines;
73 const mitk::Point2D point2d = centerPoint2d + bendDirection2d;
76 planeGeometry->
Map(point2d, point3d);
79 planeGeometry->
Map(centerPoint2d, centerPoint3d);
82 bendDirection3d.Normalize();
84 return bendDirection3d;
88 : m_Length(1), m_NumberOfSegments(1), m_TwistAngle(0), m_BendAngle(0), m_FlipDirection(false), m_FlipNormals(false)
90 m_BendDirection[0] = 0;
91 m_BendDirection[1] = 0;
93 this->SetNumberOfRequiredInputs(1);
94 this->SetNumberOfRequiredOutputs(1);
108 mitkThrow() <<
"Length is not positive!";
110 if (m_NumberOfSegments == 0)
111 mitkThrow() <<
"Number of segments is zero!";
113 if (m_BendAngle != 0 && m_BendDirection[0] == 0 && m_BendDirection[1] == 0)
114 mitkThrow() <<
"Bend direction is zero-length vector!";
116 auto *input =
dynamic_cast<PlanarFigure *
>(this->GetPrimaryInput());
118 if (input ==
nullptr)
119 mitkThrow() <<
"Primary input is not a planar figure!";
121 size_t numPolyLines = input->GetPolyLinesSize();
123 if (numPolyLines == 0)
124 mitkThrow() <<
"Primary input does not contain any poly lines!";
126 const auto *planeGeometry =
dynamic_cast<const PlaneGeometry *
>(input->GetPlaneGeometry());
128 if (planeGeometry ==
nullptr)
129 mitkThrow() <<
"Could not get plane geometry from primary input!";
131 Vector3D planeNormal = planeGeometry->GetNormal();
132 planeNormal.Normalize();
137 planeGeometry->Map(centerPoint2d, centerPoint3d);
142 const ScalarType radius = m_Length * (360 / m_BendAngle) / (2 * vnl_math::pi);
143 const Vector3D scaledBendDirection3d = bendDirection3d * radius;
145 Vector3D bendAxis = itk::CrossProduct(planeNormal, bendDirection3d);
146 bendAxis.Normalize();
148 vtkSmartPointer<vtkPoints> points = vtkSmartPointer<vtkPoints>::New();
149 vtkSmartPointer<vtkCellArray> cells = vtkSmartPointer<vtkCellArray>::New();
150 vtkIdType baseIndex = 0;
152 for (
size_t i = 0; i < numPolyLines; ++i)
154 const PolyLine polyLine = input->GetPolyLine(i);
155 const size_t numPoints = polyLine.size();
158 mitkThrow() <<
"Poly line " << i <<
" of primary input consists of less than two points!";
160 std::vector<mitk::Point3D> crossSection;
162 auto polyLineEnd = polyLine.end();
164 for (
auto polyLineIter = polyLine.begin(); polyLineIter != polyLineEnd; ++polyLineIter)
167 planeGeometry->Map(*polyLineIter, point);
168 crossSection.push_back(point);
171 const ScalarType segmentLength = m_Length / m_NumberOfSegments;
172 Vector3D translation = planeNormal * segmentLength;
174 const bool bend = std::abs(m_BendAngle) >
mitk::eps;
175 const bool twist = std::abs(m_TwistAngle) >
mitk::eps;
177 const ScalarType twistAngle = twist ? m_TwistAngle / m_NumberOfSegments * vnl_math::pi / 180 : 0;
179 ScalarType bendAngle = bend ? m_BendAngle / m_NumberOfSegments * vnl_math::pi / 180 : 0;
187 for (
size_t k = 0;
k < numPoints; ++
k)
188 points->InsertNextPoint(crossSection[
k].GetDataPointer());
190 for (
size_t j = 1; j <= m_NumberOfSegments; ++j)
192 mitk::AffineTransform3D::Pointer transform = mitk::AffineTransform3D::New();
195 transform->Translate(centerPoint3d.GetVectorFromOrigin(),
true);
199 transform->Translate(scaledBendDirection3d,
true);
200 transform->Rotate3D(bendAxis, bendAngle * j,
true);
201 transform->Translate(-scaledBendDirection3d,
true);
205 transform->Translate(translation * j,
true);
209 transform->Rotate3D(planeNormal, twistAngle * j,
true);
212 transform->Translate(-centerPoint3d.GetVectorFromOrigin(),
true);
214 for (
size_t k = 0;
k < numPoints; ++
k)
216 const mitk::Point3D transformedPoint = transform->TransformPoint(crossSection[
k]);
217 points->InsertNextPoint(transformedPoint.GetDataPointer());
221 for (
size_t j = 0; j < m_NumberOfSegments; ++j)
223 for (
size_t k = 1;
k < numPoints; ++
k)
226 cell[0] = baseIndex + j * numPoints + (
k - 1);
227 cell[1] = baseIndex + (j + 1) * numPoints + (
k - 1);
228 cell[2] = baseIndex + j * numPoints +
k;
230 cells->InsertNextCell(3, cell);
233 cell[1] = baseIndex + (j + 1) * numPoints + k;
235 cells->InsertNextCell(3, cell);
238 if (input->IsClosed() && numPoints > 2)
241 cell[0] = baseIndex + j * numPoints + (numPoints - 1);
242 cell[1] = baseIndex + (j + 1) * numPoints + (numPoints - 1);
243 cell[2] = baseIndex + j * numPoints;
245 cells->InsertNextCell(3, cell);
248 cell[1] = baseIndex + (j + 1) * numPoints;
250 cells->InsertNextCell(3, cell);
254 baseIndex += points->GetNumberOfPoints();
257 vtkSmartPointer<vtkPolyData> polyData = vtkSmartPointer<vtkPolyData>::New();
258 polyData->SetPoints(points);
259 polyData->SetPolys(cells);
261 vtkSmartPointer<vtkPolyDataNormals> polyDataNormals = vtkSmartPointer<vtkPolyDataNormals>::New();
262 polyDataNormals->SetFlipNormals(m_FlipNormals);
263 polyDataNormals->SetInputData(polyData);
264 polyDataNormals->SplittingOff();
266 polyDataNormals->Update();
268 auto *output =
static_cast<Surface *
>(this->GetPrimaryOutput());
278 return idx == 0 ?
Surface::New().GetPointer() :
nullptr;
283 return this->IsIndexedOutputName(name) ? this->
MakeOutput(this->MakeIndexFromOutputName(name)) :
nullptr;
288 Superclass::PrintSelf(os, indent);
290 os << indent <<
"Length: " << m_Length << std::endl;
291 os << indent <<
"Number of Segments: " << m_NumberOfSegments << std::endl;
292 os << indent <<
"Twist Angle: " << m_TwistAngle << std::endl;
293 os << indent <<
"Bend Angle: " << m_BendAngle << std::endl;
294 os << indent <<
"Bend Direction: " << m_BendDirection << std::endl;
295 os << indent <<
"Flip Normals: " << m_FlipNormals << std::endl;
300 this->SetPrimaryInput(planarFigure);
305 return static_cast<Surface *
>(this->GetPrimaryOutput());
Class for storing surfaces (vtkPolyData).
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...
Vector< ScalarType, 3 > Vector3D
virtual void SetVtkPolyData(vtkPolyData *polydata, unsigned int t=0)
MITKCORE_EXPORT const ScalarType eps
Describes a two-dimensional, rectangular plane.