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