View Javadoc
1   package au.gov.amsa.geo.model;
2   
3   import java.io.Serializable;
4   
5   import au.gov.amsa.risky.format.HasPosition;
6   
7   import com.google.common.base.Optional;
8   
9   /**
10   * A latitude longitude rectangle bordered by rhumb lines east-west and
11   * north-south. The rectangle is equal in degrees in width and height (but in
12   * terms of distance this can of course vary depending on the location of the
13   * cell on the earth).
14   */
15  public class Cell implements Serializable {
16  
17      private static final long serialVersionUID = 5489135874617545438L;
18      private static final double radiusEarthKm = 6371.01;
19      private static final double KM_PER_NM = 1.852;
20  
21      private final long latIndex;
22      private final long lonIndex;
23      private final int hashCode;
24  
25      /**
26       * Constructor.
27       * 
28       * @param latIndex
29       * @param lonIndex
30       */
31      Cell(long latIndex, long lonIndex) {
32          this.latIndex = latIndex;
33          this.lonIndex = lonIndex;
34          hashCode = calculateHashCode();
35      }
36  
37      public static Optional<Cell> cellAt(HasPosition p, Options options) {
38          return cellAt(p.lat(), p.lon(), options);
39      }
40  
41      public static Optional<Cell> cellAt(double lat, double lon, Options options) {
42          return options.getGrid().cellAt(lat, lon);
43      }
44  
45      public double leftEdgeLongitude(Options options) {
46          return options.getGrid().leftEdgeLongitude(this);
47      }
48  
49      public double rightEdgeLongitude(Options options) {
50          return options.getGrid().rightEdgeLongitude(this);
51      }
52  
53      public double topEdgeLatitude(Options options) {
54          return options.getGrid().topEdgeLatitude(this);
55      }
56  
57      public double bottomEdgeLatitude(Options options) {
58          return options.getGrid().bottomEdgeLatitude(this);
59      }
60  
61      public long getLatIndex() {
62          return latIndex;
63      }
64  
65      public long getLonIndex() {
66          return lonIndex;
67      }
68  
69      public double getCentreLon(Options options) {
70          return options.getGrid().centreLon(lonIndex);
71      }
72  
73      public double getCentreLat(Options options) {
74          return options.getGrid().centreLat(latIndex);
75      }
76  
77      /**
78       * From http://mathforum.org/library/drmath/view/63767.html
79       * 
80       * @param options
81       * @return
82       */
83      public double areaNauticalMiles(Options options) {
84          double topLatRads = Math.toRadians(topEdgeLatitude(options));
85          double bottomLatRads = Math.toRadians(bottomEdgeLatitude(options));
86  
87          return Math.PI / 180 * radiusEarthKm * radiusEarthKm
88                  * Math.abs(Math.sin(topLatRads) - Math.sin(bottomLatRads))
89                  * options.getCellSizeDegreesAsDouble() / (KM_PER_NM * KM_PER_NM);
90      }
91  
92      @Override
93      public int hashCode() {
94          return hashCode;
95      }
96  
97      private int calculateHashCode() {
98          final int prime = 31;
99          int result = 1;
100         result = prime * result + (int) (latIndex ^ (latIndex >>> 32));
101         result = prime * result + (int) (lonIndex ^ (lonIndex >>> 32));
102         return result;
103     }
104 
105     @Override
106     public boolean equals(Object obj) {
107         if (this == obj)
108             return true;
109         if (obj == null)
110             return false;
111         if (getClass() != obj.getClass())
112             return false;
113         Cell other = (Cell) obj;
114         if (latIndex != other.latIndex)
115             return false;
116         if (lonIndex != other.lonIndex)
117             return false;
118         return true;
119     }
120 
121     @Override
122     public String toString() {
123         return "Cell [latIndex=" + latIndex + ", lonIndex=" + lonIndex + "]";
124     }
125 
126 }