Medical Imaging Interaction Toolkit  2018.4.99-c7ee88da
Medical Imaging Interaction Toolkit
mitkTubeGraphVtkMapper3D.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 
14 
15 #include <mitkColorProperty.h>
16 
17 #include <vtkCellArray.h>
18 #include <vtkClipPolyData.h>
19 #include <vtkContourFilter.h>
20 #include <vtkCylinder.h>
21 #include <vtkFloatArray.h>
22 #include <vtkGeneralTransform.h>
23 #include <vtkImplicitBoolean.h>
24 #include <vtkImplicitModeller.h>
25 #include <vtkPlane.h>
26 #include <vtkPointData.h>
27 #include <vtkPoints.h>
28 #include <vtkPolyDataMapper.h>
29 #include <vtkProperty.h>
30 #include <vtkRenderer.h>
31 #include <vtkSampleFunction.h>
32 #include <vtkSphereSource.h>
33 #include <vtkTubeFilter.h>
34 #include <vtkUnsignedIntArray.h>
35 
37 {
38 }
39 
41 {
42 }
43 
45 {
46  return dynamic_cast<const TubeGraph *>(GetDataNode()->GetData());
47 }
48 
50 {
51  return m_LSH.GetLocalStorage(renderer)->m_vtkTubeGraphAssembly;
52 }
53 
55 {
56  bool renderTubeGraph(false);
57  LocalStorage *ls = m_LSH.GetLocalStorage(renderer);
58 
59  TubeGraph::Pointer tubeGraph = const_cast<mitk::TubeGraph *>(this->GetInput());
60  TubeGraphProperty::Pointer tubeGraphProperty =
61  dynamic_cast<TubeGraphProperty *>(tubeGraph->GetProperty("Tube Graph.Visualization Information").GetPointer());
62 
63  if (tubeGraph.IsNull() || tubeGraphProperty.IsNull())
64  {
65  itkWarningMacro(<< "Input of tube graph mapper is nullptr!");
66  return;
67  }
68  // Check if the tube graph has changed; if the data has changed, generate the spheres and tubes new;
69  if (tubeGraph->GetMTime() > ls->m_lastGenerateDataTime)
70  {
71  this->GenerateTubeGraphData(renderer);
72  renderTubeGraph = true;
73  }
74  else
75  {
76  // Check if the tube graph property has changed; if the property has changed, render the visualization information
77  // new;
78  if (tubeGraphProperty->GetMTime() > ls->m_lastRenderDataTime)
79  {
80  this->RenderTubeGraphPropertyInformation(renderer);
81  renderTubeGraph = true;
82  }
83  }
84 
85  if (renderTubeGraph)
86  {
87  std::vector<TubeGraph::VertexDescriptorType> alreadyRenderedVertexList;
88  // don't render the sphere which is the root of the graph; so add it to the list before;
89  // TODO check both spheres
90  TubeGraph::VertexDescriptorType root = tubeGraph->GetRootVertex();
91  alreadyRenderedVertexList.push_back(root);
92 
93  for (auto itTubes =
94  ls->m_vtkTubesActorMap.begin();
95  itTubes != ls->m_vtkTubesActorMap.end();
96  itTubes++)
97  {
98  if (tubeGraphProperty->IsTubeVisible(itTubes->first))
99  {
100  // add tube actor to assembly
101  ls->m_vtkTubeGraphAssembly->AddPart(itTubes->second);
102 
103  // render the clipped spheres as end-cups of a tube and connections between tubes
104  if (std::find(alreadyRenderedVertexList.begin(), alreadyRenderedVertexList.end(), itTubes->first.first) ==
105  alreadyRenderedVertexList.end())
106  {
107  auto itSourceSphere =
108  ls->m_vtkSpheresActorMap.find(itTubes->first.first);
109  if (itSourceSphere != ls->m_vtkSpheresActorMap.end())
110  ls->m_vtkTubeGraphAssembly->AddPart(itSourceSphere->second);
111  alreadyRenderedVertexList.push_back(itSourceSphere->first);
112  }
113  if (std::find(alreadyRenderedVertexList.begin(), alreadyRenderedVertexList.end(), itTubes->first.second) ==
114  alreadyRenderedVertexList.end())
115  {
116  auto itTargetSphere =
117  ls->m_vtkSpheresActorMap.find(itTubes->first.second);
118  if (itTargetSphere != ls->m_vtkSpheresActorMap.end())
119  ls->m_vtkTubeGraphAssembly->AddPart(itTargetSphere->second);
120  alreadyRenderedVertexList.push_back(itTargetSphere->first);
121  }
122  }
123  }
124  }
125 
127  //{
128  // float opacity = 1.0f;
129  // if( this->GetDataNode()->GetOpacity(opacity,renderer) )
130  // ls->m_vtkTubesActor->GetProperty()->SetOpacity( opacity );
131  //}
132 }
133 
135 {
136  MITK_INFO << "Render tube graph property information!";
137  LocalStorage *ls = m_LSH.GetLocalStorage(renderer);
138  TubeGraph::ConstPointer tubeGraph = this->GetInput();
139  TubeGraphProperty::Pointer tubeGraphProperty =
140  dynamic_cast<TubeGraphProperty *>(tubeGraph->GetProperty("Tube Graph.Visualization Information").GetPointer());
141 
142  if (tubeGraphProperty.IsNull())
143  {
144  MITK_INFO << "No tube graph property!! So no special render information...";
145  return;
146  }
147 
148  std::vector<TubeGraphVertex> allVertices = tubeGraph->GetVectorOfAllVertices();
149  for (auto vertex = allVertices.begin(); vertex != allVertices.end(); ++vertex)
150  {
151  TubeGraph::VertexDescriptorType vertexDesc = tubeGraph->GetVertexDescriptor(*vertex);
152 
153  double sphereColorR = 0;
154  double sphereColorG = 0;
155  double sphereColorB = 0;
156 
157  int numberOfVisibleEdges = 0;
158  std::vector<TubeGraphEdge> allEdgesOfVertex = tubeGraph->GetAllEdgesOfAVertex(vertexDesc);
159  for (auto edge = allEdgesOfVertex.begin(); edge != allEdgesOfVertex.end(); ++edge)
160  {
161  // get edge descriptor
162  EdgeDescriptorType edgeDesc = tubeGraph->GetEdgeDescriptor(*edge);
163 
164  // get source and target vertex descriptor
165  std::pair<TubeGraphVertex, TubeGraphVertex> soureTargetPair = tubeGraph->GetVerticesOfAnEdge(edgeDesc);
166  TubeGraphVertex source = soureTargetPair.first;
167  TubeGraphVertex target = soureTargetPair.second;
168 
169  // build tube descriptor [sourceId,targetId]
171  tube.first = tubeGraph->GetVertexDescriptor(source);
172  tube.second = tubeGraph->GetVertexDescriptor(target);
173 
174  if (tubeGraphProperty->IsTubeVisible(tube))
175  {
176  mitk::Color tubeColor = tubeGraphProperty->GetColorOfTube(tube);
177 
178  vtkSmartPointer<vtkDataArray> scalars =
179  ls->m_vtkTubesActorMap[tube]->GetMapper()->GetInput()->GetPointData()->GetScalars();
180  double color[3];
181  scalars->GetTuple(0, color);
182 
183  if (color[0] != tubeColor[0] || color[1] != tubeColor[1] || color[2] != tubeColor[2])
184  {
185  int numberOfPoints = scalars->GetSize();
186 
187  vtkSmartPointer<vtkUnsignedCharArray> colorScalars = vtkSmartPointer<vtkUnsignedCharArray>::New();
188  colorScalars->SetName("colorScalars");
189  colorScalars->SetNumberOfComponents(3);
190  colorScalars->SetNumberOfTuples(numberOfPoints);
191  for (int i = 0; i < numberOfPoints; i++)
192  {
193  scalars->InsertTuple3(i, tubeColor[0], tubeColor[1], tubeColor[2]);
194  }
195  ls->m_vtkTubesActorMap[tube]->GetMapper()->GetInput()->GetPointData()->SetActiveScalars("colorScalars");
196  }
197 
198  sphereColorR += tubeColor[0];
199  sphereColorG += tubeColor[1];
200  sphereColorB += tubeColor[2];
201  numberOfVisibleEdges++;
202  }
203  }
204  if (numberOfVisibleEdges > 0)
205  {
206  sphereColorR /= 255 * numberOfVisibleEdges;
207  sphereColorG /= 255 * numberOfVisibleEdges;
208  sphereColorB /= 255 * numberOfVisibleEdges;
209  }
210 
211  ls->m_vtkSpheresActorMap[vertexDesc]->GetProperty()->SetColor(sphereColorR, sphereColorG, sphereColorB);
212  }
213  ls->m_lastRenderDataTime.Modified();
214 }
215 
217 {
218  MITK_INFO << "Render tube graph!";
219  LocalStorage *ls = m_LSH.GetLocalStorage(renderer);
220 
221  ls->m_vtkTubesActorMap.clear();
222  ls->m_vtkSpheresActorMap.clear();
223 
224  TubeGraph::Pointer tubeGraph = const_cast<mitk::TubeGraph *>(this->GetInput());
225  TubeGraphProperty::Pointer tubeGraphProperty =
226  dynamic_cast<TubeGraphProperty *>(tubeGraph->GetProperty("Tube Graph.Visualization Information").GetPointer());
227  if (tubeGraphProperty.IsNull())
228  MITK_INFO << "No tube graph property!! So no special render information...";
229 
230  // render all edges as tubular structures using the vtkTubeFilter
231  std::vector<TubeGraphEdge> allEdges = tubeGraph->GetVectorOfAllEdges();
232  for (auto edge = allEdges.begin(); edge != allEdges.end(); ++edge)
233  {
234  this->GeneratePolyDataForTube(*edge, tubeGraph, tubeGraphProperty, renderer);
235  }
236 
237  // Generate all vertices as spheres
238  std::vector<TubeGraphVertex> allVertices = tubeGraph->GetVectorOfAllVertices();
239  for (auto vertex = allVertices.begin(); vertex != allVertices.end(); ++vertex)
240  {
241  this->GeneratePolyDataForFurcation(*vertex, tubeGraph, renderer);
242  if (this->ClipStructures())
243  {
244  this->ClipPolyData(*vertex, tubeGraph, tubeGraphProperty, renderer);
245  }
246 
247  ls->m_lastGenerateDataTime.Modified();
248  }
249 }
250 
252  const mitk::TubeGraph::Pointer &graph,
253  mitk::BaseRenderer *renderer)
254 {
255  LocalStorage *ls = this->m_LSH.GetLocalStorage(renderer);
256 
257  mitk::Point3D coordinates;
258  float diameter = 2;
259 
260  coordinates = (vertex.GetTubeElement())->GetCoordinates();
261  if (dynamic_cast<const mitk::CircularProfileTubeElement *>(vertex.GetTubeElement()))
262  {
263  diameter = (dynamic_cast<const mitk::CircularProfileTubeElement *>(vertex.GetTubeElement()))->GetDiameter();
264  }
265  vtkSmartPointer<vtkSphereSource> sphereSource = vtkSmartPointer<vtkSphereSource>::New();
266  sphereSource->SetCenter(coordinates[0], coordinates[1], coordinates[2]);
267  sphereSource->SetRadius(diameter / 2.0f);
268  sphereSource->SetThetaResolution(12);
269  sphereSource->SetPhiResolution(12);
270  sphereSource->Update();
271 
272  // generate a actor with a mapper for the sphere
273  vtkSmartPointer<vtkPolyDataMapper> sphereMapper = vtkSmartPointer<vtkPolyDataMapper>::New();
274  vtkSmartPointer<vtkActor> sphereActor = vtkSmartPointer<vtkActor>::New();
275 
276  sphereMapper->SetInputConnection(sphereSource->GetOutputPort());
277  sphereActor->SetMapper(sphereMapper);
278 
279  ls->m_vtkSpheresActorMap.insert(std::make_pair(graph->GetVertexDescriptor(vertex), sphereActor));
280 }
281 
283  const mitk::TubeGraph::Pointer &graph,
284  const mitk::TubeGraphProperty::Pointer &graphProperty,
285  mitk::BaseRenderer *renderer)
286 {
287  LocalStorage *ls = this->m_LSH.GetLocalStorage(renderer);
288 
289  // get edge descriptor
290  EdgeDescriptorType edgeDesc = graph->GetEdgeDescriptor(edge);
291 
292  // get source and target vertex descriptor
293  std::pair<TubeGraphVertex, TubeGraphVertex> soureTargetPair = graph->GetVerticesOfAnEdge(edgeDesc);
294  TubeGraphVertex source = soureTargetPair.first;
295  TubeGraphVertex target = soureTargetPair.second;
296 
297  // build tube descriptor [sourceId,targetId]
299  tube.first = graph->GetVertexDescriptor(source);
300  tube.second = graph->GetVertexDescriptor(target);
301 
302  Color color;
303  if (graphProperty.IsNotNull())
304  {
305  color = graphProperty->GetColorOfTube(tube);
306  }
307  else
308  {
309  color[0] = 150;
310  color[1] = 150;
311  color[2] = 150;
312  }
313 
314  // add 2 points for the source and target vertices.
315  unsigned int numberOfPoints = edge.GetNumberOfElements() + 2;
316 
317  // Initialize the required data-structures for building
318  // an appropriate input to the tube filter
319  vtkSmartPointer<vtkPoints> points = vtkSmartPointer<vtkPoints>::New();
320  points->SetNumberOfPoints(numberOfPoints);
321 
322  vtkSmartPointer<vtkFloatArray> radii = vtkSmartPointer<vtkFloatArray>::New();
323  radii->SetName("radii");
324  radii->SetNumberOfComponents(1);
325 
326  vtkSmartPointer<vtkCellArray> lines = vtkSmartPointer<vtkCellArray>::New();
327 
328  vtkSmartPointer<vtkUnsignedCharArray> colorScalars = vtkSmartPointer<vtkUnsignedCharArray>::New();
329  colorScalars->SetName("colorScalars");
330  colorScalars->SetNumberOfComponents(3);
331 
332  // resize the data-arrays
333  radii->SetNumberOfTuples(numberOfPoints);
334  colorScalars->SetNumberOfTuples(numberOfPoints);
335  lines->InsertNextCell(numberOfPoints);
336 
337  // Add the positions of the source node, the elements along the edge and
338  // the target node as lines to a cell. This cell is used as input
339  // for a Tube Filter
340  mitk::Point3D coordinates;
341  float diameter = 2;
342  unsigned int id = 0;
343 
344  // Source Node
345  coordinates = (source.GetTubeElement())->GetCoordinates();
346  if (dynamic_cast<const mitk::CircularProfileTubeElement *>(source.GetTubeElement()))
347  {
348  diameter = (dynamic_cast<const mitk::CircularProfileTubeElement *>(source.GetTubeElement()))->GetDiameter();
349  }
350  points->InsertPoint(id, coordinates[0], coordinates[1], coordinates[2]);
351  radii->InsertTuple1(id, diameter / 2.0f);
352 
353  colorScalars->InsertTuple3(id, color[0], color[1], color[2]);
354  lines->InsertCellPoint(id);
355  ++id;
356 
357  // Iterate along the edge
358  std::vector<mitk::TubeElement *> allElements = edge.GetElementVector();
359  for (unsigned int index = 0; index < edge.GetNumberOfElements(); index++)
360  {
361  coordinates = allElements[index]->GetCoordinates();
362  if (dynamic_cast<mitk::CircularProfileTubeElement *>(allElements[index]))
363  {
364  diameter = (dynamic_cast<mitk::CircularProfileTubeElement *>(allElements[index]))->GetDiameter();
365  }
366  points->InsertPoint(id, coordinates[0], coordinates[1], coordinates[2]);
367  radii->InsertTuple1(id, diameter / 2.0f);
368  colorScalars->InsertTuple3(id, color[0], color[1], color[2]);
369  lines->InsertCellPoint(id);
370  ++id;
371  }
372 
373  // Target Node
374  coordinates = (target.GetTubeElement())->GetCoordinates();
375  if (dynamic_cast<const mitk::CircularProfileTubeElement *>(target.GetTubeElement()))
376  {
377  diameter = (dynamic_cast<const mitk::CircularProfileTubeElement *>(target.GetTubeElement()))->GetDiameter();
378  }
379  points->InsertPoint(id, coordinates[0], coordinates[1], coordinates[2]);
380  radii->InsertTuple1(id, diameter / 2.0f);
381  colorScalars->InsertTuple3(id, color[0], color[1], color[2]);
382  lines->InsertCellPoint(id);
383  ++id;
384 
385  // Initialize poly data from the point set and the cell array
386  // (representing topology)
387  vtkSmartPointer<vtkPolyData> polyData = vtkSmartPointer<vtkPolyData>::New();
388  polyData->SetPoints(points);
389  polyData->SetLines(lines);
390  polyData->GetPointData()->AddArray(radii);
391  polyData->GetPointData()->AddArray(colorScalars);
392  polyData->GetPointData()->SetActiveScalars(radii->GetName());
393 
394  // Generate a tube for all lines in the polydata object
395  double *range = radii->GetRange();
396 
397  assert(range[0] != 0.0f && range[1] != 0.0f);
398 
399  vtkSmartPointer<vtkTubeFilter> tubeFilter = vtkSmartPointer<vtkTubeFilter>::New();
400  tubeFilter->SetInputData(polyData);
401  tubeFilter->SetRadius(range[0]);
402  tubeFilter->SetRadiusFactor(range[1] / range[0]);
403 
404  if (range[0] != range[1])
405  tubeFilter->SetVaryRadiusToVaryRadiusByScalar();
406 
407  tubeFilter->SetNumberOfSides(9);
408  tubeFilter->SidesShareVerticesOn();
409  tubeFilter->CappingOff();
410  tubeFilter->Update();
411 
412  tubeFilter->GetOutput()->GetPointData()->SetActiveScalars("colorScalars");
413 
414  // generate a actor with a mapper for the
415  vtkSmartPointer<vtkPolyDataMapper> tubeMapper = vtkSmartPointer<vtkPolyDataMapper>::New();
416  vtkSmartPointer<vtkActor> tubeActor = vtkSmartPointer<vtkActor>::New();
417 
418  tubeMapper->SetInputConnection(tubeFilter->GetOutputPort());
419  tubeActor->SetMapper(tubeMapper);
420  tubeActor->GetProperty()->SetColor(color[0], color[1], color[2]);
421 
422  ls->m_vtkTubesActorMap.insert(std::pair<TubeGraph::TubeDescriptorType, vtkSmartPointer<vtkActor>>(tube, tubeActor));
423 }
424 
426  const mitk::TubeGraph::Pointer &graph,
427  const mitk::TubeGraphProperty::Pointer &graphProperty,
428  mitk::BaseRenderer *renderer)
429 {
430  LocalStorage *ls = this->m_LSH.GetLocalStorage(renderer);
431 
432  mitk::Point3D centerVertex = vertex.GetTubeElement()->GetCoordinates();
433  float diameter = 2;
434  if (dynamic_cast<const mitk::CircularProfileTubeElement *>(vertex.GetTubeElement()))
435  {
436  diameter = (dynamic_cast<const mitk::CircularProfileTubeElement *>(vertex.GetTubeElement()))->GetDiameter();
437  }
438 
439  TubeGraph::VertexDescriptorType vertexDesc = graph->GetVertexDescriptor(vertex);
440 
441  std::map<TubeGraph::TubeDescriptorType, vtkSmartPointer<vtkImplicitBoolean>> cylinderForClipping;
442 
443  // generate for all edges/tubes cylinders. With this structure you can clip the sphere and the other tubes, so that no
444  // fragments are shown in the tube.
445  std::vector<TubeGraphEdge> allEdgesOfVertex = graph->GetAllEdgesOfAVertex(vertexDesc);
446  for (auto edge = allEdgesOfVertex.begin(); edge != allEdgesOfVertex.end(); ++edge)
447  {
448  // get edge descriptor
449  EdgeDescriptorType edgeDesc = graph->GetEdgeDescriptor(*edge);
450 
451  // get source and target vertex descriptor
452  auto soureTargetPair = graph->GetVerticesOfAnEdge(edgeDesc);
453  TubeGraphVertex source = soureTargetPair.first;
454  TubeGraphVertex target = soureTargetPair.second;
455 
456  // build tube descriptor [sourceId,targetId]
458  tube.first = graph->GetVertexDescriptor(source);
459  tube.second = graph->GetVertexDescriptor(target);
460 
461  // get reference point in the tube for the direction
462  mitk::Point3D edgeDirectionPoint;
463  // get reference diameter
464  double cylinderDiameter = diameter;
465  float radius = diameter / 2;
466  // if the vertex is the source vertex of the edge get the first element of elementVector; otherwise get the last
467  // element.
468  if (source == vertex)
469  {
470  // if the edge has no element get the other vertex
471  if ((*edge).GetNumberOfElements() != 0)
472  {
473  double lastDistance = 0, distance = 0;
474 
475  unsigned int index = 0;
476  // Get the first element behind the radius of the sphere
477  for (; index < (*edge).GetNumberOfElements(); index++)
478  {
479  mitk::Vector3D diffVec = (*edge).GetTubeElement(index)->GetCoordinates() - centerVertex;
480  distance = std::sqrt(pow(diffVec[0], 2) + pow(diffVec[1], 2) + pow(diffVec[2], 2));
481  if (distance > radius)
482  break;
483  lastDistance = distance;
484  }
485  // if the last element is not inside the sphere
486  if (index < (*edge).GetNumberOfElements())
487  {
488  double withinSphereDiameter = diameter, outsideSphereDiameter = diameter, interpolationValue = 0.5;
489 
490  interpolationValue = (radius - lastDistance) / (distance - lastDistance);
491  // if first element is outside of the sphere use sphere diameter and the element diameter for interpolation
492  if (index == 0)
493  {
494  if (dynamic_cast<mitk::CircularProfileTubeElement *>((*edge).GetTubeElement(0)))
495  outsideSphereDiameter =
496  (dynamic_cast<mitk::CircularProfileTubeElement *>((*edge).GetTubeElement(0)))->GetDiameter();
497  }
498  else
499  {
500  if (dynamic_cast<mitk::CircularProfileTubeElement *>((*edge).GetTubeElement(index - 1)))
501  withinSphereDiameter =
502  (dynamic_cast<mitk::CircularProfileTubeElement *>((*edge).GetTubeElement(index - 1)))->GetDiameter();
503 
504  if (dynamic_cast<mitk::CircularProfileTubeElement *>((*edge).GetTubeElement(index)))
505  outsideSphereDiameter =
506  (dynamic_cast<mitk::CircularProfileTubeElement *>((*edge).GetTubeElement(index)))->GetDiameter();
507  }
508  // interpolate the diameter for clipping
509  cylinderDiameter =
510  (1 - interpolationValue) * withinSphereDiameter + interpolationValue * outsideSphereDiameter;
511  }
512  // Get the reference point, so the direction of the tube can be calculated
513  edgeDirectionPoint = (*edge).GetTubeElement(0)->GetCoordinates();
514  }
515  else
516  {
517  // Get the reference point, so the direction of the tube can be calculated
518  edgeDirectionPoint = target.GetTubeElement()->GetCoordinates();
519  }
520  }
521 
522  // if vertex is target of the tube
523  else
524  {
525  // if the edge has no element, get the other vertex
526  if ((*edge).GetNumberOfElements() != 0)
527  {
528  double lastDistance = 0, distance = 0;
529  // Get the first element behind the radius of the sphere; now backwards through the element list
530  int index = (*edge).GetNumberOfElements();
531  for ( ; index >= 0; --index)
532  {
533  mitk::Vector3D diffVec = (*edge).GetTubeElement(index)->GetCoordinates() - centerVertex;
534  distance = std::sqrt(pow(diffVec[0], 2) + pow(diffVec[1], 2) + pow(diffVec[2], 2));
535  if (distance > radius)
536  break;
537  lastDistance = distance;
538  }
539 
540  if (index >= 0)
541  {
542  double withinSphereDiameter = diameter, outsideSphereDiameter = diameter, interpolationValue = 0.5;
543 
544  interpolationValue = (radius - lastDistance) / (distance - lastDistance);
545 
546  if (index == static_cast<int>((*edge).GetNumberOfElements() - 1))
547  {
548  if (dynamic_cast<mitk::CircularProfileTubeElement *>(
549  (*edge).GetTubeElement((*edge).GetNumberOfElements() - 1)))
550  outsideSphereDiameter = (dynamic_cast<mitk::CircularProfileTubeElement *>(
551  (*edge).GetTubeElement((*edge).GetNumberOfElements() - 1)))
552  ->GetDiameter();
553  }
554  else
555  {
556  if (dynamic_cast<mitk::CircularProfileTubeElement *>((*edge).GetTubeElement(index + 1)))
557  withinSphereDiameter =
558  (dynamic_cast<mitk::CircularProfileTubeElement *>((*edge).GetTubeElement(index + 1)))->GetDiameter();
559 
560  if (dynamic_cast<mitk::CircularProfileTubeElement *>((*edge).GetTubeElement(index)))
561  outsideSphereDiameter =
562  (dynamic_cast<mitk::CircularProfileTubeElement *>((*edge).GetTubeElement(index)))->GetDiameter();
563  }
564  // interpolate the diameter for clipping
565  cylinderDiameter =
566  (1 - interpolationValue) * withinSphereDiameter + interpolationValue * outsideSphereDiameter;
567  }
568  // Get the reference point, so the direction of the tube can be calculated
569  edgeDirectionPoint = (*edge).GetTubeElement((*edge).GetNumberOfElements() - 1)->GetCoordinates();
570  }
571  else
572  {
573  // Get the reference point, so the direction of the tube can be calculated
574  edgeDirectionPoint = source.GetTubeElement()->GetCoordinates();
575  }
576  }
577 
579  // get the normalized vector for the orientation (tube element direction)
580  mitk::Vector3D vecOrientation;
581  mitk::FillVector3D(vecOrientation,
582  (edgeDirectionPoint[0] - centerVertex[0]),
583  (edgeDirectionPoint[1] - centerVertex[1]),
584  (edgeDirectionPoint[2] - centerVertex[2]));
585  vecOrientation.Normalize();
586 
587  // generate a random vector
588  mitk::Vector3D vecRandom;
589  mitk::FillVector3D(vecRandom, (rand() % 100 - 50), (rand() % 100 - 50), (rand() % 100 - 50));
590  // project the random vector on the plane-->orthogonal vector to plane normal; normalize it!
591  mitk::Vector3D vecOrthoToOrientation;
592  vecOrthoToOrientation = vecRandom - (vecRandom * vecOrientation) * vecOrientation;
593  vecOrthoToOrientation.Normalize();
594 
595  // get the cross product of both orthogonale vectors to get a third one
596  mitk::Vector3D vecCrossProduct;
597  vecCrossProduct = itk::CrossProduct(vecOrientation, vecOrthoToOrientation);
598  vecCrossProduct.Normalize();
599 
600  // Fill matrix
601  vtkSmartPointer<vtkMatrix4x4> vtkTransformMatrix = vtkSmartPointer<vtkMatrix4x4>::New();
602  vtkTransformMatrix->Identity();
603  // 1. column
604  vtkTransformMatrix->SetElement(0, 0, vecOrthoToOrientation[0]);
605  vtkTransformMatrix->SetElement(1, 0, vecOrthoToOrientation[1]);
606  vtkTransformMatrix->SetElement(2, 0, vecOrthoToOrientation[2]);
607  // 2. column
608  vtkTransformMatrix->SetElement(0, 1, vecOrientation[0]);
609  vtkTransformMatrix->SetElement(1, 1, vecOrientation[1]);
610  vtkTransformMatrix->SetElement(2, 1, vecOrientation[2]);
611  // 3. column
612  vtkTransformMatrix->SetElement(0, 2, vecCrossProduct[0]);
613  vtkTransformMatrix->SetElement(1, 2, vecCrossProduct[1]);
614  vtkTransformMatrix->SetElement(2, 2, vecCrossProduct[2]);
615  // 4. column
616  vtkTransformMatrix->SetElement(0, 3, centerVertex[0]);
617  vtkTransformMatrix->SetElement(1, 3, centerVertex[1]);
618  vtkTransformMatrix->SetElement(2, 3, centerVertex[2]);
619 
620  vtkSmartPointer<vtkGeneralTransform> transform = vtkSmartPointer<vtkGeneralTransform>::New();
621  transform->Concatenate(vtkTransformMatrix);
622  // transform->Translate(centerVertex[0],centerVertex[1],centerVertex[2]);
623 
624  transform->Inverse();
625  transform->Update();
626 
627  // Generate plane in center [0,0,0] with n= (0,1,0) as normal vector
628  vtkSmartPointer<vtkPlane> plane = vtkSmartPointer<vtkPlane>::New();
629  plane->SetOrigin(0, 0, 0);
630  plane->SetNormal(0, 1, 0);
631 
632  // Generate a cylinder in center [0,0,0] and the axes of rotation is along the y-axis; radius is vertex diameter/2;
633  vtkSmartPointer<vtkCylinder> cylinder = vtkSmartPointer<vtkCylinder>::New();
634  cylinder->SetCenter(0, 0, 0);
635  cylinder->SetRadius(cylinderDiameter / 2);
636  // cylinder->SetTransform(transform);
637 
638  // Truncate the infinite cylinder with the plane
639  vtkSmartPointer<vtkImplicitBoolean> cutCylinder = vtkSmartPointer<vtkImplicitBoolean>::New();
640  cutCylinder->SetOperationTypeToDifference();
641  cutCylinder->SetTransform(transform);
642  cutCylinder->AddFunction(cylinder);
643  cutCylinder->AddFunction(plane);
644 
645  cylinderForClipping.insert(
646  std::pair<TubeGraph::TubeDescriptorType, vtkSmartPointer<vtkImplicitBoolean>>(tube, cutCylinder));
647 
649  // vtkSmartPointer<vtkSampleFunction> sample = vtkSmartPointer<vtkSampleFunction>::New();
650  // sample->SetSampleDimensions(100,100,100);
651  // sample->SetImplicitFunction(cutCylinder);
653  // double xmin = centerVertex[0]-(2*diameter), xmax = centerVertex[0]+(2*diameter),
654  // ymin = centerVertex[1]-(2*diameter), ymax = centerVertex[1]+(2*diameter),
655  // zmin = centerVertex[2]-(2*diameter), zmax = centerVertex[2]+(2*diameter);
656  // sample->SetModelBounds(xmin, xmax, ymin, ymax, zmin, zmax);
657 
658  // vtkSmartPointer<vtkContourFilter> contour =vtkSmartPointer<vtkContourFilter>::New();
659  // contour->SetInputConnection(sample->GetOutputPort());
660  // contour->SetValue( 0, 0.25);
661 
662  // vtkSmartPointer<vtkPolyDataMapper> impMapper = vtkSmartPointer<vtkPolyDataMapper>::New();
663  // impMapper->SetInputConnection (contour->GetOutputPort());
664  // impMapper->ScalarVisibilityOff();
665  // vtkSmartPointer<vtkActor> impActor = vtkSmartPointer<vtkActor>::New();
666  // impActor->SetMapper(impMapper);
667 
668  // ls->m_vtkTubeGraphAssembly->AddPart(impActor);
669  }
670 
671  double sphereColorR = 0;
672  double sphereColorG = 0;
673  double sphereColorB = 0;
674 
675  for (auto itClipStructure =
676  cylinderForClipping.begin();
677  itClipStructure != cylinderForClipping.end();
678  itClipStructure++)
679  {
680  vtkSmartPointer<vtkPolyDataMapper> sphereMapper =
681  dynamic_cast<vtkPolyDataMapper *>(ls->m_vtkSpheresActorMap[vertexDesc]->GetMapper());
682 
683  if (sphereMapper != nullptr)
684  {
685  // first clip the sphere with the cylinder
686  vtkSmartPointer<vtkClipPolyData> clipperSphere = vtkSmartPointer<vtkClipPolyData>::New();
687  clipperSphere->SetInputData(sphereMapper->GetInput());
688  clipperSphere->SetClipFunction(itClipStructure->second);
689  clipperSphere->GenerateClippedOutputOn();
690  clipperSphere->Update();
691 
692  sphereMapper->SetInputConnection(clipperSphere->GetOutputPort());
693  sphereMapper->Update();
694  }
695 
696  mitk::Color tubeColor = graphProperty->GetColorOfTube(itClipStructure->first);
697  sphereColorR += tubeColor[0];
698  sphereColorG += tubeColor[1];
699  sphereColorB += tubeColor[2];
700 
701  // than clip with all other tubes
702  for (auto itTobBeClipped =
703  cylinderForClipping.begin();
704  itTobBeClipped != cylinderForClipping.end();
705  itTobBeClipped++)
706  {
707  TubeGraph::TubeDescriptorType toBeClippedTube = itTobBeClipped->first;
708 
709  if (itClipStructure->first != toBeClippedTube)
710  {
711  vtkSmartPointer<vtkPolyDataMapper> tubeMapper =
712  dynamic_cast<vtkPolyDataMapper *>(ls->m_vtkTubesActorMap[toBeClippedTube]->GetMapper());
713 
714  if (tubeMapper != nullptr)
715  {
716  // first clip the sphere with the cylinder
717  vtkSmartPointer<vtkClipPolyData> clipperTube = vtkSmartPointer<vtkClipPolyData>::New();
718  tubeMapper->Update();
719  clipperTube->SetInputData(tubeMapper->GetInput());
720  clipperTube->SetClipFunction(itClipStructure->second);
721  clipperTube->GenerateClippedOutputOn();
722  clipperTube->Update();
723 
724  tubeMapper->SetInputConnection(clipperTube->GetOutputPort());
725  tubeMapper->Update();
726  }
727  }
728  }
729  }
730  if (cylinderForClipping.size() != 0)
731  {
732  sphereColorR /= 255 * cylinderForClipping.size();
733  sphereColorG /= 255 * cylinderForClipping.size();
734  sphereColorB /= 255 * cylinderForClipping.size();
735  }
736 
737  ls->m_vtkSpheresActorMap[vertexDesc]->GetProperty()->SetColor(sphereColorR, sphereColorG, sphereColorB);
738 }
739 
740 bool mitk::TubeGraphVtkMapper3D::ClipStructures()
741 {
742  DataNode::Pointer node = this->GetDataNode();
743  if (node.IsNull())
744  {
745  itkWarningMacro(<< "associated node is nullptr!");
746  return false;
747  }
748 
749  bool clipStructures = false;
750  node->GetBoolProperty("Tube Graph.Clip Structures", clipStructures);
751 
752  return clipStructures;
753 }
#define ls
Definition: MitkMCxyz.cpp:57
L * GetLocalStorage(mitk::BaseRenderer *forRenderer)
Retrieves a LocalStorage for a specific BaseRenderer.
void GenerateDataForRenderer(mitk::BaseRenderer *renderer) override
void GeneratePolyDataForTube(TubeGraphEdge &edge, const TubeGraph::Pointer &graph, const TubeGraphProperty::Pointer &graphProperty, mitk::BaseRenderer *renderer)
void ClipPolyData(TubeGraphVertex &vertex, const TubeGraph::Pointer &graph, const TubeGraphProperty::Pointer &graphProperty, mitk::BaseRenderer *renderer)
#define MITK_INFO
Definition: mitkLogMacros.h:18
virtual DataNode * GetDataNode() const
Get the DataNode containing the data to map. Method only returns valid DataNode Pointer if the mapper...
Definition: mitkMapper.cpp:31
Base Class for Tube Graphs.
Definition: mitkTubeGraph.h:43
virtual void GenerateTubeGraphData(mitk::BaseRenderer *renderer)
Base Class for Tube Graph Vertices.
Organizes the rendering process.
void GeneratePolyDataForFurcation(TubeGraphVertex &vertex, const TubeGraph::Pointer &graph, mitk::BaseRenderer *renderer)
void FillVector3D(Tout &out, mitk::ScalarType x, mitk::ScalarType y, mitk::ScalarType z)
Definition: mitkArray.h:106
virtual void RenderTubeGraphPropertyInformation(mitk::BaseRenderer *renderer)
BaseData * GetData() const
Get the data object (instance of BaseData, e.g., an Image) managed by this DataNode.
TubeGraph::EdgeDescriptorType EdgeDescriptorType
std::pair< VertexDescriptorType, VertexDescriptorType > TubeDescriptorType
Definition: mitkTubeGraph.h:49
Property for tube graphs.
Class for elements which describes tubular structur with a circular cross section.
Base Class for Tube Graph Edges.
virtual const TubeGraph * GetInput()
itk::RGBPixel< float > Color
Color Standard RGB color typedef (float)
const TubeElement * GetTubeElement() const
vtkProp * GetVtkProp(mitk::BaseRenderer *renderer) override
boost::graph_traits< GraphType >::vertex_descriptor VertexDescriptorType
virtual const Point3D & GetCoordinates() const =0
std::vector< TubeElement * > GetElementVector()
unsigned int GetNumberOfElements() const