mitk::BaseGeometry::BaseGeometry(const BaseGeometry& other) : Superclass(), mitk::OperationActor(), m_FrameOfReferenceID(other.m_FrameOfReferenceID), m_IndexToWorldTransformLastModified(other.m_IndexToWorldTransformLastModified), m_ImageGeometry(other.m_ImageGeometry), m_ModifiedLockFlag(false), m_ModifiedCalledFlag(false) { m_GeometryTransform = new GeometryTransformHolder(*other.GetGeometryTransformHolder()); other.InitializeGeometry(this); }
static IntensityProfile::Pointer ComputeIntensityProfile(Image::Pointer image, itk::PolyLineParametricPath<3>::Pointer path) { IntensityProfile::Pointer intensityProfile = IntensityProfile::New(); itk::PolyLineParametricPath<3>::InputType input = path->StartOfInput(); BaseGeometry* imageGeometry = image->GetGeometry(); const PixelType pixelType = image->GetPixelType(); IntensityProfile::MeasurementVectorType measurementVector; itk::PolyLineParametricPath<3>::OffsetType offset; Point3D worldPoint; itk::Index<3> index; do { imageGeometry->IndexToWorld(path->Evaluate(input), worldPoint); imageGeometry->WorldToIndex(worldPoint, index); mitkPixelTypeMultiplex3(ReadPixel, pixelType, image, index, measurementVector.GetDataPointer()); intensityProfile->PushBack(measurementVector); offset = path->IncrementInput(input); } while ((offset[0] | offset[1] | offset[2]) != 0); return intensityProfile; }
bool mitk::SegTool2D::DetermineAffectedImageSlice( const Image* image, const PlaneGeometry* plane, int& affectedDimension, int& affectedSlice ) { assert(image); assert(plane); // compare normal of plane to the three axis vectors of the image Vector3D normal = plane->GetNormal(); Vector3D imageNormal0 = image->GetSlicedGeometry()->GetAxisVector(0); Vector3D imageNormal1 = image->GetSlicedGeometry()->GetAxisVector(1); Vector3D imageNormal2 = image->GetSlicedGeometry()->GetAxisVector(2); normal.Normalize(); imageNormal0.Normalize(); imageNormal1.Normalize(); imageNormal2.Normalize(); imageNormal0.SetVnlVector( vnl_cross_3d<ScalarType>(normal.GetVnlVector(),imageNormal0.GetVnlVector()) ); imageNormal1.SetVnlVector( vnl_cross_3d<ScalarType>(normal.GetVnlVector(),imageNormal1.GetVnlVector()) ); imageNormal2.SetVnlVector( vnl_cross_3d<ScalarType>(normal.GetVnlVector(),imageNormal2.GetVnlVector()) ); double eps( 0.00001 ); // axial if ( imageNormal2.GetNorm() <= eps ) { affectedDimension = 2; } // sagittal else if ( imageNormal1.GetNorm() <= eps ) { affectedDimension = 1; } // frontal else if ( imageNormal0.GetNorm() <= eps ) { affectedDimension = 0; } else { affectedDimension = -1; // no idea return false; } // determine slice number in image BaseGeometry* imageGeometry = image->GetGeometry(0); Point3D testPoint = imageGeometry->GetCenter(); Point3D projectedPoint; plane->Project( testPoint, projectedPoint ); Point3D indexPoint; imageGeometry->WorldToIndex( projectedPoint, indexPoint ); affectedSlice = ROUND( indexPoint[affectedDimension] ); MITK_DEBUG << "indexPoint " << indexPoint << " affectedDimension " << affectedDimension << " affectedSlice " << affectedSlice; // check if this index is still within the image if ( affectedSlice < 0 || affectedSlice >= static_cast<int>(image->GetDimension(affectedDimension)) ) return false; return true; }
mitk::BaseGeometry::BaseGeometry(const BaseGeometry& other): Superclass(), mitk::OperationActor(), //m_TimeBounds(other.m_TimeBounds), m_FrameOfReferenceID(other.m_FrameOfReferenceID), m_IndexToWorldTransformLastModified(other.m_IndexToWorldTransformLastModified), m_Origin(other.m_Origin), m_ImageGeometry(other.m_ImageGeometry), m_ModifiedLockFlag(false), m_ModifiedCalledFlag(false) { m_VtkMatrix = vtkMatrix4x4::New(); m_VtkIndexToWorldTransform = vtkMatrixToLinearTransform::New(); m_VtkIndexToWorldTransform->SetInput(m_VtkMatrix); other.InitializeGeometry(this); }
void PlaneGeometryDataVtkMapper3D::GenerateDataForRenderer(BaseRenderer* renderer) { SetVtkMapperImmediateModeRendering(m_EdgeMapper); SetVtkMapperImmediateModeRendering(m_BackgroundMapper); // Remove all actors from the assembly, and re-initialize it with the // edge actor m_ImageAssembly->GetParts()->RemoveAllItems(); bool visible = true; GetDataNode()->GetVisibility(visible, renderer, "visible"); if ( !visible ) { // visibility has explicitly to be set in the single actors // due to problems when using cell picking: // even if the assembly is invisible, the renderer contains // references to the assemblies parts. During picking the // visibility of each part is checked, and not only for the // whole assembly. m_ImageAssembly->VisibilityOff(); m_EdgeActor->VisibilityOff(); return; } // visibility has explicitly to be set in the single actors // due to problems when using cell picking: // even if the assembly is invisible, the renderer contains // references to the assemblies parts. During picking the // visibility of each part is checked, and not only for the // whole assembly. m_ImageAssembly->VisibilityOn(); bool drawEdges = true; this->GetDataNode()->GetBoolProperty("draw edges", drawEdges, renderer); m_EdgeActor->SetVisibility(drawEdges); PlaneGeometryData::Pointer input = const_cast< PlaneGeometryData * >(this->GetInput()); if (input.IsNotNull() && (input->GetPlaneGeometry() != NULL)) { SmartPointerProperty::Pointer surfacecreatorprop; surfacecreatorprop = dynamic_cast< SmartPointerProperty * >(GetDataNode()->GetProperty("surfacegeometry", renderer)); if ( (surfacecreatorprop.IsNull()) || (surfacecreatorprop->GetSmartPointer().IsNull()) || ((m_SurfaceCreator = dynamic_cast<PlaneGeometryDataToSurfaceFilter*> (surfacecreatorprop->GetSmartPointer().GetPointer())).IsNull() ) ) { m_SurfaceCreator->PlaceByGeometryOn(); surfacecreatorprop = SmartPointerProperty::New( m_SurfaceCreator ); GetDataNode()->SetProperty("surfacegeometry", surfacecreatorprop); } m_SurfaceCreator->SetInput(input); int res; if (GetDataNode()->GetIntProperty("xresolution", res, renderer)) { m_SurfaceCreator->SetXResolution(res); } if (GetDataNode()->GetIntProperty("yresolution", res, renderer)) { m_SurfaceCreator->SetYResolution(res); } double tubeRadius = 1.0; // Radius of tubular edge surrounding plane // Clip the PlaneGeometry with the reference geometry bounds (if available) if ( input->GetPlaneGeometry()->HasReferenceGeometry() ) { BaseGeometry *referenceGeometry = input->GetPlaneGeometry()->GetReferenceGeometry(); BoundingBox::PointType boundingBoxMin, boundingBoxMax; boundingBoxMin = referenceGeometry->GetBoundingBox()->GetMinimum(); boundingBoxMax = referenceGeometry->GetBoundingBox()->GetMaximum(); if ( referenceGeometry->GetImageGeometry() ) { for ( unsigned int i = 0; i < 3; ++i ) { boundingBoxMin[i] -= 0.5; boundingBoxMax[i] -= 0.5; } } m_SurfaceCreatorPointsContainer->CreateElementAt( 0 ) = boundingBoxMin; m_SurfaceCreatorPointsContainer->CreateElementAt( 1 ) = boundingBoxMax; m_SurfaceCreatorBoundingBox->ComputeBoundingBox(); m_SurfaceCreator->SetBoundingBox( m_SurfaceCreatorBoundingBox ); tubeRadius = referenceGeometry->GetDiagonalLength() / 450.0; } // If no reference geometry is available, clip with the current global // bounds else if (m_DataStorage.IsNotNull()) { m_SurfaceCreator->SetBoundingBox(m_DataStorage->ComputeVisibleBoundingBox(NULL, "includeInBoundingBox")); tubeRadius = sqrt( m_SurfaceCreator->GetBoundingBox()->GetDiagonalLength2() ) / 450.0; } // Calculate the surface of the PlaneGeometry m_SurfaceCreator->Update(); Surface *surface = m_SurfaceCreator->GetOutput(); // Check if there's something to display, otherwise return if ( (surface->GetVtkPolyData() == 0 ) || (surface->GetVtkPolyData()->GetNumberOfCells() == 0) ) { m_ImageAssembly->VisibilityOff(); return; } // add a graphical representation of the surface normals if requested DataNode* node = this->GetDataNode(); bool displayNormals = false; bool colorTwoSides = false; bool invertNormals = false; node->GetBoolProperty("draw normals 3D", displayNormals, renderer); node->GetBoolProperty("color two sides", colorTwoSides, renderer); node->GetBoolProperty("invert normals", invertNormals, renderer); //if we want to draw the display normals or render two sides we have to get the colors if( displayNormals || colorTwoSides ) { //get colors float frontColor[3] = { 0.0, 0.0, 1.0 }; node->GetColor( frontColor, renderer, "front color" ); float backColor[3] = { 1.0, 0.0, 0.0 }; node->GetColor( backColor, renderer, "back color" ); if ( displayNormals ) { m_NormalsTransformer->SetInputData( surface->GetVtkPolyData() ); m_NormalsTransformer->SetTransform(node->GetVtkTransform(this->GetTimestep()) ); m_FrontHedgeHog->SetInputConnection(m_NormalsTransformer->GetOutputPort() ); m_FrontHedgeHog->SetVectorModeToUseNormal(); m_FrontHedgeHog->SetScaleFactor( invertNormals ? 1.0 : -1.0 ); m_FrontHedgeHog->Update(); m_FrontNormalsActor->GetProperty()->SetColor( frontColor[0], frontColor[1], frontColor[2] ); m_BackHedgeHog->SetInputConnection( m_NormalsTransformer->GetOutputPort() ); m_BackHedgeHog->SetVectorModeToUseNormal(); m_BackHedgeHog->SetScaleFactor( invertNormals ? -1.0 : 1.0 ); m_BackHedgeHog->Update(); m_BackNormalsActor->GetProperty()->SetColor( backColor[0], backColor[1], backColor[2] ); //if there is no actor added yet, add one if ( !m_NormalsActorAdded ) { m_Prop3DAssembly->AddPart( m_FrontNormalsActor ); m_Prop3DAssembly->AddPart( m_BackNormalsActor ); m_NormalsActorAdded = true; } } //if we don't want to display normals AND there is an actor added remove the actor else if ( m_NormalsActorAdded ) { m_Prop3DAssembly->RemovePart( m_FrontNormalsActor ); m_Prop3DAssembly->RemovePart( m_BackNormalsActor ); m_NormalsActorAdded = false; } if ( colorTwoSides ) { if ( !invertNormals ) { m_BackgroundActor->GetProperty()->SetColor( backColor[0], backColor[1], backColor[2] ); m_BackgroundActor->GetBackfaceProperty()->SetColor( frontColor[0], frontColor[1], frontColor[2] ); } else { m_BackgroundActor->GetProperty()->SetColor( frontColor[0], frontColor[1], frontColor[2] ); m_BackgroundActor->GetBackfaceProperty()->SetColor( backColor[0], backColor[1], backColor[2] ); } } } // Add black background for all images (which may be transparent) m_BackgroundMapper->SetInputData( surface->GetVtkPolyData() ); m_ImageAssembly->AddPart( m_BackgroundActor ); LayerSortedActorList layerSortedActors; // Traverse the data tree to find nodes resliced by ImageMapperGL2D //use a predicate to get all data nodes which are "images" or inherit from mitk::Image mitk::TNodePredicateDataType< mitk::Image >::Pointer predicateAllImages = mitk::TNodePredicateDataType< mitk::Image >::New(); mitk::DataStorage::SetOfObjects::ConstPointer all = m_DataStorage->GetSubset(predicateAllImages); //process all found images for (mitk::DataStorage::SetOfObjects::ConstIterator it = all->Begin(); it != all->End(); ++it) { DataNode *node = it->Value(); if (node != NULL) this->ProcessNode(node, renderer, surface, layerSortedActors); } // Add all image actors to the assembly, sorted according to // layer property LayerSortedActorList::iterator actorIt; for ( actorIt = layerSortedActors.begin(); actorIt != layerSortedActors.end(); ++actorIt ) { m_ImageAssembly->AddPart( actorIt->second ); } // Configurate the tube-shaped frame: size according to the surface // bounds, color as specified in the plane's properties vtkPolyData *surfacePolyData = surface->GetVtkPolyData(); m_Cleaner->SetInputData(surfacePolyData); m_EdgeTransformer->SetTransform(this->GetDataNode()->GetVtkTransform(this->GetTimestep()) ); // Adjust the radius according to extent m_EdgeTuber->SetRadius( tubeRadius ); // Get the plane's color and set the tube properties accordingly ColorProperty::Pointer colorProperty; colorProperty = dynamic_cast<ColorProperty*>(this->GetDataNode()->GetProperty( "color" )); if ( colorProperty.IsNotNull() ) { const Color& color = colorProperty->GetColor(); m_EdgeActor->GetProperty()->SetColor(color.GetRed(), color.GetGreen(), color.GetBlue()); } else { m_EdgeActor->GetProperty()->SetColor( 1.0, 1.0, 1.0 ); } m_ImageAssembly->SetUserTransform(this->GetDataNode()->GetVtkTransform(this->GetTimestep()) ); } VtkRepresentationProperty* representationProperty; this->GetDataNode()->GetProperty(representationProperty, "material.representation", renderer); if ( representationProperty != NULL ) m_BackgroundActor->GetProperty()->SetRepresentation( representationProperty->GetVtkRepresentation() ); }
std::string mitk::TestDICOMLoading::DumpImageInformation( const Image* image ) { std::stringstream result; if (image == nullptr) return result.str(); SetDefaultLocale(); // basic image data DumpLine( "Pixeltype", ComponentTypeToString(image->GetPixelType().GetComponentType()) ); DumpLine( "BitsPerPixel", image->GetPixelType().GetBpe() ); DumpLine( "Dimension", image->GetDimension() ); result << "Dimensions: "; for (unsigned int dim = 0; dim < image->GetDimension(); ++dim) result << image->GetDimension(dim) << " "; result << "\n"; // geometry data result << "Geometry: \n"; const TimeGeometry* timeGeometry = image->GetTimeGeometry(); BaseGeometry* geometry = timeGeometry->GetGeometryForTimeStep(0); if (geometry) { AffineTransform3D* transform = geometry->GetIndexToWorldTransform(); if (transform) { result << " " << "Matrix: "; const AffineTransform3D::MatrixType& matrix = transform->GetMatrix(); for (unsigned int i = 0; i < 3; ++i) for (unsigned int j = 0; j < 3; ++j) result << matrix[i][j] << " "; result << "\n"; result << " " << "Offset: "; const AffineTransform3D::OutputVectorType& offset = transform->GetOffset(); for (unsigned int i = 0; i < 3; ++i) result << offset[i] << " "; result << "\n"; result << " " << "Center: "; const AffineTransform3D::InputPointType& center = transform->GetCenter(); for (unsigned int i = 0; i < 3; ++i) result << center[i] << " "; result << "\n"; result << " " << "Translation: "; const AffineTransform3D::OutputVectorType& translation = transform->GetTranslation(); for (unsigned int i = 0; i < 3; ++i) result << translation[i] << " "; result << "\n"; result << " " << "Scale: "; const double* scale = transform->GetScale(); for (unsigned int i = 0; i < 3; ++i) result << scale[i] << " "; result << "\n"; result << " " << "Origin: "; const Point3D& origin = geometry->GetOrigin(); for (unsigned int i = 0; i < 3; ++i) result << origin[i] << " "; result << "\n"; result << " " << "Spacing: "; const Vector3D& spacing = geometry->GetSpacing(); for (unsigned int i = 0; i < 3; ++i) result << spacing[i] << " "; result << "\n"; result << " " << "TimeBounds: "; const TimeBounds timeBounds = timeGeometry->GetTimeBounds(); for (unsigned int i = 0; i < 2; ++i) result << timeBounds[i] << " "; result << "\n"; } } ResetUserLocale(); return result.str(); }
bool mitk::MoveBaseDataInteractor::ExecuteAction( Action* action, mitk::StateEvent const* stateEvent ) { bool ok = false; /*Each case must watch the type of the event!*/ switch (action->GetActionId()) { case AcDONOTHING: ok = true; break; case AcCHECKELEMENT: /* * picking: Answer the question if the given position within stateEvent is close enough to select an object * send yes if close enough and no if not picked */ { mitk::DisplayPositionEvent const *posEvent = dynamic_cast <const mitk::DisplayPositionEvent *> (stateEvent->GetEvent()); if (posEvent == nullptr) { MITK_WARN<<"Wrong usage of mitkMoveBaseDataInteractor! Aborting interaction!\n"; return false; } mitk::Point3D worldPoint = posEvent->GetWorldPosition(); /* now we have a worldpoint. check if it is inside our object and select/deselect it accordingly */ std::auto_ptr<StateEvent> newStateEvent; const BaseGeometry* geometry = GetData()->GetUpdatedTimeGeometry()->GetGeometryForTimeStep( m_TimeStep ); if (geometry->IsInside(worldPoint)) newStateEvent.reset(new mitk::StateEvent(EIDYES, stateEvent->GetEvent())); else newStateEvent.reset(new mitk::StateEvent(EIDNO, stateEvent->GetEvent())); /* write new state (selected/not selected) to the property */ this->HandleEvent( newStateEvent.get() ); ok = true; break; } case AcSELECT: // select the data { mitk::BoolProperty::Pointer selected = dynamic_cast<mitk::BoolProperty*>(m_DataNode->GetProperty("selected")); if ( selected.IsNull() ) { selected = mitk::BoolProperty::New(); m_DataNode->GetPropertyList()->SetProperty("selected", selected); } mitk::ColorProperty::Pointer selectedColor = dynamic_cast<mitk::ColorProperty*>(m_DataNode->GetProperty("MovingInteractor.SelectedColor")); if ( selectedColor.IsNotNull() ) { m_DataNode->GetPropertyList()->SetProperty("color", selectedColor); } selected->SetValue(true); //update rendering mitk::RenderingManager::GetInstance()->RequestUpdateAll(); ok = true; break; } case AcDESELECT: //deselect the data { mitk::BoolProperty::Pointer selected = dynamic_cast<mitk::BoolProperty*>(m_DataNode->GetProperty("selected")); if ( selected.IsNull() ) { selected = mitk::BoolProperty::New(); m_DataNode->GetPropertyList()->SetProperty("selected", selected); } mitk::ColorProperty::Pointer deselectedColor = dynamic_cast<mitk::ColorProperty*>(m_DataNode->GetProperty("MovingInteractor.DeselectedColor")); if ( deselectedColor.IsNotNull() ) { m_DataNode->GetPropertyList()->SetProperty("color", deselectedColor); } selected = mitk::BoolProperty::New(false); //update rendering mitk::RenderingManager::GetInstance()->RequestUpdateAll(); ok = true; break; } case AcMOVE: { //modify Geometry from data as given in parameters or in event mitk::IntProperty* xP = dynamic_cast<mitk::IntProperty*>(action->GetProperty("DIRECTION_X")); mitk::IntProperty* yP = dynamic_cast<mitk::IntProperty*>(action->GetProperty("DIRECTION_Y")); mitk::IntProperty* zP = dynamic_cast<mitk::IntProperty*>(action->GetProperty("DIRECTION_Z")); if (xP == nullptr || yP == nullptr || zP == nullptr) { MITK_WARN<<"No properties returned\n!"; return false; } mitk::Vector3D movementVector; movementVector.SetElement(0, (float) xP->GetValue()); movementVector.SetElement(1, (float) yP->GetValue()); movementVector.SetElement(2, (float) zP->GetValue()); BaseGeometry* geometry = m_DataNode->GetData()->GetUpdatedTimeGeometry()->GetGeometryForTimeStep( m_TimeStep ); geometry->Translate(movementVector); // indicate modification of data tree node m_DataNode->Modified(); //update rendering mitk::RenderingManager::GetInstance()->RequestUpdateAll(); ok = true; break; } default: return Superclass::ExecuteAction( action, stateEvent ); } return ok; }
void mitk::SurfaceToImageFilter::Stencil3DImage(int time) { mitk::Image::Pointer output = this->GetOutput(); mitk::Image::Pointer binaryImage = mitk::Image::New(); unsigned int size = sizeof(unsigned char); if (m_MakeOutputBinary) binaryImage->Initialize(mitk::MakeScalarPixelType<unsigned char>(), *this->GetImage()->GetTimeGeometry(),1,1); else { binaryImage->Initialize(this->GetImage()->GetPixelType(), *this->GetImage()->GetTimeGeometry(),1,1); size = this->GetImage()->GetPixelType().GetSize(); } for (unsigned int i = 0; i < binaryImage->GetDimension(); ++i) size *= binaryImage->GetDimension(i); mitk::ImageWriteAccessor accessor( binaryImage ); memset( accessor.GetData(), 1, size ); const mitk::TimeGeometry *surfaceTimeGeometry = GetInput()->GetTimeGeometry(); const mitk::TimeGeometry *imageTimeGeometry = GetImage()->GetTimeGeometry(); // Convert time step from image time-frame to surface time-frame mitk::TimePointType matchingTimePoint = imageTimeGeometry->TimeStepToTimePoint(time); mitk::TimeStepType surfaceTimeStep = surfaceTimeGeometry->TimePointToTimeStep(matchingTimePoint); vtkPolyData * polydata = ( (mitk::Surface*)GetInput() )->GetVtkPolyData( surfaceTimeStep ); if(polydata) { vtkSmartPointer<vtkTransformPolyDataFilter> move = vtkSmartPointer<vtkTransformPolyDataFilter>::New(); move->SetInputData(polydata); move->ReleaseDataFlagOn(); vtkSmartPointer<vtkTransform> transform = vtkSmartPointer<vtkTransform>::New(); BaseGeometry* geometry = surfaceTimeGeometry->GetGeometryForTimeStep( surfaceTimeStep ); if(!geometry) { geometry = GetInput()->GetGeometry(); } transform->PostMultiply(); transform->Concatenate(geometry->GetVtkTransform()->GetMatrix()); // take image geometry into account. vtk-Image information will be changed to unit spacing and zero origin below. BaseGeometry* imageGeometry = imageTimeGeometry->GetGeometryForTimeStep(time); transform->Concatenate(imageGeometry->GetVtkTransform()->GetLinearInverse()); move->SetTransform(transform); vtkSmartPointer<vtkPolyDataNormals> normalsFilter = vtkSmartPointer<vtkPolyDataNormals>::New(); normalsFilter->SetFeatureAngle(50); normalsFilter->SetConsistency(1); normalsFilter->SetSplitting(1); normalsFilter->SetFlipNormals(0); normalsFilter->ReleaseDataFlagOn(); normalsFilter->SetInputConnection(move->GetOutputPort()); vtkSmartPointer<vtkPolyDataToImageStencil> surfaceConverter = vtkSmartPointer<vtkPolyDataToImageStencil>::New(); surfaceConverter->SetTolerance( 0.0 ); surfaceConverter->ReleaseDataFlagOn(); surfaceConverter->SetInputConnection( normalsFilter->GetOutputPort() ); vtkImageData *image = m_MakeOutputBinary ? binaryImage->GetVtkImageData() : const_cast<mitk::Image *>(this->GetImage())->GetVtkImageData(time); // Create stencil and use numerical minimum of pixel type as background value vtkSmartPointer<vtkImageStencil> stencil = vtkSmartPointer<vtkImageStencil>::New(); stencil->SetInputData(image); stencil->ReverseStencilOff(); stencil->ReleaseDataFlagOn(); stencil->SetStencilConnection(surfaceConverter->GetOutputPort()); stencil->SetBackgroundValue(m_MakeOutputBinary ? 0 : m_BackgroundValue); stencil->Update(); output->SetVolume( stencil->GetOutput()->GetScalarPointer(), time ); MITK_INFO << "stencil ref count: " << stencil->GetReferenceCount() << std::endl; } else { memset( accessor.GetData(), 0, size ); output->SetVolume(accessor.GetData(),time); } }
void mitk::PlaneGeometryDataToSurfaceFilter::GenerateOutputInformation() { mitk::PlaneGeometryData::ConstPointer input = this->GetInput(); mitk::Surface::Pointer output = this->GetOutput(); if ( input.IsNull() || (input->GetPlaneGeometry() == nullptr) || (input->GetPlaneGeometry()->IsValid() == false) || (m_UseBoundingBox && (m_BoundingBox.IsNull() || (m_BoundingBox->GetDiagonalLength2() < mitk::eps))) ) { return; } Point3D origin; Point3D right, bottom; vtkPolyData *planeSurface = nullptr; // Does the PlaneGeometryData contain an AbstractTransformGeometry? if ( mitk::AbstractTransformGeometry *abstractGeometry = dynamic_cast< AbstractTransformGeometry * >( input->GetPlaneGeometry() ) ) { // In the case of an AbstractTransformGeometry (which holds a possibly // non-rigid transform), we proceed slightly differently: since the // plane can be arbitrarily deformed, we need to transform it by the // abstract transform before clipping it. The setup for this is partially // done in the constructor. origin = abstractGeometry->GetPlane()->GetOrigin(); right = origin + abstractGeometry->GetPlane()->GetAxisVector( 0 ); bottom = origin + abstractGeometry->GetPlane()->GetAxisVector( 1 ); // Define the plane m_PlaneSource->SetOrigin( origin[0], origin[1], origin[2] ); m_PlaneSource->SetPoint1( right[0], right[1], right[2] ); m_PlaneSource->SetPoint2( bottom[0], bottom[1], bottom[2] ); // Set the plane's resolution (unlike for non-deformable planes, the plane // grid needs to have a certain resolution so that the deformation has the // desired effect). if ( m_UseGeometryParametricBounds ) { m_PlaneSource->SetXResolution( (int)abstractGeometry->GetParametricExtent(0) ); m_PlaneSource->SetYResolution( (int)abstractGeometry->GetParametricExtent(1) ); } else { m_PlaneSource->SetXResolution( m_XResolution ); m_PlaneSource->SetYResolution( m_YResolution ); } if ( m_PlaceByGeometry ) { // Let the output use the input geometry to appropriately transform the // coordinate system. mitk::Geometry3D::TransformType *affineTransform = abstractGeometry->GetIndexToWorldTransform(); TimeGeometry *timeGeometry = output->GetTimeGeometry(); BaseGeometry *g3d = timeGeometry->GetGeometryForTimeStep( 0 ); g3d->SetIndexToWorldTransform( affineTransform ); vtkGeneralTransform *composedResliceTransform = vtkGeneralTransform::New(); composedResliceTransform->Identity(); composedResliceTransform->Concatenate( abstractGeometry->GetVtkTransform()->GetLinearInverse() ); composedResliceTransform->Concatenate( abstractGeometry->GetVtkAbstractTransform() ); // Use the non-rigid transform for transforming the plane. m_VtkTransformPlaneFilter->SetTransform( composedResliceTransform ); } else { // Use the non-rigid transform for transforming the plane. m_VtkTransformPlaneFilter->SetTransform( abstractGeometry->GetVtkAbstractTransform() ); } if ( m_UseBoundingBox ) { mitk::BoundingBox::PointType boundingBoxMin = m_BoundingBox->GetMinimum(); mitk::BoundingBox::PointType boundingBoxMax = m_BoundingBox->GetMaximum(); //mitk::BoundingBox::PointType boundingBoxCenter = m_BoundingBox->GetCenter(); m_Box->SetXMin( boundingBoxMin[0], boundingBoxMin[1], boundingBoxMin[2] ); m_Box->SetXMax( boundingBoxMax[0], boundingBoxMax[1], boundingBoxMax[2] ); } else { // Plane will not be clipped m_Box->SetXMin( -10000.0, -10000.0, -10000.0 ); m_Box->SetXMax( 10000.0, 10000.0, 10000.0 ); } m_Transform->Identity(); m_Transform->Concatenate( input->GetPlaneGeometry()->GetVtkTransform() ); m_Transform->PreMultiply(); m_Box->SetTransform( m_Transform ); m_PlaneClipper->SetInputConnection(m_VtkTransformPlaneFilter->GetOutputPort() ); m_PlaneClipper->SetClipFunction( m_Box ); m_PlaneClipper->GenerateClippedOutputOff(); // important to NOT generate normals data for clipped part m_PlaneClipper->InsideOutOn(); m_PlaneClipper->SetValue( 0.0 ); m_PlaneClipper->Update(); planeSurface = m_PlaneClipper->GetOutput(); } // Does the PlaneGeometryData contain a PlaneGeometry? else if ( dynamic_cast< PlaneGeometry * >( input->GetPlaneGeometry() ) != nullptr ) { mitk::PlaneGeometry *planeGeometry = dynamic_cast< PlaneGeometry * >( input->GetPlaneGeometry() ); if ( m_PlaceByGeometry ) { // Let the output use the input geometry to appropriately transform the // coordinate system. mitk::Geometry3D::TransformType *affineTransform = planeGeometry->GetIndexToWorldTransform(); TimeGeometry *timeGeometry = output->GetTimeGeometry(); BaseGeometry *geometrie3d = timeGeometry->GetGeometryForTimeStep( 0 ); geometrie3d->SetIndexToWorldTransform( affineTransform ); } if ( !m_UseBoundingBox) { // We do not have a bounding box, so no clipping is required. if ( m_PlaceByGeometry ) { // Derive coordinate axes and origin from input geometry extent origin.Fill( 0.0 ); FillVector3D( right, planeGeometry->GetExtent(0), 0.0, 0.0 ); FillVector3D( bottom, 0.0, planeGeometry->GetExtent(1), 0.0 ); } else { // Take the coordinate axes and origin directly from the input geometry. origin = planeGeometry->GetOrigin(); right = planeGeometry->GetCornerPoint( false, true ); bottom = planeGeometry->GetCornerPoint( true, false ); } // Since the plane is planar, there is no need to subdivide the grid // (cf. AbstractTransformGeometry case) m_PlaneSource->SetXResolution( 1 ); m_PlaneSource->SetYResolution( 1 ); m_PlaneSource->SetOrigin( origin[0], origin[1], origin[2] ); m_PlaneSource->SetPoint1( right[0], right[1], right[2] ); m_PlaneSource->SetPoint2( bottom[0], bottom[1], bottom[2] ); m_PlaneSource->Update(); planeSurface = m_PlaneSource->GetOutput(); } else { // Set up a cube with the extent and origin of the bounding box. This // cube will be clipped by a plane later on. The intersection of the // cube and the plane will be the surface we are interested in. Note // that the bounding box needs to be explicitly specified by the user // of this class, since it is not necessarily clear from the data // available herein which bounding box to use. In most cases, this // would be the bounding box of the input geometry's reference // geometry, but this is not an inevitable requirement. mitk::BoundingBox::PointType boundingBoxMin = m_BoundingBox->GetMinimum(); mitk::BoundingBox::PointType boundingBoxMax = m_BoundingBox->GetMaximum(); mitk::BoundingBox::PointType boundingBoxCenter = m_BoundingBox->GetCenter(); m_CubeSource->SetXLength( boundingBoxMax[0] - boundingBoxMin[0] ); m_CubeSource->SetYLength( boundingBoxMax[1] - boundingBoxMin[1] ); m_CubeSource->SetZLength( boundingBoxMax[2] - boundingBoxMin[2] ); m_CubeSource->SetCenter( boundingBoxCenter[0], boundingBoxCenter[1], boundingBoxCenter[2] ); // Now we have to transform the cube, so that it will cut our plane // appropriately. (As can be seen below, the plane corresponds to the // z-plane in the coordinate system and is *not* transformed.) Therefore, // we get the inverse of the plane geometry's transform and concatenate // it with the transform of the reference geometry, if available. m_Transform->Identity(); m_Transform->Concatenate( planeGeometry->GetVtkTransform()->GetLinearInverse() ); BaseGeometry *referenceGeometry = planeGeometry->GetReferenceGeometry(); if ( referenceGeometry ) { m_Transform->Concatenate( referenceGeometry->GetVtkTransform() ); } // Transform the cube accordingly (s.a.) m_PolyDataTransformer->SetInputConnection( m_CubeSource->GetOutputPort() ); m_PolyDataTransformer->SetTransform( m_Transform ); // Initialize the plane to clip the cube with, as lying on the z-plane m_Plane->SetOrigin( 0.0, 0.0, 0.0 ); m_Plane->SetNormal( 0.0, 0.0, 1.0 ); // Cut the plane with the cube. m_PlaneCutter->SetInputConnection( m_PolyDataTransformer->GetOutputPort() ); m_PlaneCutter->SetCutFunction( m_Plane ); // The output of the cutter must be converted into appropriate poly data. m_PlaneStripper->SetInputConnection( m_PlaneCutter->GetOutputPort() ); m_PlaneStripper->Update(); if ( m_PlaneStripper->GetOutput()->GetNumberOfPoints() < 3 ) { return; } m_PlanePolyData->SetPoints( m_PlaneStripper->GetOutput()->GetPoints() ); m_PlanePolyData->SetPolys( m_PlaneStripper->GetOutput()->GetLines() ); m_PlaneTriangler->SetInputData( m_PlanePolyData ); // Get bounds of the resulting surface and use it to generate the texture // mapping information m_PlaneTriangler->Update(); m_PlaneTriangler->GetOutput()->ComputeBounds(); double *surfaceBounds = m_PlaneTriangler->GetOutput()->GetBounds(); origin[0] = surfaceBounds[0]; origin[1] = surfaceBounds[2]; origin[2] = surfaceBounds[4]; right[0] = surfaceBounds[1]; right[1] = surfaceBounds[2]; right[2] = surfaceBounds[4]; bottom[0] = surfaceBounds[0]; bottom[1] = surfaceBounds[3]; bottom[2] = surfaceBounds[4]; // Now we tell the data how it shall be textured afterwards; // description see above. m_TextureMapToPlane->SetInputConnection( m_PlaneTriangler->GetOutputPort() ); m_TextureMapToPlane->AutomaticPlaneGenerationOn(); m_TextureMapToPlane->SetOrigin( origin[0], origin[1], origin[2] ); m_TextureMapToPlane->SetPoint1( right[0], right[1], right[2] ); m_TextureMapToPlane->SetPoint2( bottom[0], bottom[1], bottom[2] ); // Need to call update so that output data and bounds are immediately // available m_TextureMapToPlane->Update(); // Return the output of this generation process planeSurface = dynamic_cast< vtkPolyData * >( m_TextureMapToPlane->GetOutput() ); } } m_NormalsUpdater->SetInputData( planeSurface ); m_NormalsUpdater->AutoOrientNormalsOn(); // that's the trick! Brings consistency between // normals direction and front/back faces direction (see bug 1440) m_NormalsUpdater->ComputePointNormalsOn(); m_NormalsUpdater->Update(); output->SetVtkPolyData( m_NormalsUpdater->GetOutput() ); output->CalculateBoundingBox(); }