1 // Copyright (C) 2007-2008 CEA/DEN, EDF R&D, OPEN CASCADE
3 // Copyright (C) 2003-2007 OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,
4 // CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS
6 // This library is free software; you can redistribute it and/or
7 // modify it under the terms of the GNU Lesser General Public
8 // License as published by the Free Software Foundation; either
9 // version 2.1 of the License.
11 // This library is distributed in the hope that it will be useful,
12 // but WITHOUT ANY WARRANTY; without even the implied warranty of
13 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 // Lesser General Public License for more details.
16 // You should have received a copy of the GNU Lesser General Public
17 // License along with this library; if not, write to the Free Software
18 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
22 #include "VISU_SphereWidget.hxx"
25 #include <vtkAssemblyNode.h>
26 #include <vtkAssemblyPath.h>
27 #include <vtkCallbackCommand.h>
28 #include <vtkCamera.h>
29 #include <vtkCellPicker.h>
30 #include <vtkDoubleArray.h>
32 #include <vtkObjectFactory.h>
33 #include <vtkPolyData.h>
34 #include <vtkPolyDataMapper.h>
35 #include <vtkProperty.h>
36 #include <vtkRenderWindowInteractor.h>
37 #include <vtkRenderer.h>
38 #include <vtkSphere.h>
39 #include <vtkSphereSource.h>
40 #include <vtkPoints.h>
41 #include <vtkSphere.h>
42 #include <vtkImplicitSum.h>
43 #include <vtkImplicitFunction.h>
45 vtkCxxRevisionMacro(VISU_SphereWidget, "$Revision$");
46 vtkStandardNewMacro(VISU_SphereWidget);
47 //====================================================================
50 //====================================================================
51 VISU_SphereWidget::VISU_SphereWidget()
53 myState = VISU_SphereWidget::Start;
54 this->EventCallbackCommand->SetCallback(VISU_SphereWidget::ProcessEvents);
56 //Build the representation of the widget
57 mySphereSource = vtkSphereSource::New();
58 mySphereSource->SetThetaResolution(16);
59 mySphereSource->SetPhiResolution(15);
60 mySphereSource->LatLongTessellationOn();
61 mySphereMapper = vtkPolyDataMapper::New();
62 mySphereMapper->SetInput(mySphereSource->GetOutput());
63 mySphereActor = vtkActor::New();
64 mySphereActor->SetMapper(mySphereMapper);
66 // Define the point coordinates
67 vtkFloatingPointType bounds[6];
68 for(int i = 0; i < 6; i += 2){
70 bounds[i+1]=-bounds[i];
72 // Initial creation of the widget, serves to initialize it
75 //Manage the picking stuff
76 myPicker = vtkCellPicker::New();
77 myPicker->SetTolerance(0.005); //need some fluff
78 myPicker->AddPickList(mySphereActor);
79 myPicker->PickFromListOn();
81 // Set up the initial properties
82 mySphereProperty = NULL;
83 mySelectedSphereProperty = NULL;
84 CreateDefaultProperties();
87 mySphere=vtkSphere::New();
88 myImplicitSum=vtkImplicitSum::New();
89 myImplicitSum->AddFunction(mySphere,-1.0);
93 //====================================================================
96 //====================================================================
97 VISU_SphereWidget::~VISU_SphereWidget()
99 mySphereActor->Delete();
100 mySphereMapper->Delete();
101 mySphereSource->Delete();
105 if ( mySphereProperty ) {
106 mySphereProperty->Delete();
108 if ( mySelectedSphereProperty ) {
109 mySelectedSphereProperty->Delete();
112 myImplicitSum->Delete();
114 //====================================================================
115 // function: SetThetaResolution
117 //====================================================================
118 void VISU_SphereWidget::SetThetaResolution(int r)
120 mySphereSource->SetThetaResolution(r);
122 //====================================================================
123 // function: GetThetaResolution
125 //====================================================================
126 int VISU_SphereWidget::GetThetaResolution()
128 return mySphereSource->GetThetaResolution();
130 //====================================================================
131 // function: SetPhiResolution
133 //====================================================================
134 void VISU_SphereWidget::SetPhiResolution(int r)
136 mySphereSource->SetPhiResolution(r);
138 //====================================================================
139 // function: SetPhiResolution
141 //====================================================================
142 int VISU_SphereWidget::GetPhiResolution()
144 return mySphereSource->GetPhiResolution();
146 //====================================================================
147 // function: SetRadius
149 //====================================================================
150 void VISU_SphereWidget::SetRadius(vtkFloatingPointType theRadius)
152 if ( theRadius <= myRmin ) {
155 mySphereSource->SetRadius(theRadius);
156 mySphere->SetRadius(theRadius);
158 //====================================================================
159 // function: GetRadius
161 //====================================================================
162 vtkFloatingPointType VISU_SphereWidget::GetRadius()
164 return mySphereSource->GetRadius();
166 //====================================================================
167 // function: SetCenter
169 //====================================================================
170 void VISU_SphereWidget::SetCenter(vtkFloatingPointType theCenter[3])
172 mySphereSource->SetCenter(theCenter);
173 mySphere->SetCenter(theCenter);
175 //====================================================================
176 // function: SetCenter
178 //====================================================================
179 void VISU_SphereWidget::SetCenter(vtkFloatingPointType theX, vtkFloatingPointType theY, vtkFloatingPointType theZ)
181 vtkFloatingPointType aCenter[3] = {theX, theY, theZ};
185 //====================================================================
186 // function: GetCenter
188 //====================================================================
189 vtkFloatingPointType* VISU_SphereWidget::GetCenter()
191 return mySphereSource->GetCenter();
193 //====================================================================
194 // function: GetCenter
196 //====================================================================
197 void VISU_SphereWidget::GetCenter(vtkFloatingPointType theCenter[3])
199 mySphereSource->GetCenter(theCenter);
201 //====================================================================
202 // function: GetSphereProperty
204 //====================================================================
205 vtkProperty* VISU_SphereWidget::GetSphereProperty ()
207 return mySphereProperty;
209 //====================================================================
210 // function: GetSelectedSphereProperty
212 //====================================================================
213 vtkProperty* VISU_SphereWidget::GetSelectedSphereProperty ()
215 return mySelectedSphereProperty;
217 //====================================================================
218 // function: ImplicitFunction
220 //====================================================================
221 vtkImplicitFunction* VISU_SphereWidget::ImplicitFunction()
223 return myImplicitSum;
225 //====================================================================
226 // function: SetEnabled
228 //====================================================================
229 void VISU_SphereWidget::SetEnabled(int enabling)
232 vtkErrorMacro(<<"The interactor must be set prior to enabling/disabling widget");
237 vtkDebugMacro(<<"Enabling sphere widget");
238 if ( Enabled ) {//already enabled, just return
242 if ( ! CurrentRenderer ) {
244 Interactor->GetLastEventPosition(aPos);
245 CurrentRenderer=Interactor->FindPokedRenderer(aPos[0], aPos[1]);
246 if (!CurrentRenderer) {
253 // listen for the following events
254 Interactor->AddObserver(vtkCommand::MouseMoveEvent,
255 EventCallbackCommand,
257 Interactor->AddObserver(vtkCommand::LeftButtonPressEvent,
258 EventCallbackCommand,
260 Interactor->AddObserver(vtkCommand::LeftButtonReleaseEvent,
261 EventCallbackCommand,
263 Interactor->AddObserver(vtkCommand::MiddleButtonPressEvent,
264 EventCallbackCommand,
266 Interactor->AddObserver(vtkCommand::MiddleButtonReleaseEvent,
267 EventCallbackCommand,
271 CurrentRenderer->AddActor(mySphereActor);
272 mySphereActor->SetProperty(mySphereProperty);
273 mySphere->SetCenter(mySphereSource->GetCenter());
274 mySphere->SetRadius(mySphereSource->GetRadius());
276 InvokeEvent(vtkCommand::EnableEvent,NULL); //!!!see what will be done
278 //disabling----------------------------------------------------------
280 vtkDebugMacro(<<"Disabling sphere widget");
282 if ( !Enabled ){ //already disabled, just return
288 // don't listen for events any more
289 Interactor->RemoveObserver(EventCallbackCommand);
291 // turn off the sphere
292 CurrentRenderer->RemoveActor(mySphereActor);
293 InvokeEvent(vtkCommand::DisableEvent,NULL);
294 CurrentRenderer = NULL;
297 Interactor->Render();
299 //====================================================================
300 // function:ProcessEvents
302 //====================================================================
303 void VISU_SphereWidget::ProcessEvents(vtkObject* vtkNotUsed(object),
306 void* vtkNotUsed(calldata))
308 VISU_SphereWidget* self = reinterpret_cast<VISU_SphereWidget *>( clientdata );
311 case vtkCommand::LeftButtonPressEvent:
312 self->OnLeftButtonDown();
314 case vtkCommand::LeftButtonReleaseEvent:
315 self->OnLeftButtonUp();
317 case vtkCommand::MiddleButtonPressEvent:
318 self->OnMiddleButtonDown();
320 case vtkCommand::MiddleButtonReleaseEvent:
321 self->OnMiddleButtonUp();
323 case vtkCommand::MouseMoveEvent:
330 //====================================================================
331 // function:OnLeftButtonDown
333 //====================================================================
334 void VISU_SphereWidget::OnLeftButtonDown()
336 int X = Interactor->GetEventPosition()[0];
337 int Y = Interactor->GetEventPosition()[1];
339 // Okay, make sure that the pick is in the current renderer
340 vtkRenderer *aRenderer = Interactor->FindPokedRenderer(X,Y);
342 if (aRenderer != CurrentRenderer) {
343 myState = VISU_SphereWidget::Outside;
346 // Okay, we can process this. Try to pick handles first;
347 // if no places picked, then try to pick the sphere.
348 myPicker->Pick(X, Y, 0., CurrentRenderer);
349 if(vtkAssemblyPath *aPath = myPicker->GetPath()){
350 if(aPath->GetFirstNode()->GetProp() == mySphereActor){
351 myState = VISU_SphereWidget::Moving;
355 myState = VISU_SphereWidget::Outside;
359 EventCallbackCommand->SetAbortFlag(1);
361 InvokeEvent(vtkCommand::StartInteractionEvent,NULL);
362 Interactor->Render();
364 //====================================================================
365 // function:OnMouseMove
367 //====================================================================
368 void VISU_SphereWidget::OnMouseMove()
370 // See whether we're active
371 if ( myState == VISU_SphereWidget::Outside ||
372 myState == VISU_SphereWidget::Start ) {
376 int X = Interactor->GetEventPosition()[0];
377 int Y = Interactor->GetEventPosition()[1];
379 // Do different things depending on state
380 // Calculations everybody does
381 double focalPoint[4], pickPoint[4], prevPickPoint[4], z;
383 vtkRenderer *aRenderer=Interactor->FindPokedRenderer(X, Y);
384 vtkCamera *aCamera=aRenderer->GetActiveCamera();
388 // Compute the two points defining the motion vector
389 aCamera->GetFocalPoint(focalPoint);
390 ComputeWorldToDisplay(focalPoint[0],
395 ComputeDisplayToWorld(double(Interactor->GetLastEventPosition()[0]),
396 double(Interactor->GetLastEventPosition()[1]),
399 ComputeDisplayToWorld(double(X), double(Y), z, pickPoint);
401 // Process the motion
402 if ( myState == VISU_SphereWidget::Moving ) {
403 Translate(prevPickPoint, pickPoint);
405 else if ( myState == VISU_SphereWidget::Scaling ) {
406 Scale(prevPickPoint, pickPoint, X, Y);
408 // Interact, if desired
409 EventCallbackCommand->SetAbortFlag(1);
410 InvokeEvent(vtkCommand::InteractionEvent,NULL);
412 Interactor->Render();
414 //====================================================================
415 // function:OnLeftButtonUp
417 //====================================================================
418 void VISU_SphereWidget::OnLeftButtonUp()
420 if ( myState == VISU_SphereWidget::Outside ) {
424 myState = VISU_SphereWidget::Start;
427 EventCallbackCommand->SetAbortFlag(1);
429 InvokeEvent(vtkCommand::EndInteractionEvent,NULL);
431 Interactor->Render();
433 //====================================================================
434 // function:OnMiddleButtonDown
436 //====================================================================
437 void VISU_SphereWidget::OnMiddleButtonDown()
439 myState = VISU_SphereWidget::Scaling;
441 int X = Interactor->GetEventPosition()[0];
442 int Y = Interactor->GetEventPosition()[1];
444 // Okay, make sure that the pick is in the current renderer
445 vtkRenderer *aRenderer = Interactor->FindPokedRenderer(X,Y);
446 if (aRenderer!=CurrentRenderer) {
447 myState = VISU_SphereWidget::Outside;
451 // Okay, we can process this. Try to pick handles first;
452 // if no handles picked, then pick the bounding box.
453 myPicker->Pick(X, Y, 0., CurrentRenderer);
454 vtkAssemblyPath *aPath = myPicker->GetPath();
456 myState=VISU_SphereWidget::Outside;
463 EventCallbackCommand->SetAbortFlag(1);
465 InvokeEvent(vtkCommand::StartInteractionEvent,NULL);
467 Interactor->Render();
469 //====================================================================
470 // function:OnMiddleButtonUp
472 //====================================================================
473 void VISU_SphereWidget::OnMiddleButtonUp()
475 if ( myState == VISU_SphereWidget::Outside ) {
478 myState = VISU_SphereWidget::Start;
481 EventCallbackCommand->SetAbortFlag(1);
483 InvokeEvent(vtkCommand::EndInteractionEvent,NULL);
485 Interactor->Render();
487 //====================================================================
488 // function:Translate
490 //====================================================================
491 void VISU_SphereWidget::Translate(double *p1, double *p2)
493 vtkFloatingPointType v[3], aC[3], aC1[3];
495 v[0] = p2[0] - p1[0];
496 v[1] = p2[1] - p1[1];
497 v[2] = p2[2] - p1[2];
499 mySphereSource->GetCenter(aC);
500 aC1[0] = aC[0] + v[0];
501 aC1[1] = aC[1] + v[1];
502 aC1[2] = aC[2] + v[2];
503 mySphereSource->SetCenter(aC1);
504 mySphere->SetCenter(mySphereSource->GetCenter());
505 mySphere->SetRadius(mySphereSource->GetRadius());
507 //====================================================================
510 //====================================================================
511 void VISU_SphereWidget::Scale(double *p1, double *p2,
515 v[0] = p2[0] - p1[0];
516 v[1] = p2[1] - p1[1];
517 v[2] = p2[2] - p1[2];
519 vtkFloatingPointType aC[3], aR, sf, aR1;
520 aR=mySphereSource->GetRadius();
521 mySphereSource->GetCenter(aC);
522 sf=vtkMath::Norm(v)/aR;
523 int aCoordLast[2], iDX, iDY, iSign;
524 Interactor->GetLastEventPosition(aCoordLast);
526 iDX=aX-aCoordLast[0];
527 iDY=aCoordLast[1]-aY;
528 iSign=(iDX+iDY>0)? 1 : -1;
534 mySphereSource->SetRadius(aR1);
535 mySphere->SetCenter(mySphereSource->GetCenter());
536 mySphere->SetRadius(mySphereSource->GetRadius());
538 //====================================================================
539 // function:GetSphere
541 //====================================================================
542 void VISU_SphereWidget::GetSphere(vtkSphere *sphere)
544 sphere->SetRadius(mySphereSource->GetRadius());
545 sphere->SetCenter(mySphereSource->GetCenter());
547 //====================================================================
548 // function:HighlightSphere
550 //====================================================================
551 void VISU_SphereWidget::HighlightSphere(int highlight)
555 myPicker->GetPickPosition(this->LastPickPosition);// -> def in vtk3DWidget
556 mySphereActor->SetProperty(mySelectedSphereProperty);
559 mySphereActor->SetProperty(mySphereProperty);
562 //====================================================================
563 // function:CreateDefaultProperties
565 //====================================================================
566 void VISU_SphereWidget::CreateDefaultProperties()
568 if (!mySphereProperty) {
569 mySphereProperty = vtkProperty::New();
570 mySphereProperty->SetColor(0.,.5, .7);
571 mySphereProperty->SetSpecular(0.5);
572 mySphereProperty->SetRepresentationToWireframe();
574 if (!mySelectedSphereProperty) {
575 mySelectedSphereProperty = vtkProperty::New();
576 mySelectedSphereProperty->SetColor(0.5, 0.5, 0.);
577 mySelectedSphereProperty->SetSpecular(1.);
578 mySelectedSphereProperty->SetRepresentationToWireframe();
581 //====================================================================
582 // function:PlaceWidget
584 //====================================================================
585 void VISU_SphereWidget::PlaceWidget(vtkFloatingPointType bds[6])
587 vtkFloatingPointType bounds[6], center[3], radius;
589 this->AdjustBounds(bds, bounds, center);
590 vtkFloatingPointType dX, dY, dZ;
592 dX=bounds[1]-bounds[0];
593 dY=bounds[3]-bounds[2];
594 dZ=bounds[5]-bounds[4];
604 mySphereSource->SetCenter(center);
605 mySphereSource->SetRadius(radius);
606 mySphereSource->Update();
608 for (int i=0; i<6; i++) {
609 InitialBounds[i]=bounds[i];
611 InitialLength = sqrt((bounds[1]-bounds[0])*(bounds[1]-bounds[0]) +
612 (bounds[3]-bounds[2])*(bounds[3]-bounds[2]) +
613 (bounds[5]-bounds[4])*(bounds[5]-bounds[4]));
615 static vtkFloatingPointType EPS = 1.0E-1;
616 myRmin = EPS*InitialLength;
620 //====================================================================
621 // function:ChangeRadius
623 //====================================================================
624 void VISU_SphereWidget::ChangeRadius(bool up)
626 SetRadius( GetRadius() * ( up ? myRatio : 1 / myRatio ) );
628 //====================================================================
629 // function:GetPolyData
631 //====================================================================
632 void VISU_SphereWidget::GetPolyData(vtkPolyData *pd)
634 pd->ShallowCopy(mySphereSource->GetOutput());
636 //====================================================================
637 // function:PrintSelf
639 //====================================================================
640 void VISU_SphereWidget::PrintSelf(ostream& os, vtkIndent indent)
642 this->Superclass::PrintSelf(os,indent);