Beispiel #1
0
bool
PlaneGeometry::IntersectionPointParam( const Line3D &line, double &t ) const
{
  Vector3D planeNormal = this->GetNormal();

  Vector3D lineDirection = line.GetDirection();

  t = planeNormal * lineDirection;

  if ( fabs( t ) < eps )
  {
    return false;
  }

  Vector3D diff;
  diff = this->GetOrigin() - line.GetPoint();
  t = ( planeNormal * diff  ) / t;
  return true;
}
Beispiel #2
0
unsigned int
PlaneGeometry::IntersectWithPlane2D(
  const PlaneGeometry* plane, Point2D& lineFrom, Point2D &lineTo ) const
{
  Line3D crossline;
  if ( this->IntersectionLine( plane, crossline ) == false )
    return 0;

  Point2D  point2;
  Vector2D direction2;

  this->Map( crossline.GetPoint(), point2 );
  this->Map( crossline.GetPoint(), crossline.GetDirection(), direction2 );

  return
    Line3D::RectangleLineIntersection(
    0, 0, GetExtentInMM(0), GetExtentInMM(1),
    point2, direction2, lineFrom, lineTo );
}
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 #5
0
bool PlaneGeometry::IntersectionPoint(
  const Line3D &line, Point3D &intersectionPoint ) const
{
  Vector3D planeNormal = this->GetNormal();
  planeNormal.Normalize();

  Vector3D lineDirection = line.GetDirection();
  lineDirection.Normalize();

  double t = planeNormal * lineDirection;
  if ( fabs( t ) < eps )
  {
    return false;
  }

  Vector3D diff;
  diff = this->GetOrigin() - line.GetPoint();
  t = ( planeNormal * diff ) / t;

  intersectionPoint = line.GetPoint() + lineDirection * t;
  return true;
}
Beispiel #6
0
double PlaneGeometry::Angle( const Line3D &line ) const
{
  return vnl_math::pi_over_2
    - angle( line.GetDirection().GetVnlVector(), GetMatrixColumn(2) );
}
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);
      }
    }
  }
}
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)
  {
    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 ) )
    {
      bool hasIntersection = referenceGeometry ? CutCrossLineWithReferenceGeometry(referenceGeometry, crossLine) :
                                                 CutCrossLineWithPlaneGeometry(inputPlaneGeometry, crossLine);

      if (!hasIntersection)
      {
        return;
      }

      point1 = crossLine.GetPoint1();
      point2 = crossLine.GetPoint2();

      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();

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


      auto intervals = IntervalSet<double>( SimpleInterval<double>(0, 1));

      ScalarType lineLength = point1.EuclideanDistanceTo(point2);
      ScalarType gapInMM = gapSize * renderer->GetScaleFactorMMPerDisplayUnit();
      float gapSizeParam = gapInMM / lineLength;

      if( gapSize != 0 )
      {
        while ( otherPlanesIt != otherPlanesEnd )
        {
          bool ignorePlane = false;
          (*otherPlanesIt)->GetPropertyValue("Crosshair.Ignore", ignorePlane);
          if (ignorePlane)
          {
              ++otherPlanesIt;
              continue;
          }

          PlaneGeometry *otherPlaneGeometry = static_cast< PlaneGeometry * >(
                static_cast< PlaneGeometryData * >((*otherPlanesIt)->GetData() )->GetPlaneGeometry() );

          if (otherPlaneGeometry != inputPlaneGeometry && otherPlaneGeometry != worldPlaneGeometry)
          {
              double intersectionParam;
              if (otherPlaneGeometry->IntersectionPointParam(crossLine, intersectionParam) && intersectionParam > 0 &&
                  intersectionParam < 1)
              {
                Point3D point = crossLine.GetPoint() + intersectionParam * crossLine.GetDirection();

                bool intersectionPointInsideOtherPlane =
                  otherPlaneGeometry->HasReferenceGeometry() ?
                    TestPointInReferenceGeometry(otherPlaneGeometry->GetReferenceGeometry(), point) :
                    TestPointInPlaneGeometry(otherPlaneGeometry, point);

                if (intersectionPointInsideOtherPlane)
                {
                  intervals -= SimpleInterval<double>(intersectionParam - gapSizeParam, intersectionParam + gapSizeParam);
                }
              }
          }
          ++otherPlanesIt;
        }
      }

      for (const auto& interval : intervals.getIntervals()) {
          this->DrawLine(crossLine.GetPoint(interval.GetLowerBoundary()), crossLine.GetPoint(interval.GetUpperBoundary()), 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 ? referenceGeometry->GetSpacing() : inputPlaneGeometry->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 * renderer->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);
      }
    }
  }
}