Statistics
| Revision:

svn-gvsig-desktop / branches / v10 / libraries / libFMap / src / com / iver / cit / gvsig / fmap / tools / geo / Geo.java @ 20100

History | View | Annotate | Download (4.45 KB)

1
package com.iver.cit.gvsig.fmap.tools.geo;
2

    
3
/**
4
 * <p>Mathematical utilities to work with geographical data:
5
 *  <ul>
6
 *  <li>Geographical constants:
7
 *   <ul>
8
 *    <li>PI / 2.</li>
9
 *    <li>Degrees per radian.</li>
10
 *    <li>Square miles per spherical degree.</li>
11
 *    <li>Square kilometres per spherical degree.</li>
12
 *    <li>Square metres per spherical degree.</li>
13
 *   </ul>
14
 *  </li>
15
 *  <li>Decimal degrees equivalent to <i>m</i> meters.</li>
16
 *  <li>The area of a spherical polygon in spherical degrees, given the latitudes and longitudes 
17
 *   of <i>n</i> points, according the <a href="http://en.wikipedia.org/wiki/Haversine_formula">Haversine function</a>.
18
 *  </ul>
19
 * </p> 
20
 *
21
 * @author Vicente Caballero Navarro
22
 */
23
public class Geo {
24
        /**
25
         * <i>PI / 2</i>, having PI = 3.14159265358979323846
26
         */
27
        public static double HalfPi = 1.5707963267948966192313;
28

    
29
    /**
30
     * Degrees per radian.
31
     */
32
        public static double Degree = 57.295779513082320876798;
33

    
34
    /**
35
     *  Square miles per spherical degree.
36
     */
37
        public static double SqMi = 273218.4;
38

    
39
    /**
40
     * Square kilometres per spherical degree.
41
     */
42
        public static double SqKm = 707632.4;
43

    
44
    /**
45
     * Square metres per spherical degree.
46
     */
47
        public static double SqM = 707632400000.0;
48
        
49
        public static void main(String[] args) {
50
                getDecimalDegrees(1000);
51
        }
52

    
53
        /**
54
         * <p>Gets the decimal degrees equivalent to the <i>m</i> meters.</p>
55
         * <p>Uses this formula:</br>
56
         * <b><i>m * R * PI</i></b>, having R = Radius of the Earth at the equator
57
         * </p>
58
         * 
59
         * @param m distance value in meters
60
         * 
61
         * @return <i>m</i> * Radius at the equator
62
         */
63
        public static double getDecimalDegrees(double m) {
64
            ///(m*180)/ (6378137.0 * Math.PI)
65
            return (m*8.983152841195214E-6);
66
    }
67

    
68
    /**
69
     * <p>Operation for calculate the <a href="http://en.wikipedia.org/wiki/Haversine_formula">Haversine function</a>:
70
     *  <b><i>hav(x)= (1-cos(x))/2</i></b>.</p>
71
     * 
72
     * @param X length between the difference of a coordinate of two points
73
     */
74
        private static double hav(double X){
75
        return (1.0 - Math.cos(X)) / 2.0;
76
    }
77

    
78
    /**
79
     * <p>Returns the area of a spherical polygon in spherical degrees,
80
     *  given the latitudes and longitudes in <i>lat</i> and <i>lon</i>, respectively.</p>
81
     *
82
     * <p>The <i>n</i> data points have indexes which range from 0 to N-1.</p>
83
     *
84
     * <p>Uses the <a href="http://en.wikipedia.org/wiki/Haversine_formula">Haversine function</a> for calculating the
85
     *  spherical area of the polygon.</p>
86
     *  
87
     * @param lat latitude of the vertexes <i>(must be in radians)</i>
88
     * @param lon longitude of the vertexes <i>(must be in radians)</i>
89
     * @param n number of vertexes in the polygon
90
     * 
91
     * @return the area of a spherical polygon in spherical degrees
92
     */
93
    public static double sphericalPolyArea(double[] lat, double[] lon, int n) {
94
        int j;
95
        int k;
96
        double lam1;
97
        double lam2 = 0;
98
        double beta1;
99
        double beta2 = 0;
100
        double cosB1;
101
        double cosB2 = 0;
102
        double havA;
103
        double t;
104
        double a;
105
        double b;
106
        double c;
107
        double s;
108
        double sum;
109
        double excess;
110

    
111
        sum = 0;
112

    
113
        for (j = 0; j <= n; j++) {
114
            k = j + 1;
115

    
116
            if (j == 0) {
117
                lam1 = lon[j];
118
                beta1 = lat[j];
119
                lam2 = lon[j + 1];
120
                beta2 = lat[j + 1];
121
                cosB1 = Math.cos(beta1);
122
                cosB2 = Math.cos(beta2);
123
            } else {
124
                k = (j + 1) % (n + 1);
125
                lam1 = lam2;
126
                beta1 = beta2;
127
                lam2 = lon[k];
128
                beta2 = lat[k];
129
                cosB1 = cosB2;
130
                cosB2 = Math.cos(beta2);
131
            }
132

    
133
            if (lam1 != lam2) {
134
                havA = hav(beta2 - beta1) + (cosB1 * cosB2 * hav(lam2 - lam1));
135
                a = 2 * Math.asin(Math.sqrt(havA));
136
                b = HalfPi - beta2;
137
                c = HalfPi - beta1;
138
                s = 0.5 * (a + b + c);
139
                t = Math.tan(s / 2) * Math.tan((s - a) / 2) * Math.tan((s - b) / 2) * Math.tan((s -
140
                        c) / 2);
141

    
142
                excess = Math.abs(4 * Math.atan(Math.sqrt(Math.abs(t)))) * Degree;
143

    
144
                if (lam2 < lam1) {
145
                    excess = -excess;
146
                }
147

    
148
                sum = sum + excess;
149
            }
150
        }
151
        return Math.abs(sum);
152
    } /*        SphericalPolyArea. */
153
}