]> gerrit.simantics Code Review - simantics/3d.git/blobdiff - org.simantics.g3d.vtk/src/org/simantics/g3d/vtk/swt/vtkCameraAndSelectorAction.java
Minor improvement for Plant3DEditor extensibility
[simantics/3d.git] / org.simantics.g3d.vtk / src / org / simantics / g3d / vtk / swt / vtkCameraAndSelectorAction.java
index 5b3e3a1fffe1ec2673039316ebb57dae685235a1..a5ea614978ee803a6df23c252205ad583f0a1622 100644 (file)
@@ -13,10 +13,13 @@ package org.simantics.g3d.vtk.swt;
 
 import java.awt.event.InputEvent;
 import java.awt.event.MouseEvent;
+import java.awt.event.MouseWheelEvent;
 import java.util.ArrayList;
 import java.util.Collection;
 import java.util.List;
 
+import javax.vecmath.Vector3d;
+
 import org.eclipse.jface.viewers.ISelection;
 import org.eclipse.jface.viewers.ISelectionChangedListener;
 import org.eclipse.jface.viewers.ISelectionProvider;
@@ -27,22 +30,24 @@ import org.simantics.g3d.tools.AdaptationUtils;
 
 import vtk.vtkCamera;
 import vtk.vtkProp;
