CustusX  16.5.0-rc9
An IGT application
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
cxCameraStyleForView.cpp
Go to the documentation of this file.
1 /*=========================================================================
2 This file is part of CustusX, an Image Guided Therapy Application.
3 
4 Copyright (c) 2008-2014, SINTEF Department of Medical Technology
5 All rights reserved.
6 
7 Redistribution and use in source and binary forms, with or without
8 modification, are permitted provided that the following conditions are met:
9 
10 1. Redistributions of source code must retain the above copyright notice,
11  this list of conditions and the following disclaimer.
12 
13 2. Redistributions in binary form must reproduce the above copyright notice,
14  this list of conditions and the following disclaimer in the documentation
15  and/or other materials provided with the distribution.
16 
17 3. Neither the name of the copyright holder nor the names of its contributors
18  may be used to endorse or promote products derived from this software
19  without specific prior written permission.
20 
21 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
22 AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23 IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
24 DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
25 FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26 DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
27 SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
28 CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
29 OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
30 OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31 =========================================================================*/
32 
33 #include "cxCameraStyleForView.h"
34 
35 #include <vtkRenderer.h>
36 #include <vtkCamera.h>
37 
38 #include "cxTrackingService.h"
39 #include "cxToolRep3D.h"
40 #include "cxView.h"
41 #include "boost/bind.hpp"
42 #include <vtkRenderWindow.h>
43 #include "vtkInteractorStyleUnicam.h"
44 #include "vtkInteractorStyleTrackballCamera.h"
45 #include "cxCoreServices.h"
46 #include "cxViewportListener.h"
47 
48 #include "cxTool.h"
49 #include <vtkRenderWindowInteractor.h>
50 #include "cxPatientModelService.h"
51 #include "cxRepContainer.h"
52 #include "cxLogger.h"
53 
54 SNW_DEFINE_ENUM_STRING_CONVERTERS_BEGIN(cx, CAMERA_STYLE_TYPE, cstCOUNT)
55 {
56  "DEFAULT_STYLE",
57  "TOOL_STYLE",
58  "ANGLED_TOOL_STYLE",
59  "UNICAM_STYLE"
60 }
61 SNW_DEFINE_ENUM_STRING_CONVERTERS_END(cx, CAMERA_STYLE_TYPE, cstCOUNT)
62 
63 namespace cx
64 {
65 
66 CameraStyleForView::CameraStyleForView(CoreServicesPtr backend) :
67  mCameraStyleForView(cstDEFAULT_STYLE),
68  mBlockCameraUpdate(false),
69  mBackend(backend)
70 {
71  mViewportListener.reset(new ViewportListener);
72  mViewportListener->setCallback(boost::bind(&CameraStyleForView::viewportChangedSlot, this));
73 
74  mPreRenderListener.reset(new ViewportPreRenderListener);
75  mPreRenderListener->setCallback(boost::bind(&CameraStyleForView::onPreRender, this));
76 
77  connect(mBackend->tracking().get(), SIGNAL(activeToolChanged(const QString&)), this, SLOT(activeToolChangedSlot()));
78 }
79 
81 {
82  this->disconnectTool();
83  mView = widget;
84  this->connectTool();
85 }
86 
87 
88 ViewPtr CameraStyleForView::getView() const
89 {
90  return mView;
91 }
92 
93 void CameraStyleForView::viewportChangedSlot()
94 {
95  if (mBlockCameraUpdate)
96  return;
97  this->updateCamera();
98 }
99 
100 void CameraStyleForView::onPreRender()
101 {
102  if (mFollowingTool)
103  this->moveCameraToolStyleSlot(mFollowingTool->get_prMt(), mFollowingTool->getTimestamp());
104 }
105 
106 ToolRep3DPtr CameraStyleForView::getToolRep() const
107 {
108  if (!this->getView())
109  return ToolRep3DPtr();
110 
111  ToolRep3DPtr rep = RepContainer(this->getView()->getReps()).findFirst<ToolRep3D>(mFollowingTool);
112  return rep;
113 }
114 
115 vtkRendererPtr CameraStyleForView::getRenderer() const
116 {
117  if (!this->getView())
118  return vtkRendererPtr();
119  return this->getView()->getRenderer();
120 }
121 
122 vtkCameraPtr CameraStyleForView::getCamera() const
123 {
124  if (!this->getRenderer())
125  return vtkCameraPtr();
126  return this->getRenderer()->GetActiveCamera();
127 }
128 
129 void CameraStyleForView::setModified()
130 {
131  mPreRenderListener->setModified();
132 }
133 
134 void CameraStyleForView::updateCamera()
135 {
136  this->setModified();
137 }
138 
139 void CameraStyleForView::moveCameraToolStyleSlot(Transform3D prMt, double timestamp)
140 {
141  if (mCameraStyleForView == cstDEFAULT_STYLE)
142  return;
143  if (!mFollowingTool)
144  return;
145 
146 
147  vtkCameraPtr camera = this->getCamera();
148  if (!camera)
149  return;
150 
151  Transform3D rMpr = mBackend->patient()->get_rMpr();
152 
153  Transform3D rMt = rMpr * prMt;
154 
155  double offset = mFollowingTool->getTooltipOffset();
156 
157  double cameraOffset = camera->GetDistance();
158 
159 // std::cout << "cameraOffset pre " << cameraOffset << std::endl;
160 // std::cout << "rMt\n" << rMt << std::endl;
161  Vector3D camera_r = rMt.coord(Vector3D(0, 0, offset - cameraOffset));
162  Vector3D focus_r = rMt.coord(Vector3D(0, 0, offset));
163 // std::cout << "cameraOffset ppost " << (focus_r-camera_r).length() << std::endl;
164  Vector3D vup_r = rMt.vector(Vector3D(-1, 0, 0));
165  if (mCameraStyleForView == cstANGLED_TOOL_STYLE)
166  {
167  // elevate 20*, but keep distance
168  double height = cameraOffset * tan(20 / 180.0 * M_PI);
169  camera_r += vup_r * height;
170  Vector3D elevated = camera_r + vup_r * height;
171  Vector3D n_foc2eye = (elevated - focus_r).normalized();
172  camera_r = focus_r + cameraOffset * n_foc2eye;
173  }
174 
175  Vector3D pos_old(camera->GetPosition());
176  Vector3D focus_old(camera->GetFocalPoint());
177  Vector3D vup_old(camera->GetViewUp());
178 
179  if (similar(pos_old, camera_r, 0.1) && similar(focus_old, focus_r, 0.1) && similar(vup_old, vup_r,0.1 ))
180  return; // break update loop: this event is triggered by camera change.
181 
182 // std::cout << "pos " << pos_old << " to " << camera_r << std::endl;
183 // std::cout << "foc " << focus_old << " to " << focus_r << std::endl;
184 
185  mBlockCameraUpdate = true;
186  camera->SetPosition(camera_r.begin());
187  camera->SetFocalPoint(focus_r.begin());
188  camera->SetViewUp(vup_r.begin());
189  camera->SetClippingRange(1, std::max<double>(1000, cameraOffset * 1.5));
190  mBlockCameraUpdate = false;
191 }
192 
193 void CameraStyleForView::activeToolChangedSlot()
194 {
195  ToolPtr newTool = mBackend->tracking()->getActiveTool();
196  if (newTool == mFollowingTool)
197  return;
198 
199  this->disconnectTool();
200  this->connectTool();
201 }
202 
203 bool CameraStyleForView::isToolFollowingStyle(CAMERA_STYLE_TYPE style) const
204 {
205  return ( style==cstTOOL_STYLE )||( style==cstANGLED_TOOL_STYLE);
206 }
207 
208 void CameraStyleForView::connectTool()
209 {
210  if (!this->isToolFollowingStyle(mCameraStyleForView))
211  return;
212 
213  mFollowingTool = mBackend->tracking()->getActiveTool();
214 
215  if (!mFollowingTool)
216  return;
217 
218  if (!this->getView())
219  return;
220 
221  connect(mFollowingTool.get(), SIGNAL(toolTransformAndTimestamp(Transform3D, double)), this,
222  SLOT(setModified()));
223 
224  ToolRep3DPtr rep = this->getToolRep();
225  if (rep)
226  {
227  rep->setOffsetPointVisibleAtZeroOffset(true);
228  if (mCameraStyleForView == cstTOOL_STYLE)
229  rep->setStayHiddenAfterVisible(true);
230  }
231 
232  mViewportListener->startListen(this->getRenderer());
233  mPreRenderListener->startListen(this->getRenderer());
234 
235  this->updateCamera();
236 
237  report("Camera is following " + mFollowingTool->getName());
238 }
239 
240 void CameraStyleForView::disconnectTool()
241 {
242  if (mCameraStyleForView == cstDEFAULT_STYLE)
243  return;
244 
245  mViewportListener->stopListen();
246  mPreRenderListener->stopListen();
247 
248  if (mFollowingTool)
249  {
250  disconnect(mFollowingTool.get(), SIGNAL(toolTransformAndTimestamp(Transform3D, double)), this,
251  SLOT(setModified()));
252 
253  ToolRep3DPtr rep = this->getToolRep();
254  if (rep)
255  rep->setStayHiddenAfterVisible(false);
256  }
257 
258  mFollowingTool.reset();
259 }
260 
261 void CameraStyleForView::setCameraStyle(CAMERA_STYLE_TYPE style)
262 {
263  if (mCameraStyleForView == style)
264  return;
265 
266  this->disconnectTool();
267 
268  ViewPtr view = this->getView();
269  if (!view)
270  return;
271  vtkRenderWindowInteractor* interactor = view->getRenderWindow()->GetInteractor();
272 
273  switch (style)
274  {
275  case cstDEFAULT_STYLE:
276  case cstTOOL_STYLE:
278  interactor->SetInteractorStyle(vtkInteractorStyleTrackballCameraPtr::New());
279  break;
280  case cstUNICAM_STYLE:
281  interactor->SetInteractorStyle(vtkInteractorStyleUnicamPtr::New());
282  default:
283  break;
284  };
285 
286  mCameraStyleForView = style;
287 
288  this->connectTool();
289 }
290 
292 {
293  return mCameraStyleForView;
294 }
295 
296 }//namespace cx
Transform3D Transform3D
Transform3D is a representation of an affine 3D transform.
boost::shared_ptr< class View > ViewPtr
cstTOOL_STYLE
Definition: cxViewService.h:61
cstDEFAULT_STYLE
Definition: cxViewService.h:61
bool similar(const DoubleBoundingBox3D &a, const DoubleBoundingBox3D &b, double tol)
Listens to changes in viewport and camera matrix.
vtkSmartPointer< class vtkRenderer > vtkRendererPtr
cstANGLED_TOOL_STYLE
Definition: cxViewService.h:61
void setView(ViewPtr widget)
SNW_DEFINE_ENUM_STRING_CONVERTERS_BEGIN(cx, CAMERA_STYLE_TYPE, cstCOUNT)
Eigen::Vector3d Vector3D
Vector3D is a representation of a point or vector in 3D.
Definition: cxVector3D.h:63
void report(QString msg)
Definition: cxLogger.cpp:90
boost::shared_ptr< class CoreServices > CoreServicesPtr
Definition: cxCameraStyle.h:59
cstUNICAM_STYLE
Definition: cxViewService.h:61
Listens to the start render event in a vtkRenderer.
boost::shared_ptr< class ToolRep3D > ToolRep3DPtr
void setCameraStyle(CAMERA_STYLE_TYPE style)
CAMERA_STYLE_TYPE getCameraStyle()
SNW_DEFINE_ENUM_STRING_CONVERTERS_END(cx, ORIENTATION_TYPE, otCOUNT)
#define M_PI
vtkSmartPointer< class vtkCamera > vtkCameraPtr
boost::shared_ptr< class Tool > ToolPtr