View Javadoc

1   // Copyright 2004-2005, FreeHEP.
2   package hep.wired.interaction;
3   
4   import java.awt.event.*;
5   import java.awt.geom.*;
6   import javax.swing.*;
7   
8   import org.freehep.application.Application;
9   
10  import hep.wired.edit.Rotate;
11  import hep.wired.services.RecordPlot;
12  import hep.wired.services.GraphicsPanel;
13  import hep.wired.feature.Rotateable3D;
14  import hep.wired.image.WiredBaseImage;
15  
16  /***
17   * Drag mouse to rotate plot using a virtual trackball.
18   *
19   * @author Mark Donszelmann
20   * @version $Id: DragBallToRotate.java 682 2005-03-14 02:24:52Z duns $
21   */
22  public class DragBallToRotate extends DefaultInteractionHandler {
23  
24      private int xp, yp;
25      private double ballRadius = 100;
26  
27      /***
28       * Create a ball handler to generate rotate edits.
29       */
30      public DragBallToRotate() {
31          super("Drag Ball to Rotate");
32      }
33  
34      public Icon getIcon(int size) {
35          return WiredBaseImage.getIcon("RotateBall%w", size);
36      }    
37  
38      public String getDescription() {
39          return "Drag to rotate using virtual ball; Shift-drag to rotate over vertical axis; Ctrl-drag to rotate over horizontal axis.";
40      }
41  
42      public boolean isSupportedBy(GraphicsPanel panel) {
43          return (new Rotate().isSupportedBy(panel)) && panel.supports(Rotateable3D.class);
44      }
45  
46      public void changeCursor(RecordPlot plot, InputEvent event) {
47          plot.setCursor(WiredBaseImage.getBestCursor("RotateBallCursor%w", 32, 32));
48      }
49  
50      public void reset(RecordPlot plot, InputEvent event) {
51          Application.getApplication().setStatusMessage(getDescription());
52      }
53  
54      public void mouseEntered(RecordPlot plot, MouseEvent event) {
55          plot.requestFocusInWindow();
56          changeCursor(plot, event);
57      }
58      
59      public void mouseButton1DragStarted(RecordPlot plot, MouseEvent event) {
60          xp = event.getX();
61          yp = event.getY();
62          plot.beginUpdate();
63          plot.getGraphicsPanel().setFastMode(true);
64      }
65  
66      public void mouseButton1Dragged(RecordPlot plot, MouseEvent event) {
67          int xd = event.getX();
68          int yd = event.getY();
69  
70          // mimic ball rotation, 
71          // see "Andrew J. Hanson, The Rolling Ball, Graphics Gems III [KIRK, 1992], pp. 51-60."
72          
73          // vector in right-hand screen coordinate system
74          int dx = event.isControlDown() ? 0 : xd - xp;
75          int dy = event.isShiftDown()   ? 0 : -(yd - yp);
76                  
77          // input device displacement
78          double drSquare = dx*dx + dy*dy;
79  		double dr = Math.sqrt(drSquare);
80  
81          // bail out if there is no displacement
82          if (dr == 0) return;
83          
84          // unit vector in screen plane
85          // NOTE, remove minus to get anti-ball rotation effect for small circle dragging
86  		double nx = -dy / dr;
87  		double ny =  dx / dr;
88      	double nz = 0;
89      	
90      	// ball radius
91      	double R = ballRadius;
92      	
93          // theta
94          double cosTheta = R / Math.sqrt(R*R + drSquare);
95  		double theta = Math.acos(cosTheta);
96  		
97          plot.postEdit(new Rotate(theta, nx, ny, nz));
98  
99          xp = xd;
100         yp = yd;
101     }
102 
103     public void mouseButton1DragEnded(RecordPlot plot, MouseEvent event) {
104         plot.getGraphicsPanel().setFastMode(false);
105         plot.endUpdate();
106         plot.repaint();
107     }
108 
109     public String toString() {
110         return "Drag to Rotate in 3D";
111     }
112 }