bool mitk::PlaneGeometryDataMapper2D::CutCrossLineWithReferenceGeometry(const BaseGeometry* referenceGeometry,
                                                                        Line3D& crossLine)
{
  Point3D boundingBoxMin, boundingBoxMax;
  boundingBoxMin = referenceGeometry->GetCornerPoint(0);
  boundingBoxMax = referenceGeometry->GetCornerPoint(7);

  Point3D indexLinePoint;
  Vector3D indexLineDirection;

  referenceGeometry->WorldToIndex(crossLine.GetPoint(), indexLinePoint);
  referenceGeometry->WorldToIndex(crossLine.GetDirection(), indexLineDirection);

  referenceGeometry->WorldToIndex(boundingBoxMin, boundingBoxMin);
  referenceGeometry->WorldToIndex(boundingBoxMax, boundingBoxMax);

  Point3D point1, point2;

  // Then, clip this line with the (transformed) bounding box of the
  // reference geometry.
  int nIntersections = Line3D::BoxLineIntersection(boundingBoxMin[0],
                                                   boundingBoxMin[1],
                                                   boundingBoxMin[2],
                                                   boundingBoxMax[0],
                                                   boundingBoxMax[1],
                                                   boundingBoxMax[2],
                                                   indexLinePoint,
                                                   indexLineDirection,
                                                   point1,
                                                   point2);

  if (nIntersections < 2)
  {
    return false;
  }

  referenceGeometry->IndexToWorld(point1, point1);
  referenceGeometry->IndexToWorld(point2, point2);
  crossLine.SetPoints(point1, point2);

  return true;
}
bool mitk::PlaneGeometryDataMapper2D::CutCrossLineWithPlaneGeometry(const PlaneGeometry* planeGeometry,
                                                                    Line3D& crossLine)
{
  Point2D indexLinePoint;
  Vector2D indexLineDirection;

  planeGeometry->Map(crossLine.GetPoint(), indexLinePoint);
  planeGeometry->Map(crossLine.GetPoint(), crossLine.GetDirection(), indexLineDirection);

  planeGeometry->WorldToIndex(indexLinePoint, indexLinePoint);
  planeGeometry->WorldToIndex(indexLineDirection, indexLineDirection);

  mitk::Point2D intersectionPoints[2];

  // Then, clip this line with the (transformed) bounding box of the
  // reference geometry.
  int nIntersections = Line3D::RectangleLineIntersection(planeGeometry->GetBounds()[0],
                                                         planeGeometry->GetBounds()[2],
                                                         planeGeometry->GetBounds()[1],
                                                         planeGeometry->GetBounds()[3],
                                                         indexLinePoint,
                                                         indexLineDirection,
                                                         intersectionPoints[0],
                                                         intersectionPoints[1]);

  if (nIntersections < 2)
  {
    return false;
  }

  planeGeometry->IndexToWorld(intersectionPoints[0], intersectionPoints[0]);
  planeGeometry->IndexToWorld(intersectionPoints[1], intersectionPoints[1]);

  Point3D point1, point2;

  planeGeometry->Map(intersectionPoints[0], point1);
  planeGeometry->Map(intersectionPoints[1], point2);
  crossLine.SetPoints(point1, point2);

  return true;
}
Beispiel #3
0
void mitk::PlaneCutFilter::_computeIntersection(itk::Image<TPixel, VImageDimension> *image, const PlaneGeometry *plane, const Geometry3D *geometry)
{
  typedef itk::Image<TPixel, VImageDimension> ImageType;

  const typename ImageType::RegionType &image_region = image->GetLargestPossibleRegion();
  const typename ImageType::SizeValueType
      max_x = image_region.GetSize(0ul),
      max_y = image_region.GetSize(1ul),
      max_z = image_region.GetSize(2ul),
      img_size = max_x * max_y;
  TPixel *data = image->GetBufferPointer();
  Point3D p1, p2;

  //TODO: Better solution required!
  TPixel casted_background_level = static_cast<TPixel>(this->m_BackgroundLevel);

  p1[0] = 0;
  p2[0] = max_x - 1ul;

  if (FILL == this->m_FillMode)
  {
    for (unsigned long z = 0ul; z < max_z; ++z)
    {
      p1[2] = z;
      p2[2] = z;

      for (unsigned long y = 0ul; y < max_y; ++y)
      {
        p1[1] = y;
        p2[1] = y;

        Point3D p1_t, p2_t;

        geometry->IndexToWorld(p1, p1_t);
        geometry->IndexToWorld(p2, p2_t);

        if (plane->IsAbove(p1_t))
        {
          if (plane->IsAbove(p2_t))
          {
            if (0.0f == this->m_BackgroundLevel)
            {
              memset(&data[(y * max_x) + (z * img_size)], 0, max_x * sizeof(TPixel));
            }
            else
            {
              TPixel *subdata = &data[(y * max_x) + (z * img_size)];

              for (unsigned long x = 0; x < max_x; ++x)
              {
                subdata[x] = casted_background_level;
              }
            }
          }
          else
          {
            Point3D intersection;
            Line3D line;

            line.SetPoints(p1_t, p2_t);
            plane->IntersectionPoint(line, intersection);
            geometry->WorldToIndex(intersection, intersection);

            if (0.0f == this->m_BackgroundLevel)
            {
              memset(&data[(y * max_x) + (z * img_size)], 0, (static_cast<unsigned long>(roundf(intersection[0])) + 1u) * sizeof(TPixel));
            }
            else
            {

              TPixel *subdata = &data[(y * max_x) + (z * img_size)];
              const unsigned long x_size = static_cast<unsigned long>(roundf(intersection[0])) + 1u;

              for (unsigned long x = 0; x < x_size; ++x)
              {
                subdata[x] = casted_background_level;
              }
            }
          }
        }
        else if (plane->IsAbove(p2_t))
        {
          Point3D intersection;
          Line3D line;

          line.SetPoints(p1_t, p2_t);
          plane->IntersectionPoint(line, intersection);
          geometry->WorldToIndex(intersection, intersection);

          if (0.0f == this->m_BackgroundLevel)
          {
            unsigned long x = static_cast<unsigned long>(roundf(intersection[0]));

            memset(&data[x + (y * max_x) + (z * img_size)], 0, (max_x - x) * sizeof(TPixel));
          }
          else
          {
            unsigned long x = static_cast<unsigned long>(roundf(intersection[0]));
            TPixel *subdata = &data[x + (y * max_x) + (z * img_size)];
            const unsigned long x_size = max_x - x;

            for (x = 0; x < x_size; ++x)
            {
              subdata[x] = casted_background_level;
            }
          }
        }
      }
    }
  }
  else
  {
    for (unsigned long z = 0ul; z < max_z; ++z)
    {
      p1[2] = z;
      p2[2] = z;

      for (unsigned long y = 0ul; y < max_y; ++y)
      {
        p1[1] = y;
        p2[1] = y;

        Point3D p1_t, p2_t;

        geometry->IndexToWorld(p1, p1_t);
        geometry->IndexToWorld(p2, p2_t);

        if (!plane->IsAbove(p1_t))
        {
          if (!plane->IsAbove(p2_t))
          {
            if (0.0f == this->m_BackgroundLevel)
            {
              memset(&data[(y * max_x) + (z * img_size)], 0, max_x * sizeof(TPixel));
            }
            else
            {
              TPixel *subdata = &data[(y * max_x) + (z * img_size)];

              for (unsigned long x = 0; x < max_x; ++x)
              {
                subdata[x] = casted_background_level;
              }
            }
          }
          else
          {
            Point3D intersection;
            Line3D line;

            line.SetPoints(p1_t, p2_t);
            plane->IntersectionPoint(line, intersection);
            geometry->WorldToIndex(intersection, intersection);

            if (0.0f == this->m_BackgroundLevel)
            {
              memset(&data[(y * max_x) + (z * img_size)], 0, (static_cast<unsigned long>(roundf(intersection[0])) + 1u) * sizeof(TPixel));
            }
            else
            {

              TPixel *subdata = &data[(y * max_x) + (z * img_size)];
              const unsigned long x_size = static_cast<unsigned long>(roundf(intersection[0])) + 1u;

              for (unsigned long x = 0; x < x_size; ++x)
              {
                subdata[x] = casted_background_level;
              }
            }
          }
        }
        else if (!plane->IsAbove(p2_t))
        {
          Point3D intersection;
          Line3D line;

          line.SetPoints(p1_t, p2_t);
          plane->IntersectionPoint(line, intersection);
          geometry->WorldToIndex(intersection, intersection);

          if (0.0f == this->m_BackgroundLevel)
          {
            unsigned long x = static_cast<unsigned long>(roundf(intersection[0]));

            memset(&data[x + (y * max_x) + (z * img_size)], 0, (max_x - x) * sizeof(TPixel));
          }
          else
          {
            unsigned long x = static_cast<unsigned long>(roundf(intersection[0]));
            TPixel *subdata = &data[x + (y * max_x) + (z * img_size)];
            const unsigned long x_size = max_x - x;

            for (x = 0; x < x_size; ++x)
            {
              subdata[x] = casted_background_level;
            }
          }
        }
      }
    }
  }
}
void mitk::PlaneGeometryDataMapper2D::CreateVtkCrosshair(mitk::BaseRenderer *renderer)
{
  bool visible = true;
  LocalStorage* ls = m_LSH.GetLocalStorage(renderer);
  ls->m_CrosshairActor->SetVisibility(0);
  ls->m_ArrowActor->SetVisibility(0);
  ls->m_CrosshairHelperLineActor->SetVisibility(0);

  GetDataNode()->GetVisibility(visible, renderer, "visible");

  if(!visible)
  {
    return;
  }

  PlaneGeometryData::Pointer input = const_cast< PlaneGeometryData * >(this->GetInput());
  mitk::DataNode* geometryDataNode = renderer->GetCurrentWorldPlaneGeometryNode();
  const PlaneGeometryData* rendererWorldPlaneGeometryData = dynamic_cast< PlaneGeometryData * >(geometryDataNode->GetData());

  // intersecting with ourself?
  if ( input.IsNull() || input.GetPointer() == rendererWorldPlaneGeometryData)
  {
    return; //nothing to do in this case
  }

  const PlaneGeometry *inputPlaneGeometry = dynamic_cast< const PlaneGeometry * >( input->GetPlaneGeometry() );

  const PlaneGeometry* worldPlaneGeometry = dynamic_cast< const PlaneGeometry* >(
        rendererWorldPlaneGeometryData->GetPlaneGeometry() );

  if ( worldPlaneGeometry && dynamic_cast<const AbstractTransformGeometry*>(worldPlaneGeometry)==NULL
       && inputPlaneGeometry && dynamic_cast<const AbstractTransformGeometry*>(input->GetPlaneGeometry() )==NULL
       && inputPlaneGeometry->GetReferenceGeometry() )
  {
    const BaseGeometry *referenceGeometry = inputPlaneGeometry->GetReferenceGeometry();

    // calculate intersection of the plane data with the border of the
    // world geometry rectangle
    Point3D point1, point2;

    Line3D crossLine;

    // Calculate the intersection line of the input plane with the world plane
    if ( worldPlaneGeometry->IntersectionLine( inputPlaneGeometry, crossLine ) )
    {
      Point3D boundingBoxMin, boundingBoxMax;
      boundingBoxMin = referenceGeometry->GetCornerPoint(0);
      boundingBoxMax = referenceGeometry->GetCornerPoint(7);

      Point3D indexLinePoint;
      Vector3D indexLineDirection;

      referenceGeometry->WorldToIndex(crossLine.GetPoint(),indexLinePoint);
      referenceGeometry->WorldToIndex(crossLine.GetDirection(),indexLineDirection);

      referenceGeometry->WorldToIndex(boundingBoxMin,boundingBoxMin);
      referenceGeometry->WorldToIndex(boundingBoxMax,boundingBoxMax);

      // Then, clip this line with the (transformed) bounding box of the
      // reference geometry.
      Line3D::BoxLineIntersection(
            boundingBoxMin[0], boundingBoxMin[1], boundingBoxMin[2],
          boundingBoxMax[0], boundingBoxMax[1], boundingBoxMax[2],
          indexLinePoint, indexLineDirection,
          point1, point2 );

      referenceGeometry->IndexToWorld(point1,point1);
      referenceGeometry->IndexToWorld(point2,point2);
      crossLine.SetPoints(point1,point2);

      vtkSmartPointer<vtkCellArray> lines = vtkSmartPointer<vtkCellArray>::New();
      vtkSmartPointer<vtkPoints> points = vtkSmartPointer<vtkPoints>::New();
      vtkSmartPointer<vtkPolyData> linesPolyData = vtkSmartPointer<vtkPolyData>::New();


      // Now iterate through all other lines displayed in this window and
      // calculate the positions of intersection with the line to be
      // rendered; these positions will be stored in lineParams to form a
      // gap afterwards.
      NodesVectorType::iterator otherPlanesIt = m_OtherPlaneGeometries.begin();
      NodesVectorType::iterator otherPlanesEnd = m_OtherPlaneGeometries.end();

      std::vector<Point3D> intersections;

      intersections.push_back(point1);

      otherPlanesIt = m_OtherPlaneGeometries.begin();
      int gapsize = 32;
      this->GetDataNode()->GetPropertyValue( "Crosshair.Gap Size",gapsize, NULL );


      ScalarType lineLength = point1.EuclideanDistanceTo(point2);
      DisplayGeometry *displayGeometry = renderer->GetDisplayGeometry();

      ScalarType gapinmm = gapsize * displayGeometry->GetScaleFactorMMPerDisplayUnit();

      float gapSizeParam = gapinmm / lineLength;

      while ( otherPlanesIt != otherPlanesEnd )
      {
        PlaneGeometry *otherPlane = static_cast< PlaneGeometry * >(
              static_cast< PlaneGeometryData * >((*otherPlanesIt)->GetData() )->GetPlaneGeometry() );

        if (otherPlane != inputPlaneGeometry && otherPlane != worldPlaneGeometry)
        {
          Point3D planeIntersection;
          otherPlane->IntersectionPoint(crossLine,planeIntersection);
          ScalarType sectionLength = point1.EuclideanDistanceTo(planeIntersection);
          ScalarType lineValue = sectionLength/lineLength;
          if(lineValue-gapSizeParam > 0.0)
            intersections.push_back(crossLine.GetPoint(lineValue-gapSizeParam));
          else intersections.pop_back();
          if(lineValue+gapSizeParam < 1.0)
            intersections.push_back(crossLine.GetPoint(lineValue+gapSizeParam));
        }
        ++otherPlanesIt;
      }
      if(intersections.size()%2 == 1)
        intersections.push_back(point2);

      if(intersections.empty())
      {
        this->DrawLine(point1,point2,lines,points);
      }
      else
        for(unsigned int i = 0 ; i< intersections.size()-1 ; i+=2)
        {
          this->DrawLine(intersections[i],intersections[i+1],lines,points);
        }

      // Add the points to the dataset
      linesPolyData->SetPoints(points);
      // Add the lines to the dataset
      linesPolyData->SetLines(lines);

      Vector3D orthogonalVector;
      orthogonalVector = inputPlaneGeometry->GetNormal();
      worldPlaneGeometry->Project(orthogonalVector,orthogonalVector);
      orthogonalVector.Normalize();

      // Visualize
      ls->m_Mapper->SetInputData(linesPolyData);
      ls->m_CrosshairActor->SetMapper(ls->m_Mapper);

      // Determine if we should draw the area covered by the thick slicing, default is false.
      // This will also show the area of slices that do not have thick slice mode enabled
      bool showAreaOfThickSlicing = false;
      GetDataNode()->GetBoolProperty( "reslice.thickslices.showarea", showAreaOfThickSlicing );

      // determine the pixelSpacing in that direction
      double thickSliceDistance = SlicedGeometry3D::CalculateSpacing( referenceGeometry->GetSpacing(), orthogonalVector );

      IntProperty *intProperty=0;
      if( GetDataNode()->GetProperty( intProperty, "reslice.thickslices.num" ) && intProperty )
        thickSliceDistance *= intProperty->GetValue()+0.5;
      else
        showAreaOfThickSlicing = false;

      // not the nicest place to do it, but we have the width of the visible bloc in MM here
      // so we store it in this fancy property
      GetDataNode()->SetFloatProperty( "reslice.thickslices.sizeinmm", thickSliceDistance*2 );

      ls->m_CrosshairActor->SetVisibility(1);

      vtkSmartPointer<vtkPolyData> arrowPolyData = vtkSmartPointer<vtkPolyData>::New();
      ls->m_Arrowmapper->SetInputData(arrowPolyData);
      if(this->m_RenderOrientationArrows)
      {
        ScalarType triangleSizeMM = 7.0 * displayGeometry->GetScaleFactorMMPerDisplayUnit();

        vtkSmartPointer<vtkCellArray> triangles = vtkSmartPointer<vtkCellArray>::New();
        vtkSmartPointer<vtkPoints> triPoints = vtkSmartPointer<vtkPoints>::New();

        DrawOrientationArrow(triangles,triPoints,triangleSizeMM,orthogonalVector,point1,point2);
        DrawOrientationArrow(triangles,triPoints,triangleSizeMM,orthogonalVector,point2,point1);
        arrowPolyData->SetPoints(triPoints);
        arrowPolyData->SetPolys(triangles);
        ls->m_ArrowActor->SetVisibility(1);
      }

      // Visualize
      vtkSmartPointer<vtkPolyData> helperlinesPolyData = vtkSmartPointer<vtkPolyData>::New();
      ls->m_HelperLinesmapper->SetInputData(helperlinesPolyData);
      if ( showAreaOfThickSlicing )
      {
        vtkSmartPointer<vtkCellArray> helperlines = vtkSmartPointer<vtkCellArray>::New();
        // vectorToHelperLine defines how to reach the helperLine from the mainLine
        // got the right direction, so we multiply the width
        Vector3D vecToHelperLine = orthogonalVector * thickSliceDistance;

        this->DrawLine(point1 - vecToHelperLine, point2 - vecToHelperLine,helperlines,points);
        this->DrawLine(point1 + vecToHelperLine, point2 + vecToHelperLine,helperlines,points);

        // Add the points to the dataset
        helperlinesPolyData->SetPoints(points);

        // Add the lines to the dataset
        helperlinesPolyData->SetLines(helperlines);

        ls->m_CrosshairActor->GetProperty()->SetLineStipplePattern(0xf0f0);
        ls->m_CrosshairActor->GetProperty()->SetLineStippleRepeatFactor(1);
        ls->m_CrosshairHelperLineActor->SetVisibility(1);
      }
    }
  }
}