View Javadoc

1   package de.fzi.wim.guibase.graphview.lens;
2   
3   import java.awt.geom.Point2D;
4   
5   /***
6    * An implementation of the lens that provides hyperbolic view. This class has been initially implemented within
7    * the <a href="http://www.touchgraph.com/">TouchGraph</a> library.
8    */
9   public class HyperbolicLens extends AbstractLens {
10      /*** The distortion factor of the hyperbolic lens. */
11      protected double m_distortionFactor;
12      /*** The table of the values of the inverse hyperbolic function. */
13      protected double[] m_inverseHyperbolicFunction=new double[200];
14  
15      /***
16       * Creates a lens for hyperbolic view.
17       */
18      public HyperbolicLens() {
19          setDistortionFactor(0.0);
20      }
21      /***
22       * Returns the current distortion factor.
23       *
24       * @return                  the current distortion factory
25       */
26      public double getDistortionFactor() {
27          return m_distortionFactor;
28      }
29      /***
30       * Sets the new distortion factor.
31       *
32       * @param distortionFactor  the new distortion factor
33       */
34      public void setDistortionFactor(double distortionFactor) {
35          m_distortionFactor=distortionFactor;
36          for (int i=0;i<m_inverseHyperbolicFunction.length;i++)
37              m_inverseHyperbolicFunction[i]=hyperDistance(10.0*i);
38          fireLensUpdated();
39      }
40      /***
41       * Computes the raw hyperbolic distance.
42       *
43       * @param distance          the distance
44       * @return                  the raw hyperbolic distance
45       */
46      protected double rawHyperDistance(double distance) {
47          return Math.log(distance/(Math.pow(1.5,(70-m_distortionFactor)/40)*80) +1);
48      }
49      /***
50       * Computes the hyperbolic distance. Points that are more than 250 units away from the center stay fixed.
51       *
52       * @param distance          the distance
53       * @return                  the raw hyperbolic distance
54       */
55      protected double hyperDistance(double distance) {
56          return rawHyperDistance(distance)/rawHyperDistance(250.0)*250.0*m_distortionFactor/100.0+distance*(100.0-m_distortionFactor)/100.0;
57      }
58      /***
59       * Computes the inverse of the hyperbolic distance.
60       *
61       * @param distance          the distance
62       * @return                  the inverse hyperbolic distance
63       */
64      protected double invHyperDistance(double distance) {
65          int i;
66          if (m_inverseHyperbolicFunction[199]<distance)
67              i=199;
68          else
69              i=findIndex(0,199,distance);
70          double x2=m_inverseHyperbolicFunction[i];
71          double x1=m_inverseHyperbolicFunction[i-1];
72          double j=(distance-x1)/(x2-x1);
73          return ((double)i+j-1)*10.0;
74      }
75      /***
76       * Locates the index of the element in the inverse array using the binary search algorithm.
77       *
78       * @param min               the minimum index
79       * @param max               the maximum index
80       * @param distance          the value being sought
81       * @return                  the index in the array
82       */
83      protected int findIndex(int min,int max,double distance) {
84          int mid=(min+max)/2;
85          if (m_inverseHyperbolicFunction[mid]<distance)
86              if (max-mid==1)
87                  return max;
88              else
89                  return findIndex(mid,max,distance);
90          else
91              if (mid-min==1)
92                  return mid;
93              else
94                  return findIndex(min,mid,distance);
95      }
96      /***
97       * Applies the lens to the point and modifies it according to the lens equations.
98       *
99       * @param point             the point that will be modified
100      */
101     public void applyLens(Point2D point) {
102         double x=point.getX();
103         double y=point.getY();
104         if (x!=0.0 || y!=0.0) {
105             double distance=Math.sqrt(x*x+y*y);
106             point.setLocation(x/distance*hyperDistance(distance),y/distance*hyperDistance(distance));
107         }
108     }
109     /***
110      * Undoes the lens effect on the point.
111      *
112      * @param point             the point that will be modified
113      */
114     public void undoLens(Point2D point) {
115         double x=point.getX();
116         double y=point.getY();
117         if (x!=0.0 || y!=0.0) {
118             double distance=Math.sqrt(x*x+y*y);
119             point.setLocation(x/distance*invHyperDistance(distance),y/distance*invHyperDistance(distance));
120         }
121     }
122 }