forked from 0x2620/oxjs
move examples
This commit is contained in:
parent
45ff502b55
commit
c3047a1586
47 changed files with 52 additions and 39 deletions
16
examples/maps/flight_paths/css/example.css
Normal file
16
examples/maps/flight_paths/css/example.css
Normal file
|
|
@ -0,0 +1,16 @@
|
|||
body {
|
||||
margin: 0;
|
||||
}
|
||||
.label {
|
||||
position: absolute;
|
||||
width: 126px;
|
||||
height: 14px;
|
||||
border: 1px solid rgba(255, 255, 255, 0.75);
|
||||
border-radius: 4px;
|
||||
background: rgba(0, 0, 0, 0.5);
|
||||
font-family: Lucida Grande; sans-serif;
|
||||
font-size: 11px;
|
||||
text-align: center;
|
||||
color: rgb(255, 255, 255);
|
||||
box-shadow: 0 0 1px rgb(0, 0, 0);
|
||||
}
|
||||
13
examples/maps/flight_paths/index.html
Normal file
13
examples/maps/flight_paths/index.html
Normal file
|
|
@ -0,0 +1,13 @@
|
|||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<title>Flight Paths</title>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
|
||||
<link rel="shortcut icon" type="image/png" href="../../../source/Ox.UI/themes/classic/png/icon16.png"/>
|
||||
<link rel="stylesheet" type="text/css" href="css/example.css"/>
|
||||
<script type="text/javascript" src="../../../dev/Ox.js"></script>
|
||||
<script type="text/javascript" src="js/example.js"></script>
|
||||
<script>window.addEventListener('message', function(e) { e.origin == window.location.origin && eval(e.data); });</script>
|
||||
</head>
|
||||
<body></body>
|
||||
</html>
|
||||
BIN
examples/maps/flight_paths/jpg/earth720.jpg
Normal file
BIN
examples/maps/flight_paths/jpg/earth720.jpg
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 169 KiB |
167
examples/maps/flight_paths/js/example.js
Normal file
167
examples/maps/flight_paths/js/example.js
Normal file
|
|
@ -0,0 +1,167 @@
|
|||
/*
|
||||
In this example, we will draw flight paths on a world map. We'll use the Image
|
||||
module and some of the built-in Ox.js functions for dealing with geographic
|
||||
coordinates.
|
||||
*/
|
||||
'use strict';
|
||||
|
||||
/*
|
||||
Include the image module.
|
||||
*/
|
||||
Ox.load('Image', function() {
|
||||
|
||||
/*
|
||||
This creates an image object from the specified source.
|
||||
*/
|
||||
Ox.Image('jpg/earth720.jpg', function(image) {
|
||||
|
||||
/*
|
||||
We want to map the route New York - London - Tokyo - Johannesburg -
|
||||
Sydney - Sao Paulo - New York.
|
||||
*/
|
||||
var airports = [
|
||||
{name: 'JFK', lat: 40.643841, lng: -73.782304},
|
||||
{name: 'LHR', lat: 51.480902, lng: -0.464773},
|
||||
{name: 'NRT', lat: 35.553457, lng: 139.76532},
|
||||
{name: 'JNB', lat: -26.140009, lng: 28.242781},
|
||||
{name: 'SYD', lat: -33.93567, lng: 151.164322},
|
||||
{name: 'GRU', lat: -23.62754, lng: -46.700821},
|
||||
],
|
||||
/*
|
||||
To get the width (and height) of the image, we call its
|
||||
<code>getSize</code> method.
|
||||
*/
|
||||
mapSize = image.getSize().width,
|
||||
/*
|
||||
Ox.getLine returns a line from one lat/lng pair to another, as an
|
||||
array of <code>Math.pow(2, precision) + 1</code> points.
|
||||
*/
|
||||
precision = 8,
|
||||
paths = airports.map(function(airport, i) {
|
||||
return Ox.getLine(
|
||||
airport,
|
||||
/*
|
||||
We make sure the last airport gets connected with the first
|
||||
one.
|
||||
*/
|
||||
airports[(i + 1) % airports.length],
|
||||
precision
|
||||
);
|
||||
});
|
||||
|
||||
/*
|
||||
Ox.getXYByLatLng takes a lat/lng pair and returns its x/y position on a
|
||||
1×1 Mercator position, <code>{x: 0, y: 0}</code> being the bottom left,
|
||||
<code>{x: 1, y: 1}</code> being the top right.
|
||||
*/
|
||||
function getXY(point) {
|
||||
var xy = Ox.getXYByLatLng(point);
|
||||
return [xy.x * mapSize, xy.y * mapSize];
|
||||
}
|
||||
|
||||
/*
|
||||
For each path, we have to check if it crosses the edge of the map that
|
||||
runs through the Pacific. Note that our test (a line crosses the edge
|
||||
if it spans more than 180 degrees longitude) is obviously incorrect,
|
||||
but works in our case, since all lines are sufficiently short.
|
||||
*/
|
||||
paths.forEach(function(path) {
|
||||
var parts = [path];
|
||||
Ox.loop(path.length - 1, function(i) {
|
||||
var lat, lng;
|
||||
if (Math.abs(path[i].lng - path[i + 1].lng) > 180) {
|
||||
/*
|
||||
We split the path in two parts.
|
||||
*/
|
||||
parts = [path.slice(0, i + 1), path.slice(i + 1)];
|
||||
/*
|
||||
We get the lat/lng of the points where the line leaves
|
||||
and enters the map...
|
||||
*/
|
||||
lat = Ox.getCenter(path[i], path[i + 1]).lat;
|
||||
lng = path[i].lng < 0 ? [-180, 180] : [180, -180];
|
||||
/*
|
||||
... and append them to the end of the first part and the
|
||||
beginning of the second part.
|
||||
*/
|
||||
parts[0].push({lat: lat, lng: lng[0]});
|
||||
parts[1].unshift({lat: lat, lng: lng[1]});
|
||||
/*
|
||||
Ox.Break() breaks the loop. Again, note that this assumes no
|
||||
path will cross the edge more than once.
|
||||
*/
|
||||
Ox.Break();
|
||||
}
|
||||
});
|
||||
/*
|
||||
We draw each part.
|
||||
*/
|
||||
parts.forEach(function(part) {
|
||||
image.drawPath(part.map(getXY), {color: 'white'});
|
||||
});
|
||||
});
|
||||
|
||||
/*
|
||||
Now lets add some markers.
|
||||
*/
|
||||
airports.forEach(function(airport, i) {
|
||||
/*
|
||||
<code>j</code> is the index of the next airport.
|
||||
*/
|
||||
var j = (i + 1) % airports.length,
|
||||
/*
|
||||
These are the options for the draw functions of the image. Some
|
||||
of the properties only apply to <code>drawPath</code>, some
|
||||
only to <code>drawText</code>, but we can pass all of them to
|
||||
both.
|
||||
*/
|
||||
options = {
|
||||
close: true,
|
||||
color: 'rgba(255, 255, 255, 0.75)',
|
||||
fill: 'rgba(0, 0, 0, 0.5)',
|
||||
font: 'bold 11px Lucida Grande, sans-serif',
|
||||
textAlign: 'center'
|
||||
},
|
||||
/*
|
||||
Ox.getDistance returns the distance, in meters, between two
|
||||
lat/lng pairs, and Ox.formatNumber adds thousands separators.
|
||||
*/
|
||||
text = airports[i].name + '-' + airports[j].name + ' '
|
||||
+ Ox.formatNumber(Math.round(
|
||||
Ox.getDistance(airports[i], airports[j]) / 1000
|
||||
)) + ' km',
|
||||
/*
|
||||
Ox.getCenter returns the midpoint between two lat/lng pairs.
|
||||
In our case, this is where we want to attach markers.
|
||||
*/
|
||||
xy = getXY(Ox.getCenter(airports[i], airports[j])),
|
||||
x = Math.round(xy[0]),
|
||||
y = Math.round(xy[1]);
|
||||
/*
|
||||
This is the marker...
|
||||
*/
|
||||
image.drawPath([
|
||||
[x, y],
|
||||
[x + 4, y - 16],
|
||||
[x + 64, y - 16],
|
||||
[x + 64, y - 32],
|
||||
[x - 64, y - 32],
|
||||
[x - 64, y - 16],
|
||||
[x - 4, y - 16]
|
||||
], options);
|
||||
/*
|
||||
... and this is the text.
|
||||
*/
|
||||
image.drawText(text, [x, y - 20], options);
|
||||
});
|
||||
|
||||
/*
|
||||
To get the dataURL for our image, we call its <code>src()</code>
|
||||
method, and to put it in the DOM, we use Ox.$, which is similar to
|
||||
jQuery's <code>$</code>.
|
||||
*/
|
||||
Ox.$('<img>').attr({src: image.src()}).appendTo(Ox.$('body'));
|
||||
|
||||
});
|
||||
|
||||
});
|
||||
13
examples/maps/ipv4_world_map/index.html
Normal file
13
examples/maps/ipv4_world_map/index.html
Normal file
|
|
@ -0,0 +1,13 @@
|
|||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<title>IPV4 World Map of the Internet</title>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
|
||||
<link rel="shortcut icon" type="image/png" href="../../../source/Ox.UI/themes/classic/png/icon16.png"/>
|
||||
<link rel="stylesheet" type="text/css" href="css/example.css"/>
|
||||
<script type="text/javascript" src="../../../dev/Ox.js"></script>
|
||||
<script type="text/javascript" src="js/example.js"></script>
|
||||
<script>window.addEventListener('message', function(e) { e.origin == window.location.origin && eval(e.data); });</script>
|
||||
</head>
|
||||
<body></body>
|
||||
</html>
|
||||
44
examples/maps/manhattan_grid/css/example.css
Normal file
44
examples/maps/manhattan_grid/css/example.css
Normal file
|
|
@ -0,0 +1,44 @@
|
|||
body {
|
||||
margin: 0;
|
||||
background-repeat: repeat-x;
|
||||
}
|
||||
img {
|
||||
position: fixed;
|
||||
left: 16px;
|
||||
top: 16px;
|
||||
border: 2px solid white;
|
||||
box-shadow: 0 0 4px black;
|
||||
}
|
||||
.marker {
|
||||
position: absolute;
|
||||
width: 8px;
|
||||
height: 8px;
|
||||
border-radius: 4px;
|
||||
background: rgb(255, 255, 0);
|
||||
cursor: pointer;
|
||||
}
|
||||
.post {
|
||||
position: absolute;
|
||||
width: 2px;
|
||||
height: 32px;
|
||||
background-color: white;
|
||||
box-shadow: 0 0 4px black;
|
||||
z-index: 1000;
|
||||
}
|
||||
.sign {
|
||||
position: absolute;
|
||||
padding: 2px 4px;
|
||||
border: 2px solid white;
|
||||
background-color: rgba(0, 128, 0, 0.75);
|
||||
font-family: Lucida Grande, Segoe UI, DejaVu Sans, Lucida Sans Unicode, Helvetica, Arial, sans-serif;
|
||||
font-size: 16px;
|
||||
text-align: center;
|
||||
color: white;
|
||||
box-shadow: 0 0 4px black;
|
||||
white-space: nowrap;
|
||||
z-index: 1001;
|
||||
}
|
||||
.latlng {
|
||||
padding: 2px 0 1px 0;
|
||||
font-size: 10px;
|
||||
}
|
||||
13
examples/maps/manhattan_grid/index.html
Normal file
13
examples/maps/manhattan_grid/index.html
Normal file
|
|
@ -0,0 +1,13 @@
|
|||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<title>Manhattan Grid Coordinate System</title>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
|
||||
<link rel="shortcut icon" type="image/png" href="../../../source/Ox.UI/themes/classic/png/icon16.png"/>
|
||||
<link rel="stylesheet" type="text/css" href="css/example.css"/>
|
||||
<script type="text/javascript" src="../../../dev/Ox.js"></script>
|
||||
<script type="text/javascript" src="js/example.js"></script>
|
||||
<script>window.addEventListener('message', function(e) { e.origin == window.location.origin && eval(e.data); });</script>
|
||||
</head>
|
||||
<body></body>
|
||||
</html>
|
||||
BIN
examples/maps/manhattan_grid/jpg/earth1024.jpg
Normal file
BIN
examples/maps/manhattan_grid/jpg/earth1024.jpg
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 318 KiB |
BIN
examples/maps/manhattan_grid/jpg/v=108&x=11174&y=6114&z=14.jpg
Normal file
BIN
examples/maps/manhattan_grid/jpg/v=108&x=11174&y=6114&z=14.jpg
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 11 KiB |
BIN
examples/maps/manhattan_grid/jpg/v=108&x=1206&y=1539&z=12.jpg
Normal file
BIN
examples/maps/manhattan_grid/jpg/v=108&x=1206&y=1539&z=12.jpg
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 22 KiB |
BIN
examples/maps/manhattan_grid/jpg/v=108&x=4148&y=2817&z=13.jpg
Normal file
BIN
examples/maps/manhattan_grid/jpg/v=108&x=4148&y=2817&z=13.jpg
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 24 KiB |
509
examples/maps/manhattan_grid/js/example.js
Normal file
509
examples/maps/manhattan_grid/js/example.js
Normal file
|
|
@ -0,0 +1,509 @@
|
|||
/*
|
||||
The idea (a slight variation of a proposal by [Harold
|
||||
Cooper](http://extendny.com/)) is to extend the Manhattan Grid in all
|
||||
directions, so that every point on Earth can be addressed as "Xth Ave & Yth
|
||||
St".
|
||||
|
||||
The origin of this coordinate system is the intersection of Zero Ave (a.k.a.
|
||||
Avenue A) and Zero St (a.k.a. Houston St). Avenues east of Zero Ave, just as
|
||||
Streets south of Zero St, have negative numbers. Broadway, which will split not
|
||||
only Manhattan but the entire globe into an eastern and a western hemisphere,
|
||||
retains its orientation, but is adjusted slightly so that it originates at the
|
||||
intersection of Zero & Zero. From there, Broadway, Zero Avenue and Zero Street
|
||||
continue as perfectly straight equatorial lines. All three will intersect once
|
||||
more, exactly halfway, in the Indian Ocean, (southwest of Australia), at the
|
||||
point furthest from Manhattan.
|
||||
|
||||
As subsequent avenues remain exactly parallel to Zero Ave, and subsequent
|
||||
streets exactly parallel to Zero St, they form smaller and smaller circles
|
||||
around the globe. The northernmost and southernmost streets are small circles
|
||||
in Central Asia (east of the Caspian Sea) and the southern Pacific (near Easter
|
||||
Island), the westernmost and easternmost avenues small circles in the North
|
||||
Pacific (west of Hawaii) and the South Atlantic (near St. Helena). These four
|
||||
extreme points are the North Pole, South Pole, West Pole and East Pole of the
|
||||
coordinate system.
|
||||
*/
|
||||
|
||||
'use strict';
|
||||
|
||||
/*
|
||||
Include the Image module.
|
||||
*/
|
||||
Ox.load('Image', function() {
|
||||
|
||||
/*
|
||||
Ox.EARTH_CIRCUMFERENCE (40075016.68557849) is a built-in constant.
|
||||
*/
|
||||
var C = Ox.EARTH_CIRCUMFERENCE,
|
||||
/*
|
||||
We need a few points to determine the orientation and spacing of
|
||||
avenues and streets.
|
||||
*/
|
||||
points = {
|
||||
/*
|
||||
Columbus Circle, the lower western corner of Central Park
|
||||
*/
|
||||
'8 & 59': {lat: 40.76807,lng: -73.98190},
|
||||
/*
|
||||
The upper western corner of Central Park, 51 streets up from
|
||||
Columbus Circle
|
||||
*/
|
||||
'8 & 110': {lat: 40.80058, lng: -73.95818},
|
||||
/*
|
||||
The lower eastern corner of Central Park, 3 avenues east of
|
||||
Columbus Circle
|
||||
*/
|
||||
'5 & 59': {lat: 40.76429, lng: -73.97301},
|
||||
},
|
||||
/*
|
||||
Ox.getBearing returns the bearing, in degrees, from one lat/lng pair to
|
||||
another. To make sure that avenues and streets cross at an exact right
|
||||
angle, we first calculate the bearing of a line that cuts the upper
|
||||
western quadrant of Columbus Circle in half, then add 45 degrees for
|
||||
the direction of the avenues and subtract 45 degrees for the direction
|
||||
of the streets.
|
||||
*/
|
||||
bearing = (
|
||||
Ox.getBearing(points['8 & 59'], points['8 & 110'])
|
||||
+ Ox.getBearing(points['5 & 59'], points['8 & 59'])
|
||||
) / 2 + 180,
|
||||
bearings = {
|
||||
// fixme: Ox.mod ?
|
||||
avenues: (bearing + 45) % 360,
|
||||
streets: (bearing - 45) % 360
|
||||
},
|
||||
/*
|
||||
Ox.getDistance returns the distance, in meters, from one lat/lng pair
|
||||
to another. We use this to determine the spacing between avenues and
|
||||
between streets. The result is 287 meters between Avenues and 81 meters
|
||||
between streets, which is not too far from the actual
|
||||
<a href="http://en.wikipedia.org/wiki/Commissioners'_Plan_of_1811">Plan</a>
|
||||
of the grid.
|
||||
*/
|
||||
distances = {
|
||||
avenues: Ox.getDistance(points['8 & 59'], points['5 & 59']) / 3,
|
||||
streets: Ox.getDistance(points['8 & 59'], points['8 & 110']) / 51
|
||||
},
|
||||
/*
|
||||
The number of avenues and streets, in each direction, is a quarter of
|
||||
the Earth's circumference divided by the respective spacing. The result
|
||||
is 34,966 avenues and 123,582 streets.
|
||||
*/
|
||||
numbers = Ox.map(distances, function(distance) {
|
||||
return C / 4 / distance;
|
||||
}),
|
||||
colors = {
|
||||
broadway: 'rgba(0, 0, 255, 0.5)',
|
||||
avenues: 'rgba(0, 255, 0, 0.5)',
|
||||
streets: 'rgba(255, 0, 0, 0.5)'
|
||||
},
|
||||
precision = 8,
|
||||
step = 10000,
|
||||
$body = Ox.$('body'),
|
||||
$post = Ox.$('<div>').addClass('post').hide().appendTo($body),
|
||||
$sign = Ox.$('<div>').addClass('sign').hide().appendTo($body),
|
||||
$images = [],
|
||||
lines, mapSize, poles;
|
||||
/*
|
||||
Ox.getPoint takes a lat/lng pair, a distance and a bearing, and returns the
|
||||
resulting point. We use this to construct the origin of the coordinate
|
||||
system, by moving Columbus Circle by minus 59 streets in the direction of
|
||||
the avenues and then by minus 8 avenues in the direction of the streets.
|
||||
The resulting point is on Stanton St between Norfolk St and Suffolk St,
|
||||
which is pretty close to where we expected it to be.
|
||||
*/
|
||||
points['0 & 0'] = Ox.getPoint(
|
||||
Ox.getPoint(
|
||||
points['8 & 59'],
|
||||
-59 * distances.streets,
|
||||
bearings.avenues
|
||||
),
|
||||
-8 * distances.avenues,
|
||||
bearings.streets
|
||||
);
|
||||
/*
|
||||
The second intersection of Zero Avenue, Zero Street and Broadway is half of
|
||||
the Earth's circumference away from the first one, in any direction.
|
||||
*/
|
||||
points['-0 & -0'] = Ox.getPoint(
|
||||
points['0 & 0'],
|
||||
Ox.EARTH_CIRCUMFERENCE / 2,
|
||||
0
|
||||
);
|
||||
/*
|
||||
Now that we have constructed the origin, we can calculate the bearing of
|
||||
Broadway, which runs from Zero & Zero through Columbus Circle.
|
||||
*/
|
||||
bearings.broadway = Ox.getBearing(points['0 & 0'], points['8 & 59']),
|
||||
/*
|
||||
Also, we can construct the poles, each of which is a quarter of Earth's
|
||||
circumference away from Zero & Zero.
|
||||
*/
|
||||
poles = {
|
||||
north: Ox.getPoint(points['0 & 0'], C / 4, bearings.avenues),
|
||||
south: Ox.getPoint(points['0 & 0'], -C / 4, bearings.avenues),
|
||||
west: Ox.getPoint(points['0 & 0'], C / 4, bearings.streets),
|
||||
east: Ox.getPoint(points['0 & 0'], -C / 4, bearings.streets),
|
||||
/*
|
||||
Broadway has two poles as well, and constructing them will make drawing
|
||||
easier. Ox.mod is the modulo function. Unlike `-90 % 360`,
|
||||
which in JavaScript is -90, Ox.mod(-90, 360) returns 270.
|
||||
*/
|
||||
westBroadway: Ox.getPoint(
|
||||
points['0 & 0'],
|
||||
C / 4,
|
||||
Ox.mod(bearings.broadway - 90, 360)
|
||||
),
|
||||
eastBroadway: Ox.getPoint(
|
||||
points['0 & 0'],
|
||||
C / 4,
|
||||
Ox.mod(bearings.broadway + 90, 360)
|
||||
)
|
||||
};
|
||||
/*
|
||||
Now we calculate circles for Broadway, Avenues and Streets. Ox.getCircle
|
||||
returns an array of lat/lng pairs that form a circle around a given point,
|
||||
with a given radius and a given precision, so that the circle will have
|
||||
`Math.pow(2, precision)` segments.
|
||||
*/
|
||||
lines = {
|
||||
/*
|
||||
Since there is only one Broadway, this is an array with just one circle
|
||||
that runs around one of the Broadway Poles, at a distance of a quarter
|
||||
of the Earth's circumference.
|
||||
*/
|
||||
broadway: [Ox.getCircle(poles.westBroadway, C / 4, precision)],
|
||||
/*
|
||||
For each 10,000th avenue, we compute a circle around the East Pole.
|
||||
From there, avenues range from -34,966th to 34,966th, so we start at a
|
||||
distance of 966 avenues from the pole, stop once the distance is half
|
||||
of the Earth's circumference (the West Pole), and in each step increase
|
||||
the distance by 10,000 avenues.
|
||||
*/
|
||||
avenues: Ox.range(
|
||||
distances.avenues * (numbers.avenues % step),
|
||||
C / 2,
|
||||
distances.avenues * step
|
||||
).map(function(distance) {
|
||||
return Ox.getCircle(poles.east, distance, precision);
|
||||
}),
|
||||
/*
|
||||
Then we do the same for streets, starting at the South Pole.
|
||||
*/
|
||||
streets: Ox.range(
|
||||
distances.streets * (numbers.streets % step),
|
||||
C / 2,
|
||||
distances.streets * step
|
||||
).map(function(distance) {
|
||||
return Ox.getCircle(poles.south, distance, precision);
|
||||
})
|
||||
};
|
||||
/*
|
||||
Print our data to the console.
|
||||
*/
|
||||
Ox.print(JSON.stringify({
|
||||
bearings: bearings,
|
||||
distances: distances,
|
||||
numbers: numbers,
|
||||
points: points,
|
||||
poles: poles
|
||||
}, null, ' '));
|
||||
|
||||
/*
|
||||
Before we start drawing, we define a few helper functions.
|
||||
`getXYByLatLng` returns screen coordinates for a given point.
|
||||
We use Ox.getXYByLatLng, which takes a lat/lng pair and returns its x/y
|
||||
position on a 1×1 Mercator position, with `{x: 0, y: 0}` at the
|
||||
bottom left and `{x: 1, y: 1}` at the top right.
|
||||
*/
|
||||
function getXYByLatLng(point) {
|
||||
return Ox.map(Ox.getXYByLatLng(point), function(v) {
|
||||
return v * mapSize;
|
||||
});
|
||||
}
|
||||
|
||||
/*
|
||||
`getLatLngByXY` is the inverse of the above, just like
|
||||
Ox.getLatLngByXY.
|
||||
*/
|
||||
function getLatLngByXY(xy) {
|
||||
return Ox.getLatLngByXY(Ox.map(xy, function(v) {
|
||||
return v / mapSize;
|
||||
}));
|
||||
}
|
||||
|
||||
/*
|
||||
`getASByLatLng` takes lat/lng and returns avenue/street. To
|
||||
compute the avenue, we subtract the point's distance from the West Pole, in
|
||||
avenues, from the total number of avenues. To compute the street, we
|
||||
subtract the point's distance from the North Pole, in avenues, from the
|
||||
total number of streets. We also return the bearing of the avenues at this
|
||||
point (which form a right angle with the line from the point to the West
|
||||
Pole), the bearing of the streets (at a right angle with the line to the
|
||||
North Pole) and the hemisphere (east or west of Broadway).
|
||||
*/
|
||||
function getASByLatLng(point) {
|
||||
var n = Ox.getDistance(point, poles.north),
|
||||
w = Ox.getDistance(point, poles.west);
|
||||
return {
|
||||
avenue: numbers.avenues - w / distances.avenues,
|
||||
street: numbers.streets - n / distances.streets,
|
||||
bearings: {
|
||||
avenues: Ox.mod(Ox.getBearing(point, poles.west) + (
|
||||
w < C / 4 ? -90 : 90
|
||||
), 360),
|
||||
streets: Ox.mod(Ox.getBearing(point, poles.north) + (
|
||||
n < C / 4 ? -90 : 90
|
||||
), 360)
|
||||
},
|
||||
hemisphere: Ox.getDistance(point, poles.eastBroadway) < C / 4
|
||||
? 'E' : 'W'
|
||||
};
|
||||
}
|
||||
|
||||
/*
|
||||
`getASByXY` returns avenue and street at the given screen
|
||||
coordinates.
|
||||
*/
|
||||
function getASByXY(xy) {
|
||||
return getASByLatLng(getLatLngByXY(xy));
|
||||
}
|
||||
|
||||
/*
|
||||
`drawPath` draws a path of lat/lng pairs on an image. For each
|
||||
path segment, we have to check if it crosses the eastern or western edge of
|
||||
the map that splits the Pacific Ocean. Note that our test (a segment
|
||||
crosses the edge if it spans more than 180 degrees longitude) is obviously
|
||||
incorrect, but works in our case, since all segments are sufficiently
|
||||
short.
|
||||
*/
|
||||
function drawPath(image, path, options) {
|
||||
var n, parts = [[]];
|
||||
/*
|
||||
...
|
||||
*/
|
||||
path.push(path[0]);
|
||||
n = path.length;
|
||||
Ox.loop(n, function(i) {
|
||||
var lat, lng, split;
|
||||
/*
|
||||
Append each point to the last part.
|
||||
*/
|
||||
Ox.last(parts).push(path[i]);
|
||||
if (Math.abs(path[i].lng - path[(i + 1) % n].lng) > 180) {
|
||||
/*
|
||||
If the next line crosses the edge, get the lat/lng of the
|
||||
points where the line leaves and enters the map.
|
||||
*/
|
||||
lat = Ox.getCenter(path[i], path[i + 1]).lat;
|
||||
lng = path[i].lng < 0 ? [-180, 180] : [180, -180];
|
||||
/*
|
||||
Append the first point to the last part and create a new part
|
||||
with the second point.
|
||||
*/
|
||||
Ox.last(parts).push({lat: lat, lng: lng[0]});
|
||||
parts.push([{lat: lat, lng: lng[1]}]);
|
||||
}
|
||||
});
|
||||
/*
|
||||
We draw each part, translating lat/lng to [x, y].
|
||||
*/
|
||||
parts.forEach(function(part) {
|
||||
image.drawPath(part.map(function(point) {
|
||||
var xy = getXYByLatLng(point);
|
||||
return [xy.x, xy.y];
|
||||
}), options);
|
||||
});
|
||||
}
|
||||
|
||||
/*
|
||||
...
|
||||
*/
|
||||
Ox.Image('jpg/earth1024.jpg', function(image) {
|
||||
|
||||
mapSize = image.getSize().width;
|
||||
drawPath(image, Ox.getCircle(points['0 & 0'], C / 4, 8), {
|
||||
color: 'rgba(255, 255, 255, 0.25)'
|
||||
});
|
||||
['streets', 'avenues', 'broadway'].forEach(function(type) {
|
||||
lines[type].forEach(function(line, i) {
|
||||
drawPath(image, line, {
|
||||
color: colors[type],
|
||||
width: i == lines[type].length / 2 - 0.5 ? 2 : 1
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
$body.css({
|
||||
minWidth: mapSize + 'px',
|
||||
height: mapSize + 'px',
|
||||
backgroundImage: 'url(' + image.src() + ')'
|
||||
})
|
||||
.on({
|
||||
click: click,
|
||||
mouseover: mouseover,
|
||||
mousemove: mousemove,
|
||||
mouseout: mouseout
|
||||
});
|
||||
|
||||
[
|
||||
{point: points['0 & 0'], title: 'Manhattan', z: 12},
|
||||
{point: {lat: 48.87377, lng: 2.29505}, title: 'Paris', z: 13},
|
||||
{point: poles.north, title: 'Uzbekistan', z: 14}
|
||||
].forEach(function(marker, i) {
|
||||
var as = getASByLatLng(marker.point),
|
||||
g = {s: 256, v: 108, z: marker.z},
|
||||
xy = getXYByLatLng(marker.point);
|
||||
Ox.print(as)
|
||||
Ox.extend(g, Ox.map(Ox.getXYByLatLng(marker.point), function(v) {
|
||||
return Math.floor(v * Math.pow(2, g.z));
|
||||
}));
|
||||
Ox.$('<div>')
|
||||
.addClass('marker')
|
||||
.css({
|
||||
left: xy.x - 4 + 'px',
|
||||
top: xy.y - 4 + 'px'
|
||||
})
|
||||
.on({
|
||||
click: function() {
|
||||
$images.forEach(function($image) {
|
||||
$image.hide();
|
||||
});
|
||||
$images[i].show();
|
||||
}
|
||||
})
|
||||
.appendTo($body);
|
||||
Ox.Image(Ox.formatString(
|
||||
'jpg/v={v}&x={x}&y={y}&z={z}.jpg', g
|
||||
), function(image) {
|
||||
if (marker.title == 'Uzbekistan') {
|
||||
Ox.range(
|
||||
distances.streets * (numbers.streets % 1),
|
||||
2000,
|
||||
distances.streets
|
||||
).forEach(function(distance) {
|
||||
var circle = mapLine(Ox.getCircle(
|
||||
poles.north, distance, precision
|
||||
), g);
|
||||
image.drawPath(circle, {
|
||||
close: true,
|
||||
color: colors.streets
|
||||
});
|
||||
});
|
||||
} else {
|
||||
Ox.loop(-200, 200, function(street) {
|
||||
var line = getLine(g, marker.point, as, 'streets', street);
|
||||
image.drawPath(line, {
|
||||
color: colors.streets,
|
||||
width: marker.title == 'Paris' || street ? 1 : 2
|
||||
});
|
||||
});
|
||||
}
|
||||
Ox.loop(-20, 20, function(avenue) {
|
||||
var line = getLine(g, marker.point, as, 'avenues', avenue);
|
||||
image.drawPath(line, {
|
||||
color: colors.avenues,
|
||||
width: marker.title == 'Paris' || avenue ? 1 : 2
|
||||
});
|
||||
});
|
||||
if (marker.title == 'Manhattan') {
|
||||
var line = mapLine(Ox.getLine(
|
||||
Ox.getPoint(marker.point, -10000, bearings.broadway),
|
||||
Ox.getPoint(marker.point, 10000, bearings.broadway),
|
||||
1
|
||||
), g);
|
||||
image.drawPath(line, {color: 'rgba(0, 0, 255, 0.5)', width: 2});
|
||||
}
|
||||
['black', 'white'].forEach(function(color, i) {
|
||||
image.drawText(marker.title, [240 - i, 240 - i], {
|
||||
color: color,
|
||||
font: 'bold 16px Lucida Grande, sans-serif',
|
||||
textAlign: 'right'
|
||||
});
|
||||
})
|
||||
$images[i] = Ox.$('<img>')
|
||||
.attr({src: image.src()})
|
||||
.hide()
|
||||
.appendTo($body);
|
||||
});
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
function getLine(g, point, as, type, i) {
|
||||
point = Ox.getPoint(
|
||||
point,
|
||||
i * distances[type],
|
||||
as.bearings[type == 'avenues' ? 'streets' : 'avenues']
|
||||
);
|
||||
return mapLine(Ox.getLine(
|
||||
Ox.getPoint(point, -10000, as.bearings[type]),
|
||||
Ox.getPoint(point, 10000, as.bearings[type]),
|
||||
1
|
||||
), g);
|
||||
}
|
||||
|
||||
function mapLine(line, g) {
|
||||
return line.map(function(point) {
|
||||
var xy = Ox.map(Ox.getXYByLatLng(point), function(value, key) {
|
||||
return (value * Math.pow(2, g.z) - g[key]) * g.s;
|
||||
});
|
||||
return [xy.x, xy.y];
|
||||
});
|
||||
}
|
||||
|
||||
function click(e) {
|
||||
if (e.target.className != 'marker') {
|
||||
$images.forEach(function($image) {
|
||||
$image.hide();
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
function mouseover() {
|
||||
$post.show();
|
||||
$sign.show();
|
||||
}
|
||||
|
||||
function mousemove(e) {
|
||||
if (e.target.tagName == 'IMG') {
|
||||
mouseout();
|
||||
return;
|
||||
}
|
||||
var left = window.scrollX,
|
||||
right = left + window.innerWidth,
|
||||
top = window.scrollY,
|
||||
xy = {x: left + e.clientX, y: top + e.clientY},
|
||||
latlng = getLatLngByXY(xy),
|
||||
as = getASByXY(xy),
|
||||
width, height, invertX, invertY;
|
||||
$sign.html(
|
||||
Ox.formatNumber(as.avenue, 0) + 'th Av & '
|
||||
+ as.hemisphere + ' '
|
||||
+ Ox.formatNumber(as.street, 0) + 'th St'
|
||||
+ '<div class="latlng">'
|
||||
+ Ox.formatDegrees(latlng.lat, 'lat') + ' / '
|
||||
+ Ox.formatDegrees(((latlng.lng + 180) % 360) - 180, 'lng')
|
||||
+ '</div>'
|
||||
)
|
||||
width = $sign.width();
|
||||
height = $sign.height();
|
||||
invertX = xy.x + width > right;
|
||||
invertY = xy.y - height - 32 < top;
|
||||
$sign.css({
|
||||
left: xy.x + (invertX ? 1 - width : -1) + 'px',
|
||||
top: xy.y + (invertY ? 32 : -32 - height) + 'px'
|
||||
});
|
||||
$post.css({
|
||||
left: xy.x - 1 + 'px',
|
||||
top: xy.y + (invertY ? 0 : -32 - height) + 'px',
|
||||
height: $sign.height() + 32 + 'px'
|
||||
});
|
||||
}
|
||||
|
||||
function mouseout() {
|
||||
$post.hide();
|
||||
$sign.hide();
|
||||
}
|
||||
|
||||
});
|
||||
Loading…
Add table
Add a link
Reference in a new issue