PageSourceSearch

https://hoppytrails.com.au/wp-content/plugins/wp-google-maps-gold/lib/cheap-ruler.js?ver=5.2.4

js hoppytrails.com.au collected 2026-10-04 23:08:22 UTC 11,695 bytes, 423 lines download raw bytes

1jQuery(function($) {
2
3	/**
4	 * A collection of very fast approximations to common geodesic measurements. Useful for performance-sensitive code that measures things on a city scale.
5	 *
6	 * @param {number} lat latitude
7	 * @param {string} [units='kilometers']
8	 * @returns {CheapRuler}
9	 * @example
10	 * var ruler = cheapRuler(35.05, 'miles');
11	 * //=ruler
12	 */
13	function cheapRuler(lat /*: number */, units /*: ?string */) {
14		return new CheapRuler(lat, units);
15	}
16
17	/**
18	 * Multipliers for converting between units.
19	 *
20	 * @example
21	 * // convert 50 meters to yards
22	 * 50 * cheapRuler.units.yards / cheapRuler.units.meters;
23	 */
24	var factors = cheapRuler.units = {
25		kilometers: 1,
26		miles: 1000 / 1609.344,
27		nauticalmiles: 1000 / 1852,
28		meters: 1000,
29		metres: 1000,
30		yards: 1000 / 0.9144,
31		feet: 1000 / 0.3048,
32		inches: 1000 / 0.0254
33	};
34
35	/**
36	 * Creates a ruler object from tile coordinates (y and z). Convenient in tile-reduce scripts.
37	 *
38	 * @param {number} y
39	 * @param {number} z
40	 * @param {string} [units='kilometers']
41	 * @returns {CheapRuler}
42	 * @example
43	 * var ruler = cheapRuler.fromTile(1567, 12);
44	 * //=ruler
45	 */
46	cheapRuler.fromTile = function (y, z, units) {
47		var n = Math.PI * (1 - 2 * (y + 0.5) / Math.pow(2, z));
48		var lat = Math.atan(0.5 * (Math.exp(n) - Math.exp(-n))) * 180 / Math.PI;
49		return new CheapRuler(lat, units);
50	};
51
52	function CheapRuler(lat, units) {
53		if (lat === undefined) throw new Error('No latitude given.');
54		if (units && !factors[units]) throw new Error('Unknown unit ' + units + '. Use one of: ' + Object.keys(factors).join(', '));
55
56		var m = units ? factors[units] : 1;
57
58		var cos = Math.cos(lat * Math.PI / 180);
59		var cos2 = 2 * cos * cos - 1;
60		var cos3 = 2 * cos * cos2 - cos;
61		var cos4 = 2 * cos * cos3 - cos2;
62		var cos5 = 2 * cos * cos4 - cos3;
63
64		// multipliers for converting longitude and latitude degrees into distance (http://1.usa.gov/1Wb1bv7)
65		this.kx = m * (111.41513 * cos - 0.09455 * cos3 + 0.00012 * cos5);
66		this.ky = m * (111.13209 - 0.56605 * cos2 + 0.0012 * cos4);
67	}
68	
69	window.CheapRuler = CheapRuler;
70	window.cheapRuler = cheapRuler;
71
72	CheapRuler.prototype = {
73		/**
74		 * Given two points of the form [longitude, latitude], returns the distance.
75		 *
76		 * @param {Array<number>} a point [longitude, latitude]
77		 * @param {Array<number>} b point [longitude, latitude]
78		 * @returns {number} distance
79		 * @example
80		 * var distance = ruler.distance([30.5, 50.5], [30.51, 50.49]);
81		 * //=distance
82		 */
83		distance: function (a, b) {
84			var dx = (a[0] - b[0]) * this.kx;
85			var dy = (a[1] - b[1]) * this.ky;
86			return Math.sqrt(dx * dx + dy * dy);
87		},
88
89		/**
90		 * Returns the bearing between two points in angles.
91		 *
92		 * @param {Array<number>} a point [longitude, latitude]
93		 * @param {Array<number>} b point [longitude, latitude]
94		 * @returns {number} bearing
95		 * @example
96		 * var bearing = ruler.bearing([30.5, 50.5], [30.51, 50.49]);
97		 * //=bearing
98		 */
99		bearing: function (a, b) {
100			var dx = (b[0] - a[0]) * this.kx;
101			var dy = (b[1] - a[1]) * this.ky;
102			if (!dx && !dy) return 0;
103			var bearing = Math.atan2(dx, dy) * 180 / Math.PI;
104			if (bearing > 180) bearing -= 360;
105			return bearing;
106		},
107
108		/**
109		 * Returns a new point given distance and bearing from the starting point.
110		 *
111		 * @param {Array<number>} p point [longitude, latitude]
112		 * @param {number} dist distance
113		 * @param {number} bearing
114		 * @returns {Array<number>} point [longitude, latitude]
115		 * @example
116		 * var point = ruler.destination([30.5, 50.5], 0.1, 90);
117		 * //=point
118		 */
119		destination: function (p, dist, bearing) {
120			var a = bearing * Math.PI / 180;
121			return this.offset(p,
122				Math.sin(a) * dist,
123				Math.cos(a) * dist);
124		},
125
126		/**
127		 * Returns a new point given easting and northing offsets (in ruler units) from the starting point.
128		 *
129		 * @param {Array<number>} p point [longitude, latitude]
130		 * @param {number} dx easting
131		 * @param {number} dy northing
132		 * @returns {Array<number>} point [longitude, latitude]
133		 * @example
134		 * var point = ruler.offset([30.5, 50.5], 10, 10);
135		 * //=point
136		 */
137		offset: function (p, dx, dy) {
138			return [
139				p[0] + dx / this.kx,
140				p[1] + dy / this.ky
141			];
142		},
143
144		/**
145		 * Given a line (an array of points), returns the total line distance.
146		 *
147		 * @param {Array<Array<number>>} points [longitude, latitude]
148		 * @returns {number} total line distance
149		 * @example
150		 * var length = ruler.lineDistance([
151		 *     [-67.031, 50.458], [-67.031, 50.534],
152		 *     [-66.929, 50.534], [-66.929, 50.458]
153		 * ]);
154		 * //=length
155		 */
156		lineDistance: function (points) {
157			var total = 0;
158			for (var i = 0; i < points.length - 1; i++) {
159				total += this.distance(points[i], points[i + 1]);
160			}
161			return total;
162		},
163
164		/**
165		 * Given a polygon (an array of rings, where each ring is an array of points), returns the area.
166		 *
167		 * @param {Array<Array<Array<number>>>} polygon
168		 * @returns {number} area value in the specified units (square kilometers by default)
169		 * @example
170		 * var area = ruler.area([[
171		 *     [-67.031, 50.458], [-67.031, 50.534], [-66.929, 50.534],
172		 *     [-66.929, 50.458], [-67.031, 50.458]
173		 * ]]);
174		 * //=area
175		 */
176		area: function (polygon) {
177			var sum = 0;
178
179			for (var i = 0; i < polygon.length; i++) {
180				var ring = polygon[i];
181
182				for (var j = 0, len = ring.length, k = len - 1; j < len; k = j++) {
183					sum += (ring[j][0] - ring[k][0]) * (ring[j][1] + ring[k][1]) * (i ? -1 : 1);
184				}
185			}
186
187			return (Math.abs(sum) / 2) * this.kx * this.ky;
188		},
189
190		/**
191		 * Returns the point at a specified distance along the line.
192		 *
193		 * @param {Array<Array<number>>} line
194		 * @param {number} dist distance
195		 * @returns {Array<number>} point [longitude, latitude]
196		 * @example
197		 * var point = ruler.along(line, 2.5);
198		 * //=point
199		 */
200		along: function (line, dist) {
201			var sum = 0;
202
203			if (dist <= 0) return line[0];
204
205			for (var i = 0; i < line.length - 1; i++) {
206				var p0 = line[i];
207				var p1 = line[i + 1];
208				var d = this.distance(p0, p1);
209				sum += d;
210				if (sum > dist) return interpolate(p0, p1, (dist - (sum - d)) / d);
211			}
212
213			return line[line.length - 1];
214		},
215
216		/**
217		 * Returns an object of the form {point, index, t}, where point is closest point on the line
218		 * from the given point, index is the start index of the segment with the closest point,
219		 * and t is a parameter from 0 to 1 that indicates where the closest point is on that segment.
220		 *
221		 * @pointOnLine
222		 * @param {Array<Array<number>>} line
223		 * @param {Array<number>} p point [longitude, latitude]
224		 * @returns {Object} {point, index, t}
225		 * @example
226		 * var point = ruler.pointOnLine(line, [-67.04, 50.5]).point;
227		 * //=point
228		 */
229		pointOnLine: function (line, p) {
230			var minDist = Infinity;
231			var minX, minY, minI, minT;
232
233			for (var i = 0; i < line.length - 1; i++) {
234
235				var x = line[i][0];
236				var y = line[i][1];
237				var dx = (line[i + 1][0] - x) * this.kx;
238				var dy = (line[i + 1][1] - y) * this.ky;
239
240				if (dx !== 0 || dy !== 0) {
241
242					var t = ((p[0] - x) * this.kx * dx + (p[1] - y) * this.ky * dy) / (dx * dx + dy * dy);
243
244					if (t > 1) {
245						x = line[i + 1][0];
246						y = line[i + 1][1];
247
248					} else if (t > 0) {
249						x += (dx / this.kx) * t;
250						y += (dy / this.ky) * t;
251					}
252				}
253
254				dx = (p[0] - x) * this.kx;
255				dy = (p[1] - y) * this.ky;
256
257				var sqDist = dx * dx + dy * dy;
258				if (sqDist < minDist) {
259					minDist = sqDist;
260					minX = x;
261					minY = y;
262					minI = i;
263					minT = t;
264				}
265			}
266
267			return {
268				point: [minX, minY],
269				index: minI,
270				t: Math.max(0, Math.min(1, minT))
271			};
272		},
273
274		/**
275		 * Returns a part of the given line between the start and the stop points (or their closest points on the line).
276		 *
277		 * @param {Array<number>} start point [longitude, latitude]
278		 * @param {Array<number>} stop point [longitude, latitude]
279		 * @param {Array<Array<number>>} line
280		 * @returns {Array<Array<number>>} line part of a line
281		 * @example
282		 * var line2 = ruler.lineSlice([-67.04, 50.5], [-67.05, 50.56], line1);
283		 * //=line2
284		 */
285		lineSlice: function (start, stop, line) {
286			var p1 = this.pointOnLine(line, start);
287			var p2 = this.pointOnLine(line, stop);
288
289			if (p1.index > p2.index || (p1.index === p2.index && p1.t > p2.t)) {
290				var tmp = p1;
291				p1 = p2;
292				p2 = tmp;
293			}
294
295			var slice = [p1.point];
296
297			var l = p1.index + 1;
298			var r = p2.index;
299
300			if (!equals(line[l], slice[0]) && l <= r)
301				slice.push(line[l]);
302
303			for (var i = l + 1; i <= r; i++) {
304				slice.push(line[i]);
305			}
306
307			if (!equals(line[r], p2.point))
308				slice.push(p2.point);
309
310			return slice;
311		},
312
313		/**
314		 * Returns a part of the given line between the start and the stop points indicated by distance along the line.
315		 *
316		 * @param {number} start distance
317		 * @param {number} stop distance
318		 * @param {Array<Array<number>>} line
319		 * @returns {Array<Array<number>>} line part of a line
320		 * @example
321		 * var line2 = ruler.lineSliceAlong(10, 20, line1);
322		 * //=line2
323		 */
324		lineSliceAlong: function (start, stop, line) {
325			var sum = 0;
326			var slice = [];
327
328			for (var i = 0; i < line.length - 1; i++) {
329				var p0 = line[i];
330				var p1 = line[i + 1];
331				var d = this.distance(p0, p1);
332
333				sum += d;
334
335				if (sum > start && slice.length === 0) {
336					slice.push(interpolate(p0, p1, (start - (sum - d)) / d));
337				}
338
339				if (sum >= stop) {
340					slice.push(interpolate(p0, p1, (stop - (sum - d)) / d));
341					return slice;
342				}
343
344				if (sum > start) slice.push(p1);
345			}
346
347			return slice;
348		},
349
350		/**
351		 * Given a point, returns a bounding box object ([w, s, e, n]) created from the given point buffered by a given distance.
352		 *
353		 * @param {Array<number>} p point [longitude, latitude]
354		 * @param {number} buffer
355		 * @returns {Array<number>} box object ([w, s, e, n])
356		 * @example
357		 * var bbox = ruler.bufferPoint([30.5, 50.5], 0.01);
358		 * //=bbox
359		 */
360		bufferPoint: function (p, buffer) {
361			var v = buffer / this.ky;
362			var h = buffer / this.kx;
363			return [
364				p[0] - h,
365				p[1] - v,
366				p[0] + h,
367				p[1] + v
368			];
369		},
370
371		/**
372		 * Given a bounding box, returns the box buffered by a given distance.
373		 *
374		 * @param {Array<number>} box object ([w, s, e, n])
375		 * @param {number} buffer
376		 * @returns {Array<number>} box object ([w, s, e, n])
377		 * @example
378		 * var bbox = ruler.bufferBBox([30.5, 50.5, 31, 51], 0.2);
379		 * //=bbox
380		 */
381		bufferBBox: function (bbox, buffer) {
382			var v = buffer / this.ky;
383			var h = buffer / this.kx;
384			return [
385				bbox[0] - h,
386				bbox[1] - v,
387				bbox[2] + h,
388				bbox[3] + v
389			];
390		},
391
392		/**
393		 * Returns true if the given point is inside in the given bounding box, otherwise false.
394		 *
395		 * @param {Array<number>} p point [longitude, latitude]
396		 * @param {Array<number>} box object ([w, s, e, n])
397		 * @returns {boolean}
398		 * @example
399		 * var inside = ruler.insideBBox([30.5, 50.5], [30, 50, 31, 51]);
400		 * //=inside
401		 */
402		insideBBox: function (p, bbox) {
403			return p[0] >= bbox[0] &&
404				   p[0] <= bbox[2] &&
405				   p[1] >= bbox[1] &&
406				   p[1] <= bbox[3];
407		}
408	};
409
410	function equals(a, b) {
411		return a[0] === b[0] && a[1] === b[1];
412	}
413
414	function interpolate(a, b, t) {
415		var dx = b[0] - a[0];
416		var dy = b[1] - a[1];
417		return [
418			a[0] + dx * t,
419			a[1] + dy * t
420		];
421	}
422
423});

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.