Skip to content

Instantly share code, notes, and snippets.

@drewlesueur
Created September 17, 2010 05:09
Show Gist options
  • Save drewlesueur/583757 to your computer and use it in GitHub Desktop.
Save drewlesueur/583757 to your computer and use it in GitHub Desktop.
echo("""
<!doctype html>
<head>
<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.4/jquery.min.js"></script>
<script type="text/javascript" src="http://maps.google.com/maps/api/js?sensor=false"></script>
<script src="http://ajax.googleapis.com/ajax/libs/swfobject/2.2/swfobject.js"></script>
<script>
(function ($) {
var initialized = false;
var initialized_started = false;
var level = 0;
var IE = navigator.appName.indexOf("Microsoft") != -1
var IE_version = "";
if (IE) {
var IE_version = navigator.userAgent.match(/MSIE ([\d])\./);
if (IE_version.length > 1) {
IE_version = IE_version[1] - 0;
} else {
IE_version = "?"
}
}
var callback = ""; //used for flash stuff
function thisMovie(movieName) {
if (IE) {
return window[movieName];
} else {
return document[movieName];
}
}
//http://code.google.com/apis/maps/documentation/javascript/overlays.html#TileCoordinates
//http://code.google.com/apis/maps/documentation/javascript/examples/map-coordinates.html
var MERCATOR_RANGE = 256;
function bound(value, opt_min, opt_max) {
if (opt_min != null) value = Math.max(value, opt_min);
if (opt_max != null) value = Math.min(value, opt_max);
return value;
}
function degreesToRadians(deg) {
return deg * (Math.PI / 180);
}
function radiansToDegrees(rad) {
return rad / (Math.PI / 180);
}
function MercatorProjection() {
this.pixelOrigin_ = new google.maps.Point(
MERCATOR_RANGE / 2, MERCATOR_RANGE / 2);
this.pixelsPerLonDegree_ = MERCATOR_RANGE / 360;
this.pixelsPerLonRadian_ = MERCATOR_RANGE / (2 * Math.PI);
};
MercatorProjection.prototype.fromLatLngToPoint = function (latLng, opt_point) {
var me = this;
var point = opt_point || new google.maps.Point(0, 0);
var origin = me.pixelOrigin_;
point.x = origin.x + latLng.lng() * me.pixelsPerLonDegree_;
// NOTE(appleton): Truncating to 0.9999 effectively limits latitude to
// 89.189. This is about a third of a tile past the edge of the world tile.
var siny = bound(Math.sin(degreesToRadians(latLng.lat())), -0.9999, 0.9999);
point.y = origin.y + 0.5 * Math.log((1 + siny) / (1 - siny)) * -me.pixelsPerLonRadian_;
return point;
};
MercatorProjection.prototype.fromPointToLatLng = function (point) {
var me = this;
var origin = me.pixelOrigin_;
var lng = (point.x - origin.x) / me.pixelsPerLonDegree_;
var latRadians = (point.y - origin.y) / -me.pixelsPerLonRadian_;
var lat = radiansToDegrees(2 * Math.atan(Math.exp(latRadians)) - Math.PI / 2);
return new google.maps.LatLng(lat, lng);
};
var bolus = false;
var spotImageData
function getTile() {
var options = arguments[0] || {}
var r = options.radius || 25;
var factor = 5
r *= factor;
var val_to_watch = 3
if (bolus == false) {
//var ctx = document.getElementById('canvas').getContext('2d');
var canvas = $('<canvas width="' + (r * 2) + '" height="' + (r * 2) + '"></canvas>')
$(document.body).append(canvas)
var ctx = canvas[0].getContext('2d');
var radgrad = ctx.createRadialGradient(r, r, 0, r, r, r);
radgrad.addColorStop(0, 'rgba(0,0,255,.2)');
//radgrad.addColorStop(.5, 'rgba(0,0,255,.25)');
radgrad.addColorStop(1, 'rgba(0,0,255,0)');
ctx.fillStyle = radgrad;
ctx.fillRect(0, 0, r * 2, r * 2);
spotImageData = ctx.getImageData(0, 0, r * 2, r * 2);
/*
var spotData = spotImageData.data
for (var i=0; i < spotData.length; i+=4) {
alpha = spotData[i+3]
//alpha = alpha / 255 * Math.pow(255, 1/3);
alpha = Math.pow(alpha, 1/2)//Math.log(alpha) * 255//Math.pow(alpha, 1/2)
spotData[i+3] = alpha
}
ctx.putImageData(spotImageData, 0, 0)
*/
bolus = canvas
} else {
var canvas = bolus
}
//spotImageData = blur(spotImageData, 1);
//ctx.putImageData(spotImageData, 0, 0);
var colors_canvas = $('<canvas width="256" height="5"></canvas>');
//$(document.body).append(colors_canvas)
var colors = colors_canvas[0].getContext('2d');
var lingrad = colors.createLinearGradient(0, 0, 255, 0);
if (options.stops) {
var stops = options.stops
} else if (options.gradient) {
var stops = {}
var gradient = options.gradient || ["rgba(130, 33, 122, 0)", "rgba(130, 33, 122, .9)", "#FF4F00", "#FFAA00", "#FFD200", "#FFFB73"]
var max = gradient.length - 1
for (var i = 0; i < gradient.length; i++) {
stops[(i / max) + ""] = gradient[i];
}
} else {
var stops = {
"0": "rgba(" + 0x92 + ", " + 0x42 + ", " + 0xb3 + ", 0)",
"0.5": "rgba(" + 0x92 + ", " + 0x42 + ", " + 0xb3 + ", 1)",
"0.75": "rgba(" + 0xF4 + "," + 0x98 + "," + 0x91 + ",1)",
"0.9": "rgba(" + 0xFC + "," + 0xC4 + "," + 0x41 + ",1)",
"1": "rgba(" + 0xFD + "," + 0xe7 + "," + 0x98 + ",1)"
}
}
for (var i in stops) {
lingrad.addColorStop(i - 0, stops[i]);
}
colors.fillStyle = lingrad
colors.fillRect(0, 0, 256, 5);
var colorsImageData = colors.getImageData(0, 0, 256, 1);
var colorsData = colorsImageData.data;
var tileSize = options.tileSize || 256;
var tile_canvas = $('<canvas width="' + tileSize + '" height="' + tileSize + '"></canvas>');
var tile = tile_canvas[0].getContext('2d');
var points = options.points || []
for (var i = 0; i < points.length; i++) {
var point = points[i]
for (j = 0; j < point[2]; j++) {
tile.drawImage(canvas[0], 0, 0, r * 2, r * 2, point[0] - r / factor, point[1] - r / factor, 2 * r / factor, 2 * r / factor)
}
}
var opacity = options.opacity || 0.75
var tileImageData = tile.getImageData(0, 0, tileSize, tileSize);
var data = tileImageData.data;
for (var i = 0; i < data.length; i += 4) {
if (data[i + val_to_watch] < 10) {
data[i + 3] = 0
continue;
}
data[i] = colorsData[data[i + val_to_watch] * 4];
data[i + 1] = colorsData[data[i + val_to_watch] * 4 + 1];
data[i + 2] = colorsData[data[i + val_to_watch] * 4 + 2];
data[i + 3] = colorsData[data[i + val_to_watch] * 4 + 3] * opacity;
}
//tileImageData = blur(tileImageData, 1);
tile.putImageData(tileImageData, 0, 0)
return tile_canvas[0]
}
function drawTile(options) {
return getTile(options).toDataURL();
}
$.fn.heatmap = function () {
var config = {
'radius': 25,
opacity: 0.5,
centerValue: 10,
gradient: [0, 167772262, 336396403, 504430711, 672727155, 857605496, 1025311865, 1193542778, 1361445755, 1529480062, 1714226559, 1882326399, 2050229378, 2218264197, 2386232710, 2571044231, 2739013001, 2906982028, 3075081868, 3243050383, 3427796369, 3595765395, 3763734164, 3931768213, 4099736983, 4284614554, 4284745369, 4284876441, 4285007513, 4285138585, 4285334937, 4285466009, 4285597081, 4285728153, 4285924505, 4286055577, 4286186649, 4286317721, 4286514073, 4286645145, 4286776217, 4286907289, 4287103641, 4287234713, 4287365785, 4287496857, 4287693209, 4287824281, 4287955353, 4288086425, 4288283033, 4288348568, 4288414103, 4288545431, 4288610966, 4288742293, 4288807829, 4288938900, 4289004691, 4289135763, 4289201554, 4289332625, 4289398161, 4289529488, 4289595024, 4289726351, 4289791886, 4289922958, 4289988749, 4290119820, 4290185612, 4290316683, 4290382218, 4290513546, 4290579081, 4290710409, 4290776198, 4290841987, 4290907777, 4290973822, 4291039612, 4291105401, 4291171447, 4291237236, 4291303026, 4291369071, 4291434861, 4291500650, 4291566696, 4291632485, 4291698275, 4291764320, 4291830110, 4291895899, 4291961945, 4292027734, 4292093524, 4292159569, 4292225359, 4292291148, 4292422730, 4292422983, 4292489029, 4292489282, 4292555328, 4292621118, 4292621627, 4292687417, 4292753462, 4292753972, 4292819762, 4292885807, 4292886061, 4292952106, 4292952360, 4293018406, 4293084195, 4293084705, 4293150750, 4293216540, 4293217050, 4293282839, 4293348885, 4293349138, 4293415184, 4293481230, 4293481485, 4293481996, 4293547788, 4293548299, 4293614091, 4293614602, 4293614858, 4293680905, 4293681416, 4293747208, 4293747719, 4293747975, 4293814022, 4293814278, 4293880325, 4293880581, 4293881092, 4293947139, 4293947395, 4294013442, 4294013698, 4294014209, 4294080001, 4294080512, 4294146560, 4294146816, 4294147328, 4294213376, 4294213632, 4294214144, 4294280192, 4294280704, 4294280960, 4294347008, 4294347520, 4294347776, 4294413824, 4294414336, 4294480384, 4294480640, 4294481152, 4294547200, 4294547456, 4294547968, 4294614016, 4294614528, 4294614784, 4294680832, 4294681344, 4294747392, 4294747648, 4294747904, 4294748416, 4294748672, 4294749184, 4294749440, 4294749952, 4294750208, 4294750464, 4294750976, 4294751232, 4294751744, 4294752000, 4294752512, 4294752768, 4294753280, 4294753536, 4294753792, 4294754304, 4294754560, 4294755072, 4294755328, 4294755840, 4294756096, 4294756608, 4294756869, 4294757130, 4294757391, 4294757652, 4294757913, 4294758174, 4294758435, 4294758696, 4294758957, 4294759219, 4294759480, 4294759741, 4294760258, 4294760519, 4294760780, 4294761041, 4294826838, 4294827099, 4294827360, 4294827622, 4294827883, 4294828144, 4294828405, 4294828666, 4294829183, 4294829444, 4294829705, 4294829966, 4294830227, 4294830489, 4294830750, 4294831011, 4294831272, 4294897069, 4294897330, 4294897591, 4294897852, 4294898369, 4294898630, 4294898892, 4294899153, 4294899414, 4294899675, 4294899936, 4294900197, 4294900458, 4294900719, 4294900980, 4294901241, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295],
map: '',
mapOptions: '',
'swf': 'HelloWorld.swf',
//echo : 'http://clstff.appspot.com/wave/googlewave.com%21w%2BaXCOteWYA',
echo: 'data_proxy.php',
echo2: 'data-proxy2.php',
tileSize: 256,
'useCanvas': false
};
if (arguments[0] == "addOverlay") {
} else {
settings = arguments[0]
}
if (settings) $.extend(config, settings);
//small tiles for ie because they only support data url up to 32k
if (IE) {
if (IE_version >= 8) {
config.tileSize = 100; //data url is limited. make it small
} else {
config.tileSize = 256 //server round trip..
}
}
var the_mappy = this;
var intensities = []
var lat_lngs = []
var world_coords = []
function get_coordinateMapType(config) {
function CoordMapType() {}
//CoordMapType.prototype.tileSize = new google.maps.Size(256,256);
CoordMapType.prototype.tileSize = new google.maps.Size(config.tileSize, config.tileSize);
CoordMapType.prototype.maxZoom = 19;
CoordMapType.prototype.getTile = function (coord, zoom, ownerDocument) {
var div = ownerDocument.createElement('DIV');
div.style.width = this.tileSize.width + 'px';
div.style.height = this.tileSize.height + 'px';
div.style.fontSize = '10';
var flash = thisMovie(callback + "_id");
var my_points = []
var tileSize = config.tileSize;
for (var i in world_coords) {
worldCoordinate = world_coords[i];
var pixelCoordinate = get_pixel_coord(worldCoordinate);
var tileCoordinate = get_tile_coord(pixelCoordinate);
//if (Math.abs(tileCoordinate.x - coord.x) < 2 && Math.abs(tileCoordinate.y - coord.y) < 2) { //cut off
var tile_pixel_coord = {
x: coord.x * tileSize,
y: coord.y * tileSize
}
var left_dist = pixelCoordinate.x - tile_pixel_coord.x
var right_dist = tile_pixel_coord.x + tileSize - pixelCoordinate.x
var top_dist = pixelCoordinate.y - tile_pixel_coord.y;
var bottom_dist = tile_pixel_coord.y + tileSize - pixelCoordinate.y;
var buffer = -1 * config.radius * 2 //better algorithm?
if (left_dist > buffer && right_dist > buffer && top_dist > buffer && bottom_dist > buffer) {
var x = pixelCoordinate.x - tileSize * coord.x;
var y = pixelCoordinate.y - tileSize * coord.y;
my_points.push([x, y, intensities[i]]);
}
/*
if (tileCoordinate.x == coord.x && tileCoordinate.y == coord.y) { //cut off
var x = pixelCoordinate.x - 256 * tileCoordinate.x;
var y = pixelCoordinate.y - 256 * tileCoordinate.y;
my_points.push([x,y]);
} */
//cache this and the above in the future
}
if (config.useCanvas == true) {
var canvas = getTile({
points: my_points,
tileSize: config.tileSize,
radius: config.radius,
opacity: config.opacity
});
$(div).append(canvas)
return div;
}
if (!flash.drawHeatMap) {
return div
}
var data = flash.drawHeatMap({
'points': my_points,
'radius': config.radius,
'opacity': config.opacity,
'centerValue': config.centerValue,
'gradient': config.gradient,
'tileSize': config.tileSize
});
$.post(
config.echo, {
data: data
}, function (ret) {
$(div).append("<img src='" + ret + "' />")
})
return div;
};
CoordMapType.prototype.name = "Tile #s";
CoordMapType.prototype.alt = "Tile Coordinate Map Type";
var coordinateMapType = new CoordMapType();
return coordinateMapType
}
function get_heat_map(config) {
var heat_map_options = {
getTileUrl: function (coord, zoom) {
var flash = thisMovie(callback + "_id");
var my_points = []
var tileSize = config.tileSize
for (var i in world_coords) {
worldCoordinate = world_coords[i];
var pixelCoordinate = get_pixel_coord(worldCoordinate);
var tileCoordinate = get_tile_coord(pixelCoordinate);
//if (Math.abs(tileCoordinate.x - coord.x) < 2 && Math.abs(tileCoordinate.y - coord.y) < 2) { //cut off
var tile_pixel_coord = {
x: coord.x * tileSize,
y: coord.y * tileSize
}
var left_dist = pixelCoordinate.x - tile_pixel_coord.x
var right_dist = tile_pixel_coord.x + tileSize - pixelCoordinate.x
var top_dist = pixelCoordinate.y - tile_pixel_coord.y;
var bottom_dist = tile_pixel_coord.y + tileSize - pixelCoordinate.y;
var buffer = -1 * config.radius * 2 //better algorithm?
if (left_dist > buffer && right_dist > buffer && top_dist > buffer && bottom_dist > buffer) {
var x = pixelCoordinate.x - tileSize * coord.x;
var y = pixelCoordinate.y - tileSize * coord.y;
my_points.push([x, y, intensities[i]]);
}
//cache this and the above in the future
}
/* canvas way
return drawTile({
points: my_points,
tileSize: $(the_mappy).attr('data-tile-size'),
radius : $(the_mappy).attr('data-radius')
})
*/
var data = flash.drawHeatMap({
'points': my_points,
'radius': config.radius,
'opacity': config.opacity,
'centerValue': config.centerValue,
'gradient': config.gradient,
'tileSize': config.tileSize
});
//this works for very small tiles
/*
if (IE && IE_version < 8) {
return config.echo2 + "?data=" + encodeURIComponent(data) //works for small tiles like 40
}
*/
return "data:image/png;base64," + data;
//can return an html element too
},
//tileSize: new google.maps.Size(256, 256),
tileSize: new google.maps.Size(config.tileSize, config.tileSize),
isPng: true
};
var heat_map = new google.maps.ImageMapType(heat_map_options);
return heat_map;
}
function get_tile_coord(pixelCoordinate) {
var tileCoordinate = new google.maps.Point(Math.floor(pixelCoordinate.x / MERCATOR_RANGE), Math.floor(pixelCoordinate.y / MERCATOR_RANGE));
return tileCoordinate;
}
function get_pixel_coord(worldCoordinate) {
var pixelCoordinate = new google.maps.Point(worldCoordinate.x * Math.pow(2, config.map.getZoom()), worldCoordinate.y * Math.pow(2, config.map.getZoom()));
return pixelCoordinate;
}
//http://code.google.com/apis/maps/documentation/javascript/overlays.html#ImageMapTypes
function get_points(t) {
var projection = new MercatorProjection();
t = t.split("\\n")
t = $.map(t, function (x, i) {
return $.trim(x)
})
// another way to loop thru array
$(t).each(function () {
var row = this.split(",");
intensities.push(row[0]);
var point = new google.maps.LatLng(row[1], row[2])
lat_lngs.push(point);
world_coords.push(projection.fromLatLngToPoint(point));
})
}
function rnd(low, high) {
return Math.floor(Math.random() * (high - low + 1)) + low
}
//parsing the points to values I need
get_points(config.data);
function add_overlays() {
if (initialized == false) {
setTimeout(add_overlays, 250)
return
}
config.map = $(the_mappy).data('map')
if (IE) {
if (IE_version < 8) {
config.map.overlayMapTypes.insertAt(level, get_coordinateMapType(config)) //works tile size 256
return;
}
config.map.overlayMapTypes.insertAt(level, get_heat_map(config))
} else {
if (config.useCanvas == true) {
config.map.overlayMapTypes.insertAt(level, get_coordinateMapType(config)) //works
} else {
config.map.overlayMapTypes.insertAt(level, get_heat_map(config))
}
}
level = level + 1;
}
if (initialized == true) {
add_overlays()
} else if (initialized_started == true) {
//add_overlays()
setTimeout(add_overlays, 1000)
} else {
var div = this;
var d = (new Date()).getTime() + "" + rnd(0, 100);
callback = "heatmap_" + d;
if (callback in window) {
//
} else {
window[callback] = function () {
//only call once because It may tried to be called twice
window[callback] = function () {}
//hide the flash
//$('#' + callback + '_id').css({'position': 'absolute', 'left' : '-3000px', 'top': '0'})
$('#' + callback + '_id').css({
'width': '0px',
'height': '0px'
})
if (config.map == '') {
if (config.mapOptions == '') {
var latlng = new google.maps.LatLng(33.4483771, -112.0740373);
config.mapOptions = {
zoom: 7,
center: latlng,
mapTypeId: google.maps.MapTypeId.ROADMAP
};
}
config.map = new google.maps.Map($(div)[0], config.mapOptions);
$(div).data('map', config.map)
}
add_overlays();
initialized = true;
//config.map.mapTypes.set('coordinate',coordinateMapType);
//config.map.setMapTypeId('coordinate');
}
}
$(document.body).append('<div id="' + callback + '_id"></div>')
var flashvars = {
callback: callback
}
var params = {
allowScriptAccess: 'allways',
'bgcolor': '#869ca7'
}
var attributes = {}
swfobject.embedSWF(config.swf, callback + "_id", "300", "120", "9.0.0", "", flashvars, params) //,config.swf, flashvars, params, attributes);
initialized_started = true;
}
//there is a bug where firefox and I guess chrome may load the swf twice.
//http://code.google.com/p/swfobject/wiki/faq
return this;
};
})(jQuery);
</script>
<script>
$(document).ready(function(){
$('#map').heatmap({
'data' : $('#points').val(),
'opacity' : 1,
'radius' : 20,
'centerValue' : 10
//, 'useCanvas' : true
, gradient: [0,167772415,335544575,503316726,671088889,855638261,1023410423,1191182584,1358954741,1526726902,1711276277,1879048438,2046820599,2214592757,2382364918,2566914293,2734686453,2902458614,3070230773,3238002934,3422552309,3590324469,3758096630,3925868788,4093640949,4278190326,4278191862,4278193398,4278195190,4278196726,4278198518,4278200054,4278201590,4278203382,4278204918,4278206710,4278208246,4278209782,4278211574,4278213110,4278214902,4278216438,4278217974,4278219766,4278221302,4278223094,4278224630,4278226166,4278227958,4278229494,4278296822,4278232053,4278232821,4278233588,4278234356,4278235124,4278235891,4278236659,4278237426,4278238194,4278238962,4278239729,4278240497,4278241264,4278242032,4278242800,4278243567,4278244335,4278245102,4278245870,4278246638,4278247405,4278248173,4278248940,4278249708,4278250732,4278250722,4278250969,4278251215,4278251462,4278251452,4278251699,4278251945,4278252192,4278252183,4278252429,4278252676,4278252922,4278252913,4278253159,4278253406,4278253652,4278253643,4278253890,4278254136,4278254383,4278254373,4278254620,4278254866,4278255113,4278255360,4278910720,4279566080,4280221440,4280876800,4281597696,4282253056,4282908416,4283563776,4284219136,4284940032,4285595392,4286250752,4286906112,4287561472,4288282368,4288937728,4289593088,4290248448,4290903808,4291624704,4292280064,4292935424,4293590784,4294246144,4294967040,4294900736,4294834432,4294768384,4294702080,4294636032,4294569728,4294503680,4294437376,4294371328,4294305024,4294238976,4294172672,4294106624,4294040320,4293974272,4293907968,4293841920,4293775616,4293709568,4293643264,4293577216,4293510912,4293444864,4293378560,4293378048,4293377536,4293442560,4293507584,4293572608,4293637632,4293702656,4293767680,4293832704,4293897728,4293962752,4294027776,4294092800,4294158080,4294223104,4294288128,4294353152,4294418176,4294483200,4294548224,4294613248,4294678272,4294743296,4294808320,4294873344,4294938624,4294937088,4294935552,4294934016,4294932480,4294931200,4294929664,4294928128,4294926592,4294925312,4294923776,4294922240,4294920704,4294919424,4294917888,4294916352,4294914816,4294913536,4294912000,4294910464,4294908928,4294907648,4294906112,4294904576,4294903040,4294901760,4294903045,4294904330,4294905615,4294906900,4294908185,4294909470,4294910755,4294912040,4294913325,4294914867,4294916152,4294917437,4294918722,4294920007,4294921292,4294922577,4294923862,4294925147,4294926432,4294927974,4294929259,4294930544,4294931829,4294933114,4294934399,4294935684,4294936969,4294938254,4294939539,4294941081,4294942366,4294943651,4294944936,4294946221,4294947506,4294948791,4294950076,4294951361,4294952646,4294954188,4294955473,4294956758,4294958043,4294959328,4294960613,4294961898,4294963183,4294964468,4294965753,4294967295,4294967295,4294967295,4294967295,4294967295,4294967295]
})
})
</script>
</head>
<body>
<div style="width: 100%; height: 600px" id="map"></div>
<textarea id="points" style="display:none;">
14,32.600000,-96.767751
13,32.610000,-80.152594
15,32.610000,-96.951808
4,32.620000,-96.874188
8,32.660000,-117.041286
6,32.660000,-96.762505
16,32.660000,-97.004569
5,32.670000,-95.487313
12,32.670000,-97.078613
6,32.670000,-97.368950
12,32.680000,-114.624630
9,32.680000,-97.186941
12,32.690000,-97.271407
13,32.690000,-97.336823
12,32.700000,-114.637567
2,32.700000,-97.282870
12,32.710000,-96.843588
1,32.710000,-97.097534
13,32.720000,-80.085498
13,32.720000,-80.085498
12,32.720000,-80.268430
11,32.720000,-96.783416
9,32.720000,-97.237410
16,32.720000,-97.335129
2,32.720000,-97.434713
11,32.720000,-97.495585
6,32.730000,-79.975676
4,32.730000,-94.943703
16,32.730000,-96.822811
3,32.730000,-97.123682
11,32.730000,-97.484957
12,32.740000,-96.277918
15,32.740000,-96.700085
13,32.740000,-97.394745
16,32.740000,-97.632370
4,32.750000,-117.244968
12,32.750000,-81.210350
15,32.750000,-96.822036
7,32.750000,-96.830918
7,32.750000,-97.012701
15,32.750000,-97.259562
2,32.750000,-97.332953
5,32.760000,-79.831139
16,32.760000,-96.583523
4,32.760000,-97.799249
7,32.760000,-98.890193
10,32.770000,-79.973634
2,32.770000,-96.704987
14,32.770000,-97.409242
9,32.780000,-79.929373
8,32.780000,-79.930601
14,32.780000,-80.043882
3,32.780000,-96.800000
4,32.780000,-96.800000
5,36.210000,-119.085336
9,36.210000,-86.325106
8,36.230000,-119.321921
6,36.270000,-95.855027
4,36.310000,-119.798829
9,36.320000,-76.156720
9,36.320000,-86.585245
15,36.330000,-119.308829
12,36.330000,-119.646056
16,36.420000,-119.098930
7,36.590000,-121.872689
11,36.610000,-118.057523
1,36.610000,-119.448696
15,36.670000,-77.551050
4,36.730000,-108.205284
10,36.740000,-119.678864
4,36.750000,-119.747678
15,36.750000,-76.210549
3,36.790000,-119.755365
11,36.790000,-119.755620
2,36.790000,-119.755620
3,36.810000,-119.808510
2,36.820000,-77.483162
4,36.870000,-75.981606
13,37.000000,-89.166207
3,37.060000,-120.858290
8,37.090000,-94.517643
11,37.170000,-101.353350
16,37.230000,-80.414440
16,37.250000,-121.931293
3,37.280000,-121.947017
7,37.320000,-79.999379
9,37.330000,-120.473494
13,37.350000,-120.595941
1,37.360000,-122.133343
2,37.370000,-118.400166
2,37.380000,-119.626179
3,37.410000,-79.142500
4,37.440000,-76.320278
5,37.500000,-119.975947
5,37.520000,-77.479650
15,37.560000,-77.442597
4,37.580000,-101.369589
1,37.590000,-77.548455
2,37.670000,-120.957547
3,37.690000,-85.857489
11,37.700000,-121.434713
8,37.720000,-89.219471
15,37.730000,-120.954151
10,37.730000,-88.925254
10,37.740000,-88.539324
16,37.770000,-120.849544
10,37.810000,-121.198751
2,37.900000,-88.929900
7,37.910000,-120.602011
16,37.920000,-76.474305
13,37.920000,-99.409847
15,37.940000,-101.266640
7,37.960000,-121.290647
3,37.960000,-84.480947</textarea>
</body>
</html>
""")
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment