home *** CD-ROM | disk | FTP | other *** search
-
- (* :Title: Geodesy *)
-
- (* :Author: John M. Novak *)
-
- (* :Summary:
- This package contains functions useful for or derived from geodesy,
- the science of measuring and mapping the surface of the Earth.
- For instance, the package includes functions for finding
- the distance between two points on the surface of the planet,
- using different models.
- *)
-
- (* :Context: Miscellaneous`Geodesy` *)
-
- (* :Package Version: 1.0 *)
-
- (* :History:
- V.1.0, April 1991, by John M. Novak
- *)
-
- (* :Keywords:
- geodesy, geography, distance, Earth
- *)
-
- (* :Sources:
- Griffin, Frank, An Introduction to Spherical Trigonometry,
- (Houghton Mifflin Co., 1943)
- Pearson, Frederick II, Map Projections: Theory and
- Applications, (CRC Press, 1990)
- *)
-
- (* :Mathematica Version: 2.0 *)
-
- BeginPackage["Miscellaneous`Geodesy`"]
-
- SphericalDistance::usage =
- "SphericalDistance[pt1,pt2] gives the distance between two
- points on the earth using the spherical model of the planet.
- The points are expressed as {lat,long}, where lat, long can
- be in degrees, or {d,m} or {d,m,s} form.";
-
- SpheroidalDistance::usage =
- "SpheroidalDistance[pt1,pt2] gives the distance between two
- points on the Earth in km, using the spheroidal model of
- the planet. Coordinates are expressed as in SphericalDistance.";
-
- ToAuthalicRadius::usage =
- "ToAuthalicRadius[a,e] gives the radius of the authalic
- sphere based on the spheroid with semimajor axis a and
- eccentricity e."
-
- GeodeticToAuthalic::usage =
- "GeodeticToAuthalic[{lat,long},e] returns the latitude and
- longitude of a point on an authalic sphere based on a
- spheroid of eccentricity e, where lat and long are the
- geodetic coordinates of that point on the spheroid."
-
- SemimajorAxis::usage =
- "SemimajorAxis is an option for SpheroidalDistance, that
- sets the semimajor axis for the spheroid defining the
- planet, in km. Default is for the Earth, from the WGS-84
- standard.";
-
- Eccentricity::usage =
- "Eccentricity is an option for SpheroidalDistance, which
- sets the eccentricity of the ellipsoid defining the planet.
- The default is for the Earth, from the WGS-84 standard.";
-
- Radius::usage =
- "Radius is an option for SphericalDistance, which sets the
- radius of the sphere defining the planet, in km. The default
- is for the Earth, for the authalic sphere based on the
- WGS-84 standard spheroid.";
-
- ToDegrees::usage =
- "ToDegrees[{d,m}] or ToDegrees[{d,m,s}] converts degree-minute-
- second forms of coordinates to degrees. The coordinates are
- adjusted to stay within [-180,180] degrees. Note that the
- sign of d is enforced on m and s; so {-34,3,2} means 34 deg,
- 3 min, and 2 sec W (or S), as does {-34,-3,-2}."
-
- ToDMS::usage =
- "ToDMS[deg] takes a coordinate in degrees and converts it
- to a degree-minute-second format, to the nearest second.
- The coordinates are within [-180,180] degrees."
-
- Begin["`Private`"]
-
- (* Ground distance between points on the surface of the planet. *)
-
- Options[SpheroidalDistance] =
- {SemimajorAxis->6378137/1000,
- Eccentricity->.081819}
-
- SpheroidalDistance[{p1_,l1_},{p2_,l2_},opts___] :=
- Module[{a,e,phi = ToDegrees[p1] Degree,
- dlam = deltalambda[ToDegrees[l1] Degree,
- ToDegrees[l2] Degree]},
- {a,e} = {SemimajorAxis,Eccentricity}/.{opts}/.
- Options[SpheroidalDistance];
- a dlam Cos[phi]/Sqrt[1 - e^2 Sin[phi]^2]
- ]/; p1 == p2
-
- deltalambda[l1_,l2_] :=
- Module[{diff},
- If[((diff = Abs[l1 - l2]) > Pi)//N,
- 2 Pi - diff,
- diff]
- ]
-
- SpheroidalDistance[{p1_,l1_},{p2_,l2_},opts___] :=
- Module[{a,e,phi,phi1,phi2,lam1,lam2},
- {a,e} = {SemimajorAxis,Eccentricity}/.{opts}/.
- Options[SpheroidalDistance];
- {phi1,phi2,lam1,lam2} = Map[ToDegrees,{p1,p2,l1,l2}] Degree;
- Abs[a NIntegrate[Evaluate[Sqrt[
- (1-e^2)^2/(1-e^2 Sin[phi]^2)^3 +
- (lam2-lam1)^2 (1-e^2 Sin[phi]^2)/
- (((1-e^2)(Tan[phi2] - Tan[phi1]) -
- e^2(phi2 - phi1))^2 Cos[phi]^2)]],
- Evaluate[{phi,phi1,phi2}]]]
- ]
-
- Options[SphericalDistance] =
- {Radius->6371007/1000}
-
- SphericalDistance[{p1_,l1_},{p2_,l2_},opts___] :=
- Module[{r,phi1,phi2,lam1,lam2},
- {r} = {Radius}/.{opts}/.Options[SphericalDistance];
- {phi1,phi2,lam1,lam2} = Map[ToDegrees,{p1,p2,l1,l2}] Degree;
- r ArcCos[Sin[phi1] Sin[phi2] +
- Cos[phi1] Cos[phi2] Cos[Abs[lam1 - lam2]]]
- ]
-
- (* Conversions between models. *)
-
- ToAuthalicRadius[a_?NumberQ,0] := a
-
- ToAuthalicRadius[a_?NumberQ,1] := a Sqrt[1/2]
-
- ToAuthalicRadius[a_?NumberQ,e_?NumberQ] :=
- a Sqrt[(2 e + (1 - e^2) (Log[1 + e] - Log[1 - e]))/(4e)]
-
- GeodeticToAuthalic[{lt_,ln_},0] := {ToDegrees[lt], ToDegrees[ln]}
-
- GeodeticToAuthalic[{lt_,ln_},1] := {0,ToDegrees[ln]}
-
- GeodeticToAuthalic[{lt_,ln_},e_?NumberQ] :=
- Module[{lat = ToDegrees[lt] Degree,long = ToDegrees[ln] Degree//N,
- arg},
- arg = ((1 - e^2) (2 e Sin[lat] -
- (1 - e^2 Sin[lat]^2) (Log[1 - e Sin[lat]] -
- Log[1 + e Sin[lat]])))/
- (Sin[lat] (1 - e^2 Sin[lat]^2) (2 e -
- (1 - e^2) (Log[1 - e] - Log[1 + e])));
- {Re[ArcSin[Sin[lat] arg]],long}/Degree
- ]
-
- (* Auxilliary Functions *)
-
- ToDegrees[deg_?NumberQ] :=
- If[Abs[deg] > 180,
- deg - 360 Ceiling[Quotient[deg,180]/2],
- deg]
-
- ToDegrees[{d_,m_:0,s_:0}] :=
- ToDegrees[d + (Sign[d] Abs[m])/60 + (Sign[d] Abs[s])/3600]
-
- ToDMS[deg_?NumberQ] :=
- Module[{tmp,d,m,s},
- tmp = ToDegrees[deg]; (* Make sure deg is in valid range *)
- d = Floor[Abs[tmp]];
- m = Floor[(Abs[tmp] - d) 60];
- s = Round[(Abs[tmp] - d - m/60) 3600];
- Sign[tmp]{d,m,s}]
-
- End[]
-
- EndPackage[]
-