1 // Copyright (C) 2005 OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,
2 // CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS
4 // This library is free software; you can redistribute it and/or
5 // modify it under the terms of the GNU Lesser General Public
6 // License as published by the Free Software Foundation; either
7 // version 2.1 of the License.
9 // This library is distributed in the hope that it will be useful
10 // but WITHOUT ANY WARRANTY; without even the implied warranty of
11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 // Lesser General Public License for more details.
14 // You should have received a copy of the GNU Lesser General Public
15 // License along with this library; if not, write to the Free Software
16 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
20 #include "VISU_SphereWidget.hxx"
23 #include <vtkAssemblyNode.h>
24 #include <vtkAssemblyPath.h>
25 #include <vtkCallbackCommand.h>
26 #include <vtkCamera.h>
27 #include <vtkCellPicker.h>
28 #include <vtkDoubleArray.h>
30 #include <vtkObjectFactory.h>
31 #include <vtkPolyData.h>
32 #include <vtkPolyDataMapper.h>
33 #include <vtkProperty.h>
34 #include <vtkRenderWindowInteractor.h>
35 #include <vtkRenderer.h>
36 #include <vtkSphere.h>
37 #include <vtkSphereSource.h>
38 #include <vtkPoints.h>
39 #include <vtkSphere.h>
40 #include <vtkImplicitSum.h>
41 #include <vtkImplicitFunction.h>
43 vtkCxxRevisionMacro(VISU_SphereWidget, "$Revision$");
44 vtkStandardNewMacro(VISU_SphereWidget);
45 //====================================================================
48 //====================================================================
49 VISU_SphereWidget::VISU_SphereWidget()
51 myState = VISU_SphereWidget::Start;
52 this->EventCallbackCommand->SetCallback(VISU_SphereWidget::ProcessEvents);
54 //Build the representation of the widget
55 mySphereSource = vtkSphereSource::New();
56 mySphereSource->SetThetaResolution(16);
57 mySphereSource->SetPhiResolution(15);
58 mySphereSource->LatLongTessellationOn();
59 mySphereMapper = vtkPolyDataMapper::New();
60 mySphereMapper->SetInput(mySphereSource->GetOutput());
61 mySphereActor = vtkActor::New();
62 mySphereActor->SetMapper(mySphereMapper);
64 // Define the point coordinates
65 vtkFloatingPointType bounds[6];
66 for(int i = 0; i < 6; i += 2){
68 bounds[i+1]=-bounds[i];
70 // Initial creation of the widget, serves to initialize it
73 //Manage the picking stuff
74 myPicker = vtkCellPicker::New();
75 myPicker->SetTolerance(0.005); //need some fluff
76 myPicker->AddPickList(mySphereActor);
77 myPicker->PickFromListOn();
79 // Set up the initial properties
80 mySphereProperty = NULL;
81 mySelectedSphereProperty = NULL;
82 CreateDefaultProperties();
85 mySphere=vtkSphere::New();
86 myImplicitSum=vtkImplicitSum::New();
87 myImplicitSum->AddFunction(mySphere,-1.0);
91 //====================================================================
94 //====================================================================
95 VISU_SphereWidget::~VISU_SphereWidget()
97 mySphereActor->Delete();
98 mySphereMapper->Delete();
99 mySphereSource->Delete();
103 if ( mySphereProperty ) {
104 mySphereProperty->Delete();
106 if ( mySelectedSphereProperty ) {
107 mySelectedSphereProperty->Delete();
110 myImplicitSum->Delete();
112 //====================================================================
113 // function: SetThetaResolution
115 //====================================================================
116 void VISU_SphereWidget::SetThetaResolution(int r)
118 mySphereSource->SetThetaResolution(r);
120 //====================================================================
121 // function: GetThetaResolution
123 //====================================================================
124 int VISU_SphereWidget::GetThetaResolution()
126 return mySphereSource->GetThetaResolution();
128 //====================================================================
129 // function: SetPhiResolution
131 //====================================================================
132 void VISU_SphereWidget::SetPhiResolution(int r)
134 mySphereSource->SetPhiResolution(r);
136 //====================================================================
137 // function: SetPhiResolution
139 //====================================================================
140 int VISU_SphereWidget::GetPhiResolution()
142 return mySphereSource->GetPhiResolution();
144 //====================================================================
145 // function: SetRadius
147 //====================================================================
148 void VISU_SphereWidget::SetRadius(vtkFloatingPointType theRadius)
150 if ( theRadius <= myRmin ) {
153 mySphereSource->SetRadius(theRadius);
154 mySphere->SetRadius(theRadius);
156 //====================================================================
157 // function: GetRadius
159 //====================================================================
160 vtkFloatingPointType VISU_SphereWidget::GetRadius()
162 return mySphereSource->GetRadius();
164 //====================================================================
165 // function: SetCenter
167 //====================================================================
168 void VISU_SphereWidget::SetCenter(vtkFloatingPointType theCenter[3])
170 mySphereSource->SetCenter(theCenter);
171 mySphere->SetCenter(theCenter);
173 //====================================================================
174 // function: SetCenter
176 //====================================================================
177 void VISU_SphereWidget::SetCenter(vtkFloatingPointType theX, vtkFloatingPointType theY, vtkFloatingPointType theZ)
179 vtkFloatingPointType aCenter[3] = {theX, theY, theZ};
183 //====================================================================
184 // function: GetCenter
186 //====================================================================
187 vtkFloatingPointType* VISU_SphereWidget::GetCenter()
189 return mySphereSource->GetCenter();
191 //====================================================================
192 // function: GetCenter
194 //====================================================================
195 void VISU_SphereWidget::GetCenter(vtkFloatingPointType theCenter[3])
197 mySphereSource->GetCenter(theCenter);
199 //====================================================================
200 // function: GetSphereProperty
202 //====================================================================
203 vtkProperty* VISU_SphereWidget::GetSphereProperty ()
205 return mySphereProperty;
207 //====================================================================
208 // function: GetSelectedSphereProperty
210 //====================================================================
211 vtkProperty* VISU_SphereWidget::GetSelectedSphereProperty ()
213 return mySelectedSphereProperty;
215 //====================================================================
216 // function: ImplicitFunction
218 //====================================================================
219 vtkImplicitFunction* VISU_SphereWidget::ImplicitFunction()
221 return myImplicitSum;
223 //====================================================================
224 // function: SetEnabled
226 //====================================================================
227 void VISU_SphereWidget::SetEnabled(int enabling)
230 vtkErrorMacro(<<"The interactor must be set prior to enabling/disabling widget");
235 vtkDebugMacro(<<"Enabling sphere widget");
236 if ( Enabled ) {//already enabled, just return
240 if ( ! CurrentRenderer ) {
242 Interactor->GetLastEventPosition(aPos);
243 CurrentRenderer=Interactor->FindPokedRenderer(aPos[0], aPos[1]);
244 if (!CurrentRenderer) {
251 // listen for the following events
252 Interactor->AddObserver(vtkCommand::MouseMoveEvent,
253 EventCallbackCommand,
255 Interactor->AddObserver(vtkCommand::LeftButtonPressEvent,
256 EventCallbackCommand,
258 Interactor->AddObserver(vtkCommand::LeftButtonReleaseEvent,
259 EventCallbackCommand,
261 Interactor->AddObserver(vtkCommand::MiddleButtonPressEvent,
262 EventCallbackCommand,
264 Interactor->AddObserver(vtkCommand::MiddleButtonReleaseEvent,
265 EventCallbackCommand,
269 CurrentRenderer->AddActor(mySphereActor);
270 mySphereActor->SetProperty(mySphereProperty);
271 mySphere->SetCenter(mySphereSource->GetCenter());
272 mySphere->SetRadius(mySphereSource->GetRadius());
274 InvokeEvent(vtkCommand::EnableEvent,NULL); //!!!see what will be done
276 //disabling----------------------------------------------------------
278 vtkDebugMacro(<<"Disabling sphere widget");
280 if ( !Enabled ){ //already disabled, just return
286 // don't listen for events any more
287 Interactor->RemoveObserver(EventCallbackCommand);
289 // turn off the sphere
290 CurrentRenderer->RemoveActor(mySphereActor);
291 InvokeEvent(vtkCommand::DisableEvent,NULL);
292 CurrentRenderer = NULL;
295 Interactor->Render();
297 //====================================================================
298 // function:ProcessEvents
300 //====================================================================
301 void VISU_SphereWidget::ProcessEvents(vtkObject* vtkNotUsed(object),
304 void* vtkNotUsed(calldata))
306 VISU_SphereWidget* self = reinterpret_cast<VISU_SphereWidget *>( clientdata );
309 case vtkCommand::LeftButtonPressEvent:
310 self->OnLeftButtonDown();
312 case vtkCommand::LeftButtonReleaseEvent:
313 self->OnLeftButtonUp();
315 case vtkCommand::MiddleButtonPressEvent:
316 self->OnMiddleButtonDown();
318 case vtkCommand::MiddleButtonReleaseEvent:
319 self->OnMiddleButtonUp();
321 case vtkCommand::MouseMoveEvent:
328 //====================================================================
329 // function:OnLeftButtonDown
331 //====================================================================
332 void VISU_SphereWidget::OnLeftButtonDown()
334 int X = Interactor->GetEventPosition()[0];
335 int Y = Interactor->GetEventPosition()[1];
337 // Okay, make sure that the pick is in the current renderer
338 vtkRenderer *aRenderer = Interactor->FindPokedRenderer(X,Y);
340 if (aRenderer != CurrentRenderer) {
341 myState = VISU_SphereWidget::Outside;
344 // Okay, we can process this. Try to pick handles first;
345 // if no places picked, then try to pick the sphere.
346 myPicker->Pick(X, Y, 0., CurrentRenderer);
347 if(vtkAssemblyPath *aPath = myPicker->GetPath()){
348 if(aPath->GetFirstNode()->GetProp() == mySphereActor){
349 myState = VISU_SphereWidget::Moving;
353 myState = VISU_SphereWidget::Outside;
357 EventCallbackCommand->SetAbortFlag(1);
359 InvokeEvent(vtkCommand::StartInteractionEvent,NULL);
360 Interactor->Render();
362 //====================================================================
363 // function:OnMouseMove
365 //====================================================================
366 void VISU_SphereWidget::OnMouseMove()
368 // See whether we're active
369 if ( myState == VISU_SphereWidget::Outside ||
370 myState == VISU_SphereWidget::Start ) {
374 int X = Interactor->GetEventPosition()[0];
375 int Y = Interactor->GetEventPosition()[1];
377 // Do different things depending on state
378 // Calculations everybody does
379 double focalPoint[4], pickPoint[4], prevPickPoint[4], z;
381 vtkRenderer *aRenderer=Interactor->FindPokedRenderer(X, Y);
382 vtkCamera *aCamera=aRenderer->GetActiveCamera();
386 // Compute the two points defining the motion vector
387 aCamera->GetFocalPoint(focalPoint);
388 ComputeWorldToDisplay(focalPoint[0],
393 ComputeDisplayToWorld(double(Interactor->GetLastEventPosition()[0]),
394 double(Interactor->GetLastEventPosition()[1]),
397 ComputeDisplayToWorld(double(X), double(Y), z, pickPoint);
399 // Process the motion
400 if ( myState == VISU_SphereWidget::Moving ) {
401 Translate(prevPickPoint, pickPoint);
403 else if ( myState == VISU_SphereWidget::Scaling ) {
404 Scale(prevPickPoint, pickPoint, X, Y);
406 // Interact, if desired
407 EventCallbackCommand->SetAbortFlag(1);
408 InvokeEvent(vtkCommand::InteractionEvent,NULL);
410 Interactor->Render();
412 //====================================================================
413 // function:OnLeftButtonUp
415 //====================================================================
416 void VISU_SphereWidget::OnLeftButtonUp()
418 if ( myState == VISU_SphereWidget::Outside ) {
422 myState = VISU_SphereWidget::Start;
425 EventCallbackCommand->SetAbortFlag(1);
427 InvokeEvent(vtkCommand::EndInteractionEvent,NULL);
429 Interactor->Render();
431 //====================================================================
432 // function:OnMiddleButtonDown
434 //====================================================================
435 void VISU_SphereWidget::OnMiddleButtonDown()
437 myState = VISU_SphereWidget::Scaling;
439 int X = Interactor->GetEventPosition()[0];
440 int Y = Interactor->GetEventPosition()[1];
442 // Okay, make sure that the pick is in the current renderer
443 vtkRenderer *aRenderer = Interactor->FindPokedRenderer(X,Y);
444 if (aRenderer!=CurrentRenderer) {
445 myState = VISU_SphereWidget::Outside;
449 // Okay, we can process this. Try to pick handles first;
450 // if no handles picked, then pick the bounding box.
451 myPicker->Pick(X, Y, 0., CurrentRenderer);
452 vtkAssemblyPath *aPath = myPicker->GetPath();
454 myState=VISU_SphereWidget::Outside;
461 EventCallbackCommand->SetAbortFlag(1);
463 InvokeEvent(vtkCommand::StartInteractionEvent,NULL);
465 Interactor->Render();
467 //====================================================================
468 // function:OnMiddleButtonUp
470 //====================================================================
471 void VISU_SphereWidget::OnMiddleButtonUp()
473 if ( myState == VISU_SphereWidget::Outside ) {
476 myState = VISU_SphereWidget::Start;
479 EventCallbackCommand->SetAbortFlag(1);
481 InvokeEvent(vtkCommand::EndInteractionEvent,NULL);
483 Interactor->Render();
485 //====================================================================
486 // function:Translate
488 //====================================================================
489 void VISU_SphereWidget::Translate(double *p1, double *p2)
491 vtkFloatingPointType v[3], aC[3], aC1[3];
493 v[0] = p2[0] - p1[0];
494 v[1] = p2[1] - p1[1];
495 v[2] = p2[2] - p1[2];
497 mySphereSource->GetCenter(aC);
498 aC1[0] = aC[0] + v[0];
499 aC1[1] = aC[1] + v[1];
500 aC1[2] = aC[2] + v[2];
501 mySphereSource->SetCenter(aC1);
502 mySphere->SetCenter(mySphereSource->GetCenter());
503 mySphere->SetRadius(mySphereSource->GetRadius());
505 //====================================================================
508 //====================================================================
509 void VISU_SphereWidget::Scale(double *p1, double *p2,
513 v[0] = p2[0] - p1[0];
514 v[1] = p2[1] - p1[1];
515 v[2] = p2[2] - p1[2];
517 vtkFloatingPointType aC[3], aR, sf, aR1;
518 aR=mySphereSource->GetRadius();
519 mySphereSource->GetCenter(aC);
520 sf=vtkMath::Norm(v)/aR;
521 int aCoordLast[2], iDX, iDY, iSign;
522 Interactor->GetLastEventPosition(aCoordLast);
524 iDX=aX-aCoordLast[0];
525 iDY=aCoordLast[1]-aY;
526 iSign=(iDX+iDY>0)? 1 : -1;
532 mySphereSource->SetRadius(aR1);
533 mySphere->SetCenter(mySphereSource->GetCenter());
534 mySphere->SetRadius(mySphereSource->GetRadius());
536 //====================================================================
537 // function:GetSphere
539 //====================================================================
540 void VISU_SphereWidget::GetSphere(vtkSphere *sphere)
542 sphere->SetRadius(mySphereSource->GetRadius());
543 sphere->SetCenter(mySphereSource->GetCenter());
545 //====================================================================
546 // function:HighlightSphere
548 //====================================================================
549 void VISU_SphereWidget::HighlightSphere(int highlight)
553 myPicker->GetPickPosition(this->LastPickPosition);// -> def in vtk3DWidget
554 mySphereActor->SetProperty(mySelectedSphereProperty);
557 mySphereActor->SetProperty(mySphereProperty);
560 //====================================================================
561 // function:CreateDefaultProperties
563 //====================================================================
564 void VISU_SphereWidget::CreateDefaultProperties()
566 if (!mySphereProperty) {
567 mySphereProperty = vtkProperty::New();
568 mySphereProperty->SetColor(0.,.5, .7);
569 mySphereProperty->SetSpecular(0.5);
570 mySphereProperty->SetRepresentationToWireframe();
572 if (!mySelectedSphereProperty) {
573 mySelectedSphereProperty = vtkProperty::New();
574 mySelectedSphereProperty->SetColor(0.5, 0.5, 0.);
575 mySelectedSphereProperty->SetSpecular(1.);
576 mySelectedSphereProperty->SetRepresentationToWireframe();
579 //====================================================================
580 // function:PlaceWidget
582 //====================================================================
583 void VISU_SphereWidget::PlaceWidget(vtkFloatingPointType bds[6])
585 vtkFloatingPointType bounds[6], center[3], radius;
587 this->AdjustBounds(bds, bounds, center);
588 vtkFloatingPointType dX, dY, dZ;
590 dX=bounds[1]-bounds[0];
591 dY=bounds[3]-bounds[2];
592 dZ=bounds[5]-bounds[4];
602 mySphereSource->SetCenter(center);
603 mySphereSource->SetRadius(radius);
604 mySphereSource->Update();
606 for (int i=0; i<6; i++) {
607 InitialBounds[i]=bounds[i];
609 InitialLength = sqrt((bounds[1]-bounds[0])*(bounds[1]-bounds[0]) +
610 (bounds[3]-bounds[2])*(bounds[3]-bounds[2]) +
611 (bounds[5]-bounds[4])*(bounds[5]-bounds[4]));
613 static vtkFloatingPointType EPS = 1.0E-1;
614 myRmin = EPS*InitialLength;
618 //====================================================================
619 // function:ChangeRadius
621 //====================================================================
622 void VISU_SphereWidget::ChangeRadius(bool up)
624 SetRadius( GetRadius() * ( up ? myRatio : 1 / myRatio ) );
626 //====================================================================
627 // function:GetPolyData
629 //====================================================================
630 void VISU_SphereWidget::GetPolyData(vtkPolyData *pd)
632 pd->ShallowCopy(mySphereSource->GetOutput());
634 //====================================================================
635 // function:PrintSelf
637 //====================================================================
638 void VISU_SphereWidget::PrintSelf(ostream& os, vtkIndent indent)
640 this->Superclass::PrintSelf(os,indent);