21 m_MaxSegmentLenght = 0;
27 this->m_UseProgressBar =
false;
28 this->m_ProgressStepSize = 1;
29 m_NumberOfPointsAfterReduction = 0;
32 this->SetNthOutput(0, output.GetPointer());
41 this->SetNthInput(idx, const_cast<mitk::Surface *>(surface));
47 this->SetInput(0, const_cast<mitk::Surface *>(surface));
52 unsigned int numberOfInputs = this->GetNumberOfIndexedInputs();
53 unsigned int numberOfOutputs(0);
55 vtkSmartPointer<vtkPolyData> newPolyData;
56 vtkSmartPointer<vtkCellArray> newPolygons;
57 vtkSmartPointer<vtkPoints> newPoints;
61 m_NumberOfPointsAfterReduction = 0;
63 for (
unsigned int i = 0; i < numberOfInputs; i++)
66 vtkSmartPointer<vtkPolyData> polyData = currentSurface->
GetVtkPolyData();
72 vtkSmartPointer<vtkCellArray> existingPolys = polyData->GetPolys();
74 vtkSmartPointer<vtkPoints> existingPoints = polyData->GetPoints();
76 existingPolys->InitTraversal();
78 vtkIdType *cell(
nullptr);
79 vtkIdType cellSize(0);
81 for (existingPolys->InitTraversal(); existingPolys->GetNextCell(cellSize, cell);)
83 bool incorporatePolygon =
84 this->CheckForIntersection(cell, cellSize, existingPoints, i);
85 if (!incorporatePolygon)
90 if (m_ReductionType == NTH_POINT)
92 this->ReduceNumberOfPointsByNthPoint(cellSize, cell, existingPoints, newPolygon, newPoints);
93 if (newPolygon->GetPointIds()->GetNumberOfIds() != 0)
95 newPolygons->InsertNextCell(newPolygon);
98 else if (m_ReductionType == DOUGLAS_PEUCKER)
100 this->ReduceNumberOfPointsByDouglasPeucker(cellSize, cell, existingPoints, newPolygon, newPoints);
101 if (newPolygon->GetPointIds()->GetNumberOfIds() > 3)
103 newPolygons->InsertNextCell(newPolygon);
109 m_NumberOfPointsAfterReduction += newPolygon->GetPointIds()->GetNumberOfIds();
112 if (newPolygons->GetNumberOfCells() != 0)
114 newPolyData->SetPolys(newPolygons);
115 newPolyData->SetPoints(newPoints);
116 newPolyData->BuildLinks();
118 this->SetNumberOfIndexedOutputs(numberOfOutputs + 1);
120 this->SetNthOutput(numberOfOutputs, surface.GetPointer());
121 surface->SetVtkPolyData(newPolyData);
127 this->SetNumberOfIndexedOutputs(numberOfOutputs);
129 if (numberOfOutputs == 0)
133 this->SetNthOutput(0, tmp_output.GetPointer());
136 if (this->m_UseProgressBar)
140 void mitk::ReduceContourSetFilter::ReduceNumberOfPointsByNthPoint(
141 vtkIdType cellSize, vtkIdType *cell, vtkPoints *points, vtkPolygon *reducedPolygon, vtkPoints *reducedPoints)
143 unsigned int newNumberOfPoints(0);
144 unsigned int mod = cellSize % m_StepSize;
148 newNumberOfPoints = cellSize / m_StepSize;
152 newNumberOfPoints = ((cellSize - mod) / m_StepSize) + 1;
155 if (newNumberOfPoints <= 3)
159 reducedPolygon->GetPointIds()->SetNumberOfIds(newNumberOfPoints);
160 reducedPolygon->GetPoints()->SetNumberOfPoints(newNumberOfPoints);
162 for (vtkIdType i = 0; i < cellSize; i++)
164 if (i % m_StepSize == 0)
167 points->GetPoint(cell[i], point);
168 vtkIdType
id = reducedPoints->InsertNextPoint(point);
169 reducedPolygon->GetPointIds()->SetId(i / m_StepSize,
id);
172 vtkIdType
id = cell[0];
174 points->GetPoint(
id, point);
175 id = reducedPoints->InsertNextPoint(point);
176 reducedPolygon->GetPointIds()->SetId(newNumberOfPoints - 1,
id);
179 void mitk::ReduceContourSetFilter::ReduceNumberOfPointsByDouglasPeucker(
180 vtkIdType cellSize, vtkIdType *cell, vtkPoints *points, vtkPolygon *reducedPolygon, vtkPoints *reducedPoints)
183 if (cellSize <= static_cast<vtkIdType>(m_StepSize * 3))
218 if (m_MaxSpacing > 0)
220 m_Tolerance = m_MinSpacing;
228 std::stack<LineSegment> lineSegments;
233 ls2.StartIndex = cell[cellSize / 2];
234 ls2.EndIndex = cell[cellSize - 1];
235 lineSegments.push(ls2);
238 ls1.StartIndex = cell[0];
239 ls1.EndIndex = cell[cellSize / 2];
240 lineSegments.push(ls1);
242 LineSegment currentSegment;
248 double currentMaxDistance(0);
249 vtkIdType currentMaxDistanceIndex(0);
254 vtkIdType pointId(0);
256 pointId = reducedPoints->InsertNextPoint(points->GetPoint(cell[0]));
257 reducedPolygon->GetPointIds()->InsertNextId(pointId);
259 while (!lineSegments.empty())
261 currentSegment = lineSegments.top();
266 points->GetPoint(currentSegment.EndIndex, tempV);
267 points->GetPoint(currentSegment.StartIndex, v1);
269 v1[0] = tempV[0] - v1[0];
270 v1[1] = tempV[1] - v1[1];
271 v1[2] = tempV[2] - v1[2];
273 lenghtV1 = vtkMath::Norm(v1);
276 int range = currentSegment.EndIndex - currentSegment.StartIndex;
277 for (
int i = 1; i < abs(range); ++i)
279 points->GetPoint(currentSegment.StartIndex + i, tempV);
280 points->GetPoint(currentSegment.StartIndex, v2);
282 v2[0] = tempV[0] - v2[0];
283 v2[1] = tempV[1] - v2[1];
284 v2[2] = tempV[2] - v2[2];
288 l = vtkMath::Dot(v2, v1);
290 d = vtkMath::Norm(v2);
292 if (l > 0 && l < lenghtV1)
294 d = sqrt((d * d - l * l));
296 else if (l > 0 && l > lenghtV1)
298 tempV[0] = lenghtV1 * v1[0] - v2[0];
299 tempV[1] = lenghtV1 * v1[1] - v2[1];
300 tempV[2] = lenghtV1 * v1[2] - v2[2];
301 d = vtkMath::Norm(tempV);
305 if (d > currentMaxDistance)
307 currentMaxDistance = d;
308 currentMaxDistanceIndex = currentSegment.StartIndex + i;
313 if (currentMaxDistance <= m_Tolerance)
316 int segmentLenght = currentSegment.EndIndex - currentSegment.StartIndex;
317 if (segmentLenght > (
int)m_MaxSegmentLenght)
319 m_MaxSegmentLenght = (
unsigned int)segmentLenght;
323 if (abs(segmentLenght) > 25)
325 unsigned int newLenght(segmentLenght);
326 while (newLenght > 25)
328 newLenght = newLenght * 0.5;
330 unsigned int divisions = abs(segmentLenght) / newLenght;
333 for (
unsigned int i = 1; i <= divisions; ++i)
336 pointId = reducedPoints->InsertNextPoint(points->GetPoint(currentSegment.StartIndex + newLenght * i));
337 reducedPolygon->GetPointIds()->InsertNextId(pointId);
341 pointId = reducedPoints->InsertNextPoint(points->GetPoint(currentSegment.EndIndex));
342 reducedPolygon->GetPointIds()->InsertNextId(pointId);
346 ls2.StartIndex = currentMaxDistanceIndex;
347 ls2.EndIndex = currentSegment.EndIndex;
348 lineSegments.push(ls2);
350 ls1.StartIndex = currentSegment.StartIndex;
351 ls1.EndIndex = currentMaxDistanceIndex;
352 lineSegments.push(ls1);
354 currentMaxDistance = 0;
358 bool mitk::ReduceContourSetFilter::CheckForIntersection(
359 vtkIdType *currentCell,
360 vtkIdType currentCellSize,
361 vtkPoints *currentPoints,
362 unsigned int currentInputIndex)
375 for (
unsigned int i = 0; i < this->GetNumberOfIndexedInputs(); i++)
378 if (i == currentInputIndex)
382 vtkSmartPointer<vtkPolyData> poly =
const_cast<Surface *
>(this->GetInput(i))->GetVtkPolyData();
383 vtkSmartPointer<vtkCellArray> polygonArray = poly->GetPolys();
384 polygonArray->InitTraversal();
385 vtkIdType anotherInputPolygonSize(0);
386 vtkIdType *anotherInputPolygonIDs(
nullptr);
396 for (polygonArray->InitTraversal(); polygonArray->GetNextCell(anotherInputPolygonSize, anotherInputPolygonIDs);)
410 poly->GetPoint(anotherInputPolygonIDs[0], p1);
411 poly->GetPoint(anotherInputPolygonIDs[1], p2);
413 v1[0] = p2[0] - p1[0];
414 v1[1] = p2[1] - p1[1];
415 v1[2] = p2[2] - p1[2];
419 double maxDistance(0);
420 double minDistance(10000);
422 for (vtkIdType j = 2; j < anotherInputPolygonSize; j++)
424 poly->GetPoint(anotherInputPolygonIDs[j], p3);
426 v2[0] = p3[0] - p1[0];
427 v2[1] = p3[1] - p1[1];
428 v2[2] = p3[2] - p1[2];
431 double dotV1V2 = vtkMath::Dot(v1, v2);
432 double absV1 = sqrt(vtkMath::Dot(v1, v1));
433 double absV2 = sqrt(vtkMath::Dot(v2, v2));
434 double cosV1V2 = dotV1V2 / (absV1 * absV2);
436 double arccos = acos(cosV1V2);
437 double degree = vtkMath::DegreesFromRadians(arccos);
446 vtkMath::Cross(v1, v2, normal);
450 double lambda = vtkMath::Dot(normal, p1);
456 for (vtkIdType k = 0; k < currentCellSize; k++)
458 double currentPoint[3];
459 currentPoints->GetPoint(currentCell[k], currentPoint);
462 tempPoint[0] = normal[0] * currentPoint[0];
463 tempPoint[1] = normal[1] * currentPoint[1];
464 tempPoint[2] = normal[2] * currentPoint[2];
466 double temp = tempPoint[0] + tempPoint[1] + tempPoint[2] - lambda;
467 double distance = fabs(temp);
469 if (distance > maxDistance)
471 maxDistance = distance;
473 if (distance < minDistance)
475 minDistance = distance;
479 if (maxDistance < 1.5 * m_MaxSpacing && minDistance < 0.5 * m_MinSpacing)
496 Superclass::GenerateOutputInformation();
501 for (
unsigned int i = 0; i < this->GetNumberOfIndexedInputs(); i++)
503 this->PopBackInput();
505 this->SetNumberOfIndexedInputs(0);
506 this->SetNumberOfIndexedOutputs(0);
510 this->SetNthOutput(0, output.GetPointer());
512 m_NumberOfPointsAfterReduction = 0;
517 this->m_UseProgressBar = status;
522 this->m_ProgressStepSize = stepSize;
void Progress(unsigned int steps=1)
Sets the current amount of progress to current progress + steps.
Class for storing surfaces (vtkPolyData).
virtual vtkPolyData * GetVtkPolyData(unsigned int t=0) const
void SetUseProgressBar(bool)
Set whether the mitkProgressBar should be used.
void SetProgressStepSize(unsigned int stepSize)
Set the stepsize which the progress bar should proceed.
static ProgressBar * GetInstance()
static method to get the GUI dependent ProgressBar-instance so the methods for steps to do and progre...
virtual void SetInput(const mitk::Surface *surface)
virtual ~ReduceContourSetFilter()
void Normalize(itk::Image< TPixel, VImageDimension > *itkImage, mitk::Image::Pointer im2, mitk::Image::Pointer mask1, std::string output)
virtual void GenerateOutputInformation() override
virtual void GenerateData() override
static itkEventMacro(BoundingShapeInteractionEvent, itk::AnyEvent) class MITKBOUNDINGSHAPE_EXPORT BoundingShapeInteractor Pointer New()
Basic interaction methods for mitk::GeometryData.