/*========================================================================= Program: Visualization Toolkit Module: vtkRectilinearWipeRepresentation.cxx Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen All rights reserved. See Copyright.txt or http://www.kitware.com/Copyright.htm for details. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the above copyright notice for more information. =========================================================================*/ #include "vtkRectilinearWipeRepresentation.h" #include "vtkPolyData.h" #include "vtkPoints.h" #include "vtkCellArray.h" #include "vtkPolyDataMapper2D.h" #include "vtkActor2D.h" #include "vtkProperty2D.h" #include "vtkCoordinate.h" #include "vtkDoubleArray.h" #include "vtkMath.h" #include "vtkLine.h" #include "vtkRenderer.h" #include "vtkImageRectilinearWipe.h" #include "vtkImageActor.h" #include "vtkImageData.h" #include "vtkInteractorObserver.h" #include "vtkObjectFactory.h" vtkStandardNewMacro(vtkRectilinearWipeRepresentation); vtkCxxSetObjectMacro(vtkRectilinearWipeRepresentation,RectilinearWipe,vtkImageRectilinearWipe); vtkCxxSetObjectMacro(vtkRectilinearWipeRepresentation,ImageActor,vtkImageActor); //---------------------------------------------------------------------- vtkRectilinearWipeRepresentation::vtkRectilinearWipeRepresentation() { this->RectilinearWipe = nullptr; this->ImageActor = nullptr; this->InteractionState = vtkRectilinearWipeRepresentation::Outside; this->Tolerance = 5; //pick tolerance in pixels this->Property = vtkProperty2D::New(); this->Property->SetColor(1,0,0); this->Points = vtkPoints::New(); this->Points->SetDataTypeToDouble(); this->Points->SetNumberOfPoints(9); this->ActiveParts = -1; // inidicates that the widget is uninitialized this->Lines = vtkCellArray::New(); this->Lines->Allocate(this->Lines->EstimateSize(8,2)); this->Wipe = vtkPolyData::New(); this->Wipe->SetPoints(this->Points); this->Wipe->SetLines(this->Lines); vtkCoordinate *coordinate = vtkCoordinate::New(); coordinate->SetCoordinateSystemToWorld(); this->WipeMapper = vtkPolyDataMapper2D::New(); this->WipeMapper->SetInputData(this->Wipe); this->WipeMapper->SetTransformCoordinate(coordinate); coordinate->Delete(); this->WipeActor = vtkActor2D::New(); this->WipeActor->SetMapper(this->WipeMapper); this->WipeActor->SetProperty(this->Property); } //---------------------------------------------------------------------- vtkRectilinearWipeRepresentation::~vtkRectilinearWipeRepresentation() { if ( this->RectilinearWipe ) { this->RectilinearWipe->Delete(); } if ( this->ImageActor ) { this->ImageActor->Delete(); } this->Points->Delete(); this->Lines->Delete(); this->Wipe->Delete(); this->WipeMapper->Delete(); this->WipeActor->Delete(); this->Property->Delete(); } //------------------------------------------------------------------------- int vtkRectilinearWipeRepresentation::ComputeInteractionState(int X, int Y, int vtkNotUsed(modify)) { this->InteractionState = vtkRectilinearWipeRepresentation::Outside; // Check if the widget is initialized, ie BuildRepresentation has been // invoked at least once if (this->ActiveParts != -1) { // Start by grabbing the five points that define the horizontal and vertical // panes, plus the center point double *pts = static_cast(this->Points->GetData())->GetPointer(0); double *p4 = pts + 3*4; double *p5 = pts + 3*5; double *p6 = pts + 3*6; double *p7 = pts + 3*7; double *p8 = pts + 3*8; vtkInteractorObserver::ComputeWorldToDisplay(this->Renderer, p4[0],p4[1],p4[2], this->DP4); vtkInteractorObserver::ComputeWorldToDisplay(this->Renderer, p5[0],p5[1],p5[2], this->DP5); vtkInteractorObserver::ComputeWorldToDisplay(this->Renderer, p6[0],p6[1],p6[2], this->DP6); vtkInteractorObserver::ComputeWorldToDisplay(this->Renderer, p7[0],p7[1],p7[2], this->DP7); vtkInteractorObserver::ComputeWorldToDisplay(this->Renderer, p8[0],p8[1],p8[2], this->DP8); // Compare the distance between the current event position and the widget double xyz[3], t, closest[3]; xyz[0] = X; xyz[1] = Y; xyz[2] = this->DP4[2] = this->DP5[2] = this->DP6[2] = this->DP7[2] = this->DP8[2] = 0.0; double tol = this->Tolerance * this->Tolerance; if ( (this->ActiveParts & 16) && vtkMath::Distance2BetweenPoints(xyz,this->DP8) <= tol ) { this->InteractionState = vtkRectilinearWipeRepresentation::MovingCenter; } else if ( (this->ActiveParts & 1) && vtkLine::DistanceToLine(xyz,this->DP8,this->DP4,t,closest) <= tol ) { this->InteractionState = vtkRectilinearWipeRepresentation::MovingVPane; } else if ( (this->ActiveParts & 2) && vtkLine::DistanceToLine(xyz,this->DP8,this->DP5,t,closest) <= tol ) { this->InteractionState = vtkRectilinearWipeRepresentation::MovingHPane; } else if ( (this->ActiveParts & 4) && vtkLine::DistanceToLine(xyz,this->DP8,this->DP6,t,closest) <= tol ) { this->InteractionState = vtkRectilinearWipeRepresentation::MovingVPane; } else if ( (this->ActiveParts & 8) && vtkLine::DistanceToLine(xyz,this->DP8,this->DP7,t,closest) <= tol ) { this->InteractionState = vtkRectilinearWipeRepresentation::MovingHPane; } } return this->InteractionState; } //---------------------------------------------------------------------- // Record the current event position, and the rectilinear wipe position. void vtkRectilinearWipeRepresentation::StartWidgetInteraction(double startEventPos[2]) { this->StartEventPosition[0] = startEventPos[0]; this->StartEventPosition[1] = startEventPos[1]; if ( ! this->RectilinearWipe ) { return; } int pos[2]; this->RectilinearWipe->GetPosition(pos); this->StartWipePosition[0] = static_cast(pos[0]); this->StartWipePosition[1] = static_cast(pos[1]); } //---------------------------------------------------------------------- // Based on the displacement vector (computed in display coordinates) and // the cursor state (which corresponds to which part of the widget has been // selected), the widget points are modified. // First construct a local coordinate system based on the display coordinates // of the widget. void vtkRectilinearWipeRepresentation::WidgetInteraction(double newEventPos[2]) { int i; double v75[3], v46[3]; for (i=0; i<3; i++) { v75[i] = this->DP5[i] - this->DP7[i]; v46[i] = this->DP6[i] - this->DP4[i]; } double l75 = vtkMath::Normalize(v75); double l46 = vtkMath::Normalize(v46); double xPixels = this->Dims[this->I] * (v75[0]*(newEventPos[0] - this->StartEventPosition[0]) + v75[1]*(newEventPos[1] - this->StartEventPosition[1])) / l75; double yPixels = this->Dims[this->J] * (v46[0]*(newEventPos[0] - this->StartEventPosition[0]) + v46[1]*(newEventPos[1] - this->StartEventPosition[1])) / l46; int newPosition[2]; newPosition[0] = static_cast(this->StartWipePosition[0]); newPosition[1] = static_cast(this->StartWipePosition[1]); switch ( this->InteractionState ) { case MovingVPane: newPosition[0] += static_cast(xPixels + 0.5); break; case MovingHPane: newPosition[1] += static_cast(yPixels + 0.5); break; case MovingCenter: newPosition[0] += static_cast(xPixels + 0.5); newPosition[1] += static_cast(yPixels + 0.5); } newPosition[0] = (newPosition[0] < 0 ? 0 : newPosition[0] ); newPosition[0] = (newPosition[0] >= this->Dims[this->I] ? this->Dims[this->I] - 1 : newPosition[0] ); newPosition[1] = (newPosition[1] < 0 ? 0 : newPosition[1] ); newPosition[1] = (newPosition[1] >= this->Dims[this->J] ? this->Dims[this->J] - 1 : newPosition[1] ); this->RectilinearWipe->SetPosition(newPosition); // Rebuild the widget based on the change this->BuildRepresentation(); } //---------------------------------------------------------------------- void vtkRectilinearWipeRepresentation::BuildRepresentation() { if ( ! this->RectilinearWipe || ! this->ImageActor ) { vtkWarningMacro(<<"Must define both image rectilinear wipe and image actor"); return; } // get the necessary image information double bounds[6], o[3], sp[3]; int pos[2]; vtkImageData *image = this->ImageActor->GetInput(); image->GetBounds(bounds); image->GetDimensions(this->Dims); image->GetOrigin(o); image->GetSpacing(sp); this->RectilinearWipe->GetPosition(pos); // define the geometry double s, t; double t0 = bounds[1]-bounds[0]; double t1 = bounds[3]-bounds[2]; double t2 = bounds[5]-bounds[4]; int orthoAxis = ( t0 < t1 ? (t0 < t2 ? 0 : 2) : (t1 < t2 ? 1 : 2) ); double p0[3], p1[3], p2[3], p3[3]; if ( orthoAxis == 0 ) //x-axis { this->I = 1; this->J = 2; s = static_cast(pos[0]+0.5)/(this->Dims[1]-1); t = static_cast(pos[1]+0.5)/(this->Dims[2]-1); p0[0] = bounds[0]; p0[1] = bounds[2]; p0[2] = bounds[4]; p1[0] = bounds[0]; p1[1] = bounds[3]; p1[2] = bounds[4]; p2[0] = bounds[0]; p2[1] = bounds[3]; p2[2] = bounds[5]; p3[0] = bounds[0]; p3[1] = bounds[2]; p3[2] = bounds[5]; this->Points->SetPoint(8, bounds[0], p0[1] + s*(p1[1]-p0[1]), p1[2] + t*(p2[2]-p1[2])); } else if ( orthoAxis == 1 ) //y-axis { this->I = 0; this->J = 2; s = static_cast(pos[0]+0.5)/(this->Dims[0]-1); t = static_cast(pos[1]+0.5)/(this->Dims[2]-1); p0[0] = bounds[0]; p0[1] = bounds[2]; p0[2] = bounds[4]; p1[0] = bounds[1]; p1[1] = bounds[2]; p1[2] = bounds[4]; p2[0] = bounds[1]; p2[1] = bounds[2]; p2[2] = bounds[5]; p3[0] = bounds[0]; p3[1] = bounds[2]; p3[2] = bounds[5]; this->Points->SetPoint(8, p0[0] + s*(p1[0]-p0[0]), bounds[2], p1[2] + t*(p2[2]-p1[2])); } else // if( orthoAxis == 2 ) //z-axis { this->I = 0; this->J = 1; s = static_cast(pos[0]+0.5)/(this->Dims[0]-1); t = static_cast(pos[1]+0.5)/(this->Dims[1]-1); p0[0] = bounds[0]; p0[1] = bounds[2]; p0[2] = bounds[4]; p1[0] = bounds[1]; p1[1] = bounds[2]; p1[2] = bounds[4]; p2[0] = bounds[1]; p2[1] = bounds[3]; p2[2] = bounds[4]; p3[0] = bounds[0]; p3[1] = bounds[3]; p3[2] = bounds[4]; this->Points->SetPoint(8, p0[0] + s*(p1[0]-p0[0]), p1[1] + t*(p2[1]-p1[1]), bounds[4]); } // corners this->Points->SetPoint(0, p0); this->Points->SetPoint(1, p1); this->Points->SetPoint(2, p2); this->Points->SetPoint(3, p3); // mid-edge this->Points->SetPoint(4, p0[0] + s*(p1[0]-p0[0]), p0[1] + s*(p1[1]-p0[1]), p0[2] + s*(p1[2]-p0[2])); this->Points->SetPoint(5, p1[0] + t*(p2[0]-p1[0]), p1[1] + t*(p2[1]-p1[1]), p1[2] + t*(p2[2]-p1[2])); this->Points->SetPoint(6, p3[0] + s*(p2[0]-p3[0]), p3[1] + s*(p2[1]-p3[1]), p3[2] + s*(p2[2]-p3[2])); this->Points->SetPoint(7, p0[0] + t*(p3[0]-p0[0]), p0[1] + t*(p3[1]-p0[1]), p0[2] + t*(p3[2]-p0[2])); this->Points->Modified(); // Define the lines this->Lines->Reset(); this->Lines->InsertNextCell(5); this->Lines->InsertCellPoint(0); this->Lines->InsertCellPoint(1); this->Lines->InsertCellPoint(2); this->Lines->InsertCellPoint(3); this->Lines->InsertCellPoint(0); int wipe = this->RectilinearWipe->GetWipe(); this->ActiveParts = 0; if ( wipe == VTK_WIPE_QUAD ) { this->ActiveParts |= 1; //activate center to bottom edge this->ActiveParts |= 2; //activate center to right edge this->ActiveParts |= 4; //activate center to top edge this->ActiveParts |= 8; //activate center to left edge this->ActiveParts |= 16; //activate center point this->Lines->InsertNextCell(2); this->Lines->InsertCellPoint(4); this->Lines->InsertCellPoint(6); this->Lines->InsertNextCell(2); this->Lines->InsertCellPoint(5); this->Lines->InsertCellPoint(7); } else if ( wipe == VTK_WIPE_VERTICAL ) { this->ActiveParts |= 2; this->ActiveParts |= 8; this->Lines->InsertNextCell(2); this->Lines->InsertCellPoint(5); this->Lines->InsertCellPoint(7); } else if ( wipe == VTK_WIPE_HORIZONTAL ) { this->ActiveParts |= 1; this->ActiveParts |= 4; this->Lines->InsertNextCell(2); this->Lines->InsertCellPoint(4); this->Lines->InsertCellPoint(6); } else if ( wipe == VTK_WIPE_LOWER_LEFT ) { this->ActiveParts |= 1; this->ActiveParts |= 8; this->ActiveParts |= 16; this->Lines->InsertNextCell(3); this->Lines->InsertCellPoint(4); this->Lines->InsertCellPoint(8); this->Lines->InsertCellPoint(7); } else if ( wipe == VTK_WIPE_LOWER_RIGHT ) { this->ActiveParts |= 1; this->ActiveParts |= 2; this->ActiveParts |= 16; this->Lines->InsertNextCell(3); this->Lines->InsertCellPoint(4); this->Lines->InsertCellPoint(8); this->Lines->InsertCellPoint(5); } else if ( wipe == VTK_WIPE_UPPER_LEFT ) { this->ActiveParts |= 4; this->ActiveParts |= 8; this->ActiveParts |= 16; this->Lines->InsertNextCell(3); this->Lines->InsertCellPoint(7); this->Lines->InsertCellPoint(8); this->Lines->InsertCellPoint(6); } else //if ( wipe == VTK_WIPE_UPPER_RIGHT ) { this->ActiveParts |= 2; this->ActiveParts |= 4; this->ActiveParts |= 16; this->Lines->InsertNextCell(3); this->Lines->InsertCellPoint(6); this->Lines->InsertCellPoint(8); this->Lines->InsertCellPoint(5); } } //---------------------------------------------------------------------- void vtkRectilinearWipeRepresentation::GetActors2D(vtkPropCollection *pc) { this->WipeActor->GetActors2D(pc); } //---------------------------------------------------------------------- void vtkRectilinearWipeRepresentation::ReleaseGraphicsResources(vtkWindow *win) { this->WipeActor->ReleaseGraphicsResources(win); } //---------------------------------------------------------------------- int vtkRectilinearWipeRepresentation::RenderOverlay(vtkViewport *viewport) { return this->WipeActor->RenderOverlay(viewport); } //----------------------------------------------------------------------------- int vtkRectilinearWipeRepresentation::RenderOpaqueGeometry( vtkViewport *viewport) { return this->WipeActor->RenderOpaqueGeometry(viewport); } //----------------------------------------------------------------------------- int vtkRectilinearWipeRepresentation::RenderTranslucentPolygonalGeometry( vtkViewport *viewport) { return this->WipeActor->RenderTranslucentPolygonalGeometry(viewport); } //----------------------------------------------------------------------------- int vtkRectilinearWipeRepresentation::HasTranslucentPolygonalGeometry() { return this->WipeActor->HasTranslucentPolygonalGeometry(); } //----------------------------------------------------------------------------- void vtkRectilinearWipeRepresentation::PrintSelf(ostream& os, vtkIndent indent) { //Superclass typedef defined in vtkTypeMacro() found in vtkSetGet.h this->Superclass::PrintSelf(os,indent); if ( this->ImageActor ) { os << indent << "Image Actor: " << this->ImageActor << "\n"; } else { os << indent << "Image Actor: (none)\n"; } if ( this->RectilinearWipe ) { os << indent << "RectilinearWipe: " << this->RectilinearWipe << "\n"; } else { os << indent << "Image RectilinearWipe: (none)\n"; } if ( this->Property ) { os << indent << "Property:\n"; this->Property->PrintSelf(os,indent.GetNextIndent()); } else { os << indent << "Property: (none)\n"; } os << indent << "Tolerance: " << this->Tolerance << "\n"; }