1 | import * as Util from '../core/Util';
|
2 | import {Earth} from './crs/CRS.Earth';
|
3 | import {toLatLngBounds} from './LatLngBounds';
|
4 |
|
5 | /* @class LatLng
|
6 | * @aka L.LatLng
|
7 | *
|
8 | * Represents a geographical point with a certain latitude and longitude.
|
9 | *
|
10 | * @example
|
11 | *
|
12 | * ```
|
13 | * var latlng = L.latLng(50.5, 30.5);
|
14 | * ```
|
15 | *
|
16 | * All Leaflet methods that accept LatLng objects also accept them in a simple Array form and simple object form (unless noted otherwise), so these lines are equivalent:
|
17 | *
|
18 | * ```
|
19 | * map.panTo([50, 30]);
|
20 | * map.panTo({lon: 30, lat: 50});
|
21 | * map.panTo({lat: 50, lng: 30});
|
22 | * map.panTo(L.latLng(50, 30));
|
23 | * ```
|
24 | *
|
25 | * Note that `LatLng` does not inherit from Leaflet's `Class` object,
|
26 | * which means new classes can't inherit from it, and new methods
|
27 | * can't be added to it with the `include` function.
|
28 | */
|
29 |
|
30 | export function LatLng(lat, lng, alt) {
|
31 | if (isNaN(lat) || isNaN(lng)) {
|
32 | throw new Error('Invalid LatLng object: (' + lat + ', ' + lng + ')');
|
33 | }
|
34 |
|
35 | // @property lat: Number
|
36 | // Latitude in degrees
|
37 | this.lat = +lat;
|
38 |
|
39 | // @property lng: Number
|
40 | // Longitude in degrees
|
41 | this.lng = +lng;
|
42 |
|
43 | // @property alt: Number
|
44 | // Altitude in meters (optional)
|
45 | if (alt !== undefined) {
|
46 | this.alt = +alt;
|
47 | }
|
48 | }
|
49 |
|
50 | LatLng.prototype = {
|
51 | // @method equals(otherLatLng: LatLng, maxMargin?: Number): Boolean
|
52 | // Returns `true` if the given `LatLng` point is at the same position (within a small margin of error). The margin of error can be overridden by setting `maxMargin` to a small number.
|
53 | equals: function (obj, maxMargin) {
|
54 | if (!obj) { return false; }
|
55 |
|
56 | obj = toLatLng(obj);
|
57 |
|
58 | var margin = Math.max(
|
59 | Math.abs(this.lat - obj.lat),
|
60 | Math.abs(this.lng - obj.lng));
|
61 |
|
62 | return margin <= (maxMargin === undefined ? 1.0E-9 : maxMargin);
|
63 | },
|
64 |
|
65 | // @method toString(): String
|
66 | // Returns a string representation of the point (for debugging purposes).
|
67 | toString: function (precision) {
|
68 | return 'LatLng(' +
|
69 | Util.formatNum(this.lat, precision) + ', ' +
|
70 | Util.formatNum(this.lng, precision) + ')';
|
71 | },
|
72 |
|
73 | // @method distanceTo(otherLatLng: LatLng): Number
|
74 | // Returns the distance (in meters) to the given `LatLng` calculated using the [Spherical Law of Cosines](https://en.wikipedia.org/wiki/Spherical_law_of_cosines).
|
75 | distanceTo: function (other) {
|
76 | return Earth.distance(this, toLatLng(other));
|
77 | },
|
78 |
|
79 | // @method wrap(): LatLng
|
80 | // Returns a new `LatLng` object with the longitude wrapped so it's always between -180 and +180 degrees.
|
81 | wrap: function () {
|
82 | return Earth.wrapLatLng(this);
|
83 | },
|
84 |
|
85 | // @method toBounds(sizeInMeters: Number): LatLngBounds
|
86 | // Returns a new `LatLngBounds` object in which each boundary is `sizeInMeters/2` meters apart from the `LatLng`.
|
87 | toBounds: function (sizeInMeters) {
|
88 | var latAccuracy = 180 * sizeInMeters / 40075017,
|
89 | lngAccuracy = latAccuracy / Math.cos((Math.PI / 180) * this.lat);
|
90 |
|
91 | return toLatLngBounds(
|
92 | [this.lat - latAccuracy, this.lng - lngAccuracy],
|
93 | [this.lat + latAccuracy, this.lng + lngAccuracy]);
|
94 | },
|
95 |
|
96 | clone: function () {
|
97 | return new LatLng(this.lat, this.lng, this.alt);
|
98 | }
|
99 | };
|
100 |
|
101 |
|
102 |
|
103 | // @factory L.latLng(latitude: Number, longitude: Number, altitude?: Number): LatLng
|
104 | // Creates an object representing a geographical point with the given latitude and longitude (and optionally altitude).
|
105 |
|
106 | // @alternative
|
107 | // @factory L.latLng(coords: Array): LatLng
|
108 | // Expects an array of the form `[Number, Number]` or `[Number, Number, Number]` instead.
|
109 |
|
110 | // @alternative
|
111 | // @factory L.latLng(coords: Object): LatLng
|
112 | // Expects an plain object of the form `{lat: Number, lng: Number}` or `{lat: Number, lng: Number, alt: Number}` instead.
|
113 |
|
114 | export function toLatLng(a, b, c) {
|
115 | if (a instanceof LatLng) {
|
116 | return a;
|
117 | }
|
118 | if (Util.isArray(a) && typeof a[0] !== 'object') {
|
119 | if (a.length === 3) {
|
120 | return new LatLng(a[0], a[1], a[2]);
|
121 | }
|
122 | if (a.length === 2) {
|
123 | return new LatLng(a[0], a[1]);
|
124 | }
|
125 | return null;
|
126 | }
|
127 | if (a === undefined || a === null) {
|
128 | return a;
|
129 | }
|
130 | if (typeof a === 'object' && 'lat' in a) {
|
131 | return new LatLng(a.lat, 'lng' in a ? a.lng : a.lon, a.alt);
|
132 | }
|
133 | if (b === undefined) {
|
134 | return null;
|
135 | }
|
136 | return new LatLng(a, b, c);
|
137 | }
|