+import vtk.vtkProp3D;
 import vtk.vtkRenderWindow;
 import vtk.vtkRenderer;
 
 public class vtkCameraAndSelectorAction extends vtkSwtAction implements ISelectionProvider {
-       
+
        protected vtkRenderer ren;
        protected int lastX;
        protected int lastY;
        protected vtkRenderWindow rw;
        protected vtkCamera cam;
        protected int InteractionMode = 1;
-       
+
        protected double activeRate = 5.0;
        protected double passiveRate = 0.01;
-       protected boolean doNotRotate = true; 
-       
+       protected boolean doNotRotate = true;
+       private double[] upDirection = new double[] { 0, 1, 0 };
+
        public vtkCameraAndSelectorAction(InteractiveVtkComposite panel) {
                super(panel);
                this.ren = panel.getRenderer();
@@ -50,350 +55,426 @@ public class vtkCameraAndSelectorAction extends vtkSwtAction implements ISelecti
                this.cam = ren.GetActiveCamera();
        }
        
+       public void setUpDirection(double[] upDirection) {
+               this.upDirection = upDirection;
+       }
+
        public void Lock() {
                panel.lock();
        }
-       
+
        public void UnLock() {
                panel.unlock();
        }
-       
-       public void InteractionModeRotate()
-         {
-           this.InteractionMode = 1;
-         }
-         
-         public void InteractionModeTranslate()
-         {
-           this.InteractionMode = 2;
-         }
-         
-         public void InteractionModeZoom()
-         {
-           this.InteractionMode = 3;
-         }
-         
+
+       public void InteractionModeRotate() {
+               this.InteractionMode = 1;
+       }
+
+       public void InteractionModeTranslate() {
+               this.InteractionMode = 2;
+       }
+
+       public void InteractionModeZoom() {
+               this.InteractionMode = 3;
+       }
+
        public void resetCameraClippingRange() {
-           Lock();
-           ren.ResetCameraClippingRange();
-           UnLock();
-         }
-
-         public void resetCamera() {
-           Lock();
-           ren.ResetCamera();
-           UnLock();
-         }
-         
-        public boolean mousePressed(MouseEvent e)
-         {
-             
-           if (ren.VisibleActorCount() == 0) return false;
-           rw.SetDesiredUpdateRate(activeRate);
-           lastX = e.getX();
-           lastY = e.getY();
-           if ((e.getModifiers()==InputEvent.BUTTON2_MASK) ||
-               (e.getModifiers()==(InputEvent.BUTTON1_MASK | InputEvent.SHIFT_MASK)))
-             {
-               InteractionModeTranslate();
-             }
-           else if (e.getModifiers()==InputEvent.BUTTON3_MASK)
-             {
-               InteractionModeZoom();
-             }
-           else 
-             {
-               InteractionModeRotate();
-             }
-           return true;
-         }
-        
-        public boolean mouseReleased(MouseEvent e)
-         {
-           rw.SetDesiredUpdateRate(passiveRate);
-           return true;
-         }
-        
-
-        
-        public boolean mouseDragged(MouseEvent e)
-         {
-           if (ren.VisibleActorCount() == 0) return false;
-           int x = e.getX();
-           int y = e.getY();
-           // rotate
-           if (this.InteractionMode == 1)
-             {
-               cam.Azimuth(lastX - x);
-               cam.Elevation(y - lastY);
-               if (doNotRotate)
-                       cam.SetRoll(0);
-               cam.OrthogonalizeViewUp();
-               resetCameraClippingRange();
-               //panel.UpdateLight();
-             }
-           // translate
-           if (this.InteractionMode == 2)
-             {
-               double  FPoint[];
-               double  PPoint[];
-               double  APoint[] = new double[3];
-               double  RPoint[];
-               double focalDepth;
-               
-               // get the current focal point and position
-               FPoint = cam.GetFocalPoint();
-               PPoint = cam.GetPosition();
-               
-               // calculate the focal depth since we'll be using it a lot
-               ren.SetWorldPoint(FPoint[0],FPoint[1],FPoint[2],1.0);
-               ren.WorldToDisplay();
-               focalDepth = ren.GetDisplayPoint()[2];
-               
-               APoint[0] = rw.GetSize()[0]/2.0 + (x - lastX);
-               APoint[1] = rw.GetSize()[1]/2.0 - (y - lastY);
-               APoint[2] = focalDepth;
-               ren.SetDisplayPoint(APoint);
-               ren.DisplayToWorld();
-               RPoint = ren.GetWorldPoint();
-               if (RPoint[3] != 0.0)
-                 {
-                   RPoint[0] = RPoint[0]/RPoint[3];
-                   RPoint[1] = RPoint[1]/RPoint[3];
-                   RPoint[2] = RPoint[2]/RPoint[3];
-                 }
-               
-               /*
-                * Compute a translation vector, moving everything 1/2 
-                * the distance to the cursor. (Arbitrary scale factor)
-                */
-               cam.SetFocalPoint(
-                                 (FPoint[0]-RPoint[0])/2.0 + FPoint[0],
-                                 (FPoint[1]-RPoint[1])/2.0 + FPoint[1],
-                                 (FPoint[2]-RPoint[2])/2.0 + FPoint[2]);
-               cam.SetPosition(
-                               (FPoint[0]-RPoint[0])/2.0 + PPoint[0],
-                               (FPoint[1]-RPoint[1])/2.0 + PPoint[1],
-                               (FPoint[2]-RPoint[2])/2.0 + PPoint[2]);
-               resetCameraClippingRange();
-             }
-           // zoom
-           if (this.InteractionMode == 3)
-             {
-               double zoomFactor;
-               //double clippingRange[];
-               
-               zoomFactor = Math.pow(1.02,(y - lastY));
-               if (cam.GetParallelProjection() == 1)
-                 {
-                   cam.SetParallelScale(cam.GetParallelScale()/zoomFactor);
-                 }
-               else
-                 {
-                   cam.Dolly(zoomFactor);
-                   resetCameraClippingRange();
-                 }
-             }
-           lastX = x;
-           lastY = y;
-           panel.refresh();
-           return true;
-         }
-
-        
-               private List<vtkProp> selectActors = new ArrayList<vtkProp>();
-               private List<vtkProp> hoverActor = new ArrayList<vtkProp>();
-        
-               @Override
-               public boolean mouseClicked(MouseEvent e) {
-                       if (!panel.getComponent().isFocusControl())
-                               return false;
-                       if (e.getButton() != MouseEvent.BUTTON1)
-                               return false;
-                       vtkProp spick[] = panel.pick(e.getX(), e.getY());
-                       if (spick != null && spick.length > 0) {
-                               for (vtkProp selectActor : spick) {
-                                       if (!e.isControlDown()) {
-                                               selectActors.clear();
-                                               selectActors.add(selectActor);
-                                       } else {
-                                               if (selectActors.contains(selectActor))
-                                                       selectActors.remove(selectActor);
-                                               else
-                                                       selectActors.add(selectActor);
-                                       }
-                               }
-                               fireSelectionChanged();
-                       } else if (!e.isControlDown()) {
-                               selectActors.clear();
-                               fireSelectionChanged();
-                       }
-                       return true;
-//                     if (e.getClickCount() > 1)
-//                             updatePickRay(e.getX(), e.getY());
-                       
+               Lock();
+               ren.ResetCameraClippingRange();
+               UnLock();
+       }
+
+       public void resetCamera() {
+               Lock();
+               ren.ResetCamera();
+               UnLock();
+       }
+
+       public boolean mousePressed(MouseEvent e) {
+
+               if (ren.VisibleActorCount() == 0)
+                       return false;
+               rw.SetDesiredUpdateRate(activeRate);
+               lastX = e.getX();
+               lastY = e.getY();
+               if ((e.getModifiers() == InputEvent.BUTTON2_MASK)
+                               || (e.getModifiers() == (InputEvent.BUTTON1_MASK | InputEvent.SHIFT_MASK))) {
+                       InteractionModeTranslate();
+               } else if (e.getModifiers() == InputEvent.BUTTON3_MASK) {
+                       InteractionModeZoom();
+               } else {
+                       InteractionModeRotate();
                }
-               
-//             private void updatePickRay(double x , double y) {
-//                     Ray ray = vtkUtil.createMouseRay(panel.GetRenderer(), x, y);
-//                     
-//                     
-//                     System.out.println(ray.pos + " " + ray.dir);
-//                     vtkPoints linePoints = new vtkPoints();
-//                     linePoints.InsertPoint(0,ray.pos.x, ray.pos.y, ray.pos.z);
-//                     linePoints.InsertPoint(1, ray.pos.x + ray.dir.x, ray.pos.y + ray.dir.y, ray.pos.z + ray.dir.z);
-//                     vtkLine aLine = new vtkLine();
-//                     aLine.GetPointIds().SetId(0, 0);
-//                     aLine.GetPointIds().SetId(1, 1);
-//                     vtkUnstructuredGrid aLineGrid = new vtkUnstructuredGrid();
-//                     aLineGrid.Allocate(1, 1);
-//                     aLineGrid.InsertNextCell(aLine.GetCellType(), aLine.GetPointIds());
-//                     aLineGrid.SetPoints(linePoints);
-//                     vtkDataSetMapper aLineMapper = new vtkDataSetMapper();
-//                     aLineMapper.SetInput(aLineGrid);
-//                     vtkActor aLineActor = new vtkActor();
-//                     aLineActor.SetMapper(aLineMapper);
-//                     aLineActor.GetProperty().SetDiffuseColor(.2, 1, 1);
-//                     
-//                 if (rayActor != null) {
-//                     panel.GetRenderer().RemoveActor(rayActor);
-//                     rayActor.Delete();
-//                 }
-//                 rayActor = aLineActor;
-//                 panel.GetRenderer().AddActor(rayActor);
-//                 
-//                 linePoints.Delete();
-//                 aLine.Delete();
-//                 aLineGrid.Delete();
-//                 aLineMapper.Delete();
-//                 panel.repaint();
-//             }
-//             
-//             private vtkActor rayActor;
-               
-               @Override
-               public boolean mouseMoved(MouseEvent e) {
-                       lastX = e.getX();
-                   lastY = e.getY();
-                   
-                   if (!panel.getComponent().isFocusControl())
-                               return false;
-                       List<vtkProp> prevHover = new ArrayList<vtkProp>();
-                       prevHover.addAll(hoverActor);
-                       hoverActor.clear();
-                       vtkProp pick[] =  panel.pick(e.getX(),e.getY());
-                       if (pick != null) {
-                               for (vtkProp p : pick)
-                                       hoverActor.add(p);
+               return true;
+       }
+
+       public boolean mouseReleased(MouseEvent e) {
+               rw.SetDesiredUpdateRate(passiveRate);
+               return true;
+       }
+
+       public boolean mouseDragged(MouseEvent e) {
+               if (ren.VisibleActorCount() == 0)
+                       return false;
+               int x = e.getX();
+               int y = e.getY();
+               // rotate
+               if (this.InteractionMode == 1) {
+                       cam.Elevation(clampElevationDelta(y - lastY));
+                       if (doNotRotate)
+                               cam.SetViewUp(upDirection);
+                       cam.Azimuth(lastX - x);
+                       cam.OrthogonalizeViewUp();
+                       resetCameraClippingRange();
+                       // panel.UpdateLight();
+               }
+               // translate
+               if (this.InteractionMode == 2) {
+                       double FPoint[];
+                       double PPoint[];
+                       double APoint[];
+                       double RPoint[];
+
+                       // get the current focal point and position
+                       FPoint = cam.GetFocalPoint();
+                       PPoint = cam.GetPosition();
+
+                       // calculate the focal depth since we'll be using it a lot
+                       ren.SetWorldPoint(FPoint[0], FPoint[1], FPoint[2], 1.0);
+                       ren.WorldToDisplay();
+                       APoint = ren.GetDisplayPoint();
+                       
+//                     int[] size = rw.GetSize();
+                       APoint[0] -= x - lastX;
+                       APoint[1] += y - lastY;
+                       ren.SetDisplayPoint(APoint);
+                       ren.DisplayToWorld();
+                       RPoint = ren.GetWorldPoint();
+                       
+                       if (RPoint[3] != 0.0) {
+                               RPoint[0] = RPoint[0] / RPoint[3];
+                               RPoint[1] = RPoint[1] / RPoint[3];
+                               RPoint[2] = RPoint[2] / RPoint[3];
                        }
-                               
-                       if (!prevHover.containsAll(hoverActor) || !hoverActor.containsAll(prevHover)) {
-                               fireHoverChanged();
+
+                       /*
+                        * Compute a translation vector, moving everything 1/2 the distance to the
+                        * cursor. (Arbitrary scale factor)
+                        */
+                       cam.SetFocalPoint(RPoint);
+                       cam.SetPosition((RPoint[0] - FPoint[0]) + PPoint[0], (RPoint[1] - FPoint[1]) + PPoint[1],
+                                       (RPoint[2] - FPoint[2]) + PPoint[2]);
+                       resetCameraClippingRange();
+               }
+               // zoom
+               if (this.InteractionMode == 3) {
+                       double zoomFactor;
+                       zoomFactor = Math.pow(1.02, (y - lastY));
+                       cam.Dolly(zoomFactor);
+                       
+                       if (cam.GetParallelProjection() == 1) {
+                               updateParallelScale();
                        }
-                       return true;
+                       resetCameraClippingRange();
                }
+               lastX = x;
+               lastY = y;
+               panel.refresh();
+               return true;
+       }
+
+       private static double dot(double[] a, double[] b) {
+               return a[0] * b[0] + a[1] * b[1] + a[2] * b[2];
+       }
+       
+       /** Calculate change in elevation, clamped to vertical directions. */
+       private double clampElevationDelta(double elevationDelta) {
+               if (!doNotRotate)
+                       return elevationDelta;
                
-               public List<vtkProp> getSelectActor() {
-                       return selectActors;
+               double[] direction = cam.GetDirectionOfProjection();
+               double d = Math.min(1.0,  Math.max(-1.0, dot(direction, upDirection)));
+               double elevation = Math.toDegrees(Math.acos(d)) + elevationDelta;
+               if (elevation < 0)
+                       elevationDelta -= elevation - 1e-5;
+               else if (elevation > 180)
+                       elevationDelta -= elevation - 180 + 1e-5;
+               return elevationDelta;
+       }
+
+       @Override
+       public boolean mouseWheelMoved(MouseWheelEvent e) {
+               double zoomFactor;
+               // double clippingRange[];
+               zoomFactor = Math.pow(1.02, (e.getWheelRotation()));
+               cam.Dolly(zoomFactor);
+               updateParallelScale();
+               resetCameraClippingRange();
+               panel.refresh();
+               return true;
+       }
+
+       private void updateParallelScale() {
+               // Make height of parallel projection match the distance
+               double distance = cam.GetDistance();
+               double angle = cam.GetViewAngle();
+               double scale = Math.tan(Math.toRadians(angle / 2)) * distance;
+               cam.SetParallelScale(scale);
+       }
+
+       protected List<vtkProp> selectActors = new ArrayList<vtkProp>();
+       protected List<vtkProp> hoverActor = new ArrayList<vtkProp>();
+
+       @Override
+       public boolean mouseClicked(MouseEvent e) {
+               if (!panel.getComponent().isFocusControl())
+                       return false;
+               if (e.getButton() != MouseEvent.BUTTON1)
+                       return false;
+               vtkProp spick[] = panel.pick(e.getX(), e.getY());
+               if (spick != null && spick.length > 0) {
+                       for (vtkProp selectActor : spick) {
+                               if (!e.isControlDown()) {
+                                       selectActors.clear();
+                                       selectActors.add(selectActor);
+                               } else {
+                                       if (selectActors.contains(selectActor))
+                                               selectActors.remove(selectActor);
+                                       else
+                                               selectActors.add(selectActor);
+                               }
+                       }
+                       fireSelectionChanged();
+               } else if (!e.isControlDown()) {
+                       selectActors.clear();
+                       fireSelectionChanged();
                }
-               
-               public List<vtkProp> getHoverActor() {
-                       return hoverActor;
+               return true;
+               // if (e.getClickCount() > 1)
+               // updatePickRay(e.getX(), e.getY());
+
+       }
+
+       // private void updatePickRay(double x , double y) {
+       // Ray ray = vtkUtil.createMouseRay(panel.GetRenderer(), x, y);
+       //
+       //
+       // System.out.println(ray.pos + " " + ray.dir);
+       // vtkPoints linePoints = new vtkPoints();
+       // linePoints.InsertPoint(0,ray.pos.x, ray.pos.y, ray.pos.z);
+       // linePoints.InsertPoint(1, ray.pos.x + ray.dir.x, ray.pos.y + ray.dir.y,
+       // ray.pos.z + ray.dir.z);
+       // vtkLine aLine = new vtkLine();
+       // aLine.GetPointIds().SetId(0, 0);
+       // aLine.GetPointIds().SetId(1, 1);
+       // vtkUnstructuredGrid aLineGrid = new vtkUnstructuredGrid();
+       // aLineGrid.Allocate(1, 1);
+       // aLineGrid.InsertNextCell(aLine.GetCellType(), aLine.GetPointIds());
+       // aLineGrid.SetPoints(linePoints);
+       // vtkDataSetMapper aLineMapper = new vtkDataSetMapper();
+       // aLineMapper.SetInput(aLineGrid);
+       // vtkActor aLineActor = new vtkActor();
+       // aLineActor.SetMapper(aLineMapper);
+       // aLineActor.GetProperty().SetDiffuseColor(.2, 1, 1);
+       //
+       // if (rayActor != null) {
+       // panel.GetRenderer().RemoveActor(rayActor);
+       // rayActor.Delete();
+       // }
+       // rayActor = aLineActor;
+       // panel.GetRenderer().AddActor(rayActor);
+       //
+       // linePoints.Delete();
+       // aLine.Delete();
+       // aLineGrid.Delete();
+       // aLineMapper.Delete();
+       // panel.repaint();
+       // }
+       //
+       // private vtkActor rayActor;
+
+       @Override
+       public boolean mouseMoved(MouseEvent e) {
+               lastX = e.getX();
+               lastY = e.getY();
+
+               if (!panel.getComponent().isFocusControl())
+                       return false;
+               List<vtkProp> prevHover = new ArrayList<vtkProp>();
+               prevHover.addAll(hoverActor);
+               hoverActor.clear();
+               vtkProp pick[] = panel.pick(e.getX(), e.getY());
+               if (pick != null) {
+                       for (vtkProp p : pick)
+                               hoverActor.add(p);
                }
-               
-               private List<ISelectionChangedListener> selectionListeners = new ArrayList<ISelectionChangedListener>();
-                
-               @Override
-               public void addSelectionChangedListener(ISelectionChangedListener listener) {
-                       selectionListeners.add(listener);
+
+               if (!prevHover.containsAll(hoverActor) || !hoverActor.containsAll(prevHover)) {
+                       fireHoverChanged();
                }
-               
-               @Override
-               public ISelection getSelection() {
-                       return new StructuredSelection(selectActors);
+               return true;
+       }
+
+       public List<vtkProp> getSelectActor() {
+               return selectActors;
+       }
+
+       public List<vtkProp> getHoverActor() {
+               return hoverActor;
+       }
+
+       private List<ISelectionChangedListener> selectionListeners = new ArrayList<ISelectionChangedListener>();
+
+       @Override
+       public void addSelectionChangedListener(ISelectionChangedListener listener) {
+               selectionListeners.add(listener);
+       }
+
+       @Override
+       public ISelection getSelection() {
+               return new StructuredSelection(selectActors);
+       }
+
+       @Override
+       public void removeSelectionChangedListener(ISelectionChangedListener listener) {
+               selectionListeners.remove(listener);
+       }
+
+       @Override
+       public void setSelection(ISelection selection) {
+               setSelection(selection, false);
+
+       }
+
+       public void setSelection(ISelection selection, boolean fire) {
+               Collection<vtkProp> selectedProps = AdaptationUtils.adaptToCollection(selection, vtkProp.class);
+
+               selectActors.clear();
+               selectActors.addAll(selectedProps);
+               if (fire)
+                       fireSelectionChanged();
+       }
+
+       protected void fireSelectionChanged() {
+               Display.getDefault().asyncExec(new Runnable() {
+                       @Override
+                       public void run() {
+
+                               SelectionChangedEvent evt = new SelectionChangedEvent(vtkCameraAndSelectorAction.this,
+                                               new StructuredSelection(selectActors));
+                               for (ISelectionChangedListener l : selectionListeners) {
+                                       l.selectionChanged(evt);
+                               }
+
+                       }
+               });
+       }
+
+       private List<ISelectionChangedListener> hoverListeners = new ArrayList<ISelectionChangedListener>();
+
+       public void addHoverChangedListener(ISelectionChangedListener listener) {
+               hoverListeners.add(listener);
+       }
+
+       public ISelection getHoverSelection() {
+               return new StructuredSelection(hoverActor);
+       }
+
+       public void removeHoverChangedListener(ISelectionChangedListener listener) {
+               hoverListeners.remove(listener);
+       }
+
+       private void fireHoverChanged() {
+               Display.getDefault().asyncExec(new Runnable() {
+                       @Override
+                       public void run() {
+                               StructuredSelection sel = null;
+                               if (hoverActor == null)
+                                       sel = new StructuredSelection();
+                               else
+                                       sel = new StructuredSelection(hoverActor);
+                               SelectionChangedEvent evt = new SelectionChangedEvent(vtkCameraAndSelectorAction.this, sel);
+                               for (ISelectionChangedListener l : hoverListeners) {
+                                       l.selectionChanged(evt);
+                               }
+
+                       }
+               });
+       }
+
+       public void focus(double x, double y, double z) {
+               Lock();
+               cam.SetFocalPoint(x, y, z);
+               if (doNotRotate) {
+                       double[] proj = cam.GetDirectionOfProjection();
+                       if (Math.abs(proj[1] * upDirection[2] - proj[2] * upDirection[1]) < 1e-6 &&
+                               Math.abs(proj[2] * upDirection[0] - proj[0] * upDirection[2]) < 1e-6 &&
+                               Math.abs(proj[0] * upDirection[1] - proj[1] * upDirection[0]) < 1e-6)
+                               cam.SetViewUp(upDirection[1], upDirection[2], upDirection[0]);
+                       else
+                               cam.SetViewUp(upDirection);
                }
+               cam.OrthogonalizeViewUp();
+               resetCameraClippingRange();
+               // panel.UpdateLight();
+               UnLock();
+       }
+       
+       public void fitToView(Collection<vtkProp3D> props) {
+               if (props.isEmpty())
+                       return;
                
-               @Override
-               public void removeSelectionChangedListener(
-                               ISelectionChangedListener listener) {
-                       selectionListeners.remove(listener);
+               double[] bounds = new double[] { Double.MAX_VALUE, -Double.MAX_VALUE,  Double.MAX_VALUE, -Double.MAX_VALUE,  Double.MAX_VALUE, -Double.MAX_VALUE }, b = new double[6];
+               for (vtkProp3D prop : props) {
+                       prop.GetBounds(b);
+                       for (int i = 0; i < 6; i+=2)
+                               bounds[i] = Math.min(bounds[i], b[i]);
+                       for (int i = 1; i < 6; i+=2)
+                               bounds[i] = Math.max(bounds[i], b[i]);
                }
                
-               @Override
-               public void setSelection(ISelection selection) {
-                       setSelection(selection, false);
+               fitToView(bounds);
+       }
 
-               }
+       public void fitToView(double[] bounds) {
+               Vector3d center = new Vector3d((bounds[0] + bounds[1])/2, (bounds[2] + bounds[3])/2, (bounds[4] + bounds[5])/2);
+               Vector3d viewDir = new Vector3d(cam.GetDirectionOfProjection());
+               Vector3d upDir = new Vector3d(cam.GetViewUp());
+               viewDir.normalize();
+               upDir.normalize();
+               Vector3d sideDir = new Vector3d();
+               sideDir.cross(viewDir, upDir);
+               sideDir.normalize();
                
-               public void setSelection(ISelection selection, boolean fire) {
-                       Collection<vtkProp> selectedProps = AdaptationUtils.adaptToCollection(selection, vtkProp.class);
-                       
-                       selectActors.clear();
-                       selectActors.addAll(selectedProps);
-                       if (fire)
-                               fireSelectionChanged();
-               }
+               double width = getBoxWidth(bounds, sideDir);
+               double height = getBoxWidth(bounds, upDir);
+               double depth = getBoxWidth(bounds, viewDir);
                
-               private void fireSelectionChanged() {
-                       Display.getDefault().asyncExec(new Runnable() {
-                               @Override
-                               public void run() {
-                                       
-                                       SelectionChangedEvent evt = new SelectionChangedEvent(vtkCameraAndSelectorAction.this, new StructuredSelection(selectActors));
-                                       for (ISelectionChangedListener l :selectionListeners) {
-                                               l.selectionChanged(evt);
-                                       }
-                                       
-                               }
-                       });
-               }
+               int[] size = rw.GetActualSize();
                
+               double distance1 = height / 2 / Math.tan(Math.toRadians(cam.GetViewAngle()) / 2);
+               double distance2 = distance1 * (width / size[0] / (height / size[1]));
                
-               private List<ISelectionChangedListener> hoverListeners = new ArrayList<ISelectionChangedListener>();
-                
-       
-               public void addHoverChangedListener(ISelectionChangedListener listener) {
-                       hoverListeners.add(listener);
-               }
+               double distance = Math.max(distance1, distance2) + depth / 2;
                
+               viewDir.scale(-distance);
+               viewDir.add(center);
                
-               public ISelection getHoverSelection() {
-                       return new StructuredSelection(hoverActor);
-               }
+               cam.SetPosition(viewDir.x, viewDir.y, viewDir.z);
+               focus(center.x, center.y, center.z);
                
-               public void removeHoverChangedListener(
-                               ISelectionChangedListener listener) {
-                       hoverListeners.remove(listener);
+               if (cam.GetParallelProjection() == 1) {
+                       cam.SetParallelScale(Math.max(height, width * size[1] / size[0]) / 2);
                }
+       }
 
-               private void fireHoverChanged() {
-                       Display.getDefault().asyncExec(new Runnable() {
-                               @Override
-                               public void run() {
-                                       StructuredSelection sel = null;
-                                       if (hoverActor == null)
-                                               sel = new StructuredSelection();
-                                       else
-                                               sel = new StructuredSelection(hoverActor);
-                                       SelectionChangedEvent evt = new SelectionChangedEvent(vtkCameraAndSelectorAction.this, sel);
-                                       for (ISelectionChangedListener l :hoverListeners) {
-                                               l.selectionChanged(evt);
-                                       }
-                                       
-                               }
-                       });
-               }
-               
-               public void focus(double x, double y, double z) {
-                       Lock();
-                       cam.SetFocalPoint(x, y, z);
-                       if (doNotRotate)
-                       cam.SetRoll(0);
-               cam.OrthogonalizeViewUp();
-               resetCameraClippingRange();
-               //panel.UpdateLight();
-                       UnLock();
-               }
-               
+       private static double getBoxWidth(double[] bounds, Vector3d dir) {
+               double dx = bounds[1] - bounds[0];
+               double dy = bounds[3] - bounds[2];
+               double dz = bounds[5] - bounds[4];
                
+               return Math.abs(dx * dir.x) + Math.abs(dy * dir.y) + Math.abs(dz * dir.z);
+       }
+
 }