/*========================================================================= Program: Visualization Toolkit Module: vtkInteractorStyleTerrain.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 "vtkInteractorStyleTerrain.h" #include "vtkActor.h" #include "vtkCallbackCommand.h" #include "vtkCamera.h" #include "vtkExtractEdges.h" #include "vtkMath.h" #include "vtkObjectFactory.h" #include "vtkPolyData.h" #include "vtkPolyDataMapper.h" #include "vtkRenderWindow.h" #include "vtkRenderWindowInteractor.h" #include "vtkRenderer.h" #include "vtkSphereSource.h" vtkStandardNewMacro(vtkInteractorStyleTerrain); //------------------------------------------------------------------------------ vtkInteractorStyleTerrain::vtkInteractorStyleTerrain() { this->LatLongLines = 0; this->LatLongSphere = nullptr; this->LatLongExtractEdges = nullptr; this->LatLongMapper = nullptr; this->LatLongActor = nullptr; this->MotionFactor = 10.0; } //------------------------------------------------------------------------------ vtkInteractorStyleTerrain::~vtkInteractorStyleTerrain() { if (this->LatLongSphere != nullptr) { this->LatLongSphere->Delete(); } if (this->LatLongMapper != nullptr) { this->LatLongMapper->Delete(); } if (this->LatLongActor != nullptr) { this->LatLongActor->Delete(); } if (this->LatLongExtractEdges != nullptr) { this->LatLongExtractEdges->Delete(); } } //------------------------------------------------------------------------------ void vtkInteractorStyleTerrain::OnMouseMove() { int x = this->Interactor->GetEventPosition()[0]; int y = this->Interactor->GetEventPosition()[1]; switch (this->State) { case VTKIS_ROTATE: this->FindPokedRenderer(x, y); this->Rotate(); this->InvokeEvent(vtkCommand::InteractionEvent, nullptr); break; case VTKIS_PAN: this->FindPokedRenderer(x, y); this->Pan(); this->InvokeEvent(vtkCommand::InteractionEvent, nullptr); break; case VTKIS_DOLLY: this->FindPokedRenderer(x, y); this->Dolly(); this->InvokeEvent(vtkCommand::InteractionEvent, nullptr); break; } } //------------------------------------------------------------------------------ void vtkInteractorStyleTerrain::OnLeftButtonDown() { this->FindPokedRenderer( this->Interactor->GetEventPosition()[0], this->Interactor->GetEventPosition()[1]); if (this->CurrentRenderer == nullptr) { return; } this->GrabFocus(this->EventCallbackCommand); this->StartRotate(); } //------------------------------------------------------------------------------ void vtkInteractorStyleTerrain::OnLeftButtonUp() { switch (this->State) { case VTKIS_ROTATE: this->EndRotate(); if (this->Interactor) { this->ReleaseFocus(); } break; } } //------------------------------------------------------------------------------ void vtkInteractorStyleTerrain::OnMiddleButtonDown() { this->FindPokedRenderer( this->Interactor->GetEventPosition()[0], this->Interactor->GetEventPosition()[1]); if (this->CurrentRenderer == nullptr) { return; } this->GrabFocus(this->EventCallbackCommand); this->StartPan(); } //------------------------------------------------------------------------------ void vtkInteractorStyleTerrain::OnMiddleButtonUp() { switch (this->State) { case VTKIS_PAN: this->EndPan(); if (this->Interactor) { this->ReleaseFocus(); } break; } } //------------------------------------------------------------------------------ void vtkInteractorStyleTerrain::OnRightButtonDown() { this->FindPokedRenderer( this->Interactor->GetEventPosition()[0], this->Interactor->GetEventPosition()[1]); if (this->CurrentRenderer == nullptr) { return; } this->GrabFocus(this->EventCallbackCommand); this->StartDolly(); } //------------------------------------------------------------------------------ void vtkInteractorStyleTerrain::OnRightButtonUp() { switch (this->State) { case VTKIS_DOLLY: this->EndDolly(); if (this->Interactor) { this->ReleaseFocus(); } break; } } //------------------------------------------------------------------------------ void vtkInteractorStyleTerrain::Rotate() { if (this->CurrentRenderer == nullptr) { return; } vtkRenderWindowInteractor* rwi = this->Interactor; int dx = -(rwi->GetEventPosition()[0] - rwi->GetLastEventPosition()[0]); int dy = -(rwi->GetEventPosition()[1] - rwi->GetLastEventPosition()[1]); const int* size = this->CurrentRenderer->GetRenderWindow()->GetSize(); double a = dx / static_cast(size[0]) * 180.0; double e = dy / static_cast(size[1]) * 180.0; if (rwi->GetShiftKey()) { if (abs(dx) >= abs(dy)) { e = 0.0; } else { a = 0.0; } } // Move the camera. // Make sure that we don't hit the north pole singularity. vtkCamera* camera = this->CurrentRenderer->GetActiveCamera(); camera->Azimuth(a); double dop[3], vup[3]; camera->GetDirectionOfProjection(dop); vtkMath::Normalize(dop); camera->GetViewUp(vup); vtkMath::Normalize(vup); double angle = vtkMath::DegreesFromRadians(acos(vtkMath::Dot(dop, vup))); if ((angle + e) > 179.0 || (angle + e) < 1.0) { e = 0.0; } camera->Elevation(e); if (this->AutoAdjustCameraClippingRange) { this->CurrentRenderer->ResetCameraClippingRange(); } rwi->Render(); } //------------------------------------------------------------------------------ void vtkInteractorStyleTerrain::Pan() { if (this->CurrentRenderer == nullptr) { return; } vtkRenderWindowInteractor* rwi = this->Interactor; // Get the vector of motion double fp[3], focalPoint[3], pos[3], v[3], p1[4], p2[4]; vtkCamera* camera = this->CurrentRenderer->GetActiveCamera(); camera->GetPosition(pos); camera->GetFocalPoint(fp); this->ComputeWorldToDisplay(fp[0], fp[1], fp[2], focalPoint); this->ComputeDisplayToWorld( rwi->GetEventPosition()[0], rwi->GetEventPosition()[1], focalPoint[2], p1); this->ComputeDisplayToWorld( rwi->GetLastEventPosition()[0], rwi->GetLastEventPosition()[1], focalPoint[2], p2); for (int i = 0; i < 3; i++) { v[i] = p2[i] - p1[i]; pos[i] += v[i]; fp[i] += v[i]; } camera->SetPosition(pos); camera->SetFocalPoint(fp); if (rwi->GetLightFollowCamera()) { this->CurrentRenderer->UpdateLightsGeometryToFollowCamera(); } rwi->Render(); } //------------------------------------------------------------------------------ void vtkInteractorStyleTerrain::Dolly() { if (this->CurrentRenderer == nullptr) { return; } vtkRenderWindowInteractor* rwi = this->Interactor; vtkCamera* camera = this->CurrentRenderer->GetActiveCamera(); double* center = this->CurrentRenderer->GetCenter(); int dy = rwi->GetEventPosition()[1] - rwi->GetLastEventPosition()[1]; double dyf = this->MotionFactor * dy / center[1]; double zoomFactor = pow(1.1, dyf); if (camera->GetParallelProjection()) { camera->SetParallelScale(camera->GetParallelScale() / zoomFactor); } else { camera->Dolly(zoomFactor); if (this->AutoAdjustCameraClippingRange) { this->CurrentRenderer->ResetCameraClippingRange(); } } if (rwi->GetLightFollowCamera()) { this->CurrentRenderer->UpdateLightsGeometryToFollowCamera(); } rwi->Render(); } //------------------------------------------------------------------------------ void vtkInteractorStyleTerrain::OnChar() { vtkRenderWindowInteractor* rwi = this->Interactor; switch (rwi->GetKeyCode()) { case 'l': this->FindPokedRenderer(rwi->GetEventPosition()[0], rwi->GetEventPosition()[1]); this->CreateLatLong(); if (this->LatLongLines) { this->LatLongLinesOff(); } else { double bounds[6]; this->CurrentRenderer->ComputeVisiblePropBounds(bounds); double radius = sqrt((bounds[1] - bounds[0]) * (bounds[1] - bounds[0]) + (bounds[3] - bounds[2]) * (bounds[3] - bounds[2]) + (bounds[5] - bounds[4]) * (bounds[5] - bounds[4])) / 2.0; this->LatLongSphere->SetRadius(radius); this->LatLongSphere->SetCenter((bounds[0] + bounds[1]) / 2.0, (bounds[2] + bounds[3]) / 2.0, (bounds[4] + bounds[5]) / 2.0); this->LatLongLinesOn(); } this->SelectRepresentation(); rwi->Render(); break; default: this->Superclass::OnChar(); break; } } //------------------------------------------------------------------------------ void vtkInteractorStyleTerrain::CreateLatLong() { if (this->LatLongSphere == nullptr) { this->LatLongSphere = vtkSphereSource::New(); this->LatLongSphere->SetPhiResolution(13); this->LatLongSphere->SetThetaResolution(25); this->LatLongSphere->LatLongTessellationOn(); } if (this->LatLongExtractEdges == nullptr) { this->LatLongExtractEdges = vtkExtractEdges::New(); this->LatLongExtractEdges->SetInputConnection(this->LatLongSphere->GetOutputPort()); } if (this->LatLongMapper == nullptr) { this->LatLongMapper = vtkPolyDataMapper::New(); this->LatLongMapper->SetInputConnection(this->LatLongExtractEdges->GetOutputPort()); } if (this->LatLongActor == nullptr) { this->LatLongActor = vtkActor::New(); this->LatLongActor->SetMapper(this->LatLongMapper); this->LatLongActor->PickableOff(); } } //------------------------------------------------------------------------------ void vtkInteractorStyleTerrain::SelectRepresentation() { if (this->CurrentRenderer == nullptr) { return; } this->CurrentRenderer->RemoveActor(this->LatLongActor); if (this->LatLongLines) { this->CurrentRenderer->AddActor(this->LatLongActor); this->LatLongActor->VisibilityOn(); } else { this->LatLongActor->VisibilityOff(); } } //------------------------------------------------------------------------------ void vtkInteractorStyleTerrain::PrintSelf(ostream& os, vtkIndent indent) { this->Superclass::PrintSelf(os, indent); os << indent << "Latitude/Longitude Lines: " << (this->LatLongLines ? "On\n" : "Off\n"); }