CustusX  16.12
An IGT application
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
cxCameraControl.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 /*
34  * cxCameraControl.cpp
35  *
36  * \date Oct 15, 2010
37  * \author christiana
38  */
39 #include "cxCameraControl.h"
40 
41 #include <QAction>
42 #include "vtkRenderer.h"
43 #include "vtkCamera.h"
44 #include "cxView.h"
45 #include <QDomNode>
46 #include "cxTypeConversions.h"
47 #include "cxLogger.h"
48 
49 namespace cx
50 {
51 
53 {
54 }
55 
57 {
58  mCamera = camera;
59 }
60 
62 {
63  if (!mCamera)
64  mCamera = vtkCameraPtr::New();
65  return mCamera;
66 }
67 
68 void CameraData::addTextElement(QDomNode parentNode, QString name, QString value) const
69 {
70  QDomDocument doc = parentNode.ownerDocument();
71  QDomElement node = doc.createElement(name);
72  node.appendChild(doc.createTextNode(value));
73  parentNode.appendChild(node);
74 }
75 
76 void CameraData::addXml(QDomNode dataNode) const
77 {
78  if (!mCamera)
79  return;
80 
81  this->addTextElement(dataNode, "position", qstring_cast(Vector3D(mCamera->GetPosition())));
82  this->addTextElement(dataNode, "focalPoint", qstring_cast(Vector3D(mCamera->GetFocalPoint())));
83  this->addTextElement(dataNode, "viewUp", qstring_cast(Vector3D(mCamera->GetViewUp())));
84  this->addTextElement(dataNode, "nearClip", qstring_cast(mCamera->GetClippingRange()[0]));
85  this->addTextElement(dataNode, "farClip", qstring_cast(mCamera->GetClippingRange()[1]));
86  this->addTextElement(dataNode, "parallelScale", qstring_cast(mCamera->GetParallelScale()));
87 }
88 
89 void CameraData::parseXml(QDomNode dataNode)
90 {
91  Vector3D position = Vector3D::fromString(dataNode.namedItem("position").toElement().text());
92  Vector3D focalPoint = Vector3D::fromString(dataNode.namedItem("focalPoint").toElement().text());
93  Vector3D viewUp = Vector3D::fromString(dataNode.namedItem("viewUp").toElement().text());
94  double nearClip = dataNode.namedItem("nearClip").toElement().text().toDouble();
95  double farClip = dataNode.namedItem("farClip").toElement().text().toDouble();
96  double parallelScale = dataNode.namedItem("parallelScale").toElement().text().toDouble();
97 
98  if (similar(viewUp.length(), 0.0))
99  return; // ignore reading if undefined data
100  double LARGE_NUMBER = 1.0E6; // corresponding to a distance of 1km - unphysical for human-sized data
101  if ((position-focalPoint).length() > LARGE_NUMBER)
102  return;
103  if (focalPoint.length() > LARGE_NUMBER)
104  return;
105  if (fabs(parallelScale) > LARGE_NUMBER)
106  return;
107 
108  this->getCamera();
109 
110  mCamera->SetClippingRange(nearClip, farClip);
111  mCamera->SetPosition(position.begin());
112  mCamera->SetFocalPoint(focalPoint.begin());
113  mCamera->ComputeViewPlaneNormal();
114  mCamera->SetViewUp(viewUp.begin());
115  mCamera->SetParallelScale(parallelScale);
116 }
117 
121 
122 
124  QObject(parent),
125  mSuperiorViewAction(NULL)
126 {
127 }
128 
130 {
131 }
132 
133 /*Move the camera focus to p_r. Keep the view direction and distance constant
134  * (i.e. keep pos of camera constant relative to focus).
135  *
136  */
138 {
139  vtkCameraPtr camera = this->getCamera();
140  if (!camera)
141  return;
142 
143  Vector3D f(camera->GetFocalPoint());
144  Vector3D p(camera->GetPosition());
145  Vector3D delta = p_r - f;
146  f += delta;
147  p += delta;
148  camera->SetFocalPoint(f.begin());
149  camera->SetPosition(p.begin());
150 }
151 
153 {
154  if(mSuperiorViewAction)
155  mSuperiorViewAction->trigger();
156 }
157 
159 {
160  QActionGroup* group = new QActionGroup(this);
161  this->addStandard3DViewAction("A", "Anterior View", Vector3D(0, 1, 0), group);
162  this->addStandard3DViewAction("P", "Posterior View", Vector3D(0, -1, 0), group);
163  mSuperiorViewAction = this->addStandard3DViewAction("S", "Superior View", Vector3D(0, 0, -1), group);
164  this->addStandard3DViewAction("I", "Inferior View", Vector3D(0, 0, 1), group);
165  this->addStandard3DViewAction("L", "Left View", Vector3D(-1, 0, 0), group);
166  this->addStandard3DViewAction("R", "Right View", Vector3D(1, 0, 0), group);
167  this->addStandard3DViewAction("O", "Orthogonal View", Vector3D(-1, 1, -1).normal(), group);
168  return group;
169 }
170 
173 QAction* CameraControl::addStandard3DViewAction(QString caption, QString help, Vector3D viewDirection,
174  QActionGroup* group)
175 {
176  QAction* action = new QAction(help, group);
177  action->setStatusTip(help);
178  action->setWhatsThis(help);
179  action->setIcon(QIcon(":/icons/camera_view_" + caption + ".png"));
180  // QFont font;
181  // font.setBold(true);
182  // if (font.pointSize()>=0)
183  // font.setPointSize(font.pointSize()*1.5);
184  // action->setFont(font);
185  action->setData(QVariant(qstring_cast(viewDirection)));
186  connect(action, &QAction::triggered, this, &CameraControl::setStandard3DViewActionSlot);
187  return action;
188 }
189 
191 {
192  this->setView(view);
193  if(view)
194  view->getRenderer()->ResetCameraClippingRange();
195 }
196 
198 {
199  mView = view;
200 }
201 
202 vtkRendererPtr CameraControl::getRenderer() const
203 {
204  if (!mView)
205  return vtkRendererPtr();
206  return mView->getRenderer();
207 }
208 vtkCameraPtr CameraControl::getCamera() const
209 {
210  if (!this->getRenderer())
211  return vtkCameraPtr();
212  return this->getRenderer()->GetActiveCamera();
213 }
214 
216 {
217  QAction* action = dynamic_cast<QAction*> (sender());
218  if (!action)
219  return;
220  Vector3D viewDirection = Vector3D::fromString(action->data().toString());
221 
222  vtkRendererPtr renderer = this->getRenderer();
223  if (!renderer)
224  return;
225  vtkCameraPtr camera = this->getCamera();
226 
227  renderer->ResetCamera();
228 
229  Vector3D focus(camera->GetFocalPoint());
230  Vector3D pos = focus - 500 * viewDirection;
231  Vector3D vup(0, 0, 1);
232  //Vector3D dir = (focus-direction).normal();
233 
234  Vector3D left = cross(vup, viewDirection);
235 // CX_LOG_CHANNEL_DEBUG("CA") << " cross(vup, viewDirection) " << cross(vup, viewDirection);
236  if (similar(left.length(), 0.0))
237  left = Vector3D(1, 0, 0);
238  vup = cross(viewDirection, left).normal();
239 
240 // CX_LOG_CHANNEL_DEBUG("CA") << "CameraControl::setStandard3DViewActionSlot()";
241 // CX_LOG_CHANNEL_DEBUG("CA") << " viewDirection " << viewDirection;
242 // CX_LOG_CHANNEL_DEBUG("CA") << " left " << left;
243 // CX_LOG_CHANNEL_DEBUG("CA") << " vup " << vup;
244 
245  camera->SetPosition(pos.begin());
246  camera->SetViewUp(vup.begin());
247 
248  renderer->ResetCamera(); // let vtk do the zooming base work
249  camera->Dolly(1.5); // zoom in a bit more than the default vtk value
250  renderer->ResetCameraClippingRange();
251 }
252 
253 } // namespace cx
QString qstring_cast(const T &val)
PlainObject normal() const
void setSuperiorView() const
vtkCameraPtr getCamera() const
void translateByFocusTo(Vector3D p_r)
boost::shared_ptr< class View > ViewPtr
Vector3D cross(const Vector3D &a, const Vector3D &b)
compute cross product of a and b.
Definition: cxVector3D.cpp:62
QActionGroup * createStandard3DViewActions()
vtkSmartPointer< class vtkRenderer > vtkRendererPtr
void setView(ViewPtr view)
void refreshView(ViewPtr view)
void parseXml(QDomNode dataNode)
load internal state info from dataNode
void addXml(QDomNode dataNode) const
store internal state info in dataNode
Eigen::Vector3d Vector3D
Vector3D is a representation of a point or vector in 3D.
Definition: cxVector3D.h:63
void setCamera(vtkCameraPtr camera)
bool similar(const CameraInfo &lhs, const CameraInfo &rhs, double tol)
CameraControl(QObject *parent=NULL)
void setStandard3DViewActionSlot()
vtkSmartPointer< class vtkCamera > vtkCameraPtr