1 // Copyright (C) 2007-2010 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
23 #include "VISU_SphereWidget.hxx"
26 #include <vtkAssemblyNode.h>
27 #include <vtkAssemblyPath.h>
28 #include <vtkCallbackCommand.h>
29 #include <vtkCamera.h>
30 #include <vtkCellPicker.h>
31 #include <vtkDoubleArray.h>
33 #include <vtkObjectFactory.h>
34 #include <vtkPolyData.h>
35 #include <vtkPolyDataMapper.h>
36 #include <vtkProperty.h>
37 #include <vtkRenderWindowInteractor.h>
38 #include <vtkRenderer.h>
39 #include <vtkSphere.h>
40 #include <vtkSphereSource.h>
41 #include <vtkPoints.h>
42 #include <vtkSphere.h>
43 #include <vtkImplicitSum.h>
44 #include <vtkImplicitFunction.h>
46 vtkCxxRevisionMacro(VISU_SphereWidget, "$Revision$");
47 vtkStandardNewMacro(VISU_SphereWidget);
48 //====================================================================
51 //====================================================================
52 VISU_SphereWidget::VISU_SphereWidget()
54 myState = VISU_SphereWidget::Start;
55 this->EventCallbackCommand->SetCallback(VISU_SphereWidget::ProcessEvents);
57 //Build the representation of the widget
58 mySphereSource = vtkSphereSource::New();
59 mySphereSource->SetThetaResolution(16);
60 mySphereSource->SetPhiResolution(15);
61 mySphereSource->LatLongTessellationOn();
62 mySphereMapper = vtkPolyDataMapper::New();
63 mySphereMapper->SetInput(mySphereSource->GetOutput());
64 mySphereActor = vtkActor::New();
65 mySphereActor->SetMapper(mySphereMapper);
67 // Define the point coordinates
68 vtkFloatingPointType bounds[6];
69 for(int i = 0; i < 6; i += 2){
71 bounds[i+1]=-bounds[i];
73 // Initial creation of the widget, serves to initialize it
76 //Manage the picking stuff
77 myPicker = vtkCellPicker::New();
78 myPicker->SetTolerance(0.005); //need some fluff
79 myPicker->AddPickList(mySphereActor);
80 myPicker->PickFromListOn();
82 // Set up the initial properties
83 mySphereProperty = NULL;
84 mySelectedSphereProperty = NULL;
85 CreateDefaultProperties();
88 mySphere=vtkSphere::New();
89 myImplicitSum=vtkImplicitSum::New();
90 myImplicitSum->AddFunction(mySphere,-1.0);
94 //====================================================================
97 //====================================================================
98 VISU_SphereWidget::~VISU_SphereWidget()
100 mySphereActor->Delete();
101 mySphereMapper->Delete();
102 mySphereSource->Delete();
106 if ( mySphereProperty ) {
107 mySphereProperty->Delete();
109 if ( mySelectedSphereProperty ) {
110 mySelectedSphereProperty->Delete();
113 myImplicitSum->Delete();
115 //====================================================================
116 // function: SetThetaResolution
118 //====================================================================
119 void VISU_SphereWidget::SetThetaResolution(int r)
121 mySphereSource->SetThetaResolution(r);
123 //====================================================================
124 // function: GetThetaResolution
126 //====================================================================
127 int VISU_SphereWidget::GetThetaResolution()
129 return mySphereSource->GetThetaResolution();
131 //====================================================================
132 // function: SetPhiResolution
134 //====================================================================
135 void VISU_SphereWidget::SetPhiResolution(int r)
137 mySphereSource->SetPhiResolution(r);
139 //====================================================================
140 // function: SetPhiResolution
142 //====================================================================
143 int VISU_SphereWidget::GetPhiResolution()
145 return mySphereSource->GetPhiResolution();
147 //====================================================================
148 // function: SetRadius
150 //====================================================================
151 void VISU_SphereWidget::SetRadius(vtkFloatingPointType theRadius)
153 if ( theRadius <= myRmin ) {
156 mySphereSource->SetRadius(theRadius);
157 mySphere->SetRadius(theRadius);
159 //====================================================================
160 // function: GetRadius
162 //====================================================================
163 vtkFloatingPointType VISU_SphereWidget::GetRadius()
165 return mySphereSource->GetRadius();
167 //====================================================================
168 // function: SetCenter
170 //====================================================================
171 void VISU_SphereWidget::SetCenter(vtkFloatingPointType theCenter[3])
173 mySphereSource->SetCenter(theCenter);
174 mySphere->SetCenter(theCenter);
176 //====================================================================
177 // function: SetCenter
179 //====================================================================
180 void VISU_SphereWidget::SetCenter(vtkFloatingPointType theX, vtkFloatingPointType theY, vtkFloatingPointType theZ)
182 vtkFloatingPointType aCenter[3] = {theX, theY, theZ};
186 //====================================================================
187 // function: GetCenter
189 //====================================================================
190 vtkFloatingPointType* VISU_SphereWidget::GetCenter()
192 return mySphereSource->GetCenter();
194 //====================================================================
195 // function: GetCenter
197 //====================================================================
198 void VISU_SphereWidget::GetCenter(vtkFloatingPointType theCenter[3])
200 mySphereSource->GetCenter(theCenter);
202 //====================================================================
203 // function: GetSphereProperty
205 //====================================================================
206 vtkProperty* VISU_SphereWidget::GetSphereProperty ()
208 return mySphereProperty;
210 //====================================================================
211 // function: GetSelectedSphereProperty
213 //====================================================================
214 vtkProperty* VISU_SphereWidget::GetSelectedSphereProperty ()
216 return mySelectedSphereProperty;
218 //====================================================================
219 // function: ImplicitFunction
221 //====================================================================
222 vtkImplicitFunction* VISU_SphereWidget::ImplicitFunction()
224 return myImplicitSum;
226 //====================================================================
227 // function: SetEnabled
229 //====================================================================
230 void VISU_SphereWidget::SetEnabled(int enabling)
233 vtkErrorMacro(<<"The interactor must be set prior to enabling/disabling widget");
238 vtkDebugMacro(<<"Enabling sphere widget");
239 if ( Enabled ) {//already enabled, just return
243 if ( ! CurrentRenderer ) {
245 Interactor->GetLastEventPosition(aPos);
246 CurrentRenderer=Interactor->FindPokedRenderer(aPos[0], aPos[1]);
247 if (!CurrentRenderer) {
254 // listen for the following events
255 Interactor->AddObserver(vtkCommand::MouseMoveEvent,
256 EventCallbackCommand,
258 Interactor->AddObserver(vtkCommand::LeftButtonPressEvent,
259 EventCallbackCommand,
261 Interactor->AddObserver(vtkCommand::LeftButtonReleaseEvent,
262 EventCallbackCommand,
264 Interactor->AddObserver(vtkCommand::MiddleButtonPressEvent,
265 EventCallbackCommand,
267 Interactor->AddObserver(vtkCommand::MiddleButtonReleaseEvent,
268 EventCallbackCommand,
272 CurrentRenderer->AddActor(mySphereActor);
273 mySphereActor->SetProperty(mySphereProperty);
274 mySphere->SetCenter(mySphereSource->GetCenter());
275 mySphere->SetRadius(mySphereSource->GetRadius());
277 InvokeEvent(vtkCommand::EnableEvent,NULL); //!!!see what will be done
279 //disabling----------------------------------------------------------
281 vtkDebugMacro(<<"Disabling sphere widget");
283 if ( !Enabled ){ //already disabled, just return
289 // don't listen for events any more
290 Interactor->RemoveObserver(EventCallbackCommand);
292 // turn off the sphere
293 CurrentRenderer->RemoveActor(mySphereActor);
294 InvokeEvent(vtkCommand::DisableEvent,NULL);
295 CurrentRenderer = NULL;
298 Interactor->Render();
300 //====================================================================
301 // function:ProcessEvents
303 //====================================================================
304 void VISU_SphereWidget::ProcessEvents(vtkObject* vtkNotUsed(object),
307 void* vtkNotUsed(calldata))
309 VISU_SphereWidget* self = reinterpret_cast<VISU_SphereWidget *>( clientdata );
312 case vtkCommand::LeftButtonPressEvent:
313 self->OnLeftButtonDown();
315 case vtkCommand::LeftButtonReleaseEvent:
316 self->OnLeftButtonUp();
318 case vtkCommand::MiddleButtonPressEvent:
319 self->OnMiddleButtonDown();
321 case vtkCommand::MiddleButtonReleaseEvent:
322 self->OnMiddleButtonUp();
324 case vtkCommand::MouseMoveEvent:
331 //====================================================================
332 // function:OnLeftButtonDown
334 //====================================================================
335 void VISU_SphereWidget::OnLeftButtonDown()
337 int X = Interactor->GetEventPosition()[0];
338 int Y = Interactor->GetEventPosition()[1];
340 // Okay, make sure that the pick is in the current renderer
341 vtkRenderer *aRenderer = Interactor->FindPokedRenderer(X,Y);
343 if (aRenderer != CurrentRenderer) {
344 myState = VISU_SphereWidget::Outside;
347 // Okay, we can process this. Try to pick handles first;
348 // if no places picked, then try to pick the sphere.
349 myPicker->Pick(X, Y, 0., CurrentRenderer);
350 if(vtkAssemblyPath *aPath = myPicker->GetPath()){
351 if(aPath->GetFirstNode()->GetProp() == mySphereActor){
352 myState = VISU_SphereWidget::Moving;
356 myState = VISU_SphereWidget::Outside;
360 EventCallbackCommand->SetAbortFlag(1);
362 InvokeEvent(vtkCommand::StartInteractionEvent,NULL);
363 Interactor->Render();
365 //====================================================================
366 // function:OnMouseMove
368 //====================================================================
369 void VISU_SphereWidget::OnMouseMove()
371 // See whether we're active
372 if ( myState == VISU_SphereWidget::Outside ||
373 myState == VISU_SphereWidget::Start ) {
377 int X = Interactor->GetEventPosition()[0];
378 int Y = Interactor->GetEventPosition()[1];
380 // Do different things depending on state
381 // Calculations everybody does
382 double focalPoint[4], pickPoint[4], prevPickPoint[4], z;
384 vtkRenderer *aRenderer=Interactor->FindPokedRenderer(X, Y);
385 vtkCamera *aCamera=aRenderer->GetActiveCamera();
389 // Compute the two points defining the motion vector
390 aCamera->GetFocalPoint(focalPoint);
391 ComputeWorldToDisplay(focalPoint[0],
396 ComputeDisplayToWorld(double(Interactor->GetLastEventPosition()[0]),
397 double(Interactor->GetLastEventPosition()[1]),
400 ComputeDisplayToWorld(double(X), double(Y), z, pickPoint);
402 // Process the motion
403 if ( myState == VISU_SphereWidget::Moving ) {
404 Translate(prevPickPoint, pickPoint);
406 else if ( myState == VISU_SphereWidget::Scaling ) {
407 Scale(prevPickPoint, pickPoint, X, Y);
409 // Interact, if desired
410 EventCallbackCommand->SetAbortFlag(1);
411 InvokeEvent(vtkCommand::InteractionEvent,NULL);
413 Interactor->Render();
415 //====================================================================
416 // function:OnLeftButtonUp
418 //====================================================================
419 void VISU_SphereWidget::OnLeftButtonUp()
421 if ( myState == VISU_SphereWidget::Outside ) {
425 myState = VISU_SphereWidget::Start;
428 EventCallbackCommand->SetAbortFlag(1);
430 InvokeEvent(vtkCommand::EndInteractionEvent,NULL);
432 Interactor->Render();
434 //====================================================================
435 // function:OnMiddleButtonDown
437 //====================================================================
438 void VISU_SphereWidget::OnMiddleButtonDown()
440 myState = VISU_SphereWidget::Scaling;
442 int X = Interactor->GetEventPosition()[0];
443 int Y = Interactor->GetEventPosition()[1];
445 // Okay, make sure that the pick is in the current renderer
446 vtkRenderer *aRenderer = Interactor->FindPokedRenderer(X,Y);
447 if (aRenderer!=CurrentRenderer) {
448 myState = VISU_SphereWidget::Outside;
452 // Okay, we can process this. Try to pick handles first;
453 // if no handles picked, then pick the bounding box.
454 myPicker->Pick(X, Y, 0., CurrentRenderer);
455 vtkAssemblyPath *aPath = myPicker->GetPath();
457 myState=VISU_SphereWidget::Outside;
464 EventCallbackCommand->SetAbortFlag(1);
466 InvokeEvent(vtkCommand::StartInteractionEvent,NULL);
468 Interactor->Render();
470 //====================================================================
471 // function:OnMiddleButtonUp
473 //====================================================================
474 void VISU_SphereWidget::OnMiddleButtonUp()
476 if ( myState == VISU_SphereWidget::Outside ) {
479 myState = VISU_SphereWidget::Start;
482 EventCallbackCommand->SetAbortFlag(1);
484 InvokeEvent(vtkCommand::EndInteractionEvent,NULL);
486 Interactor->Render();
488 //====================================================================
489 // function:Translate
491 //====================================================================
492 void VISU_SphereWidget::Translate(double *p1, double *p2)
494 vtkFloatingPointType v[3], aC[3], aC1[3];
496 v[0] = p2[0] - p1[0];
497 v[1] = p2[1] - p1[1];
498 v[2] = p2[2] - p1[2];
500 mySphereSource->GetCenter(aC);
501 aC1[0] = aC[0] + v[0];
502 aC1[1] = aC[1] + v[1];
503 aC1[2] = aC[2] + v[2];
504 mySphereSource->SetCenter(aC1);
505 mySphere->SetCenter(mySphereSource->GetCenter());
506 mySphere->SetRadius(mySphereSource->GetRadius());
508 //====================================================================
511 //====================================================================
512 void VISU_SphereWidget::Scale(double *p1, double *p2,
516 v[0] = p2[0] - p1[0];
517 v[1] = p2[1] - p1[1];
518 v[2] = p2[2] - p1[2];
520 vtkFloatingPointType aC[3], aR, sf, aR1;
521 aR=mySphereSource->GetRadius();
522 mySphereSource->GetCenter(aC);
523 sf=vtkMath::Norm(v)/aR;
524 int aCoordLast[2], iDX, iDY, iSign;
525 Interactor->GetLastEventPosition(aCoordLast);
527 iDX=aX-aCoordLast[0];
528 iDY=aCoordLast[1]-aY;
529 iSign=(iDX+iDY>0)? 1 : -1;
535 mySphereSource->SetRadius(aR1);
536 mySphere->SetCenter(mySphereSource->GetCenter());
537 mySphere->SetRadius(mySphereSource->GetRadius());
539 //====================================================================
540 // function:GetSphere
542 //====================================================================
543 void VISU_SphereWidget::GetSphere(vtkSphere *sphere)
545 sphere->SetRadius(mySphereSource->GetRadius());
546 sphere->SetCenter(mySphereSource->GetCenter());
548 //====================================================================
549 // function:HighlightSphere
551 //====================================================================
552 void VISU_SphereWidget::HighlightSphere(int highlight)
556 myPicker->GetPickPosition(this->LastPickPosition);// -> def in vtk3DWidget
557 mySphereActor->SetProperty(mySelectedSphereProperty);
560 mySphereActor->SetProperty(mySphereProperty);
563 //====================================================================
564 // function:CreateDefaultProperties
566 //====================================================================
567 void VISU_SphereWidget::CreateDefaultProperties()
569 if (!mySphereProperty) {
570 mySphereProperty = vtkProperty::New();
571 mySphereProperty->SetColor(0.,.5, .7);
572 mySphereProperty->SetSpecular(0.5);
573 mySphereProperty->SetRepresentationToWireframe();
575 if (!mySelectedSphereProperty) {
576 mySelectedSphereProperty = vtkProperty::New();
577 mySelectedSphereProperty->SetColor(0.5, 0.5, 0.);
578 mySelectedSphereProperty->SetSpecular(1.);
579 mySelectedSphereProperty->SetRepresentationToWireframe();
582 //====================================================================
583 // function:PlaceWidget
585 //====================================================================
586 void VISU_SphereWidget::PlaceWidget(vtkFloatingPointType bds[6])
588 vtkFloatingPointType bounds[6], center[3], radius;
590 this->AdjustBounds(bds, bounds, center);
591 vtkFloatingPointType dX, dY, dZ;
593 dX=bounds[1]-bounds[0];
594 dY=bounds[3]-bounds[2];
595 dZ=bounds[5]-bounds[4];
605 mySphereSource->SetCenter(center);
606 mySphereSource->SetRadius(radius);
607 mySphereSource->Update();
609 for (int i=0; i<6; i++) {
610 InitialBounds[i]=bounds[i];
612 InitialLength = sqrt((bounds[1]-bounds[0])*(bounds[1]-bounds[0]) +
613 (bounds[3]-bounds[2])*(bounds[3]-bounds[2]) +
614 (bounds[5]-bounds[4])*(bounds[5]-bounds[4]));
616 static vtkFloatingPointType EPS = 1.0E-1;
617 myRmin = EPS*InitialLength;
621 //====================================================================
622 // function:ChangeRadius
624 //====================================================================
625 void VISU_SphereWidget::ChangeRadius(bool up)
627 SetRadius( GetRadius() * ( up ? myRatio : 1 / myRatio ) );
629 //====================================================================
630 // function:GetPolyData
632 //====================================================================
633 void VISU_SphereWidget::GetPolyData(vtkPolyData *pd)
635 pd->ShallowCopy(mySphereSource->GetOutput());
637 //====================================================================
638 // function:PrintSelf
640 //====================================================================
641 void VISU_SphereWidget::PrintSelf(ostream& os, vtkIndent indent)
643 this->Superclass::PrintSelf(os,indent);