/*========================================================================= Program: Visualization Toolkit Module: vtkMagnifierRepresentation.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 "vtkMagnifierRepresentation.h" #include "vtkActor2D.h" #include "vtkCamera.h" #include "vtkCellArray.h" #include "vtkObjectFactory.h" #include "vtkPoints.h" #include "vtkPolyData.h" #include "vtkPolyDataMapper2D.h" #include "vtkProperty2D.h" #include "vtkRenderWindow.h" #include "vtkRenderer.h" #include "vtkWindow.h" vtkStandardNewMacro(vtkMagnifierRepresentation); //------------------------------------------------------------------------------ vtkMagnifierRepresentation::vtkMagnifierRepresentation() { this->MagnificationFactor = 10.0; this->Props = vtkPropCollection::New(); this->Size[0] = this->Size[1] = 75; this->Border = false; this->InteractionState = Invisible; this->MagnificationRenderer = vtkRenderer::New(); this->Coordinate = vtkCoordinate::New(); this->Coordinate->SetCoordinateSystemToDisplay(); this->InsideRenderer = false; // Create the geometry in canonical coordinates this->BorderPoints = vtkPoints::New(); this->BorderPoints->SetDataTypeToDouble(); this->BorderPoints->SetNumberOfPoints(4); this->BorderPoints->SetPoint(0, 0.0, 0.0, 0.0); this->BorderPoints->SetPoint(1, 1.0, 0.0, 0.0); this->BorderPoints->SetPoint(2, 1.0, 1.0, 0.0); this->BorderPoints->SetPoint(3, 0.0, 1.0, 0.0); vtkCellArray* outline = vtkCellArray::New(); outline->InsertNextCell(5); outline->InsertCellPoint(0); outline->InsertCellPoint(1); outline->InsertCellPoint(2); outline->InsertCellPoint(3); outline->InsertCellPoint(0); this->BorderPolyData = vtkPolyData::New(); this->BorderPolyData->SetPoints(this->BorderPoints); this->BorderPolyData->SetLines(outline); outline->Delete(); this->BorderMapper = vtkPolyDataMapper2D::New(); this->BorderMapper->SetInputData(this->BorderPolyData); this->BorderActor = vtkActor2D::New(); this->BorderActor->SetMapper(this->BorderMapper); this->BorderProperty = vtkProperty2D::New(); this->BorderProperty->SetLineWidth(2); this->BorderProperty->SetColor(1, 0, 0); this->BorderActor->SetProperty(this->BorderProperty); } //------------------------------------------------------------------------------ vtkMagnifierRepresentation::~vtkMagnifierRepresentation() { this->Props->Delete(); this->BorderProperty->Delete(); if (this->Renderer && this->Renderer->GetRenderWindow()) { this->Renderer->GetRenderWindow()->RemoveRenderer(this->MagnificationRenderer); } this->MagnificationRenderer->Delete(); this->Coordinate->Delete(); this->BorderPoints->Delete(); this->BorderPolyData->Delete(); this->BorderMapper->Delete(); this->BorderActor->Delete(); } //------------------------------------------------------------------------------ // Move the magnifier around. This method is invoked every time the mouse // moves. void vtkMagnifierRepresentation::WidgetInteraction(double eventPos[2]) { int XF = eventPos[0]; int YF = eventPos[1]; // Make sure the renderer and render window have been defined vtkRenderWindow* renWin; if (!this->Renderer || !(renWin = this->Renderer->GetRenderWindow())) { return; } // If event outside of this window, turn off magnify renderer this->InsideRenderer = (this->Renderer->IsInViewport(XF, YF) != 0); // Build the representation as necessary this->BuildRepresentation(); // Move the viewport /renderer to the current mouse position int* winSize = this->Renderer->GetRenderWindow()->GetSize(); int* vpSize = this->Renderer->GetSize(); double vpxMax = static_cast(vpSize[0]) / winSize[0]; double vpyMax = static_cast(vpSize[1]) / winSize[1]; double viewPort[4]; viewPort[0] = eventPos[0] / winSize[0]; viewPort[1] = eventPos[1] / winSize[1]; viewPort[2] = viewPort[0] + static_cast(this->Size[0]) / winSize[0]; viewPort[3] = viewPort[1] + static_cast(this->Size[1]) / winSize[1]; viewPort[2] = (viewPort[2] > vpxMax ? vpxMax : viewPort[2]); viewPort[3] = (viewPort[3] > vpyMax ? vpyMax : viewPort[3]); this->MagnificationRenderer->SetViewport(viewPort); // Update the magnificationcamera // Grab the containing renderer's camera and copy it. Adjust the view angle vtkCamera* cam = this->Renderer->GetActiveCamera(); double viewAngle = cam->GetViewAngle(); vtkCamera* magCam = this->MagnificationRenderer->GetActiveCamera(); magCam->DeepCopy(cam); magCam->SetViewAngle(viewAngle / this->MagnificationFactor); // Specify the focal point this->Coordinate->SetValue(XF, YF); double* focal = this->Coordinate->GetComputedWorldValue(this->Renderer); this->MagnificationRenderer->GetActiveCamera()->SetFocalPoint(focal); // Setup the border if requested. We offset the border slightly to // accomodate the width of the line. if (this->Border) { this->BorderPoints->SetPoint(0, 1, 1, 0.0); this->BorderPoints->SetPoint(1, (this->Size[0] - 1), 1, 0.0); this->BorderPoints->SetPoint(2, (this->Size[0] - 1), (this->Size[1] - 1), 0.0); this->BorderPoints->SetPoint(3, 1, (this->Size[1] - 1), 0.0); } } //------------------------------------------------------------------------------ // This method is invoked when this class or dependent classes change (based // on modified time). void vtkMagnifierRepresentation::BuildRepresentation() { // Make sure a renderer and render window are available if (!this->Renderer || !this->Renderer->GetRenderWindow()) { return; } // If we've been turned off, make it so if (this->InteractionState == Invisible || !this->InsideRenderer) { this->Renderer->GetRenderWindow()->RemoveRenderer(this->MagnificationRenderer); return; } // Set up the renderer and build the border if requested. // Add the magnification renderer to the render window this->Renderer->GetRenderWindow()->AddRenderer(this->MagnificationRenderer); // If props are specifically listed, add them to the magnification // renderer. Otherwise, use the containing renderer's props. this->MagnificationRenderer->RemoveAllViewProps(); vtkPropCollection* props; if (this->Props->GetNumberOfItems() > 0) { props = this->Props; } else { props = this->Renderer->GetViewProps(); } int numItems = props->GetNumberOfItems(); props->InitTraversal(); for (auto i = 0; i < numItems; ++i) { this->MagnificationRenderer->AddViewProp(static_cast(props->GetNextItemAsObject())); } // Add the border if desired if (this->Border) { this->MagnificationRenderer->AddViewProp(this->BorderActor); } } //------------------------------------------------------------------------------ vtkMTimeType vtkMagnifierRepresentation::GetMTime() { vtkMTimeType mTime = this->Superclass::GetMTime(); mTime = std::max(mTime, this->BorderProperty->GetMTime()); return mTime; } //------------------------------------------------------------------------------ // Optionally, use different view props than that used by the associated // renderer. This enables special effects etc during magnification (or the // ability to remove props from the scence like widgets etc). void vtkMagnifierRepresentation::AddViewProp(vtkProp* prop) { this->Props->AddItem(prop); } //------------------------------------------------------------------------------ int vtkMagnifierRepresentation::HasViewProp(vtkProp* prop) { return (prop && this->Props->IsItemPresent(prop)); } //------------------------------------------------------------------------------ void vtkMagnifierRepresentation::RemoveViewProp(vtkProp* prop) { this->Props->RemoveItem(prop); } //------------------------------------------------------------------------------ void vtkMagnifierRepresentation::RemoveAllViewProps() { return this->Props->RemoveAllItems(); } //------------------------------------------------------------------------------ void vtkMagnifierRepresentation::ReleaseGraphicsResources(vtkWindow* w) { this->BorderActor->ReleaseGraphicsResources(w); } //------------------------------------------------------------------------------ int vtkMagnifierRepresentation::RenderOverlay(vtkViewport* w) { if (this->Border && w == this->MagnificationRenderer) { this->BuildRepresentation(); return this->BorderActor->RenderOverlay(w); } return 0; } //------------------------------------------------------------------------------ int vtkMagnifierRepresentation::RenderOpaqueGeometry(vtkViewport* w) { if (this->Border && w == this->MagnificationRenderer) { this->BuildRepresentation(); return this->BorderActor->RenderOpaqueGeometry(w); } return 0; } //------------------------------------------------------------------------------ int vtkMagnifierRepresentation::RenderTranslucentPolygonalGeometry(vtkViewport* w) { if (this->Border && w == this->MagnificationRenderer) { this->BuildRepresentation(); return this->BorderActor->RenderTranslucentPolygonalGeometry(w); } return 0; } //------------------------------------------------------------------------------ // Description: // Does this prop have some translucent polygonal geometry? vtkTypeBool vtkMagnifierRepresentation::HasTranslucentPolygonalGeometry() { if (this->Border) { this->BuildRepresentation(); return this->BorderActor->HasTranslucentPolygonalGeometry(); } return false; } //------------------------------------------------------------------------------ void vtkMagnifierRepresentation::PrintSelf(ostream& os, vtkIndent indent) { this->Superclass::PrintSelf(os, indent); os << indent << "Interaction State: " << (this->InteractionState == Visible ? "Visible\n" : "Invisible\n"); os << indent << "Magnification Factor: " << this->MagnificationFactor << "\n"; os << indent << "Props:\n"; this->Props->PrintSelf(os, indent.GetNextIndent()); os << indent << "Size: " << this->Size[0] << " " << this->Size[1] << endl; os << indent << "Border: " << (this->Border ? "On\n" : "Off\n"); if (this->BorderProperty) { os << indent << "Border Property:\n"; this->BorderProperty->PrintSelf(os, indent.GetNextIndent()); } else { os << indent << "Border Property: (none)\n"; } }