misc updates; add geo demo
This commit is contained in:
parent
09a3537dc1
commit
34753cb2ed
9 changed files with 219 additions and 81 deletions
|
|
@ -5,24 +5,29 @@
|
|||
// fixme: make all this work with different types of "points"
|
||||
// i.e. {lat, lng}, [lat, lng]
|
||||
|
||||
function deg(point) {
|
||||
return Ox.map(point, function(val) {
|
||||
return Ox.mod(Ox.deg(val) + 180, 360) - 180;
|
||||
});
|
||||
}
|
||||
|
||||
function rad(point) {
|
||||
return {
|
||||
lat: Ox.rad(point.lat),
|
||||
lng: Ox.rad(point.lng)
|
||||
};
|
||||
return Ox.map(point, function(val) {
|
||||
return Ox.rad(val);
|
||||
});
|
||||
}
|
||||
|
||||
/*@
|
||||
Ox.crossesDateline <f> Returns true if a given rectangle crosses the dateline
|
||||
Ox.crossesDateline <f> Returns true if a given line crosses the dateline
|
||||
@*/
|
||||
Ox.crossesDateline = function(point0, point1) {
|
||||
return point0.lng > point1.lng;
|
||||
}
|
||||
Ox.crossesDateline = function(pointA, pointB) {
|
||||
return pointA.lng > pointB.lng;
|
||||
};
|
||||
|
||||
/*@
|
||||
Ox.getArea <f> Returns the area in square meters of a given rectancle
|
||||
@*/
|
||||
Ox.getArea = function(point0, point1) {
|
||||
Ox.getArea = function(pointA, pointB) {
|
||||
/*
|
||||
area of a ring between two latitudes:
|
||||
2 * PI * r^2 * abs(sin(lat0) - sin(lat1))
|
||||
|
|
@ -35,14 +40,14 @@
|
|||
Math.abs(Ox.rad(0) - Ox.rad(1)) /
|
||||
(2 * Math.PI)
|
||||
*/
|
||||
if (Ox.crossesDateline(point0, point1)) {
|
||||
point1.lng += 360;
|
||||
if (Ox.crossesDateline(pointA, pointB)) {
|
||||
pointB.lng += 360;
|
||||
}
|
||||
var point0 = rad(point0),
|
||||
point1 = rad(point1);
|
||||
return Math.pow(Ox.EARTH_RADIUS, 2) *
|
||||
Math.abs(Math.sin(point0.lat) - Math.sin(point1.lat)) *
|
||||
Math.abs(point0.lng - point1.lng);
|
||||
pointA = rad(pointA);
|
||||
pointB = rad(pointB);
|
||||
return Math.pow(Ox.EARTH_RADIUS, 2)
|
||||
* Math.abs(Math.sin(pointA.lat) - Math.sin(pointB.lat))
|
||||
* Math.abs(pointA.lng - pointB.lng);
|
||||
};
|
||||
|
||||
/*@
|
||||
|
|
@ -50,14 +55,14 @@
|
|||
> Ox.getBearing({lat: -45, lng: 0}, {lat: 45, lng: 0})
|
||||
0
|
||||
@*/
|
||||
Ox.getBearing = function(point0, point1) {
|
||||
var point0 = rad(point0),
|
||||
point1 = rad(point1),
|
||||
x = Math.cos(point0.lat) * Math.sin(point1.lat) -
|
||||
Math.sin(point0.lat) * Math.cos(point1.lat) *
|
||||
Math.cos(point1.lng - point0.lng),
|
||||
y = Math.sin(point1.lng - point0.lng) *
|
||||
Math.cos(point1.lat);
|
||||
Ox.getBearing = function(pointA, pointB) {
|
||||
var pointA = rad(pointA),
|
||||
pointB = rad(pointB),
|
||||
x = Math.cos(pointA.lat) * Math.sin(pointB.lat)
|
||||
- Math.sin(pointA.lat) * Math.cos(pointB.lat)
|
||||
* Math.cos(pointB.lng - pointA.lng),
|
||||
y = Math.sin(pointB.lng - pointA.lng)
|
||||
* Math.cos(pointB.lat);
|
||||
return (Ox.deg(Math.atan2(y, x)) + 360) % 360;
|
||||
};
|
||||
|
||||
|
|
@ -66,23 +71,34 @@
|
|||
> Ox.getCenter({lat: -45, lng: -90}, {lat: 45, lng: 90})
|
||||
{lat: 0, lng: 0}
|
||||
@*/
|
||||
Ox.getCenter = function(point0, point1) {
|
||||
var point0 = rad(point0),
|
||||
point1 = rad(point1),
|
||||
x = Math.cos(point1.lat) *
|
||||
Math.cos(point1.lng - point0.lng),
|
||||
y = Math.cos(point1.lat) *
|
||||
Math.sin(point1.lng - point0.lng),
|
||||
Ox.getCenter = function(pointA, pointB) {
|
||||
var pointA = rad(pointA),
|
||||
pointB = rad(pointB),
|
||||
x = Math.cos(pointB.lat)
|
||||
* Math.cos(pointB.lng - pointA.lng),
|
||||
y = Math.cos(pointB.lat)
|
||||
* Math.sin(pointB.lng - pointA.lng),
|
||||
d = Math.sqrt(
|
||||
Math.pow(Math.cos(point0.lat) + x, 2) + Math.pow(y, 2)
|
||||
Math.pow(Math.cos(pointA.lat) + x, 2) + Math.pow(y, 2)
|
||||
),
|
||||
lat = Ox.deg(
|
||||
Math.atan2(Math.sin(point0.lat) + Math.sin(point1.lat), d)
|
||||
),
|
||||
lng = Ox.deg(
|
||||
point0.lng + Math.atan2(y, Math.cos(point0.lat) + x)
|
||||
);
|
||||
return {lat: lat, lng: lng};
|
||||
lat = Math.atan2(Math.sin(pointA.lat) + Math.sin(pointB.lat), d),
|
||||
lng = pointA.lng + Math.atan2(y, Math.cos(pointA.lat) + x);
|
||||
return deg({lat: lat, lng: lng});
|
||||
};
|
||||
|
||||
/*@
|
||||
Ox.getCircle <f> Returns points on a circle around a given point
|
||||
(center, radius, precision) -> <a> Points
|
||||
center <o> Center point ({lat, lng})
|
||||
radius <n> Radius in meters
|
||||
precision <n> Precision (the circle will have 2^precision segments)
|
||||
@*/
|
||||
Ox.getCircle = function(center, radius, precision) {
|
||||
return Ox.range(
|
||||
0, 360, 360 / Math.pow(2, precision)
|
||||
).map(function(bearing) {
|
||||
return Ox.getPoint(center, radius, bearing);
|
||||
});
|
||||
};
|
||||
|
||||
/*@
|
||||
|
|
@ -99,13 +115,13 @@
|
|||
> Ox.getDistance({lat: -45, lng: -90}, {lat: 45, lng: 90}) * 2
|
||||
Ox.EARTH_CIRCUMFERENCE
|
||||
@*/
|
||||
Ox.getDistance = function(point0, point1) {
|
||||
var point0 = rad(point0),
|
||||
point1 = rad(point1);
|
||||
Ox.getDistance = function(pointA, pointB) {
|
||||
var pointA = rad(pointA),
|
||||
pointB = rad(pointB);
|
||||
return Math.acos(
|
||||
Math.sin(point0.lat) * Math.sin(point1.lat) +
|
||||
Math.cos(point0.lat) * Math.cos(point1.lat) *
|
||||
Math.cos(point1.lng - point0.lng)
|
||||
Math.sin(pointA.lat) * Math.sin(pointB.lat)
|
||||
+ Math.cos(pointA.lat) * Math.cos(pointB.lat)
|
||||
* Math.cos(pointB.lng - pointA.lng)
|
||||
) * Ox.EARTH_RADIUS;
|
||||
};
|
||||
|
||||
|
|
@ -121,7 +137,30 @@
|
|||
return {
|
||||
lat: -Ox.deg(Math.atan(Ox.sinh(getVal(xy.y)))),
|
||||
lng: Ox.deg(getVal(xy.x))
|
||||
};
|
||||
};
|
||||
|
||||
/*@
|
||||
Ox.getLine <f> Returns points on a line between two points
|
||||
(pointA, pointB, precision) -> <a> Points
|
||||
pointA <o> Start point ({lat, lng})
|
||||
pointB <o> End point ({lat, lng})
|
||||
precision <n> Precision (the line will have 2^precision segments)
|
||||
@*/
|
||||
Ox.getLine = function(pointA, pointB, precision) {
|
||||
var line = [pointA, pointB], points;
|
||||
while (precision > 0) {
|
||||
points = [line[0]];
|
||||
Ox.loop(line.length - 1, function(i) {
|
||||
points.push(
|
||||
Ox.getCenter(line[i], line[i + 1]),
|
||||
line[i + 1]
|
||||
);
|
||||
});
|
||||
line = points;
|
||||
precision--;
|
||||
}
|
||||
return line;
|
||||
};
|
||||
|
||||
/*@
|
||||
|
|
@ -133,6 +172,27 @@
|
|||
return Math.cos(lat * Math.PI / 180) * Ox.EARTH_CIRCUMFERENCE / 360;
|
||||
};
|
||||
|
||||
/*@
|
||||
Ox.getPoint <f> Returns a point at a given distance/bearing from a given point
|
||||
> Ox.getPoint({lat: -45, lng: 0}, Ox.EARTH_CIRCUMFERENCE / 4, 0)
|
||||
{lat: 45, lng: 0}
|
||||
@*/
|
||||
Ox.getPoint = function(point, distance, bearing) {
|
||||
var pointB = {};
|
||||
point = rad(point);
|
||||
distance /= Ox.EARTH_RADIUS;
|
||||
bearing = Ox.rad(bearing);
|
||||
pointB.lat = Math.asin(
|
||||
Math.sin(point.lat) * Math.cos(distance)
|
||||
+ Math.cos(point.lat) * Math.sin(distance) * Math.cos(bearing)
|
||||
);
|
||||
pointB.lng = point.lng + Math.atan2(
|
||||
Math.sin(bearing) * Math.sin(distance) * Math.cos(point.lat),
|
||||
Math.cos(distance) - Math.sin(point.lat) * Math.sin(pointB.lat)
|
||||
);
|
||||
return deg(pointB);
|
||||
};
|
||||
|
||||
/*@
|
||||
Ox.getXYByLatLng <f> Returns x/y on a 1x1 mercator projection for a given lat/lng
|
||||
> Ox.getXYByLatLng({lat: 0, lng: 0})
|
||||
|
|
@ -148,13 +208,20 @@
|
|||
};
|
||||
};
|
||||
|
||||
/*@
|
||||
Ox.isPolar <f> Returns true if a given point is outside the bounds of a mercator projection
|
||||
@*/
|
||||
Ox.isPolar = function(point) {
|
||||
return point.lat < Ox.MIN_LATITUDE || point.lat > Ox.MAX_LATITUDE;
|
||||
};
|
||||
|
||||
}());
|
||||
|
||||
//@ Ox.Line <f> (undocumented)
|
||||
Ox.Line = function(point0, point1) {
|
||||
Ox.Line = function(pointA, pointB) {
|
||||
|
||||
var self = {
|
||||
points: [point0, point1]
|
||||
points: [pointA, pointB]
|
||||
},
|
||||
that = this;
|
||||
|
||||
|
|
@ -244,17 +311,17 @@ Ox.Point = function(lat, lng) {
|
|||
};
|
||||
|
||||
//@ Ox.Rectangle <f> (undocumented)
|
||||
Ox.Rectangle = function(point0, point1) {
|
||||
Ox.Rectangle = function(pointA, pointB) {
|
||||
|
||||
var self = {
|
||||
points: [
|
||||
new Point(
|
||||
Math.min(point0.lat(), point1.lat()),
|
||||
point0.lng()
|
||||
Math.min(pointA.lat(), pointB.lat()),
|
||||
pointA.lng()
|
||||
),
|
||||
new Point(
|
||||
Math.max(point0.lat(), point1.lat()),
|
||||
point1.lng()
|
||||
Math.max(pointA.lat(), pointB.lat()),
|
||||
pointB.lng()
|
||||
)
|
||||
]
|
||||
},
|
||||
|
|
@ -262,7 +329,7 @@ Ox.Rectangle = function(point0, point1) {
|
|||
|
||||
that.contains = function(rectangle) {
|
||||
|
||||
}
|
||||
};
|
||||
|
||||
that.crossesDateline = function() {
|
||||
return self.points[0].lng > self.points[1].lng;
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue