Developer documentation | Axl-2.5.1

axlActorCylinder.cpp
Go to the documentation of this file.
1 /* axlActorCylinder.cpp ---
2  *
3  * Author: Meriadeg Perrinel
4  * Copyright (C) 2008 - Meriadeg Perrinel, Inria.
5  * Created: Fri Dec 17 10:59:21 2010 (+0100)
6  * Version: $Id$
7  * Last-Updated: Mon Dec 17 15:03:08 2012 (+0100)
8  * By: Julien Wintz
9  * Update #: 32
10  */
11 
12 /* Commentary:
13  *
14  */
15 
16 /* Change log:
17  *
18  */
19 #include "axlActorCylinder.h"
20 
21 #include "axlActorComposite.h"
23 
24 #include <axlCore/axlCylinder.h>
25 #include <axlCore/axlPoint.h>
26 
27 #include <QVTKOpenGLWidget.h>
28 
29 #include <vtkActor.h>
30 #include <vtkAssemblyPath.h>
31 //#include <vtkCellPicker.h>
32 #include <vtkCommand.h>
33 #include <vtkGlyph3D.h>
34 #include <vtkInteractorStyleSwitch.h>
35 #include <vtkLight.h>
36 #include <vtkLightCollection.h>
37 #include <vtkCylinderSource.h>
38 #include <vtkLineWidget.h>
39 #include <vtkObjectFactory.h>
40 #include <vtkPoints.h>
41 #include <vtkPointWidget.h>
42 #include <vtkPolyData.h>
43 #include <vtkPolyDataMapper.h>
44 #include <vtkProperty.h>
45 #include <vtkRenderer.h>
46 #include <vtkRendererCollection.h>
47 #include <vtkRenderWindow.h>
48 #include <vtkRenderWindowInteractor.h>
49 #include <vtkSmartPointer.h>
50 #include <vtkTransform.h>
51 
52 
53 class axlActorCylinderObserver : public vtkCommand
54 {
55 public:
57  {
58  return new axlActorCylinderObserver;
59  }
60 
61  virtual void Execute(vtkObject *caller, unsigned long event, void *)
62  {
63  // vtkRenderWindowInteractor *interactor = observerDataAssembly->getInteractor(); //interactor->Render();
64 
65 
66  if(event == vtkCommand::InteractionEvent)
67  {
68  if(!lineWidget || !radiusWidget)
69  return;
70 
72 // axlPoint p1(lineWidget->GetPoint1()[0], lineWidget->GetPoint1()[1], lineWidget->GetPoint1()[2]);
73 // axlPoint p2(lineWidget->GetPoint2()[0], lineWidget->GetPoint2()[1], lineWidget->GetPoint2()[2]);
74 // if(!(axlPoint::distance(&p1, observerData_cylinder->firstPoint())< 0.0001 && axlPoint::distance(&p2, observerData_cylinder->secondPoint())<0.0001))
75 // {// There we move the line widget
76  if (caller == lineWidget){
77  observerData_cylinderSource->Modified();
83  }
84  else if (caller == radiusWidget)
85  {// There we move the point widget
86 
88  axlPoint p3(radiusWidget->GetPosition()[0], radiusWidget->GetPosition()[1], radiusWidget->GetPosition()[2]);
89  axlPoint mp3 = p3 - center;
91  double pv = (mp3.x() * p1p2.x() + mp3.y() * p1p2.y() + mp3.z() * p1p2.z());
92 
93  axlPoint ps = p1p2 * pv;
94  double norm = observerData_cylinder->length();
95 
96  axlPoint c = p3 - (ps /= (norm*norm));
97 
98  radiusWidget->SetPosition(c.coordinates());
99  double r = axlPoint::distance(&c, &center);
100 
102  observerData_cylinderSource->SetRadius(r);
103  observerData_cylinderSource->Modified();
104  observerData_cylinderSource->Update();
106  if(!observerData_cylinder->fields().isEmpty())
108  }
109 // }
110  }
111 
112 // if(event == vtkCommand::MouseMoveEvent)
113 // {
114 // if(observerData_cylinder)
115 // {
116 // // we need the matrix transform of this actor
117 
118 // vtkAssemblyPath *path;
119 // vtkRenderWindow *renderWindow = interactor->GetRenderWindow();
120 // vtkRendererCollection * rendererCollection = renderWindow->GetRenderers();
121 // vtkRenderer *render = rendererCollection->GetFirstRenderer();
122 // axlInteractorStyle = dynamic_cast<axlInteractorStyleSwitch *>(interactor->GetInteractorStyle());
123 
124 // int X = observerDataAssembly->getInteractor()->GetEventPosition()[0];
125 // int Y = observerDataAssembly->getInteractor()->GetEventPosition()[1];
126 
127 // if (!render || !render->IsInViewport(X, Y))
128 // {
129 // //qDebug()<<" No renderer or bad cursor coordonates";
130 // }
131 
132 // axlCylinderPicker->Pick(X,Y,0.0,render);
133 // path = axlCylinderPicker->GetPath();
134 
135 // if ( path != NULL)
136 // {
137 // double *position = observerDataAssembly->GetPosition();
138 // (void)position;
139 
140 // for(int j=0;j<3;j++)
141 // {
142 // //qDebug()<<"axlActorCylinderObserver :: Execute "<<position[j];
143 // //observerData_line->coordinates()[j] = position[j];
144 // }
145 
146 // }
147 
148 // }
149 // }
150  }
151 
153 // vtkCellPicker *axlCylinderPicker;
156  vtkCylinderSource *observerData_cylinderSource;
157 
158  vtkLineWidget *lineWidget = nullptr;
159  vtkPointWidget *radiusWidget = nullptr;
160 
161 
162 };
163 
164 // /////////////////////////////////////////////////////////////////
165 // axlActorCylinderPrivate
166 // /////////////////////////////////////////////////////////////////
167 
168 class axlActorCylinderPrivate
169 {
170 public:
171  axlCylinder *cylinder;
172  vtkCylinderSource *cylinderSource;
173  vtkPointWidget *radiusWidget;
174  vtkLineWidget *lineWidget;
175  axlActorCylinderObserver *cylinderObserver;
176  QVTKOpenGLWidget *widget;
177 // vtkCellPicker *axlCylinderPicker ;
178 
179 };
180 
181 #if (VTK_MAJOR_VERSION <= 5)
182 vtkCxxRevisionMacro(axlActorCylinder, "$Revision: 0.0.1 $");
183 #endif
184 
186 
187 dtkAbstractData *axlActorCylinder::data(void)
188 {
189  return d->cylinder;
190 }
191 
192 vtkCylinderSource *axlActorCylinder::cylinder(void)
193 {
194  return d->cylinderSource;
195 }
196 
197 void axlActorCylinder::setQVTKWidget(QVTKOpenGLWidget *widget)
198 {
199  d->widget = widget;
200 }
201 
202 
203 void axlActorCylinder::setData(dtkAbstractData *cylinder1)
204 {
205  axlCylinder *cylinder = dynamic_cast<axlCylinder *>(cylinder1);
206  if(cylinder)
207  {
208  d->cylinder = cylinder;
209  this->setMapper(vtkSmartPointer<vtkPolyDataMapper>::New());
210  this->setActor(vtkSmartPointer<vtkActor>::New());
211 
212  d->cylinderSource = vtkCylinderSource::New();
213  // d->cylinderSource->SetPoint1(d->cylinder->firstPoint()->coordinates());
214  // d->cylinderSource->SetPoint2(d->cylinder->secondPoint()->coordinates());
215 
216  d->cylinderSource->SetResolution(200);
217  //this->SetPosition(d->cylinder->coordinates());
218 
219  // connection of data to actor
220  //this->getMapper()->SetInput(d->cylinderSource->GetOutput());
221 
222  this->onUpdateGeometry();
223 #if (VTK_MAJOR_VERSION <= 5)
224  this->getMapper()->SetInput(d->cylinderSource->GetOutput());
225 #else
226  this->getMapper()->SetInputData(d->cylinderSource->GetOutput());
227 #endif
228 
229  this->getActor()->SetMapper(this->getMapper());
230 
231  this->AddPart(this->getActor());
232 
233  if(!d->cylinderObserver)
234  {
235 // d->axlCylinderPicker = vtkCellPicker::New();
236  d->cylinderObserver = axlActorCylinderObserver::New() ;
237  this->getInteractor()->AddObserver(vtkCommand::InteractionEvent, d->cylinderObserver);
238  this->getInteractor()->AddObserver(vtkCommand::MouseMoveEvent, d->cylinderObserver);
239 
240 
241  d->cylinderObserver->observerDataAssembly = this;
242 // d->cylinderObserver->axlCylinderPicker = d->axlCylinderPicker;
243  d->cylinderObserver->observerData_cylinderSource = d->cylinderSource;
244  d->cylinderObserver->observerData_cylinder = d->cylinder;
245  d->cylinderObserver->axlInteractorStyle = dynamic_cast<axlInteractorStyleSwitch *> (this->getInteractor()->GetInteractorStyle());
246  }
247 
248  QColor color = d->cylinder->color();
249  this->getActor()->GetProperty()->SetColor(color.redF(), color.greenF(), color.blueF());
250 
251  QString shader = d->cylinder->shader();
252  if(!shader.isEmpty())
253  this->setShader(shader);
254 
255  //this->getActor()->SetScale(d->cylinder->size());
256 
257  this->setOpacity(d->cylinder->opacity());
258 
259  connect(d->cylinder,SIGNAL(modifiedGeometry()),this,SLOT(onUpdateGeometry()));
260  connect(d->cylinder,SIGNAL(modifiedProperty()),this,SLOT(onUpdateProperty()));
261  }
262  else
263  qDebug()<< "no axlCylinder available";
264 
265 }
266 
267 
269 {
270  axlActor::setDisplay(display);
271 
272  if(display && d->lineWidget){
273  this->showCylinderWidget(true);
274  }
275 
276  if(!display && d->lineWidget){
277  this->showCylinderWidget(false);
278  }
279 }
280 
282 {
283  if(!d->lineWidget || !d->radiusWidget) {
284  qDebug() << "No tet actor computed for this axlActorCylinder.";
285  return;
286  }
287 
288  if(show){
289  d->lineWidget->SetEnabled(1);
290  d->radiusWidget->SetEnabled(1);
291  }
292 
293  if(!show){
294  d->lineWidget->SetEnabled(0);
295  d->radiusWidget->SetEnabled(0);
296 
297  }
298 }
299 
300 void axlActorCylinder::setCylinderWidget(bool cylinderWidget)
301 {
302 
303  if(cylinderWidget) {
304  if(!d->lineWidget || !d->radiusWidget)
305  {
306  //widget drawing
307 
308  d->lineWidget = vtkLineWidget::New();
309  d->lineWidget->SetInteractor(this->getInteractor());
310  d->lineWidget->SetProp3D(this->getActor());
311  d->lineWidget->PlaceWidget();
312  d->lineWidget->SetPoint1(d->cylinder->firstPoint()->coordinates());
313  d->lineWidget->SetPoint2(d->cylinder->secondPoint()->coordinates());
314 
315  d->radiusWidget = vtkPointWidget::New();
316  d->radiusWidget->SetInteractor(this->getInteractor());
317  d->radiusWidget->SetProp3D(this->getActor());
318  d->radiusWidget->PlaceWidget();
319  d->radiusWidget->AllOff();
320  d->radiusWidget->SetTranslationMode(1);
321 // axlPoint v = *(d->cylinder->firstPoint())+(*(d->cylinder->secondPoint()));
322 // //normal of v with 0 in x
323 // axlPoint n(-v.y(), v.x(), v.z());
324 // if(v.x() < 0.0005 && v.y() < 0.0005)
325 // n.setCoordinates(1.0, 0.0, 0.0); // need if cylinder is in z direction
326 // n.normalize();
327 // n *= d->cylinder->radius();
328 // v /= 2.0;
329 //
330 // v += n;
331 //
332 // d->radiusWidget->SetPosition(v.x(), v.y(), v.z());
333  axlPoint center = (*(d->cylinder->firstPoint())+(*(d->cylinder->secondPoint()))) / 2.0;
334  axlPoint p1p2 = (*(d->cylinder->secondPoint())-(*(d->cylinder->firstPoint())));
335  axlPoint mp3(1.0, 1.0, 1.0);
336  axlPoint pv = axlPoint::crossProduct(mp3, p1p2);
337  pv.normalize();
338  pv *= d->cylinder->radius();
339  pv += center;
340  d->radiusWidget->SetPosition(pv.coordinates());
341  }
342 
343  if(d->cylinderObserver)
344  {
345  d->lineWidget->AddObserver(vtkCommand::InteractionEvent, d->cylinderObserver);
346  d->radiusWidget->AddObserver(vtkCommand::InteractionEvent, d->cylinderObserver);
347 
348 
349  d->cylinderObserver->lineWidget = d->lineWidget;
350  d->cylinderObserver->radiusWidget = d->radiusWidget;
351  }
352 
353  // there is always the controlPoints there
354  d->lineWidget->SetEnabled(true);
355  d->radiusWidget->SetEnabled(true);
356 
357 
358 
359  }
360 
361  if (!cylinderWidget)
362  {
363  if (this->getActor()) {
364  // this->getMapper()->SetInput(this->getPolyData());
365 
366  if(d->lineWidget)
367  {
368  d->lineWidget->RemoveAllObservers();
369  d->lineWidget->SetEnabled(false);
370  d->lineWidget->Delete(); // warning not sure
371  d->lineWidget = NULL;
372  }
373 
374  if(d->radiusWidget)
375  {
376  d->radiusWidget->RemoveAllObservers();
377  d->radiusWidget->SetEnabled(false);
378  d->radiusWidget->Delete(); // warning not sure
379  d->radiusWidget = NULL;
380  }
381  }
382  }
383  if (d->cylinderObserver){
384  d->cylinderObserver->lineWidget = d->lineWidget;
385  d->cylinderObserver->radiusWidget = d->radiusWidget;
386  }
387 }
388 
390 {
391 
392  if(!d->lineWidget || !d->radiusWidget) {
393  qDebug() << "No tet actor computed for this axlActorBSpline.";
394  return false;
395  }
396 
397  return d->lineWidget->GetEnabled() && d->radiusWidget->GetEnabled();
398 }
399 
400 
402 {
403  this->onModeChanged(state);
404 
405  emit stateChanged(this->data(), state);
406 }
407 
409 {
410  if(state == 0)
411  {
413  this->getActor()->SetPickable(1);
414 
415  if(axlAbstractData *data = dynamic_cast<axlAbstractData *>(this->data()))
416  {
417  QColor color = data->color();
418  this->getActor()->GetProperty()->SetColor(color.redF(), color.greenF(), color.blueF());
419  }
420  this->setCylinderWidget(false);
421 
422  }
423  else if(state == 1)
424  {
425 
427  this->setCylinderWidget(false);
428  this->getActor()->SetPickable(1);
429  vtkProperty *prop = this->getActor()->GetProperty();
430 
431  if(axlAbstractData *data = dynamic_cast<axlAbstractData *>(this->data()))
432  {
433  QColor color = data->color();
434  qreal *h = new qreal(0.0);
435  qreal *s = new qreal(0.0);
436  qreal *l = new qreal(0.0);
437  color.getHslF(h, s, l);
438  color.setHslF(*h, *s, *l + (1.0 - *l) / 2.0);
439  prop->SetColor(color.redF(), color.greenF(), color.blueF());
440  delete l;
441  delete s;
442  delete h;
443  }
444 
445  }
446  else if(state == 2)
447  {
449  this->setCylinderWidget(true);
450  this->getActor()->SetPickable(0);
451  vtkProperty *prop = this->getActor()->GetProperty();
452  if(axlAbstractData *data = dynamic_cast<axlAbstractData *>(this->data()))
453  {
454  QColor color = data->color();
455  qreal *h = new qreal(0.0);
456  qreal *s = new qreal(0.0);
457  qreal *l = new qreal(0.0);
458  color.getHslF(h, s, l);
459  color.setHslF(*h, *s, *l + (1.0 - *l)/2.0);
460  prop->SetColor(color.redF(), color.greenF(), color.blueF());
461  delete l;
462  delete s;
463  delete h;
464  }
465  }
466 
467  this->Modified();
468 }
469 
470 
472 {
473  // if on edit mode, change to selection mode (for stability)
474  if (this->getState() == 2)
475  setMode(1);
476 
477  //remove line specificity
478  if(d->cylinderObserver)
479  {
480  this->getInteractor()->RemoveObservers(vtkCommand::InteractionEvent, d->cylinderObserver);
481  this->getInteractor()->RemoveObservers(vtkCommand::MouseMoveEvent, d->cylinderObserver);
482  d->cylinderObserver->observerDataAssembly = NULL;
483 // d->cylinderObserver->axlCylinderPicker = NULL;
484  d->cylinderObserver->observerData_cylinderSource = NULL;
485  d->cylinderObserver->observerData_cylinder = NULL;
486  d->cylinderObserver->axlInteractorStyle = NULL;
487  d->cylinderObserver->Delete();
488  d->cylinderObserver = NULL;
489 
490 // d->axlCylinderPicker->Delete();
491 // d->axlCylinderPicker = NULL;
492 
493  }
494  if(d->cylinderSource)
495  {
496  d->cylinderSource->Delete();
497  d->cylinderSource = NULL;
498  }
499  if(d->widget)
500  {
501  d->widget = NULL;
502  }
503  if(d->cylinder)
504  {
505  d->cylinder = NULL;
506  }
507  if(d->lineWidget && d->radiusWidget)
508  {
509  this->setCylinderWidget(false);
510  d->lineWidget = NULL;
511  d->radiusWidget = NULL;
512  }
513 
514  //remove actor specificity
515  this->RemoveAllObservers();
516  this->RemovePart(this->getActor());
517  this->getActor()->RemoveAllObservers();
518 
519  if(axlActorComposite *actorComposite = dynamic_cast<axlActorComposite *>(this->parent()) )
520  actorComposite->removeActorReference(this);
521 }
522 
524 {
525  d->cylinderSource->SetHeight(axlPoint::distance(d->cylinder->firstPoint(), d->cylinder->secondPoint()));
526  d->cylinderSource->SetRadius(d->cylinder->radius());
527  d->cylinderSource->Modified();
528  d->cylinderSource->Update();
529  if(d->lineWidget)
530  {
531  d->lineWidget->SetPoint1(d->cylinder->firstPoint()->coordinates());
532  d->lineWidget->SetPoint2(d->cylinder->secondPoint()->coordinates());
533  }
534 
535  axlPoint center = (*(d->cylinder->firstPoint())+(*(d->cylinder->secondPoint()))) / 2.0;
536 
537  // Find the good axes
538  axlPoint v = *(d->cylinder->firstPoint()) - center;
539  v.normalize();
540 
541  // vectorial product
542  axlPoint n(-v.z(), 0.0, v.x());
543  if(!(fabs(n.x()) < 0.00001 && fabs(n.z()) < 0.0001))// vectorial product is not null
544  {
545  n.normalize();
546  //rotation
547  this->getActor()->SetOrientation(0.0, 0.0, 0.0);
548  this->getActor()->RotateWXYZ(-acos(v.y()) * 180 / 3.14159, n.x(), 0.0, n.z());
549  }
550 
551  if(d->radiusWidget) {
552  axlPoint p1p2 = (*(d->cylinder->secondPoint())-(*(d->cylinder->firstPoint())));
553  axlPoint mp3(1.0, 1.0, 1.0);
554 
555  //axlPoint pv(mp3.y() * p1p2.z() - mp3.z() * p1p2.y(), mp3.x() * p1p2.z() - mp3.z() * p1p2.x(), mp3.x() * p1p2.y() - mp3.y() * p1p2.x());
556  axlPoint pv = axlPoint::crossProduct(mp3, p1p2);
557  pv.normalize();
558  pv *= d->cylinder->radius();
559  pv += center;
560 
561  d->radiusWidget->SetPosition(pv.coordinates());
562  }
563 
564  //Translation
565  this->getActor()->SetPosition(center.coordinates());
566 
567  if(!d->cylinder->fields().isEmpty())
568  d->cylinder->touchField();
569 
570  if(d->cylinder->updateView())
571  emit updated();
572 }
573 
574 axlActorCylinder::axlActorCylinder(void) : axlActor(), d(new axlActorCylinderPrivate)
575 {
576  d->cylinder = NULL;
577  d->lineWidget = NULL;
578  d->radiusWidget = NULL;
579 // d->axlCylinderPicker = NULL;
580  d->cylinderObserver = NULL;
581  d->cylinderSource =NULL;
582  d->widget = NULL;
583 }
584 
586 {
587  delete d;
588 
589  d = NULL;
590 }
591 
593 
594  return axlActorCylinder::New();
595 }
void touchGeometry(void)
Class axlPoint defines 3D points.
Definition: axlPoint.h:34
dtkAbstractData * data(void)
void setFirstPoint(axlPoint *p1)
Change first point of this cylinder.
static axlActorCylinder * New(void)
virtual void touchField(void)
virtual void setDisplay(bool display)
Definition: axlActor.cpp:440
void setCylinderWidget(bool cylinderWidget)
void setRadius(double radius)
Change radius of this cylinder.
double * coordinates(void) const
Returns coordinates of this point.
Definition: axlPoint.cpp:445
void stateChanged(dtkAbstractData *data, int mode)
void setMode(int state)
vtkStandardNewMacro(axlActorCylinder)
bool isShowCylinderWidget(void)
axlPoint * secondPoint(void) const
Returns second point of the cylinder.
Class axlCylinder defines 3D cylinders.
Definition: axlCylinder.h:33
static axlActorCylinderObserver * New(void)
void setSecondPoint(axlPoint *p2)
Change second point of this cylinder.
virtual void setState(int state)
Definition: axlActor.cpp:434
vtkCylinderSource * observerData_cylinderSource
axlPoint * firstPoint(void) const
Returns first point of the cylinder.
virtual int getState(void)
Definition: axlActor.cpp:429
void updated(void)
axlActorCylinder * observerDataAssembly
double length(void) const
Returns length of the cylinder.
axlInteractorStyleSwitch * axlInteractorStyle
void normalize(void)
Definition: axlPoint.cpp:410
virtual void setShader(QString vsfile)
Definition: axlActor.cpp:517
virtual void setData(dtkAbstractData *cylinder1)
void onModeChanged(int state)
virtual axlAbstractActor * parent(void)
virtual void setOpacity(double opacity)
Definition: axlActor.cpp:461
void setQVTKWidget(QVTKOpenGLWidget *widget)
void setMapper(vtkSmartPointer< vtkPolyDataMapper > mapper)
Definition: axlActor.cpp:332
vtkCylinderSource * cylinder(void)
virtual void Execute(vtkObject *caller, unsigned long event, void *)
void setActor(vtkSmartPointer< vtkActor > actor)
Definition: axlActor.cpp:322
vtkSmartPointer< vtkActor > getActor(void)
Definition: axlActor.cpp:317
double y
Definition: axlPoint.h:37
vtkCxxRevisionMacro(axlActorCylinder,"$Revision: 0.0.1 $")
virtual void onUpdateProperty(void)
vtkSmartPointer< vtkPolyDataMapper > getMapper(void)
Definition: axlActor.cpp:327
double z
Definition: axlPoint.h:38
axlAbstractActor * createAxlActorCylinder(void)
QList< axlAbstractField * > fields(void)
static axlPoint crossProduct(const axlPoint &lhs, const axlPoint &rhs)
Returns the cross product between lhs (coords) and rhs (coords).
Definition: axlPoint.cpp:485
static double distance(const axlPoint &lhs, const axlPoint &rhs)
Returns the distance between lhs point and rhs point.
Definition: axlPoint.cpp:459
void setDisplay(bool display)
double x
Definition: axlPoint.h:37
virtual vtkRenderWindowInteractor * getInteractor(void)
Definition: axlActor.cpp:264
void showCylinderWidget(bool show)
Class axlAbstractData defines an API for all type of axel data.