/*========================================================================= medInria Copyright (c) INRIA 2013 - 2018. All rights reserved. See LICENSE.txt for details. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. =========================================================================*/ #include #include "vtkActor2D.h" #include "vtkCallbackCommand.h" #include "vtkCamera.h" #include "vtkCoordinate.h" #include "vtkObjectFactory.h" #include "vtkPoints.h" #include "vtkPolyData.h" #include "vtkPolyDataMapper2D.h" #include "vtkProperty2D.h" #include "vtkProp.h" #include "vtkRenderer.h" #include "vtkRenderWindow.h" #include "vtkRenderWindowInteractor.h" vtkStandardNewMacro(vtkRulerWidget); class vtkRulerWidgetObserver : public vtkCommand { public: static vtkRulerWidgetObserver *New() { return new vtkRulerWidgetObserver; }; vtkRulerWidgetObserver() { this->RulerWidget = 0; } virtual void Execute(vtkObject* wdg, unsigned long event, void *calldata) { if (this->RulerWidget) { this->RulerWidget->ExecuteCameraUpdateEvent(wdg, event, calldata); } } vtkRulerWidget *RulerWidget; }; vtkRulerWidget::vtkRulerWidget() { this->StartEventObserverId = 0; this->Observer = vtkRulerWidgetObserver::New(); this->Observer->RulerWidget = this; this->RendererX = vtkRenderer::New(); this->RendererX->SetViewport( 0.1, 0.1, 0.13, 0.95 ); this->RendererX->SetLayer( 1 ); this->RendererX->InteractiveOff(); this->RendererY = vtkRenderer::New(); this->RendererY->SetViewport( 0.1, 0.1, 0.95, 0.13 ); this->RendererY->SetLayer( 1 ); this->RendererY->InteractiveOff(); this->OutlineX = vtkPolyData::New(); this->OutlineX->Allocate(); vtkPoints *xpoints = vtkPoints::New(); vtkIdType ptIds[31]; for( int i=0; i<31; i++) ptIds[i] = xpoints->InsertNextPoint( 0, 0, 0 ); this->OutlineX->SetPoints( xpoints ); this->OutlineX->InsertNextCell( VTK_POLY_LINE, 31, ptIds ); this->OutlineY = vtkPolyData::New(); this->OutlineY->Allocate(); vtkPoints *ypoints = vtkPoints::New(); for( int i=0; i<31; i++) ptIds[i] = ypoints->InsertNextPoint( 0, 0, 0 ); this->OutlineY->SetPoints( ypoints ); this->OutlineY->InsertNextCell( VTK_POLY_LINE, 31, ptIds ); vtkCoordinate *tcoord = vtkCoordinate::New(); tcoord->SetCoordinateSystemToDisplay(); vtkPolyDataMapper2D *xmapper = vtkPolyDataMapper2D::New(); xmapper->SetInputData( this->OutlineX ); xmapper->SetTransformCoordinate( tcoord ); this->OutlineXActor = vtkActor2D::New(); this->OutlineXActor->SetMapper( xmapper ); this->OutlineXActor->SetPosition( 0, 0 ); this->OutlineXActor->SetPosition2( 1, 1 ); this->OutlineXActor->GetProperty()->SetColor(0.0,1.0,0.0); this->OutlineXActor->PickableOff(); vtkPolyDataMapper2D *ymapper = vtkPolyDataMapper2D::New(); ymapper->SetInputData( this->OutlineY ); ymapper->SetTransformCoordinate( tcoord ); this->OutlineYActor = vtkActor2D::New(); this->OutlineYActor->SetMapper( ymapper ); this->OutlineYActor->SetPosition( 0, 0 ); this->OutlineYActor->SetPosition2( 1, 1 ); this->OutlineYActor->GetProperty()->SetColor(0.0,1.0,0.0); this->OutlineYActor->PickableOff(); xpoints->Delete(); ypoints->Delete(); xmapper->Delete(); ymapper->Delete(); tcoord->Delete(); } vtkRulerWidget::~vtkRulerWidget() { this->Observer->Delete(); this->RendererX->Delete(); this->RendererY->Delete(); this->OutlineXActor->Delete(); this->OutlineX->Delete(); this->OutlineYActor->Delete(); this->OutlineY->Delete(); } void vtkRulerWidget::SetEnabled (int enabling) { if (!this->Interactor) { vtkErrorMacro("The interactor must be set prior to enabling/disabling widget"); return; } if (enabling) { if (this->Enabled) { return; } if (!this->CurrentRenderer) { this->SetCurrentRenderer( this->Interactor->FindPokedRenderer( this->Interactor->GetLastEventPosition()[0], this->Interactor->GetLastEventPosition()[1])); if (this->CurrentRenderer == nullptr) { return; } } this->Enabled = 1; vtkRenderWindow* renwin = this->CurrentRenderer->GetRenderWindow(); renwin->AddRenderer( this->RendererX ); renwin->AddRenderer( this->RendererY ); if (renwin->GetNumberOfLayers() < 2) { renwin->SetNumberOfLayers( 2 ); } this->CurrentRenderer->AddViewProp( this->OutlineXActor ); this->OutlineXActor->VisibilityOn(); this->CurrentRenderer->AddViewProp( this->OutlineYActor ); this->OutlineYActor->VisibilityOn(); vtkCamera* pcam = this->CurrentRenderer->GetActiveCamera(); vtkCamera* xcam = this->RendererX->GetActiveCamera(); vtkCamera* ycam = this->RendererY->GetActiveCamera(); if (pcam && xcam) { xcam->SetParallelProjection( pcam->GetParallelProjection() ); } if (pcam && ycam) { ycam->SetParallelProjection( pcam->GetParallelProjection() ); } // We need to copy the camera before the compositing observer is called. // Compositing temporarily changes the camera to display an image. this->StartEventObserverId = this->CurrentRenderer->AddObserver( vtkCommand::StartEvent, this->Observer, 1 ); this->InvokeEvent( vtkCommand::EnableEvent, nullptr ); } else { if (!this->Enabled) { return; } this->Enabled = 0; this->OutlineXActor->VisibilityOff(); this->CurrentRenderer->RemoveViewProp( this->OutlineXActor ); this->OutlineYActor->VisibilityOff(); this->CurrentRenderer->RemoveViewProp( this->OutlineYActor ); // if the render window is still around, remove our renderer from it if (this->CurrentRenderer->GetRenderWindow()) { this->CurrentRenderer->GetRenderWindow()-> RemoveRenderer( this->RendererX ); this->CurrentRenderer->GetRenderWindow()-> RemoveRenderer( this->RendererY ); } if ( this->StartEventObserverId != 0 ) { this->CurrentRenderer->RemoveObserver( this->StartEventObserverId ); } this->InvokeEvent( vtkCommand::DisableEvent, nullptr ); this->SetCurrentRenderer(nullptr); } } void vtkRulerWidget::ExecuteCameraUpdateEvent(vtkObject *vtkNotUsed(o), unsigned long vtkNotUsed(event), void *vtkNotUsed(calldata)) { if (!this->CurrentRenderer) { return; } vtkCamera *cam = this->CurrentRenderer->GetActiveCamera(); double pos[3], fp[3], viewup[3]; cam->GetPosition( pos ); cam->GetFocalPoint( fp ); cam->GetViewUp( viewup ); double vp[4]; this->RendererX->GetViewport( vp ); this->RendererX->NormalizedDisplayToDisplay( vp[0], vp[1] ); this->RendererX->NormalizedDisplayToDisplay( vp[2], vp[3] ); vtkPoints *xpoints = this->OutlineX->GetPoints(); double mid[2]={0.5, 0.5}; this->RendererX->NormalizedDisplayToDisplay( mid[0], mid[1] ); double ww1[4] = {0.0, 0.0, 0.0, 1.0}; double ww2[4] = {10.0, 10.0, 10.0, 1.0}; double norma = 300; // = ( 3*10*10 ) this->CurrentRenderer->SetWorldPoint(ww1); this->CurrentRenderer->WorldToDisplay(); this->CurrentRenderer->GetDisplayPoint( ww1 ); this->CurrentRenderer->SetWorldPoint( ww2 ); this->CurrentRenderer->WorldToDisplay(); this->CurrentRenderer->GetDisplayPoint( ww2 ); vp[0] = 20; vp[2] = 30; double dist = 0.0; for (int i=0; i<3; i++) { dist += (ww1[i]-ww2[i])*(ww1[i]-ww2[i]); } double yfactor = sqrt(dist/norma)*10; //fabs(ww2[1]-ww1[1]); double ymin = mid[1] - 5.0 * yfactor; double ymax = mid[1] + 5.0 * yfactor; double xstep = ( vp[2] - vp[0] )/ 3.0; double ystep = yfactor; /* double xpoints[31]={vp[2], vp[0], vp[0], vp[0]+xstep, vp[0], vp[0], vp[0]+xstep, vp[0], vp[0], vp[0]+xstep, vp[0], vp[0], vp[0]+xstep, vp[0], vp[0], vp[2], vp[0], vp[0], vp[0]+xstep, vp[0], vp[0], vp[0]+xstep, vp[0], vp[0], vp[0]+xstep, vp[0], vp[0], vp[0]+xstep, vp[0], vp[0], vp[2]}; */ xpoints->SetPoint( 0, vp[2], ymin, 0 ); xpoints->SetPoint( 1, vp[0], ymin, 0 ); xpoints->SetPoint( 2, vp[0], mid[1] - 4.0*ystep, 0 ); xpoints->SetPoint( 3, vp[0]+xstep, mid[1] - 4.0*ystep, 0 ); xpoints->SetPoint( 4, vp[0], mid[1] - 4.0*ystep, 0 ); xpoints->SetPoint( 5, vp[0], mid[1] - 3.0*ystep, 0 ); xpoints->SetPoint( 6, vp[0]+xstep, mid[1] - 3.0*ystep, 0 ); xpoints->SetPoint( 7, vp[0], mid[1] - 3.0*ystep, 0 ); xpoints->SetPoint( 8, vp[0], mid[1] - 2.0*ystep, 0 ); xpoints->SetPoint( 9, vp[0]+xstep, mid[1] - 2.0*ystep, 0 ); xpoints->SetPoint( 10, vp[0], mid[1] - 2.0*ystep, 0 ); xpoints->SetPoint( 11, vp[0], mid[1] - 1.0*ystep, 0 ); xpoints->SetPoint( 12, vp[0]+xstep, mid[1] - 1.0*ystep, 0 ); xpoints->SetPoint( 13, vp[0], mid[1] - 1.0*ystep, 0 ); xpoints->SetPoint( 14, vp[0], mid[1], 0 ); xpoints->SetPoint( 15, vp[2], mid[1], 0 ); xpoints->SetPoint( 16, vp[0], mid[1], 0 ); xpoints->SetPoint( 17, vp[0], mid[1] + 1.0*ystep, 0 ); xpoints->SetPoint( 18, vp[0]+xstep, mid[1] + 1.0*ystep, 0 ); xpoints->SetPoint( 19, vp[0], mid[1] + 1.0*ystep, 0 ); xpoints->SetPoint( 20, vp[0], mid[1] + 2.0*ystep, 0 ); xpoints->SetPoint( 21, vp[0]+xstep, mid[1] + 2.0*ystep, 0 ); xpoints->SetPoint( 22, vp[0], mid[1] + 2.0*ystep, 0 ); xpoints->SetPoint( 23, vp[0], mid[1] + 3.0*ystep, 0 ); xpoints->SetPoint( 24, vp[0]+xstep, mid[1] + 3.0*ystep, 0 ); xpoints->SetPoint( 25, vp[0], mid[1] + 3.0*ystep, 0 ); xpoints->SetPoint( 26, vp[0], mid[1] + 4.0*ystep, 0 ); xpoints->SetPoint( 27, vp[0]+xstep, mid[1] + 4.0*ystep, 0 ); xpoints->SetPoint( 28, vp[0], mid[1] + 4.0*ystep, 0 ); xpoints->SetPoint( 29, vp[0], ymax, 0 ); xpoints->SetPoint( 30, vp[2], ymax, 0 ); this->RendererY->GetViewport( vp ); this->RendererY->NormalizedDisplayToDisplay( vp[0], vp[1] ); this->RendererY->NormalizedDisplayToDisplay( vp[2], vp[3] ); vp[1] = 20; vp[3] = 30; vtkPoints *ypoints = this->OutlineY->GetPoints(); double xfactor = yfactor; //sqrt(dist); //fabs(ww2[0]-ww1[0]); //double xfactor = fabs(ww2[2]-ww1[2]); double xmin = mid[0] - 5.0 * xfactor; double xmax = mid[0] + 5.0 * xfactor; ystep = ( vp[3] - vp[1] )/ 3.0; xstep = xfactor; ypoints->SetPoint( 0, xmin, vp[3], 0 ); ypoints->SetPoint( 1, xmin, vp[1], 0 ); ypoints->SetPoint( 2, mid[0] - 4.0*xstep, vp[1], 0 ); ypoints->SetPoint( 3, mid[0] - 4.0*xstep, vp[1]+ystep, 0 ); ypoints->SetPoint( 4, mid[0] - 4.0*xstep, vp[1], 0 ); ypoints->SetPoint( 5, mid[0] - 3.0*xstep, vp[1], 0 ); ypoints->SetPoint( 6, mid[0] - 3.0*xstep, vp[1]+ystep, 0 ); ypoints->SetPoint( 7, mid[0] - 3.0*xstep, vp[1], 0 ); ypoints->SetPoint( 8, mid[0] - 2.0*xstep, vp[1], 0 ); ypoints->SetPoint( 9, mid[0] - 2.0*xstep, vp[1]+ystep, 0 ); ypoints->SetPoint( 10, mid[0] - 2.0*xstep, vp[1], 0 ); ypoints->SetPoint( 11, mid[0] - 1.0*xstep, vp[1], 0 ); ypoints->SetPoint( 12, mid[0] - 1.0*xstep, vp[1]+ystep, 0 ); ypoints->SetPoint( 13, mid[0] - 1.0*xstep, vp[1], 0 ); ypoints->SetPoint( 14, mid[0], vp[1], 0 ); ypoints->SetPoint( 15, mid[0], vp[3], 0 ); ypoints->SetPoint( 16, mid[0], vp[1], 0 ); ypoints->SetPoint( 17, mid[0] + 1.0*xstep, vp[1], 0 ); ypoints->SetPoint( 18, mid[0] + 1.0*xstep, vp[1]+ystep, 0 ); ypoints->SetPoint( 19, mid[0] + 1.0*xstep, vp[1], 0 ); ypoints->SetPoint( 20, mid[0] + 2.0*xstep, vp[1], 0 ); ypoints->SetPoint( 21, mid[0] + 2.0*xstep, vp[1]+ystep,0 ); ypoints->SetPoint( 22, mid[0] + 2.0*xstep, vp[1], 0 ); ypoints->SetPoint( 23, mid[0] + 3.0*xstep, vp[1], 0 ); ypoints->SetPoint( 24, mid[0] + 3.0*xstep, vp[1]+ystep, 0 ); ypoints->SetPoint( 25, mid[0] + 3.0*xstep, vp[1], 0 ); ypoints->SetPoint( 26, mid[0] + 4.0*xstep, vp[1], 0 ); ypoints->SetPoint( 27, mid[0] + 4.0*xstep, vp[1]+ystep, 0 ); ypoints->SetPoint( 28, mid[0] + 4.0*xstep, vp[1], 0 ); ypoints->SetPoint( 29, xmax, vp[1],0 ); ypoints->SetPoint( 30, xmax, vp[3], 0 ); }