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