CustusX  2021.09.21-dev+develop.e3cd0
An IGT application
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) SINTEF Department of Medical Technology.
5 All rights reserved.
6 
7 CustusX is released under a BSD 3-Clause license.
8 
9 See Lisence.txt (https://github.com/SINTEFMedtek/CustusX/blob/master/License.txt) for details.
10 =========================================================================*/
11 
12 /*
13  * cxCameraControl.cpp
14  *
15  * \date Oct 15, 2010
16  * \author christiana
17  */
18 #include "cxCameraControl.h"
19 
20 #include <QAction>
21 #include "vtkRenderer.h"
22 #include "vtkCamera.h"
23 #include "cxView.h"
24 #include <QDomNode>
25 #include "cxTypeConversions.h"
26 #include "cxLogger.h"
27 
28 namespace cx
29 {
30 
32 {
33 }
34 
36 {
37  mCamera = camera;
38 }
39 
41 {
42  if (!mCamera)
43  mCamera = vtkCameraPtr::New();
44  return mCamera;
45 }
46 
47 void CameraData::addTextElement(QDomNode parentNode, QString name, QString value) const
48 {
49  QDomDocument doc = parentNode.ownerDocument();
50  QDomElement node = doc.createElement(name);
51  node.appendChild(doc.createTextNode(value));
52  parentNode.appendChild(node);
53 }
54 
55 void CameraData::addXml(QDomNode dataNode) const
56 {
57  if (!mCamera)
58  return;
59 
60  this->addTextElement(dataNode, "position", qstring_cast(Vector3D(mCamera->GetPosition())));
61  this->addTextElement(dataNode, "focalPoint", qstring_cast(Vector3D(mCamera->GetFocalPoint())));
62  this->addTextElement(dataNode, "viewUp", qstring_cast(Vector3D(mCamera->GetViewUp())));
63  this->addTextElement(dataNode, "nearClip", qstring_cast(mCamera->GetClippingRange()[0]));
64  this->addTextElement(dataNode, "farClip", qstring_cast(mCamera->GetClippingRange()[1]));
65  this->addTextElement(dataNode, "parallelScale", qstring_cast(mCamera->GetParallelScale()));
66 }
67 
68 void CameraData::parseXml(QDomNode dataNode)
69 {
70  Vector3D position = Vector3D::fromString(dataNode.namedItem("position").toElement().text());
71  Vector3D focalPoint = Vector3D::fromString(dataNode.namedItem("focalPoint").toElement().text());
72  Vector3D viewUp = Vector3D::fromString(dataNode.namedItem("viewUp").toElement().text());
73  double nearClip = dataNode.namedItem("nearClip").toElement().text().toDouble();
74  double farClip = dataNode.namedItem("farClip").toElement().text().toDouble();
75  double parallelScale = dataNode.namedItem("parallelScale").toElement().text().toDouble();
76 
77  if (similar(viewUp.length(), 0.0))
78  return; // ignore reading if undefined data
79  double LARGE_NUMBER = 1.0E6; // corresponding to a distance of 1km - unphysical for human-sized data
80  if ((position-focalPoint).length() > LARGE_NUMBER)
81  return;
82  if (focalPoint.length() > LARGE_NUMBER)
83  return;
84  if (fabs(parallelScale) > LARGE_NUMBER)
85  return;
86 
87  this->getCamera();
88 
89  mCamera->SetClippingRange(nearClip, farClip);
90  mCamera->SetPosition(position.begin());
91  mCamera->SetFocalPoint(focalPoint.begin());
92  mCamera->ComputeViewPlaneNormal();
93  mCamera->SetViewUp(viewUp.begin());
94  mCamera->SetParallelScale(parallelScale);
95 }
96 
100 
101 
103  QObject(parent),
104  mSuperiorViewAction(NULL),
105  mAnteriorViewAction(NULL)
106 {
107 }
108 
110 {
111 }
112 
114 {
115  return Vector3D(0, 1, 0);
116 }
118 {
119  return Vector3D(0, -1, 0);
120 }
122 {
123  return Vector3D(0, 0, -1);
124 }
126 {
127  return Vector3D(0, 0, 1);
128 }
130 {
131  return Vector3D(-1, 0, 0);
132 }
134 {
135  return Vector3D(1, 0, 0);
136 }
138 {
139  return Vector3D(-1, 1, -1).normal();
140 }
141 
142 /*Move the camera focus to p_r. Keep the view direction and distance constant
143  * (i.e. keep pos of camera constant relative to focus).
144  *
145  */
147 {
148  vtkCameraPtr camera = this->getCamera();
149  if (!camera)
150  return;
151 
152  Vector3D f(camera->GetFocalPoint());
153  Vector3D p(camera->GetPosition());
154  Vector3D delta = p_r - f;
155  f += delta;
156  p += delta;
157  camera->SetFocalPoint(f.begin());
158  camera->SetPosition(p.begin());
159 }
160 
162 {
163  if(mSuperiorViewAction)
164  mSuperiorViewAction->trigger();
165 }
166 
168 {
169  if(mAnteriorViewAction)
170  mAnteriorViewAction->trigger();
171 }
172 
174 {
175  QActionGroup* group = new QActionGroup(this);
176  mAnteriorViewAction = this->addStandard3DViewAction("A", "Anterior View", AnteriorDirection(), group);
177  this->addStandard3DViewAction("P", "Posterior View", PosteriorDirection(), group);
178  mSuperiorViewAction = this->addStandard3DViewAction("S", "Superior View", SuperiorDirection(), group);
179  this->addStandard3DViewAction("I", "Inferior View", InferiorDirection(), group);
180  this->addStandard3DViewAction("L", "Left View", LeftDirection(), group);
181  this->addStandard3DViewAction("R", "Right View", RightDirection(), group);
182  this->addStandard3DViewAction("O", "Orthogonal View", OrthogonalDirection(), group);
183  return group;
184 }
185 
188 QAction* CameraControl::addStandard3DViewAction(QString caption, QString help, Vector3D viewDirection,
189  QActionGroup* group)
190 {
191  QAction* action = new QAction(help, group);
192  action->setStatusTip(help);
193  action->setWhatsThis(help);
194  action->setIcon(QIcon(":/icons/camera_view_" + caption + ".png"));
195  // QFont font;
196  // font.setBold(true);
197  // if (font.pointSize()>=0)
198  // font.setPointSize(font.pointSize()*1.5);
199  // action->setFont(font);
200  action->setData(QVariant(qstring_cast(viewDirection)));
201  connect(action, &QAction::triggered, this, &CameraControl::setStandard3DViewActionSlot);
202  return action;
203 }
204 
206 {
207  this->setView(view);
208  if(view)
209  view->getRenderer()->ResetCameraClippingRange();
210 }
211 
213 {
214  mView = view;
215 }
216 
218 {
219  return mView;
220 }
221 
222 vtkRendererPtr CameraControl::getRenderer() const
223 {
224  if (!mView)
225  return vtkRendererPtr();
226  return mView->getRenderer();
227 }
228 vtkCameraPtr CameraControl::getCamera() const
229 {
230  if (!this->getRenderer())
231  return vtkCameraPtr();
232  return this->getRenderer()->GetActiveCamera();
233 }
234 
236 {
237  QAction* action = dynamic_cast<QAction*> (sender());
238  if (!action)
239  return;
240  Vector3D viewDirection = Vector3D::fromString(action->data().toString());
241  this->setStandard3DView(viewDirection);
242 }
243 
245 {
246  vtkRendererPtr renderer = this->getRenderer();
247  if (!renderer)
248  return;
249  vtkCameraPtr camera = this->getCamera();
250 
251  renderer->ResetCamera();
252 
253  Vector3D focus(camera->GetFocalPoint());
254  Vector3D pos = focus - 500 * viewDirection;
255  Vector3D vup(0, 0, 1);
256 
257  Vector3D left = cross(vup, viewDirection);
258  if (similar(left.length(), 0.0))
259  left = RightDirection();
260  vup = cross(viewDirection, left).normal();
261 
262  camera->SetPosition(pos.begin());
263  camera->SetViewUp(vup.begin());
264 
265  renderer->ResetCamera(); // let vtk do the zooming base work
266  camera->Dolly(1.5); // zoom in a bit more than the default vtk value
267  renderer->ResetCameraClippingRange();
268 }
269 
270 } // namespace cx
QString qstring_cast(const T &val)
static Vector3D LeftDirection()
void setSuperiorView() const
vtkCameraPtr getCamera() const
void translateByFocusTo(Vector3D p_r)
static Vector3D OrthogonalDirection()
boost::shared_ptr< class View > ViewPtr
Vector3D cross(const Vector3D &a, const Vector3D &b)
compute cross product of a and b.
Definition: cxVector3D.cpp:41
QActionGroup * createStandard3DViewActions()
static Vector3D SuperiorDirection()
static Vector3D InferiorDirection()
vtkSmartPointer< class vtkRenderer > vtkRendererPtr
void setView(ViewPtr view)
void refreshView(ViewPtr view)
void setStandard3DView(Vector3D viewDirection)
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:42
void setCamera(vtkCameraPtr camera)
static Vector3D AnteriorDirection()
void setAnteriorView() const
bool similar(const CameraInfo &lhs, const CameraInfo &rhs, double tol)
static Vector3D RightDirection()
static Vector3D PosteriorDirection()
ViewPtr getView() const
CameraControl(QObject *parent=NULL)
void setStandard3DViewActionSlot()
vtkSmartPointer< class vtkCamera > vtkCameraPtr
Namespace for all CustusX production code.