void mitk::ConnectomicsNetworkCreator::CreateNetworkFromFibersAndSegmentation()
{

  //empty graph
  m_ConNetwork->clear();
  m_LabelToVertexMap.clear();
  m_LabelToNodePropertyMap.clear();

  vtkSmartPointer<vtkPolyData> fiberPolyData = m_FiberBundle->GetFiberPolyData();
  vtkSmartPointer<vtkCellArray> vLines = fiberPolyData->GetLines();
  vLines->InitTraversal();

  int numFibers = m_FiberBundle->GetNumFibers();
  for( int fiberID( 0 ); fiberID < numFibers; fiberID++ )
  {
    vtkIdType   numPointsInCell(0);
    vtkIdType*  pointsInCell(NULL);
    vLines->GetNextCell ( numPointsInCell, pointsInCell );

    TractType::Pointer singleTract = TractType::New();
    for( int pointInCellID( 0 ); pointInCellID < numPointsInCell ; pointInCellID++)
    {
      // push back point
      PointType point = GetItkPoint( fiberPolyData->GetPoint( pointsInCell[ pointInCellID ] ) );
      singleTract->InsertElement( singleTract->Size(), point );
    }

    //MappingStrategy strategy = EndElementPosition;
    //MappingStrategy strategy = JustEndPointVerticesNoLabel;
    MappingStrategy strategy = EndElementPositionAvoidingWhiteMatter;
    if ( singleTract && ( singleTract->Size() > 0 ) )
    {
      AddConnectionToNetwork( 
        ReturnAssociatedVertexPairForLabelPair( 
        ReturnLabelForFiberTract( singleTract, strategy ) 
        ) 
        );
    }
  }

  // Prune unconnected nodes
  m_ConNetwork->PruneUnconnectedSingleNodes();
  // provide network with geometry
  m_ConNetwork->SetGeometry( m_Segmentation->GetGeometry() );
  m_ConNetwork->UpdateBounds();
  m_ConNetwork->SetIsModified( true );

  MBI_INFO << mitk::ConnectomicsConstantsManager::CONNECTOMICS_WARNING_INFO_NETWORK_CREATED;
}
TractContainerType QmitkTbssRoiAnalysisWidget::CreateTracts(mitk::FiberBundle *fib,
                                                            mitk::DataNode *startRoi,
                                                            mitk::DataNode *endRoi)
{
    mitk::PlaneGeometry* startGeometry2D = const_cast<mitk::PlaneGeometry*>(dynamic_cast<mitk::PlanarFigure*>(startRoi->GetData())->GetPlaneGeometry());
    mitk::PlaneGeometry* endGeometry2D = const_cast<mitk::PlaneGeometry*>(dynamic_cast<mitk::PlanarFigure*>(endRoi->GetData())->GetPlaneGeometry());


    mitk::Point3D startCenter = dynamic_cast<mitk::PlanarFigure*>(startRoi->GetData())->GetWorldControlPoint(0); //center Point of start roi
    mitk::Point3D endCenter = dynamic_cast<mitk::PlanarFigure*>(startRoi->GetData())->GetWorldControlPoint(0); //center Point of end roi

    mitk::FiberBundle::Pointer inStart = fib->ExtractFiberSubset(startRoi, NULL);
    mitk::FiberBundle::Pointer inBoth = inStart->ExtractFiberSubset(endRoi, NULL);



    int num = inBoth->GetNumFibers();


    TractContainerType tracts;


    vtkSmartPointer<vtkPolyData> fiberPolyData = inBoth->GetFiberPolyData();
    vtkCellArray* lines = fiberPolyData->GetLines();
    lines->InitTraversal();



    // Now find out for each fiber which ROI is encountered first. If this is the startRoi, the direction is ok
    // Otherwise the plot should be in the reverse direction
    for( int fiberID( 0 ); fiberID < num; fiberID++ )
    {
      vtkIdType   numPointsInCell(0);
      vtkIdType*  pointsInCell(NULL);
      lines->GetNextCell ( numPointsInCell, pointsInCell );

      int startId = 0;
      int endId = 0;

      mitk::ScalarType minDistStart = std::numeric_limits<mitk::ScalarType>::max();
      mitk::ScalarType minDistEnd = std::numeric_limits<mitk::ScalarType>::max();



      for( int pointInCellID( 0 ); pointInCellID < numPointsInCell ; pointInCellID++)
      {


        mitk::ScalarType *p = fiberPolyData->GetPoint( pointsInCell[ pointInCellID ] );

        mitk::Point3D point;
        point[0] = p[0];
        point[1] = p[1];
        point[2] = p[2];

        mitk::ScalarType distanceToStart = point.EuclideanDistanceTo(startCenter);
        mitk::ScalarType distanceToEnd = point.EuclideanDistanceTo(endCenter);

        if(distanceToStart < minDistStart)
        {
          minDistStart = distanceToStart;
          startId = pointInCellID;
        }

        if(distanceToEnd < minDistEnd)
        {
          minDistEnd = distanceToEnd;
          endId = pointInCellID;
        }



      }

      /* We found the start and end points of of the part that should be plottet for
         the current fiber. now we need to plot them. If the endId is smaller than the startId the plot order
         must be reversed*/

      TractType singleTract;
      PointType point;

      if(startId < endId)
      {

        // Calculate the intersection of the ROI with the startRoi and decide if the startId is part of the roi or must be cut of
        mitk::ScalarType *p = fiberPolyData->GetPoint( pointsInCell[ startId ] );
        mitk::Vector3D p0;
        p0[0] = p[0];      p0[1] = p[1];      p0[2] = p[2];

        p = fiberPolyData->GetPoint( pointsInCell[ startId+1 ] );
        mitk::Vector3D p1;
        p1[0] = p[0];       p1[1] = p[1];       p1[2] = p[2];

        // Check if p and p2 are both on the same side of the plane
        mitk::Vector3D normal = startGeometry2D->GetNormal();

        mitk::Point3D pStart;
        pStart[0] = p0[0];      pStart[1] = p0[1];      pStart[2] = p0[2];

        mitk::Point3D pSecond;
        pSecond[0] = p1[0];      pSecond[1] = p1[1];      pSecond[2] = p1[2];

        bool startOnPositive = startGeometry2D->IsAbove(pStart);
        bool secondOnPositive = startGeometry2D->IsAbove(pSecond);


        mitk::Vector3D onPlane;
        onPlane[0] = startCenter[0];      onPlane[1] = startCenter[1];      onPlane[2] = startCenter[2];



        if(! (secondOnPositive ^ startOnPositive) )
        {
          /* startId and startId+1 lie on the same side of the plane, so we need
             need startId-1 to calculate the intersection with the planar figure*/
          p = fiberPolyData->GetPoint( pointsInCell[ startId-1 ] );
          p1[0] = p[0];        p1[1] = p[1];        p1[2] = p[2];
        }


        mitk::ScalarType d = ( (onPlane-p0)*normal) / ( (p0-p1) * normal );
        mitk::Vector3D newPoint = (p0-p1);

        point[0] = d*newPoint[0] + p0[0];
        point[1] = d*newPoint[1] + p0[1];
        point[2] = d*newPoint[2] + p0[2];

        singleTract.push_back(point);

        if(! (secondOnPositive ^ startOnPositive) )
        {
          /* StartId and startId+1 lie on the same side of the plane
             so startId is also part of the ROI*/

          mitk::ScalarType *start = fiberPolyData->GetPoint( pointsInCell[startId] );
          point[0] = start[0]; point[1] = start[1]; point[2] = start[2];
          singleTract.push_back(point);
        }



        for( int pointInCellID( startId+1 ); pointInCellID < endId ; pointInCellID++)
        {
          // push back point
          mitk::ScalarType *p = fiberPolyData->GetPoint( pointsInCell[ pointInCellID ] );
          point[0] = p[0]; point[1] = p[1]; point[2] = p[2];
          singleTract.push_back( point );

        }

        /* endId must be included if endId and endId-1 lie on the same side of the
                 plane defined by endRoi*/


        p = fiberPolyData->GetPoint( pointsInCell[ endId ] );
        p0[0] = p[0];      p0[1] = p[1];      p0[2] = p[2];

        p = fiberPolyData->GetPoint( pointsInCell[ endId-1 ] );
        p1[0] = p[0];      p1[1] = p[1];      p1[2] = p[2];

        mitk::Point3D pLast;
        pLast[0] = p0[0];      pLast[1] = p0[1];      pLast[2] = p0[2];

        mitk::Point3D pBeforeLast;
        pBeforeLast[0] = p1[0];      pBeforeLast[1] = p1[1];      pBeforeLast[2] = p1[2];

        normal = endGeometry2D->GetNormal();
        bool lastOnPositive = endGeometry2D->IsAbove(pLast);
        bool secondLastOnPositive = endGeometry2D->IsAbove(pBeforeLast);


        onPlane[0] = endCenter[0];
        onPlane[1] = endCenter[1];
        onPlane[2] = endCenter[2];

        if(! (lastOnPositive ^ secondLastOnPositive) )
        {
          /* endId and endId-1 lie on the same side of the plane, so we need
             need endId+1 to calculate the intersection with the planar figure.
             this should exist since we know that the fiber crosses the planar figure
             endId is also part of the tract and can be inserted here */

          p = fiberPolyData->GetPoint( pointsInCell[ endId ] );
          point[0] = p[0]; point[1] = p[1]; point[2] = p[2];
          singleTract.push_back( point );

          p = fiberPolyData->GetPoint( pointsInCell[ endId+1 ] );
        }

        d = ( (onPlane-p0)*normal) / ( (p0-p1) * normal );

        newPoint = (p0-p1);

        point[0] = d*newPoint[0] + p0[0];
        point[1] = d*newPoint[1] + p0[1];
        point[2] = d*newPoint[2] + p0[2];

        singleTract.push_back(point);



      }
      else{

        // Calculate the intersection of the ROI with the startRoi and decide if the startId is part of the roi or must be cut of
        mitk::ScalarType *p = fiberPolyData->GetPoint( pointsInCell[ startId ] );
        mitk::Vector3D p0;
        p0[0] = p[0];      p0[1] = p[1];      p0[2] = p[2];

        p = fiberPolyData->GetPoint( pointsInCell[ startId-1 ] );
        mitk::Vector3D p1;
        p1[0] = p[0];       p1[1] = p[1];       p1[2] = p[2];

        // Check if p and p2 are both on the same side of the plane
        mitk::Vector3D normal = startGeometry2D->GetNormal();

        mitk::Point3D pStart;
        pStart[0] = p0[0];      pStart[1] = p0[1];      pStart[2] = p0[2];

        mitk::Point3D pSecond;
        pSecond[0] = p1[0];      pSecond[1] = p1[1];      pSecond[2] = p1[2];

        bool startOnPositive = startGeometry2D->IsAbove(pStart);
        bool secondOnPositive = startGeometry2D->IsAbove(pSecond);

        mitk::Vector3D onPlane;
        onPlane[0] = startCenter[0];      onPlane[1] = startCenter[1];      onPlane[2] = startCenter[2];


        if(! (secondOnPositive ^ startOnPositive) )
        {
          /* startId and startId+1 lie on the same side of the plane, so we need
             need startId-1 to calculate the intersection with the planar figure*/
          p = fiberPolyData->GetPoint( pointsInCell[ startId-1 ] );
          p1[0] = p[0];        p1[1] = p[1];        p1[2] = p[2];
        }


        mitk::ScalarType d = ( (onPlane-p0)*normal) / ( (p0-p1) * normal );
        mitk::Vector3D newPoint = (p0-p1);


        point[0] = d*newPoint[0] + p0[0];
        point[1] = d*newPoint[1] + p0[1];
        point[2] = d*newPoint[2] + p0[2];


        singleTract.push_back(point);

        if(! (secondOnPositive ^ startOnPositive) )
        {
          /* StartId and startId+1 lie on the same side of the plane
             so startId is also part of the ROI*/

          mitk::ScalarType *start = fiberPolyData->GetPoint( pointsInCell[startId] );
          point[0] = start[0]; point[1] = start[1]; point[2] = start[2];
          singleTract.push_back(point);
        }



        for( int pointInCellID( startId-1 ); pointInCellID > endId ; pointInCellID--)
        {
          // push back point
          mitk::ScalarType *p = fiberPolyData->GetPoint( pointsInCell[ pointInCellID ] );
          point[0] = p[0]; point[1] = p[1]; point[2] = p[2];
          singleTract.push_back( point );

        }

        /* endId must be included if endId and endI+1 lie on the same side of the
                 plane defined by endRoi*/


        p = fiberPolyData->GetPoint( pointsInCell[ endId ] );
        p0[0] = p[0];      p0[1] = p[1];      p0[2] = p[2];

        p = fiberPolyData->GetPoint( pointsInCell[ endId+1 ] );
        p1[0] = p[0];      p1[1] = p[1];      p1[2] = p[2];

        mitk::Point3D pLast;
        pLast[0] = p0[0];      pLast[1] = p0[1];      pLast[2] = p0[2];

        mitk::Point3D pBeforeLast;
        pBeforeLast[0] = p1[0];      pBeforeLast[1] = p1[1];      pBeforeLast[2] = p1[2];

        bool lastOnPositive = endGeometry2D->IsAbove(pLast);
        bool secondLastOnPositive = endGeometry2D->IsAbove(pBeforeLast);
        normal = endGeometry2D->GetNormal();



        onPlane[0] = endCenter[0];
        onPlane[1] = endCenter[1];
        onPlane[2] = endCenter[2];

        if(! (lastOnPositive ^ secondLastOnPositive) )
        {
          /* endId and endId+1 lie on the same side of the plane, so we need
             need endId-1 to calculate the intersection with the planar figure.
             this should exist since we know that the fiber crosses the planar figure
             endId is also part of the tract and can be inserted here */

          p = fiberPolyData->GetPoint( pointsInCell[ endId ] );
          point[0] = p[0]; point[1] = p[1]; point[2] = p[2];
          singleTract.push_back( point );

          p = fiberPolyData->GetPoint( pointsInCell[ endId-1 ] );
        }

        d = ( (onPlane-p0)*normal) / ( (p0-p1) * normal );

        newPoint = (p0-p1);

        point[0] = d*newPoint[0] + p0[0];
        point[1] = d*newPoint[1] + p0[1];
        point[2] = d*newPoint[2] + p0[2];

        singleTract.push_back(point);

      }


      tracts.push_back(singleTract);


    }

    return tracts;
}