CustusX  15.3.3-beta
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->getToolManager().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->getPatientService()->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 
178  if (similar(pos_old, camera_r, 1) && similar(focus_old, focus_r, 1))
179  return; // break update loop: this event is triggered by camera change.
180 
181 // std::cout << "pos " << pos_old << " to " << camera_r << std::endl;
182 // std::cout << "foc " << focus_old << " to " << focus_r << std::endl;
183 
184  mBlockCameraUpdate = true;
185  camera->SetPosition(camera_r.begin());
186  camera->SetFocalPoint(focus_r.begin());
187  camera->SetViewUp(vup_r.begin());
188  camera->SetClippingRange(1, std::max<double>(1000, cameraOffset * 1.5));
189  mBlockCameraUpdate = false;
190 }
191 
192 void CameraStyleForView::activeToolChangedSlot()
193 {
194  ToolPtr newTool = mBackend->getToolManager()->getActiveTool();
195  if (newTool == mFollowingTool)
196  return;
197 
198  this->disconnectTool();
199  this->connectTool();
200 }
201 
202 bool CameraStyleForView::isToolFollowingStyle(CAMERA_STYLE_TYPE style) const
203 {
204  return ( style==cstTOOL_STYLE )||( style==cstANGLED_TOOL_STYLE);
205 }
206 
207 void CameraStyleForView::connectTool()
208 {
209  if (!this->isToolFollowingStyle(mCameraStyleForView))
210  return;
211 
212  mFollowingTool = mBackend->getToolManager()->getActiveTool();
213 
214  if (!mFollowingTool)
215  return;
216 
217  if (!this->getView())
218  return;
219 
220  connect(mFollowingTool.get(), SIGNAL(toolTransformAndTimestamp(Transform3D, double)), this,
221  SLOT(setModified()));
222 
223  ToolRep3DPtr rep = this->getToolRep();
224  if (rep)
225  {
226  rep->setOffsetPointVisibleAtZeroOffset(true);
227  if (mCameraStyleForView == cstTOOL_STYLE)
228  rep->setStayHiddenAfterVisible(true);
229  }
230 
231  mViewportListener->startListen(this->getRenderer());
232  mPreRenderListener->startListen(this->getRenderer());
233 
234  this->updateCamera();
235 
236  report("Camera is following " + mFollowingTool->getName());
237 }
238 
239 void CameraStyleForView::disconnectTool()
240 {
241  if (mCameraStyleForView == cstDEFAULT_STYLE)
242  return;
243 
244  mViewportListener->stopListen();
245  mPreRenderListener->stopListen();
246 
247  if (mFollowingTool)
248  {
249  disconnect(mFollowingTool.get(), SIGNAL(toolTransformAndTimestamp(Transform3D, double)), this,
250  SLOT(setModified()));
251 
252  ToolRep3DPtr rep = this->getToolRep();
253  if (rep)
254  rep->setStayHiddenAfterVisible(false);
255  }
256 
257  mFollowingTool.reset();
258 }
259 
260 void CameraStyleForView::setCameraStyle(CAMERA_STYLE_TYPE style)
261 {
262  if (mCameraStyleForView == style)
263  return;
264 
265  this->disconnectTool();
266 
267  ViewPtr view = this->getView();
268  if (!view)
269  return;
270  vtkRenderWindowInteractor* interactor = view->getRenderWindow()->GetInteractor();
271 
272  switch (style)
273  {
274  case cstDEFAULT_STYLE:
275  case cstTOOL_STYLE:
277  interactor->SetInteractorStyle(vtkInteractorStyleTrackballCameraPtr::New());
278  break;
279  case cstUNICAM_STYLE:
280  interactor->SetInteractorStyle(vtkInteractorStyleUnicamPtr::New());
281  default:
282  break;
283  };
284 
285  mCameraStyleForView = style;
286 
287  this->connectTool();
288 }
289 
290 }//namespace cx
Transform3D Transform3D
Transform3D is a representation of an affine 3D transform.
boost::shared_ptr< class View > ViewPtr
cstUNICAM_STYLE
bool similar(const DoubleBoundingBox3D &a, const DoubleBoundingBox3D &b, double tol)
Listens to changes in viewport and camera matrix.
vtkSmartPointer< class vtkRenderer > vtkRendererPtr
void setView(ViewPtr widget)
SNW_DEFINE_ENUM_STRING_CONVERTERS_BEGIN(cx, CAMERA_STYLE_TYPE, cstCOUNT)
cstDEFAULT_STYLE
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
Listens to the start render event in a vtkRenderer.
cstANGLED_TOOL_STYLE
boost::shared_ptr< class ToolRep3D > ToolRep3DPtr
void setCameraStyle(CAMERA_STYLE_TYPE style)
SNW_DEFINE_ENUM_STRING_CONVERTERS_END(cx, ORIENTATION_TYPE, otCOUNT)
#define M_PI
vtkSmartPointer< class vtkCamera > vtkCameraPtr
boost::shared_ptr< class Tool > ToolPtr