1 #include "VISU_SphereWidget.hxx"
4 #include <vtkAssemblyNode.h>
5 #include <vtkAssemblyPath.h>
6 #include <vtkCallbackCommand.h>
8 #include <vtkCellPicker.h>
9 #include <vtkDoubleArray.h>
11 #include <vtkObjectFactory.h>
12 #include <vtkPolyData.h>
13 #include <vtkPolyDataMapper.h>
14 #include <vtkProperty.h>
15 #include <vtkRenderWindowInteractor.h>
16 #include <vtkRenderer.h>
17 #include <vtkSphere.h>
18 #include <vtkSphereSource.h>
19 #include <vtkPoints.h>
20 #include <vtkSphere.h>
21 #include <vtkImplicitSum.h>
22 #include <vtkImplicitFunction.h>
24 vtkCxxRevisionMacro(VISU_SphereWidget, "$Revision$");
25 vtkStandardNewMacro(VISU_SphereWidget);
26 //====================================================================
29 //====================================================================
30 VISU_SphereWidget::VISU_SphereWidget()
32 myState = VISU_SphereWidget::Start;
33 this->EventCallbackCommand->SetCallback(VISU_SphereWidget::ProcessEvents);
35 //Build the representation of the widget
36 mySphereSource = vtkSphereSource::New();
37 mySphereSource->SetThetaResolution(16);
38 mySphereSource->SetPhiResolution(15);
39 mySphereSource->LatLongTessellationOn();
40 mySphereMapper = vtkPolyDataMapper::New();
41 mySphereMapper->SetInput(mySphereSource->GetOutput());
42 mySphereActor = vtkActor::New();
43 mySphereActor->SetMapper(mySphereMapper);
45 // Define the point coordinates
47 for(int i = 0; i < 6; i += 2){
49 bounds[i+1]=-bounds[i];
51 // Initial creation of the widget, serves to initialize it
54 //Manage the picking stuff
55 myPicker = vtkCellPicker::New();
56 myPicker->SetTolerance(0.005); //need some fluff
57 myPicker->AddPickList(mySphereActor);
58 myPicker->PickFromListOn();
60 // Set up the initial properties
61 mySphereProperty = NULL;
62 mySelectedSphereProperty = NULL;
63 CreateDefaultProperties();
66 mySphere=vtkSphere::New();
67 myImplicitSum=vtkImplicitSum::New();
68 myImplicitSum->AddFunction(mySphere,-1.0);
72 //====================================================================
75 //====================================================================
76 VISU_SphereWidget::~VISU_SphereWidget()
78 mySphereActor->Delete();
79 mySphereMapper->Delete();
80 mySphereSource->Delete();
84 if ( mySphereProperty ) {
85 mySphereProperty->Delete();
87 if ( mySelectedSphereProperty ) {
88 mySelectedSphereProperty->Delete();
91 myImplicitSum->Delete();
93 //====================================================================
94 // function: SetThetaResolution
96 //====================================================================
97 void VISU_SphereWidget::SetThetaResolution(int r)
99 mySphereSource->SetThetaResolution(r);
101 //====================================================================
102 // function: GetThetaResolution
104 //====================================================================
105 int VISU_SphereWidget::GetThetaResolution()
107 return mySphereSource->GetThetaResolution();
109 //====================================================================
110 // function: SetPhiResolution
112 //====================================================================
113 void VISU_SphereWidget::SetPhiResolution(int r)
115 mySphereSource->SetPhiResolution(r);
117 //====================================================================
118 // function: SetPhiResolution
120 //====================================================================
121 int VISU_SphereWidget::GetPhiResolution()
123 return mySphereSource->GetPhiResolution();
125 //====================================================================
126 // function: SetRadius
128 //====================================================================
129 void VISU_SphereWidget::SetRadius(float theRadius)
131 if ( theRadius <= myRmin ) {
134 mySphereSource->SetRadius(theRadius);
135 mySphere->SetRadius(theRadius);
137 //====================================================================
138 // function: GetRadius
140 //====================================================================
141 float VISU_SphereWidget::GetRadius()
143 return mySphereSource->GetRadius();
145 //====================================================================
146 // function: SetCenter
148 //====================================================================
149 void VISU_SphereWidget::SetCenter(float theCenter[3])
151 mySphereSource->SetCenter(theCenter);
152 mySphere->SetCenter(theCenter);
154 //====================================================================
155 // function: SetCenter
157 //====================================================================
158 void VISU_SphereWidget::SetCenter(float theX, float theY, float theZ)
160 float aCenter[3] = {theX, theY, theZ};
164 //====================================================================
165 // function: GetCenter
167 //====================================================================
168 float* VISU_SphereWidget::GetCenter()
170 return mySphereSource->GetCenter();
172 //====================================================================
173 // function: GetCenter
175 //====================================================================
176 void VISU_SphereWidget::GetCenter(float theCenter[3])
178 mySphereSource->GetCenter(theCenter);
180 //====================================================================
181 // function: GetSphereProperty
183 //====================================================================
184 vtkProperty* VISU_SphereWidget::GetSphereProperty ()
186 return mySphereProperty;
188 //====================================================================
189 // function: GetSelectedSphereProperty
191 //====================================================================
192 vtkProperty* VISU_SphereWidget::GetSelectedSphereProperty ()
194 return mySelectedSphereProperty;
196 //====================================================================
197 // function: ImplicitFunction
199 //====================================================================
200 vtkImplicitFunction* VISU_SphereWidget::ImplicitFunction()
202 return myImplicitSum;
204 //====================================================================
205 // function: SetEnabled
207 //====================================================================
208 void VISU_SphereWidget::SetEnabled(int enabling)
211 vtkErrorMacro(<<"The interactor must be set prior to enabling/disabling widget");
216 vtkDebugMacro(<<"Enabling sphere widget");
217 if ( Enabled ) {//already enabled, just return
221 if ( ! CurrentRenderer ) {
223 Interactor->GetLastEventPosition(aPos);
224 CurrentRenderer=Interactor->FindPokedRenderer(aPos[0], aPos[1]);
225 if (!CurrentRenderer) {
232 // listen for the following events
233 Interactor->AddObserver(vtkCommand::MouseMoveEvent,
234 EventCallbackCommand,
236 Interactor->AddObserver(vtkCommand::LeftButtonPressEvent,
237 EventCallbackCommand,
239 Interactor->AddObserver(vtkCommand::LeftButtonReleaseEvent,
240 EventCallbackCommand,
242 Interactor->AddObserver(vtkCommand::MiddleButtonPressEvent,
243 EventCallbackCommand,
245 Interactor->AddObserver(vtkCommand::MiddleButtonReleaseEvent,
246 EventCallbackCommand,
250 CurrentRenderer->AddActor(mySphereActor);
251 mySphereActor->SetProperty(mySphereProperty);
252 mySphere->SetCenter(mySphereSource->GetCenter());
253 mySphere->SetRadius(mySphereSource->GetRadius());
255 InvokeEvent(vtkCommand::EnableEvent,NULL); //!!!see what will be done
257 //disabling----------------------------------------------------------
259 vtkDebugMacro(<<"Disabling sphere widget");
261 if ( !Enabled ){ //already disabled, just return
267 // don't listen for events any more
268 Interactor->RemoveObserver(EventCallbackCommand);
270 // turn off the sphere
271 CurrentRenderer->RemoveActor(mySphereActor);
272 InvokeEvent(vtkCommand::DisableEvent,NULL);
273 CurrentRenderer = NULL;
276 Interactor->Render();
278 //====================================================================
279 // function:ProcessEvents
281 //====================================================================
282 void VISU_SphereWidget::ProcessEvents(vtkObject* vtkNotUsed(object),
285 void* vtkNotUsed(calldata))
287 VISU_SphereWidget* self = reinterpret_cast<VISU_SphereWidget *>( clientdata );
290 case vtkCommand::LeftButtonPressEvent:
291 self->OnLeftButtonDown();
293 case vtkCommand::LeftButtonReleaseEvent:
294 self->OnLeftButtonUp();
296 case vtkCommand::MiddleButtonPressEvent:
297 self->OnMiddleButtonDown();
299 case vtkCommand::MiddleButtonReleaseEvent:
300 self->OnMiddleButtonUp();
302 case vtkCommand::MouseMoveEvent:
309 //====================================================================
310 // function:OnLeftButtonDown
312 //====================================================================
313 void VISU_SphereWidget::OnLeftButtonDown()
315 int X = Interactor->GetEventPosition()[0];
316 int Y = Interactor->GetEventPosition()[1];
318 // Okay, make sure that the pick is in the current renderer
319 vtkRenderer *aRenderer = Interactor->FindPokedRenderer(X,Y);
321 if (aRenderer != CurrentRenderer) {
322 myState = VISU_SphereWidget::Outside;
325 // Okay, we can process this. Try to pick handles first;
326 // if no places picked, then try to pick the sphere.
327 myPicker->Pick(X, Y, 0., CurrentRenderer);
328 if(vtkAssemblyPath *aPath = myPicker->GetPath()){
329 if(aPath->GetFirstNode()->GetProp() == mySphereActor){
330 myState = VISU_SphereWidget::Moving;
334 myState = VISU_SphereWidget::Outside;
338 EventCallbackCommand->SetAbortFlag(1);
340 InvokeEvent(vtkCommand::StartInteractionEvent,NULL);
341 Interactor->Render();
343 //====================================================================
344 // function:OnMouseMove
346 //====================================================================
347 void VISU_SphereWidget::OnMouseMove()
349 // See whether we're active
350 if ( myState == VISU_SphereWidget::Outside ||
351 myState == VISU_SphereWidget::Start ) {
355 int X = Interactor->GetEventPosition()[0];
356 int Y = Interactor->GetEventPosition()[1];
358 // Do different things depending on state
359 // Calculations everybody does
360 double focalPoint[4], pickPoint[4], prevPickPoint[4], z;
362 vtkRenderer *aRenderer=Interactor->FindPokedRenderer(X, Y);
363 vtkCamera *aCamera=aRenderer->GetActiveCamera();
367 // Compute the two points defining the motion vector
368 aCamera->GetFocalPoint(focalPoint);
369 ComputeWorldToDisplay(focalPoint[0],
374 ComputeDisplayToWorld(double(Interactor->GetLastEventPosition()[0]),
375 double(Interactor->GetLastEventPosition()[1]),
378 ComputeDisplayToWorld(double(X), double(Y), z, pickPoint);
380 // Process the motion
381 if ( myState == VISU_SphereWidget::Moving ) {
382 Translate(prevPickPoint, pickPoint);
384 else if ( myState == VISU_SphereWidget::Scaling ) {
385 Scale(prevPickPoint, pickPoint, X, Y);
387 // Interact, if desired
388 EventCallbackCommand->SetAbortFlag(1);
389 InvokeEvent(vtkCommand::InteractionEvent,NULL);
391 Interactor->Render();
393 //====================================================================
394 // function:OnLeftButtonUp
396 //====================================================================
397 void VISU_SphereWidget::OnLeftButtonUp()
399 if ( myState == VISU_SphereWidget::Outside ) {
403 myState = VISU_SphereWidget::Start;
406 EventCallbackCommand->SetAbortFlag(1);
408 InvokeEvent(vtkCommand::EndInteractionEvent,NULL);
410 Interactor->Render();
412 //====================================================================
413 // function:OnMiddleButtonDown
415 //====================================================================
416 void VISU_SphereWidget::OnMiddleButtonDown()
418 myState = VISU_SphereWidget::Scaling;
420 int X = Interactor->GetEventPosition()[0];
421 int Y = Interactor->GetEventPosition()[1];
423 // Okay, make sure that the pick is in the current renderer
424 vtkRenderer *aRenderer = Interactor->FindPokedRenderer(X,Y);
425 if (aRenderer!=CurrentRenderer) {
426 myState = VISU_SphereWidget::Outside;
430 // Okay, we can process this. Try to pick handles first;
431 // if no handles picked, then pick the bounding box.
432 myPicker->Pick(X, Y, 0., CurrentRenderer);
433 vtkAssemblyPath *aPath = myPicker->GetPath();
435 myState=VISU_SphereWidget::Outside;
442 EventCallbackCommand->SetAbortFlag(1);
444 InvokeEvent(vtkCommand::StartInteractionEvent,NULL);
446 Interactor->Render();
448 //====================================================================
449 // function:OnMiddleButtonUp
451 //====================================================================
452 void VISU_SphereWidget::OnMiddleButtonUp()
454 if ( myState == VISU_SphereWidget::Outside ) {
457 myState = VISU_SphereWidget::Start;
460 EventCallbackCommand->SetAbortFlag(1);
462 InvokeEvent(vtkCommand::EndInteractionEvent,NULL);
464 Interactor->Render();
466 //====================================================================
467 // function:Translate
469 //====================================================================
470 void VISU_SphereWidget::Translate(double *p1, double *p2)
472 float v[3], aC[3], aC1[3];
474 v[0] = p2[0] - p1[0];
475 v[1] = p2[1] - p1[1];
476 v[2] = p2[2] - p1[2];
478 mySphereSource->GetCenter(aC);
479 aC1[0] = aC[0] + v[0];
480 aC1[1] = aC[1] + v[1];
481 aC1[2] = aC[2] + v[2];
482 mySphereSource->SetCenter(aC1);
483 mySphere->SetCenter(mySphereSource->GetCenter());
484 mySphere->SetRadius(mySphereSource->GetRadius());
486 //====================================================================
489 //====================================================================
490 void VISU_SphereWidget::Scale(double *p1, double *p2,
494 v[0] = p2[0] - p1[0];
495 v[1] = p2[1] - p1[1];
496 v[2] = p2[2] - p1[2];
498 float aC[3], aR, sf, aR1;
499 aR=mySphereSource->GetRadius();
500 mySphereSource->GetCenter(aC);
501 sf=vtkMath::Norm(v)/aR;
502 int aCoordLast[2], iDX, iDY, iSign;
503 Interactor->GetLastEventPosition(aCoordLast);
505 iDX=aX-aCoordLast[0];
506 iDY=aCoordLast[1]-aY;
507 iSign=(iDX+iDY>0)? 1 : -1;
513 mySphereSource->SetRadius(aR1);
514 mySphere->SetCenter(mySphereSource->GetCenter());
515 mySphere->SetRadius(mySphereSource->GetRadius());
517 //====================================================================
518 // function:GetSphere
520 //====================================================================
521 void VISU_SphereWidget::GetSphere(vtkSphere *sphere)
523 sphere->SetRadius(mySphereSource->GetRadius());
524 sphere->SetCenter(mySphereSource->GetCenter());
526 //====================================================================
527 // function:HighlightSphere
529 //====================================================================
530 void VISU_SphereWidget::HighlightSphere(int highlight)
534 myPicker->GetPickPosition(this->LastPickPosition);// -> def in vtk3DWidget
535 mySphereActor->SetProperty(mySelectedSphereProperty);
538 mySphereActor->SetProperty(mySphereProperty);
541 //====================================================================
542 // function:CreateDefaultProperties
544 //====================================================================
545 void VISU_SphereWidget::CreateDefaultProperties()
547 if (!mySphereProperty) {
548 mySphereProperty = vtkProperty::New();
549 mySphereProperty->SetColor(0.,.5, .7);
550 mySphereProperty->SetSpecular(0.5);
551 mySphereProperty->SetRepresentationToWireframe();
553 if (!mySelectedSphereProperty) {
554 mySelectedSphereProperty = vtkProperty::New();
555 mySelectedSphereProperty->SetColor(0.5, 0.5, 0.);
556 mySelectedSphereProperty->SetSpecular(1.);
557 mySelectedSphereProperty->SetRepresentationToWireframe();
560 //====================================================================
561 // function:PlaceWidget
563 //====================================================================
564 void VISU_SphereWidget::PlaceWidget(float bds[6])
566 float bounds[6], center[3], radius;
568 this->AdjustBounds(bds, bounds, center);
571 dX=bounds[1]-bounds[0];
572 dY=bounds[3]-bounds[2];
573 dZ=bounds[5]-bounds[4];
583 mySphereSource->SetCenter(center);
584 mySphereSource->SetRadius(radius);
585 mySphereSource->Update();
587 for (int i=0; i<6; i++) {
588 InitialBounds[i]=bounds[i];
590 InitialLength = sqrt((bounds[1]-bounds[0])*(bounds[1]-bounds[0]) +
591 (bounds[3]-bounds[2])*(bounds[3]-bounds[2]) +
592 (bounds[5]-bounds[4])*(bounds[5]-bounds[4]));
594 static float EPS = 1.0E-1;
595 myRmin = EPS*InitialLength;
599 //====================================================================
600 // function:ChangeRadius
602 //====================================================================
603 void VISU_SphereWidget::ChangeRadius(bool up)
605 SetRadius( GetRadius() * ( up ? myRatio : 1 / myRatio ) );
607 //====================================================================
608 // function:GetPolyData
610 //====================================================================
611 void VISU_SphereWidget::GetPolyData(vtkPolyData *pd)
613 pd->ShallowCopy(mySphereSource->GetOutput());
615 //====================================================================
616 // function:PrintSelf
618 //====================================================================
619 void VISU_SphereWidget::PrintSelf(ostream& os, vtkIndent indent)
621 this->Superclass::PrintSelf(os,indent);