Skip to content

Instantly share code, notes, and snippets.

@chabb
Forked from emeeks/d3map.css
Last active December 12, 2016 16:58
Show Gist options
  • Select an option

  • Save chabb/dee07cdb964ba43ed5bd53836e6eee2e to your computer and use it in GitHub Desktop.

Select an option

Save chabb/dee07cdb964ba43ed5bd53836e6eee2e to your computer and use it in GitHub Desktop.
Raster Reprojection d3.carto.map

This is an example of automatic raster reprojection of a tiled layer from d3.carto.map.

It still needs some work. It does not reproject the raster on-the-fly but rather only reprojects it at "zoomend" which is triggered at the end of a zoom or pan event.

This uses Jason Davies' d3.geo.raster and d3.quadtiles.

(function (global, factory) {
typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports) :
typeof define === 'function' && define.amd ? define(['exports'], factory) :
(factory((global.rastertools = global.rastertools || {})));
}(this, function (exports) { 'use strict';
var isobands = function(data, geoTransform, intervals){
var bands = { "type": "FeatureCollection",
"features": []
};
for(var i=1; i<intervals.length; i++){
var lowerValue = intervals[i-1];
var upperValue = intervals[i];
var coords = projectedIsoband(data, geoTransform, lowerValue, upperValue - lowerValue);
//Change clockwise
for(var j=0; j< coords.length; j++)
coords[j].reverse();
bands['features'].push({"type": "Feature",
"geometry": {
"type": "Polygon",
"coordinates": coords},
"properties": [{"lowerValue": lowerValue, "upperValue": upperValue}]}
);
}
return bands;
};
var projectedIsoband = function(data, geoTransform, minV, bandwidth){
if(typeof(geoTransform) != typeof(new Array()) || geoTransform.length != 6)
throw new Error("GeoTransform must be a 6 elements array");
var coords = isoband(data, minV, bandwidth);
for(var i = 0; i<coords.length; i++){
for(var j = 0; j<coords[i].length; j++){
var coordsGeo = applyGeoTransform(coords[i][j][0], coords[i][j][1], geoTransform);
coords[i][j][0]= coordsGeo[0];
coords[i][j][1]= coordsGeo[1];
}
}
return coords;
};
/**
Xgeo = GT(0) + Xpixel*GT(1) + Yline*GT(2)
Ygeo = GT(3) + Xpixel*GT(4) + Yline*GT(5)
*/
var applyGeoTransform = function(x, y, geoTransform){
var xgeo = geoTransform[0] + x*geoTransform[1] + y*geoTransform[2];
var ygeo = geoTransform[3] + x*geoTransform[4] + y*geoTransform[5];
return [xgeo, ygeo];
}
/*
Compute isobands(s) of a scalar 2D field given a certain
threshold and a bandwidth by applying the Marching Squares
Algorithm. The function returns a list of path coordinates
either for individual polygons within each grid cell, or the
outline of connected polygons.
*/
var isoband = function(data, minV, bandwidth, options){
var settings = {};
var defaultSettings = {
successCallback: null,
progressCallback: null,
verbose: false
};
/* process options */
options = options ? options : {};
var optionKeys = Object.keys(defaultSettings);
for(var i = 0; i < optionKeys.length; i++){
var key = optionKeys[i];
var val = options[key];
val = ((typeof val !== 'undefined') && (val !== null)) ? val : defaultSettings[key];
settings[key] = val;
}
if(settings.verbose)
console.log("computing isobands for [" + minV + ":" + (minV + bandwidth) + "]");
var grid = computeBandGrid(data, minV, bandwidth);
var ret = BandGrid2AreaPaths(grid);
return ret;
};
/*
Thats all for the public interface, below follows the actual
implementation
*/
/* Some private variables */
var Node0 = 64;
var Node1 = 16;
var Node2 = 4;
var Node3 = 1;
/* For isoBands, each square is defined by the three states
of its corner points. However, since computers use power-2
values, we use 2bits per trit, i.e.:
00 ... below minV
01 ... between minV and maxV
10 ... above maxV
Hence we map the 4-trit configurations as follows:
0000 => 0
0001 => 1
0002 => 2
0010 => 4
0011 => 5
0012 => 6
0020 => 8
0021 => 9
0022 => 10
0100 => 16
0101 => 17
0102 => 18
0110 => 20
0111 => 21
0112 => 22
0120 => 24
0121 => 25
0122 => 26
0200 => 32
0201 => 33
0202 => 34
0210 => 36
0211 => 37
0212 => 38
0220 => 40
0221 => 41
0222 => 42
1000 => 64
1001 => 65
1002 => 66
1010 => 68
1011 => 69
1012 => 70
1020 => 72
1021 => 73
1022 => 74
1100 => 80
1101 => 81
1102 => 82
1110 => 84
1111 => 85
1112 => 86
1120 => 88
1121 => 89
1122 => 90
1200 => 96
1201 => 97
1202 => 98
1210 => 100
1211 => 101
1212 => 102
1220 => 104
1221 => 105
1222 => 106
2000 => 128
2001 => 129
2002 => 130
2010 => 132
2011 => 133
2012 => 134
2020 => 136
2021 => 137
2022 => 138
2100 => 144
2101 => 145
2102 => 146
2110 => 148
2111 => 149
2112 => 150
2120 => 152
2121 => 153
2122 => 154
2200 => 160
2201 => 161
2202 => 162
2210 => 164
2211 => 165
2212 => 166
2220 => 168
2221 => 169
2222 => 170
*/
/*
The look-up tables for tracing back the contour path
of isoBands
*/
var isoBandNextXTL = [];
var isoBandNextYTL = [];
var isoBandNextOTL = [];
var isoBandNextXTR = [];
var isoBandNextYTR = [];
var isoBandNextOTR = [];
var isoBandNextXRT = [];
var isoBandNextYRT = [];
var isoBandNextORT = [];
var isoBandNextXRB = [];
var isoBandNextYRB = [];
var isoBandNextORB = [];
var isoBandNextXBL = [];
var isoBandNextYBL = [];
var isoBandNextOBL = [];
var isoBandNextXBR = [];
var isoBandNextYBR = [];
var isoBandNextOBR = [];
var isoBandNextXLT = [];
var isoBandNextYLT = [];
var isoBandNextOLT = [];
var isoBandNextXLB = [];
var isoBandNextYLB = [];
var isoBandNextOLB = [];
isoBandNextXRT[85] = isoBandNextXRB[85] = -1;
isoBandNextYRT[85] = isoBandNextYRB[85] = 0;
isoBandNextORT[85] = isoBandNextORB[85] = 1;
isoBandNextXLT[85] = isoBandNextXLB[85] = 1;
isoBandNextYLT[85] = isoBandNextYLB[85] = 0;
isoBandNextOLT[85] = isoBandNextOLB[85] = 1;
isoBandNextXTL[85] = isoBandNextXTR[85] = 0;
isoBandNextYTL[85] = isoBandNextYTR[85] = -1;
isoBandNextOTL[85] = isoBandNextOBL[85] = 0;
isoBandNextXBR[85] = isoBandNextXBL[85] = 0;
isoBandNextYBR[85] = isoBandNextYBL[85] = 1;
isoBandNextOTR[85] = isoBandNextOBR[85] = 1;
/* triangle cases */
isoBandNextXLB[1] = isoBandNextXLB[169] = 0;
isoBandNextYLB[1] = isoBandNextYLB[169] = -1;
isoBandNextOLB[1] = isoBandNextOLB[169] = 0;
isoBandNextXBL[1] = isoBandNextXBL[169] = -1;
isoBandNextYBL[1] = isoBandNextYBL[169] = 0;
isoBandNextOBL[1] = isoBandNextOBL[169] = 0;
isoBandNextXRB[4] = isoBandNextXRB[166] = 0;
isoBandNextYRB[4] = isoBandNextYRB[166] = -1;
isoBandNextORB[4] = isoBandNextORB[166] = 1;
isoBandNextXBR[4] = isoBandNextXBR[166] = 1;
isoBandNextYBR[4] = isoBandNextYBR[166] = 0;
isoBandNextOBR[4] = isoBandNextOBR[166] = 0;
isoBandNextXRT[16] = isoBandNextXRT[154] = 0;
isoBandNextYRT[16] = isoBandNextYRT[154] = 1;
isoBandNextORT[16] = isoBandNextORT[154] = 1;
isoBandNextXTR[16] = isoBandNextXTR[154] = 1;
isoBandNextYTR[16] = isoBandNextYTR[154] = 0;
isoBandNextOTR[16] = isoBandNextOTR[154] = 1;
isoBandNextXLT[64] = isoBandNextXLT[106] = 0;
isoBandNextYLT[64] = isoBandNextYLT[106] = 1;
isoBandNextOLT[64] = isoBandNextOLT[106] = 0;
isoBandNextXTL[64] = isoBandNextXTL[106] = -1;
isoBandNextYTL[64] = isoBandNextYTL[106] = 0;
isoBandNextOTL[64] = isoBandNextOTL[106] = 1;
/* single trapezoid cases */
isoBandNextXLT[2] = isoBandNextXLT[168] = 0;
isoBandNextYLT[2] = isoBandNextYLT[168] = -1;
isoBandNextOLT[2] = isoBandNextOLT[168] = 1;
isoBandNextXLB[2] = isoBandNextXLB[168] = 0;
isoBandNextYLB[2] = isoBandNextYLB[168] = -1;
isoBandNextOLB[2] = isoBandNextOLB[168] = 0;
isoBandNextXBL[2] = isoBandNextXBL[168] = -1;
isoBandNextYBL[2] = isoBandNextYBL[168] = 0;
isoBandNextOBL[2] = isoBandNextOBL[168] = 0;
isoBandNextXBR[2] = isoBandNextXBR[168] = -1;
isoBandNextYBR[2] = isoBandNextYBR[168] = 0;
isoBandNextOBR[2] = isoBandNextOBR[168] = 1;
isoBandNextXRT[8] = isoBandNextXRT[162] = 0;
isoBandNextYRT[8] = isoBandNextYRT[162] = -1;
isoBandNextORT[8] = isoBandNextORT[162] = 0;
isoBandNextXRB[8] = isoBandNextXRB[162] = 0;
isoBandNextYRB[8] = isoBandNextYRB[162] = -1;
isoBandNextORB[8] = isoBandNextORB[162] = 1;
isoBandNextXBL[8] = isoBandNextXBL[162] = 1;
isoBandNextYBL[8] = isoBandNextYBL[162] = 0;
isoBandNextOBL[8] = isoBandNextOBL[162] = 1;
isoBandNextXBR[8] = isoBandNextXBR[162] = 1;
isoBandNextYBR[8] = isoBandNextYBR[162] = 0;
isoBandNextOBR[8] = isoBandNextOBR[162] = 0;
isoBandNextXRT[32] = isoBandNextXRT[138] = 0;
isoBandNextYRT[32] = isoBandNextYRT[138] = 1;
isoBandNextORT[32] = isoBandNextORT[138] = 1;
isoBandNextXRB[32] = isoBandNextXRB[138] = 0;
isoBandNextYRB[32] = isoBandNextYRB[138] = 1;
isoBandNextORB[32] = isoBandNextORB[138] = 0;
isoBandNextXTL[32] = isoBandNextXTL[138] = 1;
isoBandNextYTL[32] = isoBandNextYTL[138] = 0;
isoBandNextOTL[32] = isoBandNextOTL[138] = 0;
isoBandNextXTR[32] = isoBandNextXTR[138] = 1;
isoBandNextYTR[32] = isoBandNextYTR[138] = 0;
isoBandNextOTR[32] = isoBandNextOTR[138] = 1;
isoBandNextXLB[128] = isoBandNextXLB[42] = 0;
isoBandNextYLB[128] = isoBandNextYLB[42] = 1;
isoBandNextOLB[128] = isoBandNextOLB[42] = 1;
isoBandNextXLT[128] = isoBandNextXLT[42] = 0;
isoBandNextYLT[128] = isoBandNextYLT[42] = 1;
isoBandNextOLT[128] = isoBandNextOLT[42] = 0;
isoBandNextXTL[128] = isoBandNextXTL[42] = -1;
isoBandNextYTL[128] = isoBandNextYTL[42] = 0;
isoBandNextOTL[128] = isoBandNextOTL[42] = 1;
isoBandNextXTR[128] = isoBandNextXTR[42] = -1;
isoBandNextYTR[128] = isoBandNextYTR[42] = 0;
isoBandNextOTR[128] = isoBandNextOTR[42] = 0;
/* single rectangle cases */
isoBandNextXRB[5] = isoBandNextXRB[165] = -1;
isoBandNextYRB[5] = isoBandNextYRB[165] = 0;
isoBandNextORB[5] = isoBandNextORB[165] = 0;
isoBandNextXLB[5] = isoBandNextXLB[165] = 1;
isoBandNextYLB[5] = isoBandNextYLB[165] = 0;
isoBandNextOLB[5] = isoBandNextOLB[165] = 0;
isoBandNextXBR[20] = isoBandNextXBR[150] = 0;
isoBandNextYBR[20] = isoBandNextYBR[150] = 1;
isoBandNextOBR[20] = isoBandNextOBR[150] = 1;
isoBandNextXTR[20] = isoBandNextXTR[150] = 0;
isoBandNextYTR[20] = isoBandNextYTR[150] = -1;
isoBandNextOTR[20] = isoBandNextOTR[150] = 1;
isoBandNextXRT[80] = isoBandNextXRT[90] = -1;
isoBandNextYRT[80] = isoBandNextYRT[90] = 0;
isoBandNextORT[80] = isoBandNextORT[90] = 1;
isoBandNextXLT[80] = isoBandNextXLT[90] = 1;
isoBandNextYLT[80] = isoBandNextYLT[90] = 0;
isoBandNextOLT[80] = isoBandNextOLT[90] = 1;
isoBandNextXBL[65] = isoBandNextXBL[105] = 0;
isoBandNextYBL[65] = isoBandNextYBL[105] = 1;
isoBandNextOBL[65] = isoBandNextOBL[105] = 0;
isoBandNextXTL[65] = isoBandNextXTL[105] = 0;
isoBandNextYTL[65] = isoBandNextYTL[105] = -1;
isoBandNextOTL[65] = isoBandNextOTL[105] = 0;
isoBandNextXRT[160] = isoBandNextXRT[10] = -1;
isoBandNextYRT[160] = isoBandNextYRT[10] = 0;
isoBandNextORT[160] = isoBandNextORT[10] = 1;
isoBandNextXRB[160] = isoBandNextXRB[10] = -1;
isoBandNextYRB[160] = isoBandNextYRB[10] = 0;
isoBandNextORB[160] = isoBandNextORB[10] = 0;
isoBandNextXLB[160] = isoBandNextXLB[10] = 1;
isoBandNextYLB[160] = isoBandNextYLB[10] = 0;
isoBandNextOLB[160] = isoBandNextOLB[10] = 0;
isoBandNextXLT[160] = isoBandNextXLT[10] = 1;
isoBandNextYLT[160] = isoBandNextYLT[10] = 0;
isoBandNextOLT[160] = isoBandNextOLT[10] = 1;
isoBandNextXBR[130] = isoBandNextXBR[40] = 0;
isoBandNextYBR[130] = isoBandNextYBR[40] = 1;
isoBandNextOBR[130] = isoBandNextOBR[40] = 1;
isoBandNextXBL[130] = isoBandNextXBL[40] = 0;
isoBandNextYBL[130] = isoBandNextYBL[40] = 1;
isoBandNextOBL[130] = isoBandNextOBL[40] = 0;
isoBandNextXTL[130] = isoBandNextXTL[40] = 0;
isoBandNextYTL[130] = isoBandNextYTL[40] = -1;
isoBandNextOTL[130] = isoBandNextOTL[40] = 0;
isoBandNextXTR[130] = isoBandNextXTR[40] = 0;
isoBandNextYTR[130] = isoBandNextYTR[40] = -1;
isoBandNextOTR[130] = isoBandNextOTR[40] = 1;
/* single hexagon cases */
isoBandNextXRB[37] = isoBandNextXRB[133] = 0;
isoBandNextYRB[37] = isoBandNextYRB[133] = 1;
isoBandNextORB[37] = isoBandNextORB[133] = 1;
isoBandNextXLB[37] = isoBandNextXLB[133] = 0;
isoBandNextYLB[37] = isoBandNextYLB[133] = 1;
isoBandNextOLB[37] = isoBandNextOLB[133] = 0;
isoBandNextXTL[37] = isoBandNextXTL[133] = -1;
isoBandNextYTL[37] = isoBandNextYTL[133] = 0;
isoBandNextOTL[37] = isoBandNextOTL[133] = 0;
isoBandNextXTR[37] = isoBandNextXTR[133] = 1;
isoBandNextYTR[37] = isoBandNextYTR[133] = 0;
isoBandNextOTR[37] = isoBandNextOTR[133] = 0;
isoBandNextXBR[148] = isoBandNextXBR[22] = -1;
isoBandNextYBR[148] = isoBandNextYBR[22] = 0;
isoBandNextOBR[148] = isoBandNextOBR[22] = 0;
isoBandNextXLB[148] = isoBandNextXLB[22] = 0;
isoBandNextYLB[148] = isoBandNextYLB[22] = -1;
isoBandNextOLB[148] = isoBandNextOLB[22] = 1;
isoBandNextXLT[148] = isoBandNextXLT[22] = 0;
isoBandNextYLT[148] = isoBandNextYLT[22] = 1;
isoBandNextOLT[148] = isoBandNextOLT[22] = 1;
isoBandNextXTR[148] = isoBandNextXTR[22] = -1;
isoBandNextYTR[148] = isoBandNextYTR[22] = 0;
isoBandNextOTR[148] = isoBandNextOTR[22] = 1;
isoBandNextXRT[82] = isoBandNextXRT[88] = 0;
isoBandNextYRT[82] = isoBandNextYRT[88] = -1;
isoBandNextORT[82] = isoBandNextORT[88] = 1;
isoBandNextXBR[82] = isoBandNextXBR[88] = 1;
isoBandNextYBR[82] = isoBandNextYBR[88] = 0;
isoBandNextOBR[82] = isoBandNextOBR[88] = 1;
isoBandNextXBL[82] = isoBandNextXBL[88] = -1;
isoBandNextYBL[82] = isoBandNextYBL[88] = 0;
isoBandNextOBL[82] = isoBandNextOBL[88] = 1;
isoBandNextXLT[82] = isoBandNextXLT[88] = 0;
isoBandNextYLT[82] = isoBandNextYLT[88] = -1;
isoBandNextOLT[82] = isoBandNextOLT[88] = 0;
isoBandNextXRT[73] = isoBandNextXRT[97] = 0;
isoBandNextYRT[73] = isoBandNextYRT[97] = 1;
isoBandNextORT[73] = isoBandNextORT[97] = 0;
isoBandNextXRB[73] = isoBandNextXRB[97] = 0;
isoBandNextYRB[73] = isoBandNextYRB[97] = -1;
isoBandNextORB[73] = isoBandNextORB[97] = 0;
isoBandNextXBL[73] = isoBandNextXBL[97] = 1;
isoBandNextYBL[73] = isoBandNextYBL[97] = 0;
isoBandNextOBL[73] = isoBandNextOBL[97] = 0;
isoBandNextXTL[73] = isoBandNextXTL[97] = 1;
isoBandNextYTL[73] = isoBandNextYTL[97] = 0;
isoBandNextOTL[73] = isoBandNextOTL[97] = 1;
isoBandNextXRT[145] = isoBandNextXRT[25] = 0;
isoBandNextYRT[145] = isoBandNextYRT[25] = -1;
isoBandNextORT[145] = isoBandNextORT[25] = 0;
isoBandNextXBL[145] = isoBandNextXBL[25] = 1;
isoBandNextYBL[145] = isoBandNextYBL[25] = 0;
isoBandNextOBL[145] = isoBandNextOBL[25] = 1;
isoBandNextXLB[145] = isoBandNextXLB[25] = 0;
isoBandNextYLB[145] = isoBandNextYLB[25] = 1;
isoBandNextOLB[145] = isoBandNextOLB[25] = 1;
isoBandNextXTR[145] = isoBandNextXTR[25] = -1;
isoBandNextYTR[145] = isoBandNextYTR[25] = 0;
isoBandNextOTR[145] = isoBandNextOTR[25] = 0;
isoBandNextXRB[70] = isoBandNextXRB[100] = 0;
isoBandNextYRB[70] = isoBandNextYRB[100] = 1;
isoBandNextORB[70] = isoBandNextORB[100] = 0;
isoBandNextXBR[70] = isoBandNextXBR[100] = -1;
isoBandNextYBR[70] = isoBandNextYBR[100] = 0;
isoBandNextOBR[70] = isoBandNextOBR[100] = 1;
isoBandNextXLT[70] = isoBandNextXLT[100] = 0;
isoBandNextYLT[70] = isoBandNextYLT[100] = -1;
isoBandNextOLT[70] = isoBandNextOLT[100] = 1;
isoBandNextXTL[70] = isoBandNextXTL[100] = 1;
isoBandNextYTL[70] = isoBandNextYTL[100] = 0;
isoBandNextOTL[70] = isoBandNextOTL[100] = 0;
/* single pentagon cases */
isoBandNextXRB[101] = isoBandNextXRB[69] = 0;
isoBandNextYRB[101] = isoBandNextYRB[69] = 1;
isoBandNextORB[101] = isoBandNextORB[69] = 0;
isoBandNextXTL[101] = isoBandNextXTL[69] = 1;
isoBandNextYTL[101] = isoBandNextYTL[69] = 0;
isoBandNextOTL[101] = isoBandNextOTL[69] = 0;
isoBandNextXLB[149] = isoBandNextXLB[21] = 0;
isoBandNextYLB[149] = isoBandNextYLB[21] = 1;
isoBandNextOLB[149] = isoBandNextOLB[21] = 1;
isoBandNextXTR[149] = isoBandNextXTR[21] = -1;
isoBandNextYTR[149] = isoBandNextYTR[21] = 0;
isoBandNextOTR[149] = isoBandNextOTR[21] = 0;
isoBandNextXBR[86] = isoBandNextXBR[84] = -1;
isoBandNextYBR[86] = isoBandNextYBR[84] = 0;
isoBandNextOBR[86] = isoBandNextOBR[84] = 1;
isoBandNextXLT[86] = isoBandNextXLT[84] = 0;
isoBandNextYLT[86] = isoBandNextYLT[84] = -1;
isoBandNextOLT[86] = isoBandNextOLT[84] = 1;
isoBandNextXRT[89] = isoBandNextXRT[81] = 0;
isoBandNextYRT[89] = isoBandNextYRT[81] = -1;
isoBandNextORT[89] = isoBandNextORT[81] = 0;
isoBandNextXBL[89] = isoBandNextXBL[81] = 1;
isoBandNextYBL[89] = isoBandNextYBL[81] = 0;
isoBandNextOBL[89] = isoBandNextOBL[81] = 1;
isoBandNextXRT[96] = isoBandNextXRT[74] = 0;
isoBandNextYRT[96] = isoBandNextYRT[74] = 1;
isoBandNextORT[96] = isoBandNextORT[74] = 0;
isoBandNextXRB[96] = isoBandNextXRB[74] = -1;
isoBandNextYRB[96] = isoBandNextYRB[74] = 0;
isoBandNextORB[96] = isoBandNextORB[74] = 1;
isoBandNextXLT[96] = isoBandNextXLT[74] = 1;
isoBandNextYLT[96] = isoBandNextYLT[74] = 0;
isoBandNextOLT[96] = isoBandNextOLT[74] = 0;
isoBandNextXTL[96] = isoBandNextXTL[74] = 1;
isoBandNextYTL[96] = isoBandNextYTL[74] = 0;
isoBandNextOTL[96] = isoBandNextOTL[74] = 1;
isoBandNextXRT[24] = isoBandNextXRT[146] = 0;
isoBandNextYRT[24] = isoBandNextYRT[146] = -1;
isoBandNextORT[24] = isoBandNextORT[146] = 1;
isoBandNextXBR[24] = isoBandNextXBR[146] = 1;
isoBandNextYBR[24] = isoBandNextYBR[146] = 0;
isoBandNextOBR[24] = isoBandNextOBR[146] = 1;
isoBandNextXBL[24] = isoBandNextXBL[146] = 0;
isoBandNextYBL[24] = isoBandNextYBL[146] = 1;
isoBandNextOBL[24] = isoBandNextOBL[146] = 1;
isoBandNextXTR[24] = isoBandNextXTR[146] = 0;
isoBandNextYTR[24] = isoBandNextYTR[146] = -1;
isoBandNextOTR[24] = isoBandNextOTR[146] = 0;
isoBandNextXRB[6] = isoBandNextXRB[164] = -1;
isoBandNextYRB[6] = isoBandNextYRB[164] = 0;
isoBandNextORB[6] = isoBandNextORB[164] = 1;
isoBandNextXBR[6] = isoBandNextXBR[164] = -1;
isoBandNextYBR[6] = isoBandNextYBR[164] = 0;
isoBandNextOBR[6] = isoBandNextOBR[164] = 0;
isoBandNextXLB[6] = isoBandNextXLB[164] = 0;
isoBandNextYLB[6] = isoBandNextYLB[164] = -1;
isoBandNextOLB[6] = isoBandNextOLB[164] = 1;
isoBandNextXLT[6] = isoBandNextXLT[164] = 1;
isoBandNextYLT[6] = isoBandNextYLT[164] = 0;
isoBandNextOLT[6] = isoBandNextOLT[164] = 0;
isoBandNextXBL[129] = isoBandNextXBL[41] = 0;
isoBandNextYBL[129] = isoBandNextYBL[41] = 1;
isoBandNextOBL[129] = isoBandNextOBL[41] = 1;
isoBandNextXLB[129] = isoBandNextXLB[41] = 0;
isoBandNextYLB[129] = isoBandNextYLB[41] = 1;
isoBandNextOLB[129] = isoBandNextOLB[41] = 0;
isoBandNextXTL[129] = isoBandNextXTL[41] = -1;
isoBandNextYTL[129] = isoBandNextYTL[41] = 0;
isoBandNextOTL[129] = isoBandNextOTL[41] = 0;
isoBandNextXTR[129] = isoBandNextXTR[41] = 0;
isoBandNextYTR[129] = isoBandNextYTR[41] = -1;
isoBandNextOTR[129] = isoBandNextOTR[41] = 0;
isoBandNextXBR[66] = isoBandNextXBR[104] = 0;
isoBandNextYBR[66] = isoBandNextYBR[104] = 1;
isoBandNextOBR[66] = isoBandNextOBR[104] = 0;
isoBandNextXBL[66] = isoBandNextXBL[104] = -1;
isoBandNextYBL[66] = isoBandNextYBL[104] = 0;
isoBandNextOBL[66] = isoBandNextOBL[104] = 1;
isoBandNextXLT[66] = isoBandNextXLT[104] = 0;
isoBandNextYLT[66] = isoBandNextYLT[104] = -1;
isoBandNextOLT[66] = isoBandNextOLT[104] = 0;
isoBandNextXTL[66] = isoBandNextXTL[104] = 0;
isoBandNextYTL[66] = isoBandNextYTL[104] = -1;
isoBandNextOTL[66] = isoBandNextOTL[104] = 1;
isoBandNextXRT[144] = isoBandNextXRT[26] = -1;
isoBandNextYRT[144] = isoBandNextYRT[26] = 0;
isoBandNextORT[144] = isoBandNextORT[26] = 0;
isoBandNextXLB[144] = isoBandNextXLB[26] = 1;
isoBandNextYLB[144] = isoBandNextYLB[26] = 0;
isoBandNextOLB[144] = isoBandNextOLB[26] = 1;
isoBandNextXLT[144] = isoBandNextXLT[26] = 0;
isoBandNextYLT[144] = isoBandNextYLT[26] = 1;
isoBandNextOLT[144] = isoBandNextOLT[26] = 1;
isoBandNextXTR[144] = isoBandNextXTR[26] = -1;
isoBandNextYTR[144] = isoBandNextYTR[26] = 0;
isoBandNextOTR[144] = isoBandNextOTR[26] = 1;
isoBandNextXRB[36] = isoBandNextXRB[134] = 0;
isoBandNextYRB[36] = isoBandNextYRB[134] = 1;
isoBandNextORB[36] = isoBandNextORB[134] = 1;
isoBandNextXBR[36] = isoBandNextXBR[134] = 0;
isoBandNextYBR[36] = isoBandNextYBR[134] = 1;
isoBandNextOBR[36] = isoBandNextOBR[134] = 0;
isoBandNextXTL[36] = isoBandNextXTL[134] = 0;
isoBandNextYTL[36] = isoBandNextYTL[134] = -1;
isoBandNextOTL[36] = isoBandNextOTL[134] = 1;
isoBandNextXTR[36] = isoBandNextXTR[134] = 1;
isoBandNextYTR[36] = isoBandNextYTR[134] = 0;
isoBandNextOTR[36] = isoBandNextOTR[134] = 0;
isoBandNextXRT[9] = isoBandNextXRT[161] = -1;
isoBandNextYRT[9] = isoBandNextYRT[161] = 0;
isoBandNextORT[9] = isoBandNextORT[161] = 0;
isoBandNextXRB[9] = isoBandNextXRB[161] = 0;
isoBandNextYRB[9] = isoBandNextYRB[161] = -1;
isoBandNextORB[9] = isoBandNextORB[161] = 0;
isoBandNextXBL[9] = isoBandNextXBL[161] = 1;
isoBandNextYBL[9] = isoBandNextYBL[161] = 0;
isoBandNextOBL[9] = isoBandNextOBL[161] = 0;
isoBandNextXLB[9] = isoBandNextXLB[161] = 1;
isoBandNextYLB[9] = isoBandNextYLB[161] = 0;
isoBandNextOLB[9] = isoBandNextOLB[161] = 1;
/* 8-sided cases */
isoBandNextXRT[136] = 0;
isoBandNextYRT[136] = 1;
isoBandNextORT[136] = 1;
isoBandNextXRB[136] = 0;
isoBandNextYRB[136] = 1;
isoBandNextORB[136] = 0;
isoBandNextXBR[136] = -1;
isoBandNextYBR[136] = 0;
isoBandNextOBR[136] = 1;
isoBandNextXBL[136] = -1;
isoBandNextYBL[136] = 0;
isoBandNextOBL[136] = 0;
isoBandNextXLB[136] = 0;
isoBandNextYLB[136] = -1;
isoBandNextOLB[136] = 0;
isoBandNextXLT[136] = 0;
isoBandNextYLT[136] = -1;
isoBandNextOLT[136] = 1;
isoBandNextXTL[136] = 1;
isoBandNextYTL[136] = 0;
isoBandNextOTL[136] = 0;
isoBandNextXTR[136] = 1;
isoBandNextYTR[136] = 0;
isoBandNextOTR[136] = 1;
isoBandNextXRT[34] = 0;
isoBandNextYRT[34] = -1;
isoBandNextORT[34] = 0;
isoBandNextXRB[34] = 0;
isoBandNextYRB[34] = -1;
isoBandNextORB[34] = 1;
isoBandNextXBR[34] = 1;
isoBandNextYBR[34] = 0;
isoBandNextOBR[34] = 0;
isoBandNextXBL[34] = 1;
isoBandNextYBL[34] = 0;
isoBandNextOBL[34] = 1;
isoBandNextXLB[34] = 0;
isoBandNextYLB[34] = 1;
isoBandNextOLB[34] = 1;
isoBandNextXLT[34] = 0;
isoBandNextYLT[34] = 1;
isoBandNextOLT[34] = 0;
isoBandNextXTL[34] = -1;
isoBandNextYTL[34] = 0;
isoBandNextOTL[34] = 1;
isoBandNextXTR[34] = -1;
isoBandNextYTR[34] = 0;
isoBandNextOTR[34] = 0;
isoBandNextXRT[35] = 0;
isoBandNextYRT[35] = 1;
isoBandNextORT[35] = 1;
isoBandNextXRB[35] = 0;
isoBandNextYRB[35] = -1;
isoBandNextORB[35] = 1;
isoBandNextXBR[35] = 1;
isoBandNextYBR[35] = 0;
isoBandNextOBR[35] = 0;
isoBandNextXBL[35] = -1;
isoBandNextYBL[35] = 0;
isoBandNextOBL[35] = 0;
isoBandNextXLB[35] = 0;
isoBandNextYLB[35] = -1;
isoBandNextOLB[35] = 0;
isoBandNextXLT[35] = 0;
isoBandNextYLT[35] = 1;
isoBandNextOLT[35] = 0;
isoBandNextXTL[35] = -1;
isoBandNextYTL[35] = 0;
isoBandNextOTL[35] = 1;
isoBandNextXTR[35] = 1;
isoBandNextYTR[35] = 0;
isoBandNextOTR[35] = 1;
/* 6-sided cases */
isoBandNextXRT[153] = 0;
isoBandNextYRT[153] = 1;
isoBandNextORT[153] = 1;
isoBandNextXBL[153] = -1;
isoBandNextYBL[153] = 0;
isoBandNextOBL[153] = 0;
isoBandNextXLB[153] = 0;
isoBandNextYLB[153] = -1;
isoBandNextOLB[153] = 0;
isoBandNextXTR[153] = 1;
isoBandNextYTR[153] = 0;
isoBandNextOTR[153] = 1;
isoBandNextXRB[102] = 0;
isoBandNextYRB[102] = -1;
isoBandNextORB[102] = 1;
isoBandNextXBR[102] = 1;
isoBandNextYBR[102] = 0;
isoBandNextOBR[102] = 0;
isoBandNextXLT[102] = 0;
isoBandNextYLT[102] = 1;
isoBandNextOLT[102] = 0;
isoBandNextXTL[102] = -1;
isoBandNextYTL[102] = 0;
isoBandNextOTL[102] = 1;
isoBandNextXRT[155] = 0;
isoBandNextYRT[155] = -1;
isoBandNextORT[155] = 0;
isoBandNextXBL[155] = 1;
isoBandNextYBL[155] = 0;
isoBandNextOBL[155] = 1;
isoBandNextXLB[155] = 0;
isoBandNextYLB[155] = 1;
isoBandNextOLB[155] = 1;
isoBandNextXTR[155] = -1;
isoBandNextYTR[155] = 0;
isoBandNextOTR[155] = 0;
isoBandNextXRB[103] = 0;
isoBandNextYRB[103] = 1;
isoBandNextORB[103] = 0;
isoBandNextXBR[103] = -1;
isoBandNextYBR[103] = 0;
isoBandNextOBR[103] = 1;
isoBandNextXLT[103] = 0;
isoBandNextYLT[103] = -1;
isoBandNextOLT[103] = 1;
isoBandNextXTL[103] = 1;
isoBandNextYTL[103] = 0;
isoBandNextOTL[103] = 0;
/* 7-sided cases */
isoBandNextXRT[152] = 0;
isoBandNextYRT[152] = 1;
isoBandNextORT[152] = 1;
isoBandNextXBR[152] = -1;
isoBandNextYBR[152] = 0;
isoBandNextOBR[152] = 1;
isoBandNextXBL[152] = -1;
isoBandNextYBL[152] = 0;
isoBandNextOBL[152] = 0;
isoBandNextXLB[152] = 0;
isoBandNextYLB[152] = -1;
isoBandNextOLB[152] = 0;
isoBandNextXLT[152] = 0;
isoBandNextYLT[152] = -1;
isoBandNextOLT[152] = 1;
isoBandNextXTR[152] = 1;
isoBandNextYTR[152] = 0;
isoBandNextOTR[152] = 1;
isoBandNextXRT[156] = 0;
isoBandNextYRT[156] = -1;
isoBandNextORT[156] = 1;
isoBandNextXBR[156] = 1;
isoBandNextYBR[156] = 0;
isoBandNextOBR[156] = 1;
isoBandNextXBL[156] = -1;
isoBandNextYBL[156] = 0;
isoBandNextOBL[156] = 0;
isoBandNextXLB[156] = 0;
isoBandNextYLB[156] = -1;
isoBandNextOLB[156] = 0;
isoBandNextXLT[156] = 0;
isoBandNextYLT[156] = 1;
isoBandNextOLT[156] = 1;
isoBandNextXTR[156] = -1;
isoBandNextYTR[156] = 0;
isoBandNextOTR[156] = 1;
isoBandNextXRT[137] = 0;
isoBandNextYRT[137] = 1;
isoBandNextORT[137] = 1;
isoBandNextXRB[137] = 0;
isoBandNextYRB[137] = 1;
isoBandNextORB[137] = 0;
isoBandNextXBL[137] = -1;
isoBandNextYBL[137] = 0;
isoBandNextOBL[137] = 0;
isoBandNextXLB[137] = 0;
isoBandNextYLB[137] = -1;
isoBandNextOLB[137] = 0;
isoBandNextXTL[137] = 1;
isoBandNextYTL[137] = 0;
isoBandNextOTL[137] = 0;
isoBandNextXTR[137] = 1;
isoBandNextYTR[137] = 0;
isoBandNextOTR[137] = 1;
isoBandNextXRT[139] = 0;
isoBandNextYRT[139] = 1;
isoBandNextORT[139] = 1;
isoBandNextXRB[139] = 0;
isoBandNextYRB[139] = -1;
isoBandNextORB[139] = 0;
isoBandNextXBL[139] = 1;
isoBandNextYBL[139] = 0;
isoBandNextOBL[139] = 0;
isoBandNextXLB[139] = 0;
isoBandNextYLB[139] = 1;
isoBandNextOLB[139] = 0;
isoBandNextXTL[139] = -1;
isoBandNextYTL[139] = 0;
isoBandNextOTL[139] = 0;
isoBandNextXTR[139] = 1;
isoBandNextYTR[139] = 0;
isoBandNextOTR[139] = 1;
isoBandNextXRT[98] = 0;
isoBandNextYRT[98] = -1;
isoBandNextORT[98] = 0;
isoBandNextXRB[98] = 0;
isoBandNextYRB[98] = -1;
isoBandNextORB[98] = 1;
isoBandNextXBR[98] = 1;
isoBandNextYBR[98] = 0;
isoBandNextOBR[98] = 0;
isoBandNextXBL[98] = 1;
isoBandNextYBL[98] = 0;
isoBandNextOBL[98] = 1;
isoBandNextXLT[98] = 0;
isoBandNextYLT[98] = 1;
isoBandNextOLT[98] = 0;
isoBandNextXTL[98] = -1;
isoBandNextYTL[98] = 0;
isoBandNextOTL[98] = 1;
isoBandNextXRT[99] = 0;
isoBandNextYRT[99] = 1;
isoBandNextORT[99] = 0;
isoBandNextXRB[99] = 0;
isoBandNextYRB[99] = -1;
isoBandNextORB[99] = 1;
isoBandNextXBR[99] = 1;
isoBandNextYBR[99] = 0;
isoBandNextOBR[99] = 0;
isoBandNextXBL[99] = -1;
isoBandNextYBL[99] = 0;
isoBandNextOBL[99] = 1;
isoBandNextXLT[99] = 0;
isoBandNextYLT[99] = -1;
isoBandNextOLT[99] = 0;
isoBandNextXTL[99] = 1;
isoBandNextYTL[99] = 0;
isoBandNextOTL[99] = 1;
isoBandNextXRB[38] = 0;
isoBandNextYRB[38] = -1;
isoBandNextORB[38] = 1;
isoBandNextXBR[38] = 1;
isoBandNextYBR[38] = 0;
isoBandNextOBR[38] = 0;
isoBandNextXLB[38] = 0;
isoBandNextYLB[38] = 1;
isoBandNextOLB[38] = 1;
isoBandNextXLT[38] = 0;
isoBandNextYLT[38] = 1;
isoBandNextOLT[38] = 0;
isoBandNextXTL[38] = -1;
isoBandNextYTL[38] = 0;
isoBandNextOTL[38] = 1;
isoBandNextXTR[38] = -1;
isoBandNextYTR[38] = 0;
isoBandNextOTR[38] = 0;
isoBandNextXRB[39] = 0;
isoBandNextYRB[39] = 1;
isoBandNextORB[39] = 1;
isoBandNextXBR[39] = -1;
isoBandNextYBR[39] = 0;
isoBandNextOBR[39] = 0;
isoBandNextXLB[39] = 0;
isoBandNextYLB[39] = -1;
isoBandNextOLB[39] = 1;
isoBandNextXLT[39] = 0;
isoBandNextYLT[39] = 1;
isoBandNextOLT[39] = 0;
isoBandNextXTL[39] = -1;
isoBandNextYTL[39] = 0;
isoBandNextOTL[39] = 1;
isoBandNextXTR[39] = 1;
isoBandNextYTR[39] = 0;
isoBandNextOTR[39] = 0;
/*
The lookup tables for edge number given the polygon
is entered at a specific location
*/
var isoBandEdgeRT = [];
var isoBandEdgeRB = [];
var isoBandEdgeBR = [];
var isoBandEdgeBL = [];
var isoBandEdgeLB = [];
var isoBandEdgeLT = [];
var isoBandEdgeTL = [];
var isoBandEdgeTR = [];
/* triangle cases */
isoBandEdgeBL[1] = isoBandEdgeLB[1] = 18;
isoBandEdgeBL[169] = isoBandEdgeLB[169] = 18;
isoBandEdgeBR[4] = isoBandEdgeRB[4] = 12;
isoBandEdgeBR[166] = isoBandEdgeRB[166] = 12;
isoBandEdgeRT[16] = isoBandEdgeTR[16] = 4;
isoBandEdgeRT[154] = isoBandEdgeTR[154] = 4;
isoBandEdgeLT[64] = isoBandEdgeTL[64] = 22;
isoBandEdgeLT[106] = isoBandEdgeTL[106] = 22;
/* trapezoid cases */
isoBandEdgeBR[2] = isoBandEdgeLT[2] = 17;
isoBandEdgeBL[2] = isoBandEdgeLB[2] = 18;
isoBandEdgeBR[168] = isoBandEdgeLT[168] = 17;
isoBandEdgeBL[168] = isoBandEdgeLB[168] = 18;
isoBandEdgeRT[8] = isoBandEdgeBL[8] = 9;
isoBandEdgeRB[8] = isoBandEdgeBR[8] = 12;
isoBandEdgeRT[162] = isoBandEdgeBL[162] = 9;
isoBandEdgeRB[162] = isoBandEdgeBR[162] = 12;
isoBandEdgeRT[32] = isoBandEdgeTR[32] = 4;
isoBandEdgeRB[32] = isoBandEdgeTL[32] = 1;
isoBandEdgeRT[138] = isoBandEdgeTR[138] = 4;
isoBandEdgeRB[138] = isoBandEdgeTL[138] = 1;
isoBandEdgeLB[128] = isoBandEdgeTR[128] = 21;
isoBandEdgeLT[128] = isoBandEdgeTL[128] = 22;
isoBandEdgeLB[42] = isoBandEdgeTR[42] = 21;
isoBandEdgeLT[42] = isoBandEdgeTL[42] = 22;
/* rectangle cases */
isoBandEdgeRB[5] = isoBandEdgeLB[5] = 14;
isoBandEdgeRB[165] = isoBandEdgeLB[165] = 14;
isoBandEdgeBR[20] = isoBandEdgeTR[20] = 6;
isoBandEdgeBR[150] = isoBandEdgeTR[150] = 6;
isoBandEdgeRT[80] = isoBandEdgeLT[80] = 11;
isoBandEdgeRT[90] = isoBandEdgeLT[90] = 11;
isoBandEdgeBL[65] = isoBandEdgeTL[65] = 3;
isoBandEdgeBL[105] = isoBandEdgeTL[105] = 3;
isoBandEdgeRT[160] = isoBandEdgeLT[160] = 11;
isoBandEdgeRB[160] = isoBandEdgeLB[160] = 14;
isoBandEdgeRT[10] = isoBandEdgeLT[10] = 11;
isoBandEdgeRB[10] = isoBandEdgeLB[10] = 14;
isoBandEdgeBR[130] = isoBandEdgeTR[130] = 6;
isoBandEdgeBL[130] = isoBandEdgeTL[130] = 3;
isoBandEdgeBR[40] = isoBandEdgeTR[40] = 6;
isoBandEdgeBL[40] = isoBandEdgeTL[40] = 3;
/* pentagon cases */
isoBandEdgeRB[101] = isoBandEdgeTL[101] = 1;
isoBandEdgeRB[69] = isoBandEdgeTL[69] = 1;
isoBandEdgeLB[149] = isoBandEdgeTR[149] = 21;
isoBandEdgeLB[21] = isoBandEdgeTR[21] = 21;
isoBandEdgeBR[86] = isoBandEdgeLT[86] = 17;
isoBandEdgeBR[84] = isoBandEdgeLT[84] = 17;
isoBandEdgeRT[89] = isoBandEdgeBL[89] = 9;
isoBandEdgeRT[81] = isoBandEdgeBL[81] = 9;
isoBandEdgeRT[96] = isoBandEdgeTL[96] = 0;
isoBandEdgeRB[96] = isoBandEdgeLT[96] = 15;
isoBandEdgeRT[74] = isoBandEdgeTL[74] = 0;
isoBandEdgeRB[74] = isoBandEdgeLT[74] = 15;
isoBandEdgeRT[24] = isoBandEdgeBR[24] = 8;
isoBandEdgeBL[24] = isoBandEdgeTR[24] = 7;
isoBandEdgeRT[146] = isoBandEdgeBR[146] = 8;
isoBandEdgeBL[146] = isoBandEdgeTR[146] = 7;
isoBandEdgeRB[6] = isoBandEdgeLT[6] = 15;
isoBandEdgeBR[6] = isoBandEdgeLB[6] = 16;
isoBandEdgeRB[164] = isoBandEdgeLT[164] = 15;
isoBandEdgeBR[164] = isoBandEdgeLB[164] = 16;
isoBandEdgeBL[129] = isoBandEdgeTR[129] = 7;
isoBandEdgeLB[129] = isoBandEdgeTL[129] = 20;
isoBandEdgeBL[41] = isoBandEdgeTR[41] = 7;
isoBandEdgeLB[41] = isoBandEdgeTL[41] = 20;
isoBandEdgeBR[66] = isoBandEdgeTL[66] = 2;
isoBandEdgeBL[66] = isoBandEdgeLT[66] = 19;
isoBandEdgeBR[104] = isoBandEdgeTL[104] = 2;
isoBandEdgeBL[104] = isoBandEdgeLT[104] = 19;
isoBandEdgeRT[144] = isoBandEdgeLB[144] = 10;
isoBandEdgeLT[144] = isoBandEdgeTR[144] = 23;
isoBandEdgeRT[26] = isoBandEdgeLB[26] = 10;
isoBandEdgeLT[26] = isoBandEdgeTR[26] = 23;
isoBandEdgeRB[36] = isoBandEdgeTR[36] = 5;
isoBandEdgeBR[36] = isoBandEdgeTL[36] = 2;
isoBandEdgeRB[134] = isoBandEdgeTR[134] = 5;
isoBandEdgeBR[134] = isoBandEdgeTL[134] = 2;
isoBandEdgeRT[9] = isoBandEdgeLB[9] = 10;
isoBandEdgeRB[9] = isoBandEdgeBL[9] = 13;
isoBandEdgeRT[161] = isoBandEdgeLB[161] = 10;
isoBandEdgeRB[161] = isoBandEdgeBL[161] = 13;
/* hexagon cases */
isoBandEdgeRB[37] = isoBandEdgeTR[37] = 5;
isoBandEdgeLB[37] = isoBandEdgeTL[37] = 20;
isoBandEdgeRB[133] = isoBandEdgeTR[133] = 5;
isoBandEdgeLB[133] = isoBandEdgeTL[133] = 20;
isoBandEdgeBR[148] = isoBandEdgeLB[148] = 16;
isoBandEdgeLT[148] = isoBandEdgeTR[148] = 23;
isoBandEdgeBR[22] = isoBandEdgeLB[22] = 16;
isoBandEdgeLT[22] = isoBandEdgeTR[22] = 23;
isoBandEdgeRT[82] = isoBandEdgeBR[82] = 8;
isoBandEdgeBL[82] = isoBandEdgeLT[82] = 19;
isoBandEdgeRT[88] = isoBandEdgeBR[88] = 8;
isoBandEdgeBL[88] = isoBandEdgeLT[88] = 19;
isoBandEdgeRT[73] = isoBandEdgeTL[73] = 0;
isoBandEdgeRB[73] = isoBandEdgeBL[73] = 13;
isoBandEdgeRT[97] = isoBandEdgeTL[97] = 0;
isoBandEdgeRB[97] = isoBandEdgeBL[97] = 13;
isoBandEdgeRT[145] = isoBandEdgeBL[145] = 9;
isoBandEdgeLB[145] = isoBandEdgeTR[145] = 21;
isoBandEdgeRT[25] = isoBandEdgeBL[25] = 9;
isoBandEdgeLB[25] = isoBandEdgeTR[25] = 21;
isoBandEdgeRB[70] = isoBandEdgeTL[70] = 1;
isoBandEdgeBR[70] = isoBandEdgeLT[70] = 17;
isoBandEdgeRB[100] = isoBandEdgeTL[100] = 1;
isoBandEdgeBR[100] = isoBandEdgeLT[100] = 17;
/* 8-sided cases */
isoBandEdgeRT[34] = isoBandEdgeBL[34] = 9;
isoBandEdgeRB[34] = isoBandEdgeBR[34] = 12;
isoBandEdgeLB[34] = isoBandEdgeTR[34] = 21;
isoBandEdgeLT[34] = isoBandEdgeTL[34] = 22;
isoBandEdgeRT[136] = isoBandEdgeTR[136] = 4;
isoBandEdgeRB[136] = isoBandEdgeTL[136] = 1;
isoBandEdgeBR[136] = isoBandEdgeLT[136] = 17;
isoBandEdgeBL[136] = isoBandEdgeLB[136] = 18;
isoBandEdgeRT[35] = isoBandEdgeTR[35] = 4;
isoBandEdgeRB[35] = isoBandEdgeBR[35] = 12;
isoBandEdgeBL[35] = isoBandEdgeLB[35] = 18;
isoBandEdgeLT[35] = isoBandEdgeTL[35] = 22;
/* 6-sided cases */
isoBandEdgeRT[153] = isoBandEdgeTR[153] = 4;
isoBandEdgeBL[153] = isoBandEdgeLB[153] = 18;
isoBandEdgeRB[102] = isoBandEdgeBR[102] = 12;
isoBandEdgeLT[102] = isoBandEdgeTL[102] = 22;
isoBandEdgeRT[155] = isoBandEdgeBL[155] = 9;
isoBandEdgeLB[155] = isoBandEdgeTR[155] = 23;
isoBandEdgeRB[103] = isoBandEdgeTL[103] = 1;
isoBandEdgeBR[103] = isoBandEdgeLT[103] = 17;
/* 7-sided cases */
isoBandEdgeRT[152] = isoBandEdgeTR[152] = 4;
isoBandEdgeBR[152] = isoBandEdgeLT[152] = 17;
isoBandEdgeBL[152] = isoBandEdgeLB[152] = 18;
isoBandEdgeRT[156] = isoBandEdgeBR[156] = 8;
isoBandEdgeBL[156] = isoBandEdgeLB[156] = 18;
isoBandEdgeLT[156] = isoBandEdgeTR[156] = 23;
isoBandEdgeRT[137] = isoBandEdgeTR[137] = 4;
isoBandEdgeRB[137] = isoBandEdgeTL[137] = 1;
isoBandEdgeBL[137] = isoBandEdgeLB[137] = 18;
isoBandEdgeRT[139] = isoBandEdgeTR[139] = 4;
isoBandEdgeRB[139] = isoBandEdgeBL[139] = 13;
isoBandEdgeLB[139] = isoBandEdgeTL[139] = 20;
isoBandEdgeRT[98] = isoBandEdgeBL[98] = 9;
isoBandEdgeRB[98] = isoBandEdgeBR[98] = 12;
isoBandEdgeLT[98] = isoBandEdgeTL[98] = 22;
isoBandEdgeRT[99] = isoBandEdgeTL[99] = 0;
isoBandEdgeRB[99] = isoBandEdgeBR[99] = 12;
isoBandEdgeBL[99] = isoBandEdgeLT[99] = 19;
isoBandEdgeRB[38] = isoBandEdgeBR[38] = 12;
isoBandEdgeLB[38] = isoBandEdgeTR[38] = 21;
isoBandEdgeLT[38] = isoBandEdgeTL[38] = 22;
isoBandEdgeRB[39] = isoBandEdgeTR[39] = 5;
isoBandEdgeBR[39] = isoBandEdgeLB[39] = 16;
isoBandEdgeLT[39] = isoBandEdgeTL[39] = 22;
/* 0212 with flipped == 1 || 2010 with flipped == 1 */
/*
####################################
Some small helper functions
####################################
*/
/* assume that x1 == 1 && x0 == 0 */
function interpolateX(y, y0, y1){
return (y - y0) / (y1 - y0);
}
/*
####################################
Below is the actual Marching Squares implementation
####################################
*/
var computeBandGrid = function(data, minV, bandwidth){
var rows = data.length - 1;
var cols = data[0].length - 1;
var BandGrid = { rows: rows, cols: cols, cells: [] };
var maxV = minV + Math.abs(bandwidth);
for(var j = 0; j < rows; ++j){
BandGrid.cells[j] = [];
for(var i = 0; i < cols; ++i){
/* compose the 4-trit corner representation */
var cval = 0;
var tl = data[j+1][i];
var tr = data[j+1][i+1];
var br = data[j][i+1];
var bl = data[j][i];
if(isNaN(tl) || isNaN(tr) || isNaN(br) || isNaN(bl)){
continue;
}
cval |= (tl < minV) ? 0 : (tl > maxV) ? 128 : 64;
cval |= (tr < minV) ? 0 : (tr > maxV) ? 32 : 16;
cval |= (br < minV) ? 0 : (br > maxV) ? 8 : 4;
cval |= (bl < minV) ? 0 : (bl > maxV) ? 2 : 1;
var cval_real = +cval;
/* resolve ambiguity via averaging */
var flipped = 0;
if( (cval == 17) /* 0101 */
|| (cval == 18) /* 0102 */
|| (cval == 33) /* 0201 */
|| (cval == 34) /* 0202 */
|| (cval == 38) /* 0212 */
|| (cval == 68) /* 1010 */
|| (cval == 72) /* 1020 */
|| (cval == 98) /* 1202 */
|| (cval == 102) /* 1212 */
|| (cval == 132) /* 2010 */
|| (cval == 136) /* 2020 */
|| (cval == 137) /* 2021 */
|| (cval == 152) /* 2120 */
|| (cval == 153) /* 2121 */
){
var average = (tl + tr + br + bl) / 4;
/* set flipped state */
flipped = (average > maxV) ? 2 : (average < minV) ? 0 : 1;
/* adjust cval for flipped cases */
/* 8-sided cases */
if(cval === 34){
if(flipped === 1){
cval = 35;
} else if(flipped === 0){
cval = 136;
}
} else if(cval === 136){
if(flipped === 1){
cval = 35;
flipped = 4;
} else if(flipped === 0){
cval = 34;
}
}
/* 6-sided polygon cases */
else if(cval === 17){
if(flipped === 1){
cval = 155;
flipped = 4;
} else if(flipped === 0){
cval = 153;
}
} else if(cval === 68){
if(flipped === 1){
cval = 103;
flipped = 4;
} else if(flipped === 0){
cval = 102;
}
} else if(cval === 153){
if(flipped === 1)
cval = 155;
} else if(cval === 102){
if(flipped === 1)
cval = 103;
}
/* 7-sided polygon cases */
else if(cval === 152){
if(flipped < 2){
cval = 156;
flipped = 1;
}
} else if(cval === 137){
if(flipped < 2){
cval = 139;
flipped = 1;
}
} else if(cval === 98){
if(flipped < 2){
cval = 99;
flipped = 1;
}
} else if(cval === 38){
if(flipped < 2){
cval = 39;
flipped = 1;
}
} else if(cval === 18){
if(flipped > 0){
cval = 156;
flipped = 4;
} else {
cval = 152;
}
} else if(cval === 33){
if(flipped > 0){
cval = 139;
flipped = 4;
} else {
cval = 137;
}
} else if(cval === 72){
if(flipped > 0){
cval = 99;
flipped = 4;
} else {
cval = 98;
}
} else if(cval === 132){
if(flipped > 0){
cval = 39;
flipped = 4;
} else {
cval = 38;
}
}
}
/* add cell to BandGrid if it contains at least one polygon-side */
if((cval != 0) && (cval != 170)){
var topleft, topright, bottomleft, bottomright,
righttop, rightbottom, lefttop, leftbottom;
topleft = topright = bottomleft = bottomright = righttop
= rightbottom = lefttop = leftbottom = 0.5;
var edges = [];
/* do interpolation here */
/* 1st Triangles */
if(cval === 1){ /* 0001 */
bottomleft = 1 - interpolateX(minV, br, bl);
leftbottom = 1 - interpolateX(minV, tl, bl);
edges.push(isoBandEdgeBL[cval]);
} else if(cval === 169){ /* 2221 */
bottomleft = interpolateX(maxV, bl, br);
leftbottom = interpolateX(maxV, bl, tl);
edges.push(isoBandEdgeBL[cval]);
} else if(cval === 4){ /* 0010 */
rightbottom = 1 - interpolateX(minV, tr, br);
bottomright = interpolateX(minV, bl, br);
edges.push(isoBandEdgeRB[cval]);
} else if(cval === 166){ /* 2212 */
rightbottom = interpolateX(maxV, br, tr);
bottomright = 1 - interpolateX(maxV, br, bl);
edges.push(isoBandEdgeRB[cval]);
} else if(cval === 16){ /* 0100 */
righttop = interpolateX(minV, br, tr);
topright = interpolateX(minV, tl, tr);
edges.push(isoBandEdgeRT[cval]);
} else if(cval === 154){ /* 2122 */
righttop = 1 - interpolateX(maxV, tr, br);
topright = 1 - interpolateX(maxV, tr, tl);
edges.push(isoBandEdgeRT[cval]);
} else if(cval === 64){ /* 1000 */
lefttop = interpolateX(minV, bl, tl);
topleft = 1 - interpolateX(minV, tr, tl);
edges.push(isoBandEdgeLT[cval]);
} else if(cval === 106){ /* 1222 */
lefttop = 1 - interpolateX(maxV, tl, bl);
topleft = interpolateX(maxV, tl, tr);
edges.push(isoBandEdgeLT[cval]);
}
/* 2nd Trapezoids */
else if(cval === 168){ /* 2220 */
bottomright = interpolateX(maxV, bl, br);
bottomleft = interpolateX(minV, bl, br);
leftbottom = interpolateX(minV, bl, tl);
lefttop = interpolateX(maxV, bl, tl);
edges.push(isoBandEdgeBR[cval]);
edges.push(isoBandEdgeBL[cval]);
} else if(cval === 2){ /* 0002 */
bottomright = 1 - interpolateX(minV, br, bl);
bottomleft = 1 - interpolateX(maxV, br, bl);
leftbottom = 1 - interpolateX(maxV, tl, bl);
lefttop = 1 - interpolateX(minV, tl, bl);
edges.push(isoBandEdgeBR[cval]);
edges.push(isoBandEdgeBL[cval]);
} else if(cval === 162){ /* 2202 */
righttop = interpolateX(maxV, br, tr);
rightbottom = interpolateX(minV, br, tr);
bottomright = 1 - interpolateX(minV, br, bl);
bottomleft = 1 - interpolateX(maxV, br, bl);
edges.push(isoBandEdgeBR[cval]);
edges.push(isoBandEdgeBL[cval]);
} else if(cval === 8){ /* 0020 */
righttop = 1 - interpolateX(minV, tr, br);
rightbottom = 1 - interpolateX(maxV, tr, br);
bottomright = interpolateX(maxV, bl, br);
bottomleft = interpolateX(minV, bl, br);
edges.push(isoBandEdgeRT[cval]);
edges.push(isoBandEdgeRB[cval]);
} else if(cval === 138){ /* 2022 */
righttop = 1 - interpolateX(minV, tr, br);
rightbottom = 1 - interpolateX(maxV, tr, br);
topleft = 1 - interpolateX(maxV, tr, tl);
topright = 1 - interpolateX(minV, tr, tl);
edges.push(isoBandEdgeRT[cval]);
edges.push(isoBandEdgeRB[cval]);
} else if(cval === 32){ /* 0200 */
righttop = interpolateX(maxV, br, tr);
rightbottom = interpolateX(minV, br, tr);
topleft = interpolateX(minV, tl, tr);
topright = interpolateX(maxV, tl, tr);
edges.push(isoBandEdgeRT[cval]);
edges.push(isoBandEdgeRB[cval]);
} else if(cval === 42){ /* 0222 */
leftbottom = 1 - interpolateX(maxV, tl, bl);
lefttop = 1 - interpolateX(minV, tl, bl);
topleft = interpolateX(minV, tl, tr);
topright = interpolateX(maxV, tl, tr);
edges.push(isoBandEdgeLB[cval]);
edges.push(isoBandEdgeLT[cval]);
} else if(cval === 128){ /* 2000 */
leftbottom = interpolateX(minV, bl, tl);
lefttop = interpolateX(maxV, bl, tl);
topleft = 1 - interpolateX(maxV, tr, tl);
topright = 1 - interpolateX(minV, tr, tl);
edges.push(isoBandEdgeLB[cval]);
edges.push(isoBandEdgeLT[cval]);
}
/* 3rd rectangle cases */
if(cval === 5){ /* 0011 */
rightbottom = 1 - interpolateX(minV, tr, br);
leftbottom = 1 - interpolateX(minV, tl, bl);
edges.push(isoBandEdgeRB[cval]);
} else if(cval === 165){ /* 2211 */
rightbottom = interpolateX(maxV, br, tr);
leftbottom = interpolateX(maxV, bl, tl);
edges.push(isoBandEdgeRB[cval]);
} else if(cval === 20){ /* 0110 */
bottomright = interpolateX(minV, bl, br);
topright = interpolateX(minV, tl, tr);
edges.push(isoBandEdgeBR[cval]);
} else if(cval === 150){ /* 2112 */
bottomright = 1 - interpolateX(maxV, br, bl);
topright = 1 - interpolateX(maxV, tr, tl);
edges.push(isoBandEdgeBR[cval]);
} else if(cval === 80){ /* 1100 */
righttop = interpolateX(minV, br, tr);
lefttop = interpolateX(minV, bl, tl);
edges.push(isoBandEdgeRT[cval]);
} else if(cval === 90){ /* 1122 */
righttop = 1 - interpolateX(maxV, tr, br);
lefttop = 1 - interpolateX(maxV, tl, bl);
edges.push(isoBandEdgeRT[cval]);
} else if(cval === 65){ /* 1001 */
bottomleft = 1 - interpolateX(minV, br, bl);
topleft = 1 - interpolateX(minV, tr, tl);
edges.push(isoBandEdgeBL[cval]);
} else if(cval === 105){ /* 1221 */
bottomleft = interpolateX(maxV, bl, br);
topleft = interpolateX(maxV, tl, tr);
edges.push(isoBandEdgeBL[cval]);
} else if(cval === 160){ /* 2200 */
righttop = interpolateX(maxV, br, tr);
rightbottom = interpolateX(minV, br, tr);
leftbottom = interpolateX(minV, bl, tl);
lefttop = interpolateX(maxV, bl, tl);
edges.push(isoBandEdgeRT[cval]);
edges.push(isoBandEdgeRB[cval]);
} else if(cval === 10){ /* 0022 */
righttop = 1 - interpolateX(minV, tr, br);
rightbottom = 1 - interpolateX(maxV, tr, br);
leftbottom = 1 - interpolateX(maxV, tl, bl);
lefttop = 1 - interpolateX(minV, tl, bl);
edges.push(isoBandEdgeRT[cval]);
edges.push(isoBandEdgeRB[cval]);
} else if(cval === 130){ /* 2002 */
bottomright = 1 - interpolateX(minV, br, bl);
bottomleft = 1 - interpolateX(maxV, br, bl);
topleft = 1 - interpolateX(maxV, tr, tl);
topright = 1 - interpolateX(minV, tr, tl);
edges.push(isoBandEdgeBR[cval]);
edges.push(isoBandEdgeBL[cval]);
} else if(cval === 40){ /* 0220 */
bottomright = interpolateX(maxV, bl, br);
bottomleft = interpolateX(minV, bl, br);
topleft = interpolateX(minV, tl, tr);
topright = interpolateX(maxV, tl, tr);
edges.push(isoBandEdgeBR[cval]);
edges.push(isoBandEdgeBL[cval]);
}
/* 4th single pentagon cases */
else if(cval === 101){ /* 1211 */
rightbottom = interpolateX(maxV, br, tr);
topleft = interpolateX(maxV, tl, tr);
edges.push(isoBandEdgeRB[cval]);
} else if(cval === 69){ /* 1011 */
rightbottom = 1 - interpolateX(minV, tr, br);
topleft = 1 - interpolateX(minV, tr, tl);
edges.push(isoBandEdgeRB[cval]);
} else if(cval === 149){ /* 2111 */
leftbottom = interpolateX(maxV, bl, tl);
topright = 1 - interpolateX(maxV, tr, tl);
edges.push(isoBandEdgeLB[cval]);
} else if(cval === 21){ /* 0111 */
leftbottom = 1 - interpolateX(minV, tl, bl);
topright = interpolateX(minV, tl, tr);
edges.push(isoBandEdgeLB[cval]);
} else if(cval === 86){ /* 1112 */
bottomright = 1 - interpolateX(maxV, br, bl);
lefttop = 1 - interpolateX(maxV, tl, bl);
edges.push(isoBandEdgeBR[cval]);
} else if(cval === 84){ /* 1110 */
bottomright = interpolateX(minV, bl, br);
lefttop = interpolateX(minV, bl, tl);
edges.push(isoBandEdgeBR[cval]);
} else if(cval === 89){ /* 1121 */
righttop = 1 - interpolateX(maxV, tr, br);
bottomleft = interpolateX(maxV, bl, br);
edges.push(isoBandEdgeBL[cval]);
} else if(cval === 81){ /* 1101 */
righttop = interpolateX(minV, br, tr);
bottomleft = 1 - interpolateX(minV, br, bl);
edges.push(isoBandEdgeBL[cval]);
} else if(cval === 96){ /* 1200 */
righttop = interpolateX(maxV, br, tr);
rightbottom = interpolateX(minV, br, tr);
lefttop = interpolateX(minV, bl, tl);
topleft = interpolateX(maxV, tl, tr);
edges.push(isoBandEdgeRT[cval]);
edges.push(isoBandEdgeRB[cval]);
} else if(cval === 74){ /* 1022 */
righttop = 1 - interpolateX(minV, tr, br);
rightbottom = 1- interpolateX(maxV, tr, br);
lefttop = 1 - interpolateX(maxV, tl, bl);
topleft = 1 - interpolateX(minV, tr, tl);
edges.push(isoBandEdgeRT[cval]);
edges.push(isoBandEdgeRB[cval]);
} else if(cval === 24){ /* 0120 */
righttop = 1 - interpolateX(maxV, tr, br);
bottomright = interpolateX(maxV, bl, br);
bottomleft = interpolateX(minV, bl, br);
topright = interpolateX(minV, tl, tr);
edges.push(isoBandEdgeRT[cval]);
edges.push(isoBandEdgeBL[cval]);
} else if(cval === 146){ /* 2102 */
righttop = interpolateX(minV, br, tr);
bottomright = 1 - interpolateX(minV, br, bl);
bottomleft = 1 - interpolateX(maxV, br, bl);
topright = 1 - interpolateX(maxV, tr, tl);
edges.push(isoBandEdgeRT[cval]);
edges.push(isoBandEdgeBL[cval]);
} else if(cval === 6){ /* 0012 */
rightbottom = 1 - interpolateX(minV, tr, br);
bottomright = 1 - interpolateX(maxV, br, bl);
leftbottom = 1 - interpolateX(maxV, tl, bl);
lefttop = 1 - interpolateX(minV, tl, bl);
edges.push(isoBandEdgeRB[cval]);
edges.push(isoBandEdgeBR[cval]);
} else if(cval === 164){ /* 2210 */
rightbottom = interpolateX(maxV, br, tr);
bottomright = interpolateX(minV, bl, br);
leftbottom = interpolateX(minV, bl, tl);
lefttop = interpolateX(maxV, bl, tl);
edges.push(isoBandEdgeRB[cval]);
edges.push(isoBandEdgeBR[cval]);
} else if(cval === 129){ /* 2001 */
bottomleft = 1 - interpolateX(minV, br, bl);
leftbottom = interpolateX(maxV, bl, tl);
topleft = 1 - interpolateX(maxV, tr, tl);
topright = 1 - interpolateX(minV, tr, tl);
edges.push(isoBandEdgeBL[cval]);
edges.push(isoBandEdgeLB[cval]);
} else if(cval === 41){ /* 0221 */
bottomleft = interpolateX(maxV, bl, br);
leftbottom = 1 - interpolateX(minV, tl, bl);
topleft = interpolateX(minV, tl, tr);
topright = interpolateX(maxV, tl, tr);
edges.push(isoBandEdgeBL[cval]);
edges.push(isoBandEdgeLB[cval]);
} else if(cval === 66){ /* 1002 */
bottomright = 1 - interpolateX(minV, br, bl);
bottomleft = 1 - interpolateX(maxV, br, bl);
lefttop = 1 - interpolateX(maxV, tl, bl);
topleft = 1 - interpolateX(minV, tr, tl);
edges.push(isoBandEdgeBR[cval]);
edges.push(isoBandEdgeBL[cval]);
} else if(cval === 104){ /* 1220 */
bottomright = interpolateX(maxV, bl, br);
bottomleft = interpolateX(minV, bl, br);
lefttop = interpolateX(minV, bl, tl);
topleft = interpolateX(maxV, tl, tr);
edges.push(isoBandEdgeBL[cval]);
edges.push(isoBandEdgeTL[cval]);
} else if(cval === 144){ /* 2100 */
righttop = interpolateX(minV, br, tr);
leftbottom = interpolateX(minV, bl, tl);
lefttop = interpolateX(maxV, bl, tl);
topright = 1 - interpolateX(maxV, tr, tl);
edges.push(isoBandEdgeRT[cval]);
edges.push(isoBandEdgeLT[cval]);
} else if(cval === 26){ /* 0122 */
righttop = 1 - interpolateX(maxV, tr, br);
leftbottom = 1 - interpolateX(maxV, tl, bl);
lefttop = 1 - interpolateX(minV, tl, bl);
topright = interpolateX(minV, tl, tr);
edges.push(isoBandEdgeRT[cval]);
edges.push(isoBandEdgeLT[cval]);
} else if(cval === 36){ /* 0210 */
rightbottom = interpolateX(maxV, br, tr);
bottomright = interpolateX(minV, bl, br);
topleft = interpolateX(minV, tl, tr);
topright = interpolateX(maxV, tl, tr);
edges.push(isoBandEdgeRB[cval]);
edges.push(isoBandEdgeBR[cval]);
} else if(cval === 134){ /* 2012 */
rightbottom = 1 - interpolateX(minV, tr, br);
bottomright = 1 - interpolateX(maxV, br, bl);
topleft = 1 - interpolateX(maxV, tr, tl);
topright = 1 - interpolateX(minV, tr, tl);
edges.push(isoBandEdgeRB[cval]);
edges.push(isoBandEdgeBR[cval]);
} else if(cval === 9){ /* 0021 */
righttop = 1 - interpolateX(minV, tr, br);
rightbottom = 1 - interpolateX(maxV, tr, br);
bottomleft = interpolateX(maxV, bl, br);
leftbottom = 1 - interpolateX(minV, tl, bl);
edges.push(isoBandEdgeRT[cval]);
edges.push(isoBandEdgeRB[cval]);
} else if(cval === 161){ /* 2201 */
righttop = interpolateX(maxV, br, tr);
rightbottom = interpolateX(minV, br, tr);
bottomleft = 1 - interpolateX(minV, br, bl);
leftbottom = interpolateX(maxV, bl, tl);
edges.push(isoBandEdgeRT[cval]);
edges.push(isoBandEdgeRB[cval]);
}
/* 5th single hexagon cases */
else if(cval === 37){ /* 0211 */
rightbottom = interpolateX(maxV, br, tr);
leftbottom = 1- interpolateX(minV, tl, bl);
topleft = interpolateX(minV, tl, tr);
topright = interpolateX(maxV, tl, tr);
edges.push(isoBandEdgeRB[cval]);
edges.push(isoBandEdgeLB[cval]);
} else if(cval === 133){ /* 2011 */
rightbottom = 1 - interpolateX(minV, tr, br);
leftbottom = interpolateX(maxV, bl, tl);
topleft = 1 - interpolateX(maxV, tr, tl);
topright = 1 - interpolateX(minV, tr, tl);
edges.push(isoBandEdgeRB[cval]);
edges.push(isoBandEdgeLB[cval]);
} else if(cval === 148){ /* 2110 */
bottomright = interpolateX(minV, bl, br);
leftbottom = interpolateX(minV, bl, tl);
lefttop = interpolateX(maxV, bl, tl);
topright = 1 - interpolateX(maxV, tr, tl);
edges.push(isoBandEdgeBR[cval]);
edges.push(isoBandEdgeLT[cval]);
} else if(cval === 22){ /* 0112 */
bottomright = 1 - interpolateX(maxV, br, bl);
leftbottom = 1 - interpolateX(maxV, tl, bl);
lefttop = 1 - interpolateX(minV, tl, bl);
topright = interpolateX(minV, tl, tr);
edges.push(isoBandEdgeBR[cval]);
edges.push(isoBandEdgeLT[cval]);
} else if(cval === 82){ /* 1102 */
righttop = interpolateX(minV, br, tr);
bottomright = 1- interpolateX(minV, br, bl);
bottomleft = 1 - interpolateX(maxV, br, bl);
lefttop = 1 - interpolateX(maxV, tl, bl);
edges.push(isoBandEdgeRT[cval]);
edges.push(isoBandEdgeBL[cval]);
} else if(cval === 88){ /* 1120 */
righttop = 1 - interpolateX(maxV, tr, br);
bottomright = interpolateX(maxV, bl, br);
bottomleft = interpolateX(minV, bl, br);
lefttop = interpolateX(minV, bl, tl);
edges.push(isoBandEdgeRT[cval]);
edges.push(isoBandEdgeBL[cval]);
} else if(cval === 73){ /* 1021 */
righttop = 1 - interpolateX(minV, tr, br);
rightbottom = 1 - interpolateX(maxV, tr, br);
bottomleft = interpolateX(maxV, bl, br);
topleft = 1 - interpolateX(minV, tr, tl);
edges.push(isoBandEdgeRT[cval]);
edges.push(isoBandEdgeRB[cval]);
} else if(cval === 97){ /* 1201 */
righttop = interpolateX(maxV, br, tr);
rightbottom = interpolateX(minV, br, tr);
bottomleft = 1 - interpolateX(minV, br, bl);
topleft = interpolateX(maxV, tl, tr);
edges.push(isoBandEdgeRT[cval]);
edges.push(isoBandEdgeRB[cval]);
} else if(cval === 145){ /* 2101 */
righttop = interpolateX(minV, br, tr);
bottomleft = 1 - interpolateX(minV, br, bl);
leftbottom = interpolateX(maxV, bl, tl);
topright = 1 - interpolateX(maxV, tr, tl);
edges.push(isoBandEdgeRT[cval]);
edges.push(isoBandEdgeLB[cval]);
} else if(cval === 25){ /* 0121 */
righttop = 1 - interpolateX(maxV, tr, br);
bottomleft = interpolateX(maxV, bl, br);
leftbottom = 1 - interpolateX(minV, tl, bl);
topright = interpolateX(minV, tl, tr);
edges.push(isoBandEdgeRT[cval]);
edges.push(isoBandEdgeLB[cval]);
} else if(cval === 70){ /* 1012 */
rightbottom = 1 - interpolateX(minV, tr, br);
bottomright = 1 - interpolateX(maxV, br, bl);
lefttop = 1 - interpolateX(maxV, tl, bl);
topleft = 1 - interpolateX(minV, tr, tl);
edges.push(isoBandEdgeRB[cval]);
edges.push(isoBandEdgeBR[cval]);
} else if(cval === 100){ /* 1210 */
rightbottom = interpolateX(maxV, br, tr);
bottomright = interpolateX(minV, bl, br);
lefttop = interpolateX(minV, bl, tl);
topleft = interpolateX(maxV, tl, tr);
edges.push(isoBandEdgeRB[cval]);
edges.push(isoBandEdgeBR[cval]);
}
/* 8-sided cases */
else if(cval === 34){ /* 0202 || 2020 with flipped == 0 */
if(flipped === 0){
righttop = 1 - interpolateX(minV, tr, br);
rightbottom = 1 - interpolateX(maxV, tr, br);
bottomright = interpolateX(maxV, bl, br);
bottomleft = interpolateX(minV, bl, br);
leftbottom = interpolateX(minV, bl, tl);
lefttop = interpolateX(maxV, bl, tl);
topleft = 1 - interpolateX(maxV, tr, tl);
topright = 1 - interpolateX(minV, tr, tl);
} else {
righttop = interpolateX(maxV, br, tr);
rightbottom = interpolateX(minV, br, tr);
bottomright = 1 - interpolateX(minV, br, bl);
bottomleft = 1 - interpolateX(maxV, br, bl);
leftbottom = 1 - interpolateX(maxV, tl, bl);
lefttop = 1 - interpolateX(minV, tl, bl);
topleft = interpolateX(minV, tl, tr);
topright = interpolateX(maxV, tl, tr);
}
edges.push(isoBandEdgeRT[cval]);
edges.push(isoBandEdgeRB[cval]);
edges.push(isoBandEdgeLB[cval]);
edges.push(isoBandEdgeLT[cval]);
} else if(cval === 35){ /* flipped == 1 state for 0202, and 2020 with flipped == 4*/
if(flipped === 4){
righttop = 1 - interpolateX(minV, tr, br);
rightbottom = 1 - interpolateX(maxV, tr, br);
bottomright = interpolateX(maxV, bl, br);
bottomleft = interpolateX(minV, bl, br);
leftbottom = interpolateX(minV, bl, tl);
lefttop = interpolateX(maxV, bl, tl);
topleft = 1 - interpolateX(maxV, tr, tl);
topright = 1 - interpolateX(minV, tr, tl);
} else {
righttop = interpolateX(maxV, br, tr);
rightbottom = interpolateX(minV, br, tr);
bottomright = 1 - interpolateX(minV, br, bl);
bottomleft = 1 - interpolateX(maxV, br, bl);
leftbottom = 1 - interpolateX(maxV, tl, bl);
lefttop = 1 - interpolateX(minV, tl, bl);
topleft = interpolateX(minV, tl, tr);
topright = interpolateX(maxV, tl, tr);
}
edges.push(isoBandEdgeRT[cval]);
edges.push(isoBandEdgeRB[cval]);
edges.push(isoBandEdgeBL[cval]);
edges.push(isoBandEdgeLT[cval]);
} else if(cval === 136){ /* 2020 || 0202 with flipped == 0 */
if(flipped === 0){
righttop = interpolateX(maxV, br, tr);
rightbottom = interpolateX(minV, br, tr);
bottomright = 1 - interpolateX(minV, br, bl);
bottomleft = 1 - interpolateX(maxV, br, bl);
leftbottom = 1 - interpolateX(maxV, tl, bl);
lefttop = 1 - interpolateX(minV, tl, bl);
topleft = interpolateX(minV, tl, tr);
topright = interpolateX(maxV, tl, tr);
} else {
righttop = 1 - interpolateX(minV, tr, br);
rightbottom = 1 - interpolateX(maxV, tr, br);
bottomright = interpolateX(maxV, bl, br);
bottomleft = interpolateX(minV, bl, br);
leftbottom = interpolateX(minV, bl, tl);
lefttop = interpolateX(maxV, bl, tl);
topleft = 1 - interpolateX(maxV, tr, tl);
topright = 1 - interpolateX(minV, tr, tl);
}
edges.push(isoBandEdgeRT[cval]);
edges.push(isoBandEdgeRB[cval]);
edges.push(isoBandEdgeLB[cval]);
edges.push(isoBandEdgeLT[cval]);
}
/* 6-sided polygon cases */
else if(cval === 153){ /* 0101 with flipped == 0 || 2121 with flipped == 2 */
if(flipped === 0){
righttop = interpolateX(minV, br, tr);
bottomleft = 1 - interpolateX(minV, br, bl);
leftbottom = 1 - interpolateX(minV, tl, bl);
topright = interpolateX(minV, tl, tr);
} else {
righttop = 1 - interpolateX(maxV, tr, br);
bottomleft = interpolateX(maxV, bl, br);
leftbottom = interpolateX(maxV, bl, tl);
topright = 1 - interpolateX(maxV, tr, tl);
}
edges.push(isoBandEdgeRT[cval]);
edges.push(isoBandEdgeBL[cval]);
} else if(cval === 102){ /* 1010 with flipped == 0 || 1212 with flipped == 2 */
if(flipped === 0){
rightbottom = 1 - interpolateX(minV, tr, br);
bottomright = interpolateX(minV, bl, br);
lefttop = interpolateX(minV, bl, tl);
topleft = 1 - interpolateX(minV, tr, tl);
} else {
rightbottom = interpolateX(maxV, br, tr);
bottomright = 1 - interpolateX(maxV, br, bl);
lefttop = 1 - interpolateX(maxV, tl, bl);
topleft = interpolateX(maxV, tl, tr);
}
edges.push(isoBandEdgeRB[cval]);
edges.push(isoBandEdgeLT[cval]);
} else if(cval === 155){ /* 0101 with flipped == 4 || 2121 with flipped == 1 */
if(flipped === 4){
righttop = interpolateX(minV, br, tr);
bottomleft = 1 - interpolateX(minV, br, bl);
leftbottom = 1 - interpolateX(minV, tl, bl);
topright = interpolateX(minV, tl, tr);
} else {
righttop = 1 - interpolateX(maxV, tr, br);
bottomleft = interpolateX(maxV, bl, br);
leftbottom = interpolateX(maxV, bl, tl);
topright = 1 - interpolateX(maxV, tr, tl);
}
edges.push(isoBandEdgeRT[cval]);
edges.push(isoBandEdgeLB[cval]);
} else if(cval === 103){ /* 1010 with flipped == 4 || 1212 with flipped == 1 */
if(flipped === 4){
rightbottom = 1 - interpolateX(minV, tr, br);
bottomright = interpolateX(minV, bl, br);
lefttop = interpolateX(minV, bl, tl);
topleft = 1 - interpolateX(minV, tr, tl);
} else {
rightbottom = interpolateX(maxV, br, tr);
bottomright = 1 - interpolateX(maxV, br, bl);
lefttop = 1 - interpolateX(maxV, tl, bl);
topleft = interpolateX(maxV, tl, tr);
}
edges.push(isoBandEdgeRB[cval]);
edges.push(isoBandEdgeBR[cval]);
}
/* 7-sided polygon cases */
else if(cval === 152){ /* 2120 with flipped == 2 || 0102 with flipped == 0 */
if(flipped === 0){
righttop = interpolateX(minV, br, tr);
bottomright = 1 - interpolateX(minV, br, bl);
bottomleft = 1 - interpolateX(maxV, br, bl);
leftbottom = 1 - interpolateX(maxV, tl, bl);
lefttop = 1 - interpolateX(minV, tl, bl);
topright = interpolateX(minV, tl, tr);
} else {
righttop = 1 - interpolateX(maxV, tr, br);
bottomright = interpolateX(maxV, bl, br);
bottomleft = interpolateX(minV, bl, br);
leftbottom = interpolateX(minV, bl, tl);
lefttop = interpolateX(maxV, bl, tl);
topright = 1 - interpolateX(maxV, tr, tl);
}
edges.push(isoBandEdgeRT[cval]);
edges.push(isoBandEdgeBR[cval]);
edges.push(isoBandEdgeBL[cval]);
} else if(cval === 156){ /* 2120 with flipped == 1 || 0102 with flipped == 4 */
if(flipped === 4){
righttop = interpolateX(minV, br, tr);
bottomright = 1 - interpolateX(minV, br, bl);
bottomleft = 1 - interpolateX(maxV, br, bl);
leftbottom = 1 - interpolateX(maxV, tl, bl);
lefttop = 1 - interpolateX(minV, tl, bl);
topright = interpolateX(minV, tl, tr);
} else {
righttop = 1 - interpolateX(maxV, tr, br);
bottomright = interpolateX(maxV, bl, br);
bottomleft = interpolateX(minV, bl, br);
leftbottom = interpolateX(minV, bl, tl);
lefttop = interpolateX(maxV, bl, tl);
topright = 1 - interpolateX(maxV, tr, tl);
}
edges.push(isoBandEdgeRT[cval]);
edges.push(isoBandEdgeBL[cval]);
edges.push(isoBandEdgeLT[cval]);
} else if(cval === 137){ /* 2021 with flipped == 2 || 0201 with flipped == 0 */
if(flipped === 0){
righttop = interpolateX(maxV, br, tr);
rightbottom = interpolateX(minV, br, tr);
bottomleft = 1 - interpolateX(minV, br, bl);
leftbottom = 1 - interpolateX(minV, tl, bl);
topleft = interpolateX(minV, tl, tr);
topright = interpolateX(maxV, tl, tr);
} else {
righttop = 1 - interpolateX(minV, tr, br);
rightbottom = 1 - interpolateX(maxV, tr, br);
bottomleft = interpolateX(maxV, bl, br);
leftbottom = interpolateX(maxV, bl, tl);
topleft = 1 - interpolateX(maxV, tr, tl);
topright = 1 - interpolateX(minV, tr, tl);
}
edges.push(isoBandEdgeRT[cval]);
edges.push(isoBandEdgeRB[cval]);
edges.push(isoBandEdgeBL[cval]);
} else if(cval === 139){ /* 2021 with flipped == 1 || 0201 with flipped == 4 */
if(flipped === 4){
righttop = interpolateX(maxV, br, tr);
rightbottom = interpolateX(minV, br, tr);
bottomleft = 1 - interpolateX(minV, br, bl);
leftbottom = 1 - interpolateX(minV, tl, bl);
topleft = interpolateX(minV, tl, tr);
topright = interpolateX(maxV, tl, tr);
} else {
righttop = 1 - interpolateX(minV, tr, br);
rightbottom = 1 - interpolateX(maxV, tr, br);
bottomleft = interpolateX(maxV, bl, br);
leftbottom = interpolateX(maxV, bl, tl);
topleft = 1 - interpolateX(maxV, tr, tl);
topright = 1 - interpolateX(minV, tr, tl);
}
edges.push(isoBandEdgeRT[cval]);
edges.push(isoBandEdgeRB[cval]);
edges.push(isoBandEdgeLB[cval]);
} else if(cval === 98){ /* 1202 with flipped == 2 || 1020 with flipped == 0 */
if(flipped === 0){
righttop = 1 - interpolateX(minV, tr, br);
rightbottom = 1 - interpolateX(maxV, tr, br);
bottomright = interpolateX(maxV, bl, br);
bottomleft = interpolateX(minV, bl, br);
lefttop = interpolateX(minV, bl, tl);
topleft = 1 - interpolateX(minV, tr, tl);
} else {
righttop = interpolateX(maxV, br, tr);
rightbottom = interpolateX(minV, br, tr);
bottomright = 1 - interpolateX(minV, br, bl);
bottomleft = 1 - interpolateX(maxV, br, bl);
lefttop = 1 - interpolateX(maxV, tl, bl);
topleft = interpolateX(maxV, tl, tr);
}
edges.push(isoBandEdgeRT[cval]);
edges.push(isoBandEdgeRB[cval]);
edges.push(isoBandEdgeLT[cval]);
} else if(cval === 99){ /* 1202 with flipped == 1 || 1020 with flipped == 4 */
if(flipped === 4){
righttop = 1 - interpolateX(minV, tr, br);
rightbottom = 1 - interpolateX(maxV, tr, br);
bottomright = interpolateX(maxV, bl, br);
bottomleft = interpolateX(minV, bl, br);
lefttop = interpolateX(minV, bl, tl);
topleft = 1 - interpolateX(minV, tr, tl);
} else {
righttop = interpolateX(maxV, br, tr);
rightbottom = interpolateX(minV, br, tr);
bottomright = 1 - interpolateX(minV, br, bl);
bottomleft = 1 - interpolateX(maxV, br, bl);
lefttop = 1 - interpolateX(maxV, tl, bl);
topleft = interpolateX(maxV, tl, tr);
}
edges.push(isoBandEdgeRT[cval]);
edges.push(isoBandEdgeRB[cval]);
edges.push(isoBandEdgeBL[cval]);
} else if(cval === 38){ /* 0212 with flipped == 2 || 2010 with flipped == 0 */
if(flipped === 0){
rightbottom = 1 - interpolateX(minV, tr, br);
bottomright = interpolateX(minV, bl, br);
leftbottom = interpolateX(minV, bl, tl);
lefttop = interpolateX(maxV, bl, tl);
topleft = 1 - interpolateX(maxV, tr, tl);
topright = 1 - interpolateX(minV, tr, tl);
} else {
rightbottom = interpolateX(maxV, br, tr);
bottomright = 1 - interpolateX(maxV, br, bl);
leftbottom = 1 - interpolateX(maxV, tl, bl);
lefttop = 1 - interpolateX(minV, tl, bl);
topleft = interpolateX(minV, tl, tr);
topright = interpolateX(maxV, tl, tr);
}
edges.push(isoBandEdgeRB[cval]);
edges.push(isoBandEdgeLB[cval]);
edges.push(isoBandEdgeLT[cval]);
} else if(cval === 39){ /* 0212 with flipped == 1 || 2010 with flipped == 4 */
if(flipped === 4){
rightbottom = 1 - interpolateX(minV, tr, br);
bottomright = interpolateX(minV, bl, br);
leftbottom = interpolateX(minV, bl, tl);
lefttop = interpolateX(maxV, bl, tl);
topleft = 1 - interpolateX(maxV, tr, tl);
topright = 1 - interpolateX(minV, tr, tl);
} else {
rightbottom = interpolateX(maxV, br, tr);
bottomright = 1 - interpolateX(maxV, br, bl);
leftbottom = 1 - interpolateX(maxV, tl, bl);
lefttop = 1 - interpolateX(minV, tl, bl);
topleft = interpolateX(minV, tl, tr);
topright = interpolateX(maxV, tl, tr);
}
edges.push(isoBandEdgeRB[cval]);
edges.push(isoBandEdgeBR[cval]);
edges.push(isoBandEdgeLT[cval]);
}
else if(cval === 85){
righttop = 1;
rightbottom = 0;
bottomright = 1;
bottomleft = 0;
leftbottom = 0;
lefttop = 1;
topleft = 0;
topright = 1;
}
if(topleft < 0 || topleft > 1 || topright < 0 || topright > 1 || righttop < 0 || righttop > 1 || bottomright < 0 || bottomright > 1 || leftbottom < 0 || leftbottom > 1 || lefttop < 0 || lefttop > 1){
console.log(cval + " " + cval_real + " " + tl + "," + tr + "," + br + "," + bl + " " + flipped + " " + topleft + " " + topright + " " + righttop + " " + rightbottom + " " + bottomright + " " + bottomleft + " " + leftbottom + " " + lefttop);
}
BandGrid.cells[j][i] = {
cval: cval,
cval_real: cval_real,
flipped: flipped,
topleft: topleft,
topright: topright,
righttop: righttop,
rightbottom: rightbottom,
bottomright: bottomright,
bottomleft: bottomleft,
leftbottom: leftbottom,
lefttop: lefttop,
edges: edges
};
}
}
}
return BandGrid;
}
function BandGrid2AreaPaths(grid){
var areas = [];
var area_idx = 0;
var rows = grid.rows;
var cols = grid.cols;
var currentPolygon = [];
for(var j = 0; j < rows; j++){
for(var i = 0; i < cols; i++){
if((typeof grid.cells[j][i] !== 'undefined') && (grid.cells[j][i].edges.length > 0)){
/* trace back polygon path starting from this cell */
var o = 0,
x = i,
y = j;
var cell = grid.cells[j][i];
/* get start coordinates */
var cval = cell.cval;
var prev = getStartXY(cell),
next = null,
p = i,
q = j;
if(prev !== null){
currentPolygon.push([ prev.p[0] + p, prev.p[1] + q ]);
//console.log(cell);
//console.log("coords: " + (prev.p[0] + p) + " " + (prev.p[1] + q));
}
do{
//console.log(p + "," + q);
//console.log(grid.cells[q][p]);
//console.log(grid.cells[q][p].edges);
//console.log("from : " + prev.x + " " + prev.y + " " + prev.o);
next = getExitXY(grid.cells[q][p], prev.x, prev.y, prev.o);
if(next !== null){
//console.log("coords: " + (next.p[0] + p) + " " + (next.p[1] + q));
currentPolygon.push([ next.p[0] + p, next.p[1] + q ]);
p += next.x;
q += next.y;
prev = next;
} else {
//console.log("getExitXY() returned null!");
break;
}
//console.log("to : " + next.x + " " + next.y + " " + next.o);
/* special case, where we've reached the grid boundaries */
if((q < 0) || (q >= rows) || (p < 0) || (p >= cols) || (typeof grid.cells[q][p] === 'undefined')){
/* to create a closed path, we need to trace our way
arround the missing data, until we find an entry
point again
*/
/* set back coordinates of current cell */
p -= next.x;
q -= next.y;
//console.log("reached boundary at " + p + " " + q);
var missing = traceOutOfGridPath(grid, p, q, next.x, next.y, next.o);
if(missing !== null){
missing.path.forEach(function(pp){
//console.log("coords: " + (pp[0]) + " " + (pp[1]));
currentPolygon.push(pp);
});
p = missing.i;
q = missing.j;
prev = missing;
} else {
break;
}
//console.log(grid.cells[q][p]);
}
} while( (typeof grid.cells[q][p] !== 'undefined')
&& (grid.cells[q][p].edges.length > 0));
areas.push(currentPolygon);
//console.log("next polygon");
//console.log(currentPolygon);
currentPolygon = [];
if(grid.cells[j][i].edges.length > 0)
i--;
}
}
}
return areas;
}
function traceOutOfGridPath(grid, i, j, d_x, d_y, d_o){
var cell = grid.cells[j][i];
var cval = cell.cval_real;
var p = i + d_x,
q = j + d_y;
var path = [];
var rows = grid.rows;
var cols = grid.cols;
var closed = false;
while(!closed){
//console.log("processing cell " + p + "," + q + " " + d_x + " " + d_y + " " + d_o);
if((typeof grid.cells[q] === 'undefined') || (typeof grid.cells[q][p] === 'undefined')){
//console.log("which is undefined");
/* we can't move on, so we have to change direction to proceed further */
/* go back to previous cell */
q -= d_y;
p -= d_x;
cell = grid.cells[q][p];
cval = cell.cval_real;
/* check where we've left defined cells of the grid... */
if(d_y === -1){ /* we came from top */
if(d_o === 0){ /* exit left */
if(cval & Node3){ /* lower left node is within range, so we move left */
path.push([p, q]);
d_x = -1;
d_y = 0;
d_o = 0;
} else if(cval & Node2){ /* lower right node is within range, so we move right */
path.push([p + 1, q]);
d_x = 1;
d_y = 0;
d_o = 0;
} else { /* close the path */
path.push([p + cell.bottomright, q]);
d_x = 0;
d_y = 1;
d_o = 1;
closed = true;
break;
}
} else {
if(cval & Node3){
path.push([p, q]);
d_x = -1;
d_y = 0;
d_o = 0;
} else if(cval & Node2){
path.push([p + cell.bottomright, q]);
d_x = 0;
d_y = 1;
d_o = 1;
closed = true;
break;
} else {
path.push([p + cell.bottomleft, q]);
d_x = 0;
d_y = 1;
d_o = 0;
closed = true;
break;
}
}
} else if(d_y === 1){ /* we came from bottom */
//console.log("we came from bottom and hit a non-existing cell " + (p + d_x) + "," + (q + d_y) + "!");
if(d_o === 0){ /* exit left */
if(cval & Node1){ /* top right node is within range, so we move right */
path.push([p+1,q+1]);
d_x = 1;
d_y = 0;
d_o = 1;
} else if(!(cval & Node0)){ /* found entry within same cell */
path.push([p + cell.topright, q + 1]);
d_x = 0;
d_y = -1;
d_o = 1;
closed = true;
//console.log("found entry from bottom at " + p + "," + q);
break;
} else {
path.push([p + cell.topleft, q + 1]);
d_x = 0;
d_y = -1;
d_o = 0;
closed = true;
break;
}
} else {
if(cval & Node1){
path.push([p+1, q+1]);
d_x = 1;
d_y = 0;
d_o = 1;
} else { /* move right */
path.push([p+1, q+1]);
d_x = 1;
d_y = 0;
d_o = 1;
//console.log("wtf");
//break;
}
}
} else if(d_x === -1){ /* we came from right */
//console.log("we came from right and hit a non-existing cell at " + (p + d_x) + "," + (q + d_y) + "!");
if(d_o === 0){
//console.log("continue at bottom");
if(cval & Node0){
path.push([p,q+1]);
d_x = 0;
d_y = 1;
d_o = 0;
//console.log("moving upwards to " + (p + d_x) + "," + (q + d_y) + "!");
} else if(!(cval & Node3)){ /* there has to be an entry into the regular grid again! */
//console.log("exiting top");
path.push([p, q + cell.lefttop]);
d_x = 1;
d_y = 0;
d_o = 1;
closed = true;
break;
} else {
//console.log("exiting bottom");
path.push([p, q + cell.leftbottom]);
d_x = 1;
d_y = 0;
d_o = 0;
closed = true;
break;
}
} else {
//console.log("continue at top");
if(cval & Node0){
path.push([p,q+1]);
d_x = 0;
d_y = 1;
d_o = 0;
//console.log("moving upwards to " + (p + d_x) + "," + (q + d_y) + "!");
} else { /* */
console.log("wtf");
break;
}
}
} else if(d_x === 1){ /* we came from left */
//console.log("we came from left and hit a non-existing cell " + (p + d_x) + "," + (q + d_y) + "!");
if(d_o === 0){ /* exit bottom */
if(cval & Node2){
path.push([p+1,q]);
d_x = 0;
d_y = -1;
d_o = 1;
} else {
path.push([p+1,q+cell.rightbottom]);
d_x = -1;
d_y = 0;
d_o = 0;
closed = true;
break;
}
} else { /* exit top */
if(cval & Node2){
path.push([p+1,q]);
d_x = 0;
d_y = -1;
d_o = 1;
} else if(!(cval & Node1)){
path.push([p + 1, q + cell.rightbottom]);
d_x = -1;
d_y = 0;
d_o = 0;
closed = true;
break;
} else {
path.push([p+1,q+cell.righttop]);
d_x = -1;
d_y = 0;
d_o = 1;
break;
}
}
} else { /* we came from the same cell */
console.log("we came from nowhere!");
break;
}
} else { /* try to find an entry into the regular grid again! */
cell = grid.cells[q][p];
cval = cell.cval_real;
//console.log("which is defined");
if(d_x === -1){
if(d_o === 0){
/* try to go downwards */
if((typeof grid.cells[q - 1] !== 'undefined') && (typeof grid.cells[q - 1][p] !== 'undefined')){
d_x = 0;
d_y = -1;
d_o = 1;
} else if(cval & Node3){ /* proceed searching in x-direction */
//console.log("proceeding in x-direction!");
path.push([p, q]);
} else { /* we must have found an entry into the regular grid */
path.push([p + cell.bottomright, q]);
d_x = 0;
d_y = 1;
d_o = 1;
closed = true;
//console.log("found entry from bottom at " + p + "," + q);
break;
}
} else {
if(cval & Node0) { /* proceed searchin in x-direction */
console.log("proceeding in x-direction!");
} else { /* we must have found an entry into the regular grid */
console.log("found entry from top at " + p + "," + q);
break;
}
}
} else if(d_x === 1){
if(d_o === 0){
console.log("wtf");
break;
} else {
/* try to go upwards */
if((typeof grid.cells[q+1] !== 'undefined') && (typeof grid.cells[q+1][p] !== 'undefined')){
d_x = 0;
d_y = 1;
d_o = 0;
} else if(cval & Node1){
path.push([p+1,q+1]);
d_x = 1;
d_y = 0;
d_o = 1;
} else { /* found an entry point into regular grid! */
path.push([p+cell.topleft, q + 1]);
d_x = 0;
d_y = -1;
d_o = 0;
closed = true;
//console.log("found entry from bottom at " + p + "," + q);
break;
}
}
} else if(d_y === -1){
if(d_o === 1){
/* try to go right */
if(typeof grid.cells[q][p+1] !== 'undefined'){
d_x = 1;
d_y = 0;
d_o = 1;
} else if(cval & Node2){
path.push([p+1,q]);
d_x = 0;
d_y = -1;
d_o = 1;
} else { /* found entry into regular grid! */
path.push([p+1, q + cell.righttop]);
d_x = -1;
d_y = 0;
d_o = 1;
closed = true;
//console.log("found entry from top at " + p + "," + q);
break;
}
} else {
console.log("wtf");
break;
}
} else if(d_y === 1){
if(d_o === 0){
//console.log("we came from bottom left and proceed to the left");
/* try to go left */
if(typeof grid.cells[q][p - 1] !== 'undefined'){
d_x = -1;
d_y = 0;
d_o = 0;
} else if(cval & Node0){
path.push([p,q+1]);
d_x = 0;
d_y = 1;
d_o = 0;
} else { /* found an entry point into regular grid! */
path.push([p, q + cell.leftbottom]);
d_x = 1;
d_y = 0;
d_o = 0;
closed = true;
//console.log("found entry from bottom at " + p + "," + q);
break;
}
} else {
//console.log("we came from bottom right and proceed to the right");
console.log("wtf");
break;
}
} else {
console.log("where did we came from???");
break;
}
}
p += d_x;
q += d_y;
//console.log("going on to " + p + "," + q + " via " + d_x + " " + d_y + " " + d_o);
if((p === i) && (q === j)){ /* bail out, once we've closed a circle path */
break;
}
}
//console.log("exit with " + p + "," + q + " " + d_x + " " + d_y + " " + d_o);
return { path: path, i: p, j: q, x: d_x, y: d_y, o: d_o };
}
function deleteEdge(cell, edgeIdx){
delete cell.edges[edgeIdx];
for(var k = edgeIdx + 1; k < cell.edges.length; k++){
cell.edges[k-1] = cell.edges[k];
}
cell.edges.pop();
}
function getStartXY(cell){
if(cell.edges.length > 0){
var e = cell.edges[cell.edges.length - 1];
//console.log("starting with edge " + e);
var cval = cell.cval_real;
switch(e){
case 0: if(cval & Node1){ /* node 1 within range */
return {p: [1, cell.righttop], x: -1, y: 0, o: 1};
} else { /* node 1 below or above threshold */
return {p: [cell.topleft, 1], x: 0, y: -1, o: 0};
}
case 1: if(cval & Node2){
return {p: [cell.topleft, 1], x: 0, y: -1, o: 0};
} else {
return {p: [1, cell.rightbottom], x: -1, y: 0, o: 0};
}
case 2: if(cval & Node2){
return {p: [cell.bottomright, 0], x: 0, y: 1, o: 1};
} else {
return {p: [cell.topleft, 1], x: 0, y: -1, o: 0};
}
case 3: if(cval & Node3){
return {p: [cell.topleft, 1], x: 0, y: -1, o: 0};
} else {
return {p: [cell.bottomleft, 0], x: 0, y: 1, o: 0};
}
case 4: if(cval & Node1){
return {p: [1, cell.righttop], x: -1, y: 0, o: 1};
} else {
return {p: [cell.topright, 1], x: 0, y: -1, o: 1};
}
case 5: if(cval & Node2){
return {p: [cell.topright, 1], x: 0, y: -1, o: 1};
} else {
return {p: [1, cell.rightbottom], x: -1, y: 0, o: 0};
}
case 6: if(cval & Node2){
return {p: [cell.bottomright, 0], x: 0, y: 1, o: 1};
} else {
return {p: [cell.topright, 1], x: 0, y: -1, o: 1};
}
case 7: if(cval & Node3){
return {p: [cell.topright, 1], x: 0, y: -1, o: 1};
} else {
return {p: [cell.bottomleft, 0], x: 0, y: 1, o: 0};
}
case 8: if(cval & Node2){
return {p: [cell.bottomright], x: 0, y: 1, o: 1};
} else {
return {p: [1, cell.righttop], x: -1, y: 0, o: 1};
}
case 9: if(cval & Node3){
return {p: [1, cell.righttop], x: -1, y: 0, o: 1};
} else {
return {p: [cell.bottomleft, 0], x: 0, y: 1, o: 0};
}
case 10: if(cval & Node3){
return {p: [0, cell.leftbottom], x: 1, y: 0, o: 0};
} else {
return {p: [1, cell.righttop], x: -1, y: 0, o: 1};
}
case 11: if(cval & Node0){
return {p: [1, cell.righttop], x: -1, y: 0, o: 1};
} else {
return {p: [0, cell.lefttop], x: 1, y: 0, o: 1};
}
case 12: if(cval & Node2){
return {p: [cell.bottomright, 0], x: 0, y: 1, o: 1};
} else {
return {p: [1, cell.rightbottom], x: -1, y: 0, o: 0};
}
case 13: if(cval & Node3){
return {p: [1, cell.rightbottom], x: -1, y: 0, o: 0};
} else {
return {p: [cell.bottomleft, 0], x: 0, y: 1, o: 0};
}
case 14: if(cval & Node3){
return {p: [0, cell.leftbottom], x: 1, y: 0, o: 0};
} else {
return {p: [1, cell.rightbottom], x: -1, y: 0, o: 0};
}
case 15: if(cval & Node0){
return {p: [1, cell.rightbottom], x: -1, y: 0, o: 0};
} else {
return {p: [0, cell.lefttop], x: 1, y: 0, o: 1};
}
case 16: if(cval & Node2){
return {p: [cell.bottomright, 0], x: 0, y: 1, o: 1};
} else {
return {p: [0, cell.leftbottom], x: 1, y: 0, o: 0};
}
case 17: if(cval & Node0){
return {p: [cell.bottomright, 0], x: 0, y: 1, o: 1};
} else {
return {p: [0, cell.lefttop], x: 1, y: 0, o: 1};
}
case 18: if(cval & Node3){
return {p: [0, cell.leftbottom], x: 1, y: 0, o: 0};
} else {
return {p: [cell.bottomleft, 0], x: 0, y: 1, o: 0};
}
case 19: if(cval & Node0){
return {p: [cell.bottomleft, 0], x: 0, y: 1, o: 0};
} else {
return {p: [0, cell.lefttop], x: 1, y: 0, o: 1};
}
case 20: if(cval & Node0){
return {p: [cell.topleft, 1], x: 0, y: -1, o: 0};
} else {
return {p: [0, cell.leftbottom], x: 1, y: 0, o: 0};
}
case 21: if(cval & Node1){
return {p: [0, cell.leftbottom], x: 1, y: 0, o: 0};
} else {
return {p: [cell.topright, 1], x: 0, y: -1, o: 1};
}
case 22: if(cval & Node0){
return {p: [cell.topleft, 1], x: 0, y: -1, o: 0};
} else {
return {p: [0, cell.lefttop], x: 1, y: 0, o: 1};
}
case 23: if(cval & Node1){
return {p: [0, cell.lefttop], x: 1, y: 0, o: 1};
} else {
return {p: [cell.topright, 1], x: 0, y: -1, o: 1};
}
default: console.log("edge index out of range!");
console.log(cell);
break;
}
}
return null;
}
function getExitXY(cell, x, y, o){
var e, id_x, x, y, d_x, d_y, cval = cell.cval;
var d_o;
switch(x){
case -1: switch(o){
case 0: e = isoBandEdgeRB[cval];
d_x = isoBandNextXRB[cval];
d_y = isoBandNextYRB[cval];
d_o = isoBandNextORB[cval];
break;
default: e = isoBandEdgeRT[cval];
d_x = isoBandNextXRT[cval];
d_y = isoBandNextYRT[cval];
d_o = isoBandNextORT[cval];
break;
}
break;
case 1: switch(o){
case 0: e = isoBandEdgeLB[cval];
d_x = isoBandNextXLB[cval];
d_y = isoBandNextYLB[cval];
d_o = isoBandNextOLB[cval];
break;
default: e = isoBandEdgeLT[cval];
d_x = isoBandNextXLT[cval];
d_y = isoBandNextYLT[cval];
d_o = isoBandNextOLT[cval];
break;
}
break;
default: switch(y){
case -1: switch(o){
case 0: e = isoBandEdgeTL[cval];
d_x = isoBandNextXTL[cval];
d_y = isoBandNextYTL[cval];
d_o = isoBandNextOTL[cval];
break;
default: e = isoBandEdgeTR[cval];
d_x = isoBandNextXTR[cval];
d_y = isoBandNextYTR[cval];
d_o = isoBandNextOTR[cval];
break;
}
break;
case 1: switch(o){
case 0: e = isoBandEdgeBL[cval];
d_x = isoBandNextXBL[cval];
d_y = isoBandNextYBL[cval];
d_o = isoBandNextOBL[cval];
break;
default: e = isoBandEdgeBR[cval];
d_x = isoBandNextXBR[cval];
d_y = isoBandNextYBR[cval];
d_o = isoBandNextOBR[cval];
break;
}
break;
default: break;
}
break;
}
id_x = cell.edges.indexOf(e);
if(typeof cell.edges[id_x] !== 'undefined'){
deleteEdge(cell, id_x);
} else {
//console.log("wrong edges...");
//console.log(x + " " + y + " " + o);
//console.log(cell);
return null;
}
cval = cell.cval_real;
switch(e){
case 0: if(cval & Node1){ /* node 1 within range */
x = cell.topleft;
y = 1;
} else { /* node 1 below or above threshold */
x = 1;
y = cell.righttop;
}
break;
case 1: if(cval & Node2){
x = 1;
y = cell.rightbottom;
} else {
x = cell.topleft;
y = 1;
}
break;
case 2: if(cval & Node2){
x = cell.topleft;
y = 1;
} else {
x = cell.bottomright;
y = 0;
}
break;
case 3: if(cval & Node3){
x = cell.bottomleft;
y = 0;
} else {
x = cell.topleft;
y = 1;
}
break;
case 4: if(cval & Node1){
x = cell.topright;
y = 1;
} else {
x = 1;
y = cell.righttop;
}
break;
case 5: if(cval & Node2){
x = 1;
y = cell.rightbottom;
} else {
x = cell.topright;
y = 1;
}
break;
case 6: if(cval & Node2){
x = cell.topright;
y = 1;
} else {
x = cell.bottomright;
y = 0;
}
break;
case 7: if(cval & Node3){
x = cell.bottomleft;
y = 0;
} else {
x = cell.topright;
y = 1;
}
break;
case 8: if(cval & Node2){
x = 1;
y = cell.righttop;
} else {
x = cell.bottomright;
y = 0;
}
break;
case 9: if(cval & Node3){
x = cell.bottomleft;
y = 0;
} else {
x = 1;
y = cell.righttop;
}
break;
case 10: if(cval & Node3){
x = 1;
y = cell.righttop;
} else {
x = 0;
y = cell.leftbottom;
}
break;
case 11: if(cval & Node0){
x = 0;
y = cell.lefttop;
} else {
x = 1;
y = cell.righttop;
}
break;
case 12: if(cval & Node2){
x = 1;
y = cell.rightbottom;
} else {
x = cell.bottomright;
y = 0;
}
break;
case 13: if(cval & Node3){
x = cell.bottomleft;
y = 0;
} else {
x = 1;
y = cell.rightbottom;
}
break;
case 14: if(cval & Node3){
x = 1;
y = cell.rightbottom;
} else {
x = 0;
y = cell.leftbottom;
}
break;
case 15: if(cval & Node0){
x = 0;
y = cell.lefttop;
} else {
x = 1;
y = cell.rightbottom;
}
break;
case 16: if(cval & Node2){
x = 0;
y = cell.leftbottom;
} else {
x = cell.bottomright;
y = 0;
}
break;
case 17: if(cval & Node0){
x = 0;
y = cell.lefttop;
} else {
x = cell.bottomright;
y = 0;
}
break;
case 18: if(cval & Node3){
x = cell.bottomleft;
y = 0;
} else {
x = 0;
y = cell.leftbottom;
}
break;
case 19: if(cval & Node0){
x = 0;
y = cell.lefttop;
} else {
x = cell.bottomleft;
y = 0;
}
break;
case 20: if(cval & Node0){
x = 0;
y = cell.leftbottom;
} else {
x = cell.topleft;
y = 1;
}
break;
case 21: if(cval & Node1){
x = cell.topright;
y = 1;
} else {
x = 0;
y = cell.leftbottom;
}
break;
case 22: if(cval & Node0){
x = 0;
y = cell.lefttop;
} else {
x = cell.topleft;
y = 1;
}
break;
case 23: if(cval & Node1){
x = cell.topright;
y = 1;
} else {
x = 0;
y = cell.lefttop;
}
break;
default: console.log("edge index out of range!");
console.log(cell);
return null;
}
if((typeof x === 'undefined') || (typeof y === 'undefined') || (typeof d_x === 'undefined') || (typeof d_y === 'undefined') || (typeof d_o === 'undefined')){
console.log("undefined value!");
console.log(cell);
console.log(x + " " + y + " " + d_x + " " + d_y + " " + d_o);
}
return {p: [x, y], x: d_x, y: d_y, o: d_o};
}
/*
function BandGrid2Areas(grid){
var areas = [];
var area_idx = 0;
var rows = grid.rows;
var cols = grid.cols;
grid.cells.forEach(function(g, j){
g.forEach(function(gg, i){
if(typeof gg !== 'undefined'){
var a = polygon_table[gg.cval](gg);
if((typeof a === 'object') && isArray(a)){
if((typeof a[0] === 'object') && isArray(a[0])){
if((typeof a[0][0] === 'object') && isArray(a[0][0])){
a.forEach(function(aa,k){
aa.forEach(function(aaa){
aaa[0] += i;
aaa[1] += j;
});
areas[area_idx++] = aa;
});
} else {
a.forEach(function(aa,k){
aa[0] += i;
aa[1] += j;
});
areas[area_idx++] = a;
}
} else {
console.log("bandcell polygon with malformed coordinates");
}
} else {
console.log("bandcell polygon with null coordinates");
}
}
});
});
return areas;
}*/
var isolines = function(data, geoTransform, intervals){
var lines = { "type": "FeatureCollection",
"features": []
};
for(var i=0; i<intervals.length; i++){
var value = intervals[i];
var coords = projectedIsoline(data, geoTransform, value);
lines.features.push({"type": "Feature",
"geometry": {
"type": "MultiLineString",
"coordinates": coords},
"properties": [{"value": value}]}
);
}
return lines;
};
var projectedIsoline = function(data, geoTransform, value){
if(typeof(geoTransform) != typeof(new Array()) || geoTransform.length != 6)
throw new Error("GeoTransform must be a 6 elements array");
var coords = isoline(data, value);
for(var i = 0; i<coords.length; i++){
for(var j = 0; j<coords[i].length; j++){
var coordsGeo = applyGeoTransform$1(coords[i][j][0], coords[i][j][1], geoTransform);
coords[i][j][0]= coordsGeo[0];
coords[i][j][1]= coordsGeo[1];
}
}
return coords;
};
/**
Xgeo = GT(0) + Xpixel*GT(1) + Yline*GT(2)
Ygeo = GT(3) + Xpixel*GT(4) + Yline*GT(5)
*/
var applyGeoTransform$1 = function(x, y, geoTransform){
var xgeo = geoTransform[0] + x*geoTransform[1] + y*geoTransform[2];
var ygeo = geoTransform[3] + x*geoTransform[4] + y*geoTransform[5];
return [xgeo, ygeo];
};
var isoline = function(data, threshold, options){
var defaultSettings = {
successCallback: null,
progressCallback: null,
verbose: false
};
var settings = {};
/* process options */
options = options ? options : {};
var optionKeys = Object.keys(defaultSettings);
for(var i = 0; i < optionKeys.length; i++){
var key = optionKeys[i];
var val = options[key];
val = ((typeof val !== 'undefined') && (val !== null)) ? val : defaultSettings[key];
settings[key] = val;
}
if(settings.verbose)
console.log("computing isocontour for " + threshold);
var ret = ContourGrid2Paths(computeContourGrid(data, threshold));
if(typeof settings.successCallback === 'function')
settings.successCallback(ret);
return ret;
};
/*
Thats all for the public interface, below follows the actual
implementation
*/
/*
################################
Isocontour implementation below
################################
*/
/* assume that x1 == 1 && x0 == 0 */
function interpolateX$1(y, y0, y1){
return (y - y0) / (y1 - y0);
}
/* compute the isocontour 4-bit grid */
function computeContourGrid(data, threshold){
var rows = data.length - 1;
var cols = data[0].length - 1;
var ContourGrid = { rows: rows, cols: cols, cells: [] };
for(var j = 0; j < rows; ++j){
ContourGrid.cells[j] = [];
for(var i = 0; i < cols; ++i){
/* compose the 4-bit corner representation */
var cval = 0;
var tl = data[j+1][i];
var tr = data[j+1][i+1];
var br = data[j][i+1];
var bl = data[j][i];
if(isNaN(tl) || isNaN(tr) || isNaN(br) || isNaN(bl)){
continue;
}
cval |= ((tl >= threshold) ? 8 : 0);
cval |= ((tr >= threshold) ? 4 : 0);
cval |= ((br >= threshold) ? 2 : 0);
cval |= ((bl >= threshold) ? 1 : 0);
/* resolve ambiguity for cval == 5 || 10 via averaging */
var flipped = false;
if(cval == 5 || cval == 10){
var average = (tl + tr + br + bl) / 4;
if(cval == 5 && (average < threshold)){
cval = 10;
flipped = true;
} else if(cval == 10 && (average < threshold)){
cval = 5;
flipped = true;
}
}
/* add cell to ContourGrid if it contains edges */
if(cval !== 0 && cval !== 15){
var top, bottom, left, right;
top = bottom = left = right = 0.5;
/* interpolate edges of cell */
if(cval == 1){
left = 1 - interpolateX$1(threshold, tl, bl);
bottom = 1 - interpolateX$1(threshold, br, bl);
} else if(cval == 2){
bottom = interpolateX$1(threshold, bl, br);
right = 1 - interpolateX$1(threshold, tr, br);
} else if(cval == 3){
left = 1 - interpolateX$1(threshold, tl, bl);
right = 1 - interpolateX$1(threshold, tr, br);
} else if(cval == 4){
top = interpolateX$1(threshold, tl, tr);
right = interpolateX$1(threshold, br, tr);
} else if(cval == 5){
top = interpolateX$1(threshold, tl, tr);
right = interpolateX$1(threshold, br, tr);
bottom = 1 - interpolateX$1(threshold, br, bl);
left = 1 - interpolateX$1(threshold, tl, bl);
} else if(cval == 6){
bottom = interpolateX$1(threshold, bl, br);
top = interpolateX$1(threshold, tl, tr);
} else if(cval == 7){
left = 1 - interpolateX$1(threshold, tl, bl);
top = interpolateX$1(threshold, tl, tr);
} else if(cval == 8){
left = interpolateX$1(threshold, bl, tl);
top = 1 - interpolateX$1(threshold, tr, tl);
} else if(cval == 9){
bottom = 1 - interpolateX$1(threshold, br, bl);
top = 1 - interpolateX$1(threshold, tr, tl);
} else if(cval == 10){
top = 1 - interpolateX$1(threshold, tr, tl);
right = 1 - interpolateX$1(threshold, tr, br);
bottom = interpolateX$1(threshold, bl, br);
left = interpolateX$1(threshold, bl, tl);
} else if(cval == 11){
top = 1 - interpolateX$1(threshold, tr, tl);
right = 1 - interpolateX$1(threshold, tr, br);
} else if(cval == 12){
left = interpolateX$1(threshold, bl, tl);
right = interpolateX$1(threshold, br, tr);
} else if(cval == 13){
bottom = 1 - interpolateX$1(threshold, br, bl);
right = interpolateX$1(threshold, br, tr);
} else if(cval == 14){
left = interpolateX$1(threshold, bl, tl);
bottom = interpolateX$1(threshold, bl, br);
} else {
console.log("Illegal cval detected: " + cval);
}
ContourGrid.cells[j][i] = {
cval: cval,
flipped: flipped,
top: top,
right: right,
bottom: bottom,
left: left
};
}
}
}
return ContourGrid;
}
function isSaddle(cell){
return cell.cval == 5 || cell.cval == 10;
}
function isTrivial(cell){
return cell.cval === 0 || cell.cval == 15;
}
function clearCell(cell){
if((!isTrivial(cell)) && (cell.cval != 5) && (cell.cval != 10)){
cell.cval = 15;
}
}
function getXY(cell, edge){
if(edge === "top"){
return [cell.top, 1.0];
} else if(edge === "bottom"){
return [cell.bottom, 0.0];
} else if(edge === "right"){
return [1.0, cell.right];
} else if(edge === "left"){
return [0.0, cell.left];
}
}
function ContourGrid2Paths(grid){
var paths = [];
var path_idx = 0;
var rows = grid.rows;
var cols = grid.cols;
var epsilon = 1e-7;
grid.cells.forEach(function(g, j){
g.forEach(function(gg, i){
if((typeof gg !== 'undefined') && (!isSaddle(gg)) && (!isTrivial(gg))){
var p = tracePath(grid.cells, j, i);
var merged = false;
/* we may try to merge paths at this point */
if(p.info == "mergeable"){
/*
search backwards through the path array to find an entry
that starts with where the current path ends...
*/
var x = p.path[p.path.length - 1][0],
y = p.path[p.path.length - 1][1];
for(var k = path_idx - 1; k >= 0; k--){
if((Math.abs(paths[k][0][0] - x) <= epsilon) && (Math.abs(paths[k][0][1] - y) <= epsilon)){
for(var l = p.path.length - 2; l >= 0; --l){
paths[k].unshift(p.path[l]);
}
merged = true;
break;
}
}
}
if(!merged)
paths[path_idx++] = p.path;
}
});
});
return paths;
}
/*
construct consecutive line segments from starting cell by
walking arround the enclosed area clock-wise
*/
function tracePath(grid, j, i){
var maxj = grid.length;
var p = [];
var dxContour = [0, 0, 1, 1, 0, 0, 0, 0, -1, 0, 1, 1, -1, 0, -1, 0];
var dyContour = [0, -1, 0, 0, 1, 1, 1, 1, 0, -1, 0, 0, 0, -1, 0, 0];
var dx, dy;
var startEdge = ["none", "left", "bottom", "left", "right", "none", "bottom", "left", "top", "top", "none", "top", "right", "right", "bottom", "none"];
var nextEdge = ["none", "bottom", "right", "right", "top", "top", "top", "top", "left", "bottom", "right", "right", "left", "bottom", "left", "none"];
var startCell = grid[j][i];
var currentCell = grid[j][i];
var cval = currentCell.cval;
var edge = startEdge[cval];
var pt = getXY(currentCell, edge);
/* push initial segment */
p.push([i + pt[0], j + pt[1]]);
edge = nextEdge[cval];
pt = getXY(currentCell, edge);
p.push([i + pt[0], j + pt[1]]);
clearCell(currentCell);
/* now walk arround the enclosed area in clockwise-direction */
var k = i + dxContour[cval];
var l = j + dyContour[cval];
var prev_cval = cval;
while((k >= 0) && (l >= 0) && (l < maxj) && ((k != i) || (l != j))){
currentCell = grid[l][k];
if(typeof currentCell === 'undefined'){ /* path ends here */
//console.log(k + " " + l + " is undefined, stopping path!");
break;
}
cval = currentCell.cval;
if((cval === 0) || (cval === 15)){
return { path: p, info: "mergeable" };
}
edge = nextEdge[cval];
dx = dxContour[cval];
dy = dyContour[cval];
if((cval == 5) || (cval == 10)){
/* select upper or lower band, depending on previous cells cval */
if(cval == 5){
if(currentCell.flipped){ /* this is actually a flipped case 10 */
if(dyContour[prev_cval] == -1){
edge = "left";
dx = -1;
dy = 0;
} else {
edge = "right";
dx = 1;
dy = 0;
}
} else { /* real case 5 */
if(dxContour[prev_cval] == -1){
edge = "bottom";
dx = 0;
dy = -1;
}
}
} else if(cval == 10){
if(currentCell.flipped){ /* this is actually a flipped case 5 */
if(dxContour[prev_cval] == -1){
edge = "top";
dx = 0;
dy = 1;
} else {
edge = "bottom";
dx = 0;
dy = -1;
}
} else { /* real case 10 */
if(dyContour[prev_cval] == 1){
edge = "left";
dx = -1;
dy = 0;
}
}
}
}
pt = getXY(currentCell, edge);
p.push([k + pt[0], l + pt[1]]);
clearCell(currentCell);
k += dx;
l += dy;
prev_cval = cval;
}
return { path: p, info: "closed" };
}
exports.isoband = isoband;
exports.projectedIsoband = projectedIsoband;
exports.isobands = isobands;
exports.isoline = isoline;
exports.projectedIsoline = projectedIsoline;
exports.isolines = isolines;
Object.defineProperty(exports, '__esModule', { value: true });
}));
path,circle,rect,polygon,ellipse,line {
vector-effect: non-scaling-stroke;
}
svg, canvas {
top: 0;
}
#d3MapZoomBox {
position: absolute;
z-index: 10;
height: 100px;
width: 25px;
top: 10px;
right: 50px;
}
#d3MapZoomBox > button {
height:25px;
width: 25px;
line-height: 25px;
}
.d3MapControlsBox > button {
font-size:22px;
font-weight:900;
border: none;
height:25px;
width:25px;
background: rgba(35,31,32,.85);
color: white;
padding: 0;
cursor: pointer;
}
.d3MapControlsBox > button:hover {
background: black;
}
#d3MapPanBox {
position: absolute;
z-index: 10;
height: 100px;
width: 25px;
top: 60px;
right: 50px;
}
#d3MapPanBox > button {
height:25px;
width: 25px;
line-height: 25px;
}
#d3MapPanBox > button#left {
position: absolute;
left: -25px;
top: 10px;
}
#d3MapPanBox > button#right {
position: absolute;
right: -25px;
top: 10px;
}
#d3MapLayerBox {
position: relative;
z-index: 10;
height: 100px;
width: 120px;
top: 10px;
left: 10px;
overflow: auto;
color: white;
background: rgba(35,31,32,.85);
}
#d3MapLayerBox > div {
margin: 5px;
border: none;
}
#d3MapLayerBox ul {
list-style: none;
padding: 0;
margin: 0;
cursor: pointer;
}
#d3MapLayerBox li {
list-style: none;
padding: 0;
}
#d3MapLayerBox li:hover {
font-weight:700;
}
#d3MapLayerBox li input {
cursor: pointer;
}
div.d3MapModal {
position: absolute;
z-index: 11;
background: rgba(35,31,32,.90);
top: 50px;
left: 50px;
color: white;
max-width: 400px;
}
div.d3MapModalContent {
width:100%;
height: 100%;
overflow: auto;
}
div.d3MapModalContent > p {
padding: 0px 20px;
margin: 5px 0;
}
div.d3MapModalContent > h1 {
padding: 0px 20px;
font-size: 20px;
}
div.d3MapModalArrow {
content: "";
width: 0;
height: 0;
border-left: 20px solid transparent;
border-right: 20px solid transparent;
border-top: 20px solid rgba(35,31,32,.90);
position: absolute;
bottom: -20px;
left: 33px;
}
#d3MapSVG {
}
rect.minimap-extent {
fill: rgba(200,255,255,0.35);
stroke: black;
stroke-width: 2px;
stroke-dasharray: 5 5;
}
circle.newpoints {
fill: black;
stroke: red;
stroke-width: 2px;
}
path.newfeatures {
fill: steelblue;
fill-opacity: .5;
stroke: pink;
stroke-width: 2px;
}
.countrylabel {
font-size: 12px;
color: red;
text-anchor: middle;
pointer-events: none;
font-weight: 900;
}
.wards {
fill: gray;
stroke: gray;
stroke-width: 1px;
}
.countryborders {
fill: rgba(0,0,0,0);
stroke-width: 1px;
stroke: gray;
cursor: pointer;
}
.invisible {
fill: rgba(0,0,0,0);
stroke-width: 0;
stroke: black;
cursor: pointer;
}
.countries {
fill: none;
stroke-width: 1px;
stroke: black;
opacity: 1;
}
.halffilledcountries {
fill: rgba(224,224,209,0.5);
stroke-width: 1px;
stroke: black;
opacity: 1;
}
.filledcountries {
fill: #E0E0D1;
stroke-width: 1px;
stroke: black;
opacity: 1;
}
.francelike {
fill: steelblue;
stroke-width: 2px;
stroke: lightgray;
}
.roads {
stroke: brown;
stroke-width: 1px;
fill: none;
}
.rivers {
stroke: blue;
stroke-width: 2px;
fill: none;
opacity: 1;
}
.thickborders {
stroke: brown;
stroke-width: 2px;
fill: none;
}
circle {
fill: black;
stroke: red;
}
circle.pinkcircle {
fill: pink;
stroke: black;
stroke-width: 1;
opacity: 1
}
circle.greencircle {
fill: green;
stroke: red;
opacity: 1;
stroke-width: 3;
}
#infoBox {
position: fixed;
z-index: 1;
bottom: 150px;
right: 150px;
background: white;
border: 1px gray dashed;
padding:20px;
width: 200px;
}
(function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error("Cannot find module '"+o+"'");throw f.code="MODULE_NOT_FOUND",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s})({1:[function(require,module,exports){
"use strict";
function AbstractDecoder() {}
AbstractDecoder.prototype = {
isAsync: function isAsync() {
// TODO: check if async reading func is enabled or not.
return typeof this.decodeBlock === "undefined";
}
};
module.exports = AbstractDecoder;
},{}],2:[function(require,module,exports){
"use strict";
var AbstractDecoder = require("../abstractdecoder.js");
/*
var Buffer = require('buffer');
var inflate = require('inflate');
var through = require('through');
*/
function DeflateDecoder() {}
DeflateDecoder.prototype = Object.create(AbstractDecoder.prototype, {
decodeBlockAsync: function decodeBlockAsync(buffer, callback) {
// through(function (data) {
// this.queue(new Buffer(new Uint8Array(buffer)));
// },
// function() {
// this.queue(null);
// })
// .pipe(inflate())
// /*.pipe(function() {
// alert(arguments);
// })*/
// .on("data", function(data) {
// buffers.push(data);
// })
// .on("end", function() {
// var buffer = Buffer.concat(buffers);
// var arrayBuffer = new ArrayBuffer(buffer.length);
// var view = new Uint8Array(ab);
// for (var i = 0; i < buffer.length; ++i) {
// view[i] = buffer[i];
// }
// callback(null, arrayBuffer);
// })
// .on("error", function(error) {
// callback(error, null)
// });
throw new Error("DeflateDecoder is not yet implemented.");
}
});
DeflateDecoder.prototype.constructor = DeflateDecoder;
module.exports = DeflateDecoder;
},{"../abstractdecoder.js":1}],3:[function(require,module,exports){
"use strict";
//var lzwCompress = require("lzwcompress");
var AbstractDecoder = require("../abstractdecoder.js");
function LZWDecoder() {}
LZWDecoder.prototype = Object.create(AbstractDecoder.prototype, {
decodeBlock: function decodeBlock(buffer) {
throw new Error("LZWDecoder is not yet implemented");
//return lzwCompress.unpack(Array.prototype.slice.call(new Uint8Array(buffer)));
}
});
LZWDecoder.prototype.constructor = LZWDecoder;
module.exports = LZWDecoder;
},{"../abstractdecoder.js":1}],4:[function(require,module,exports){
"use strict";
var AbstractDecoder = require("../abstractdecoder.js");
function PackbitsDecoder() {}
PackbitsDecoder.prototype = Object.create(AbstractDecoder.prototype, {
decodeBlock: function decodeBlock(buffer) {
var dataView = new DataView(buffer);
var out = [];
var i, j;
for (i = 0; i < buffer.byteLength; ++i) {
var header = dataView.getInt8(i);
if (header < 0) {
var next = dataView.getUint8(i + 1);
header = -header;
for (j = 0; j <= header; ++j) {
out.push(next);
}
i += 1;
} else {
for (j = 0; j <= header; ++j) {
out.push(dataView.getUint8(i + j + 1));
}
i += header + 1;
}
}
return new Uint8Array(out).buffer;
}
});
PackbitsDecoder.prototype.constructor = PackbitsDecoder;
module.exports = PackbitsDecoder;
},{"../abstractdecoder.js":1}],5:[function(require,module,exports){
"use strict";
var AbstractDecoder = require("../abstractdecoder.js");
function RawDecoder() {}
RawDecoder.prototype = Object.create(AbstractDecoder.prototype);
//, {
//});
RawDecoder.prototype.constructor = RawDecoder;
RawDecoder.prototype.decodeBlock = function (buffer) {
return buffer;
};
module.exports = RawDecoder;
},{"../abstractdecoder.js":1}],6:[function(require,module,exports){
"use strict";
var globals = require("./globals.js");
var GeoTIFFImage = require("./geotiffimage.js");
var fieldTypes = globals.fieldTypes,
fieldTagNames = globals.fieldTagNames,
arrayFields = globals.arrayFields,
geoKeyNames = globals.geoKeyNames;
/**
* The abstraction for a whole GeoTIFF file.
* @constructor
* @param {ArrayBuffer} rawData the raw data stream of the file as an ArrayBuffer.
* @param {Object} [options] further options.
* @param {Boolean} [options.cache=false] whether or not decoded tiles shall be cached.
*/
function GeoTIFF(rawData, options) {
this.dataView = new DataView(rawData);
options = options || {};
this.cache = options.cache || false;
var BOM = this.dataView.getUint16(0, 0);
if (BOM === 0x4949) {
this.littleEndian = true;
} else if (BOM === 0x4D4D) {
this.littleEndian = false;
} else {
throw new TypeError("Invalid byte order value.");
}
if (this.dataView.getUint16(2, this.littleEndian) !== 42) {
throw new TypeError("Invalid magic number.");
}
this.fileDirectories = this.parseFileDirectories(this.dataView.getUint32(4, this.littleEndian));
}
GeoTIFF.prototype = {
getFieldTypeLength: function getFieldTypeLength(fieldType) {
switch (fieldType) {
case fieldTypes.BYTE:case fieldTypes.ASCII:case fieldTypes.SBYTE:case fieldTypes.UNDEFINED:
return 1;
case fieldTypes.SHORT:case fieldTypes.SSHORT:
return 2;
case fieldTypes.LONG:case fieldTypes.SLONG:case fieldTypes.FLOAT:
return 4;
case fieldTypes.RATIONAL:case fieldTypes.SRATIONAL:case fieldTypes.DOUBLE:
return 8;
default:
throw new RangeError("Invalid field type: " + fieldType);
}
},
getValues: function getValues(fieldType, count, offset) {
var values = null;
var readMethod = null;
var fieldTypeLength = this.getFieldTypeLength(fieldType);
var i;
switch (fieldType) {
case fieldTypes.BYTE:case fieldTypes.ASCII:case fieldTypes.UNDEFINED:
values = new Uint8Array(count);readMethod = this.dataView.getUint8;
break;
case fieldTypes.SBYTE:
values = new Int8Array(count);readMethod = this.dataView.getInt8;
break;
case fieldTypes.SHORT:
values = new Uint16Array(count);readMethod = this.dataView.getUint16;
break;
case fieldTypes.SSHORT:
values = new Int16Array(count);readMethod = this.dataView.getInt16;
break;
case fieldTypes.LONG:
values = new Uint32Array(count);readMethod = this.dataView.getUint32;
break;
case fieldTypes.SLONG:
values = new Int32Array(count);readMethod = this.dataView.getInt32;
break;
case fieldTypes.RATIONAL:
values = new Uint32Array(count * 2);readMethod = this.dataView.getUint32;
break;
case fieldTypes.SRATIONAL:
values = new Int32Array(count * 2);readMethod = this.dataView.getInt32;
break;
case fieldTypes.FLOAT:
values = new Float32Array(count);readMethod = this.dataView.getFloat32;
break;
case fieldTypes.DOUBLE:
values = new Float64Array(count);readMethod = this.dataView.getFloat64;
break;
default:
throw new RangeError("Invalid field type: " + fieldType);
}
// normal fields
if (!(fieldType === fieldTypes.RATIONAL || fieldType === fieldTypes.SRATIONAL)) {
for (i = 0; i < count; ++i) {
values[i] = readMethod.call(this.dataView, offset + i * fieldTypeLength, this.littleEndian);
}
}
// RATIONAL or SRATIONAL
else {
for (i = 0; i < count * 2; i += 2) {
values[i] = readMethod.call(this.dataView, offset + i * fieldTypeLength, this.littleEndian);
values[i + 1] = readMethod.call(this.dataView, offset + (i + 1) * fieldTypeLength, this.littleEndian);
}
}
if (fieldType === fieldTypes.ASCII) {
return String.fromCharCode.apply(null, values);
}
return values;
},
getFieldValues: function getFieldValues(fieldTag, fieldType, typeCount, valueOffset) {
var fieldValues;
var fieldTypeLength = this.getFieldTypeLength(fieldType);
if (fieldTypeLength * typeCount <= 4) {
fieldValues = this.getValues(fieldType, typeCount, valueOffset);
} else {
var actualOffset = this.dataView.getUint32(valueOffset, this.littleEndian);
fieldValues = this.getValues(fieldType, typeCount, actualOffset);
}
if (typeCount === 1 && arrayFields.indexOf(fieldTag) === -1 && !(fieldType === fieldTypes.RATIONAL || fieldType === fieldTypes.SRATIONAL)) {
return fieldValues[0];
}
return fieldValues;
},
parseGeoKeyDirectory: function parseGeoKeyDirectory(fileDirectory) {
var rawGeoKeyDirectory = fileDirectory.GeoKeyDirectory;
if (!rawGeoKeyDirectory) {
return null;
}
var geoKeyDirectory = {};
for (var i = 4; i < rawGeoKeyDirectory[3] * 4; i += 4) {
var key = geoKeyNames[rawGeoKeyDirectory[i]],
location = rawGeoKeyDirectory[i + 1] ? fieldTagNames[rawGeoKeyDirectory[i + 1]] : null,
count = rawGeoKeyDirectory[i + 2],
offset = rawGeoKeyDirectory[i + 3];
var value = null;
if (!location) {
value = offset;
} else {
value = fileDirectory[location];
if (typeof value === "undefined" || value === null) {
throw new Error("Could not get value of geoKey '" + key + "'.");
} else if (typeof value === "string") {
value = value.substring(offset, offset + count - 1);
} else if (value.subarray) {
value = value.subarray(offset, offset + count - 1);
}
}
geoKeyDirectory[key] = value;
}
return geoKeyDirectory;
},
parseFileDirectories: function parseFileDirectories(byteOffset) {
var nextIFDByteOffset = byteOffset;
var fileDirectories = [];
while (nextIFDByteOffset !== 0x00000000) {
var numDirEntries = this.dataView.getUint16(nextIFDByteOffset, this.littleEndian);
var fileDirectory = {};
for (var i = byteOffset + 2, entryCount = 0; entryCount < numDirEntries; i += 12, ++entryCount) {
var fieldTag = this.dataView.getUint16(i, this.littleEndian);
var fieldType = this.dataView.getUint16(i + 2, this.littleEndian);
var typeCount = this.dataView.getUint32(i + 4, this.littleEndian);
fileDirectory[fieldTagNames[fieldTag]] = this.getFieldValues(fieldTag, fieldType, typeCount, i + 8);
}
fileDirectories.push([fileDirectory, this.parseGeoKeyDirectory(fileDirectory)]);
nextIFDByteOffset = this.dataView.getUint32(i, this.littleEndian);
}
return fileDirectories;
},
/**
* Get the n-th internal subfile a an image. By default, the first is returned.
*
* @param {Number} [index=0] the index of the image to return.
* @returns {GeoTIFFImage} the image at the given index
*/
getImage: function getImage(index) {
index = index || 0;
var fileDirectoryAndGeoKey = this.fileDirectories[index];
if (!fileDirectoryAndGeoKey) {
throw new RangeError("Invalid image index");
}
return new GeoTIFFImage(fileDirectoryAndGeoKey[0], fileDirectoryAndGeoKey[1], this.dataView, this.littleEndian, this.cache);
},
/**
* Returns the count of the internal subfiles.
*
* @returns {Number} the number of internal subfile images
*/
getImageCount: function getImageCount() {
return this.fileDirectories.length;
}
};
module.exports = GeoTIFF;
},{"./geotiffimage.js":7,"./globals.js":8}],7:[function(require,module,exports){
"use strict";
var globals = require("./globals.js");
var RawDecoder = require("./compression/raw.js");
var LZWDecoder = require("./compression/lzw.js");
var DeflateDecoder = require("./compression/deflate.js");
var PackbitsDecoder = require("./compression/packbits.js");
var sum = function sum(array, start, end) {
var s = 0;
for (var i = start; i < end; ++i) {
s += array[i];
}
return s;
};
var arrayForType = function arrayForType(format, bitsPerSample, size) {
switch (format) {
case 1:
// unsigned integer data
switch (bitsPerSample) {
case 8:
return new Uint8Array(size);
case 16:
return new Uint16Array(size);
case 32:
return new Uint32Array(size);
}
break;
case 2:
// twos complement signed integer data
switch (bitsPerSample) {
case 8:
return new Int8Array(size);
case 16:
return new Int16Array(size);
case 32:
return new Int32Array(size);
}
break;
case 3:
// floating point data
switch (bitsPerSample) {
case 32:
return new Float32Array(size);
case 64:
return new Float64Array(size);
}
break;
}
throw Error("Unsupported data format/bitsPerSample");
};
/**
* GeoTIFF sub-file image.
* @constructor
* @param {Object} fileDirectory The parsed file directory
* @param {Object} geoKeys The parsed geo-keys
* @param {DataView} dataView The DataView for the underlying file.
* @param {Boolean} littleEndian Whether the file is encoded in little or big endian
* @param {Boolean} cache Whether or not decoded tiles shall be cached
*/
function GeoTIFFImage(fileDirectory, geoKeys, dataView, littleEndian, cache) {
this.fileDirectory = fileDirectory;
this.geoKeys = geoKeys;
this.dataView = dataView;
this.littleEndian = littleEndian;
this.tiles = cache ? {} : null;
this.isTiled = fileDirectory.StripOffsets ? false : true;
var planarConfiguration = fileDirectory.PlanarConfiguration;
this.planarConfiguration = typeof planarConfiguration === "undefined" ? 1 : planarConfiguration;
if (this.planarConfiguration !== 1 && this.planarConfiguration !== 2) {
throw new Error("Invalid planar configuration.");
}
switch (this.fileDirectory.Compression) {
case 1:
// no compression
this.decoder = new RawDecoder();
break;
case 5:
// LZW
this.decoder = new LZWDecoder();
break;
case 6:
// JPEG
throw new Error("JPEG compression not supported.");
case 8:
// Deflate
this.decoder = new DeflateDecoder();
break;
//case 32946: // deflate ??
// throw new Error("Deflate compression not supported.");
case 32773:
// packbits
this.decoder = new PackbitsDecoder();
break;
default:
throw new Error("Unknown compresseion method identifier: " + this.fileDirectory.Compression);
}
}
GeoTIFFImage.prototype = {
/**
* Returns the associated parsed file directory.
* @returns {Object} the parsed file directory
*/
getFileDirectory: function getFileDirectory() {
return this.fileDirectory;
},
/**
* Returns the associated parsed geo keys.
* @returns {Object} the parsed geo keys
*/
getGeoKeys: function getGeoKeys() {
return this.geoKeys;
},
/**
* Returns the width of the image.
* @returns {Number} the width of the image
*/
getWidth: function getWidth() {
return this.fileDirectory.ImageWidth;
},
/**
* Returns the height of the image.
* @returns {Number} the height of the image
*/
getHeight: function getHeight() {
return this.fileDirectory.ImageLength;
},
/**
* Returns the number of samples per pixel.
* @returns {Number} the number of samples per pixel
*/
getSamplesPerPixel: function getSamplesPerPixel() {
return this.fileDirectory.SamplesPerPixel;
},
/**
* Returns the width of each tile.
* @returns {Number} the width of each tile
*/
getTileWidth: function getTileWidth() {
return this.isTiled ? this.fileDirectory.TileWidth : this.getWidth();
},
/**
* Returns the height of each tile.
* @returns {Number} the height of each tile
*/
getTileHeight: function getTileHeight() {
return this.isTiled ? this.fileDirectory.TileLength : this.fileDirectory.RowsPerStrip;
},
/**
* Calculates the number of bytes for each pixel across all samples. Only full
* bytes are supported, an exception is thrown when this is not the case.
* @returns {Number} the bytes per pixel
*/
getBytesPerPixel: function getBytesPerPixel() {
var bitsPerSample = 0;
for (var i = 0; i < this.fileDirectory.BitsPerSample.length; ++i) {
var bits = this.fileDirectory.BitsPerSample[i];
if (bits % 8 !== 0) {
throw new Error("Sample bit-width of " + bits + " is not supported.");
} else if (bits !== this.fileDirectory.BitsPerSample[0]) {
throw new Error("Differing size of samples in a pixel are not supported.");
}
bitsPerSample += bits;
}
return bitsPerSample / 8;
},
getSampleByteSize: function getSampleByteSize(i) {
if (i >= this.fileDirectory.BitsPerSample.length) {
throw new RangeError("Sample index " + i + " is out of range.");
}
var bits = this.fileDirectory.BitsPerSample[i];
if (bits % 8 !== 0) {
throw new Error("Sample bit-width of " + bits + " is not supported.");
}
return bits / 8;
},
getReaderForSample: function getReaderForSample(sampleIndex) {
var format = this.fileDirectory.SampleFormat[sampleIndex];
var bitsPerSample = this.fileDirectory.BitsPerSample[sampleIndex];
switch (format) {
case 1:
// unsigned integer data
switch (bitsPerSample) {
case 8:
return DataView.prototype.getUint8;
case 16:
return DataView.prototype.getUint16;
case 32:
return DataView.prototype.getUint32;
}
break;
case 2:
// twos complement signed integer data
switch (bitsPerSample) {
case 8:
return DataView.prototype.getInt8;
case 16:
return DataView.prototype.getInt16;
case 32:
return DataView.prototype.getInt32;
}
break;
case 3:
switch (bitsPerSample) {
case 32:
return DataView.prototype.getFloat32;
case 64:
return DataView.prototype.getFloat64;
}
break;
}
},
getArrayForSample: function getArrayForSample(sampleIndex, size) {
var format = this.fileDirectory.SampleFormat[sampleIndex];
var bitsPerSample = this.fileDirectory.BitsPerSample[sampleIndex];
return arrayForType(format, bitsPerSample, size);
},
getDecoder: function getDecoder() {
return this.decoder;
},
/**
* Returns the decoded strip or tile.
* @param {Number} x the strip or tile x-offset
* @param {Number} y the tile y-offset (0 for stripped images)
* @param {Number} plane the planar configuration (1: "chunky", 2: "separate samples")
* @returns {(Int8Array|Uint8Array|Int16Array|Uint16Array|Int32Array|Uint32Array|Float32Array|Float64Array)}
*/
getTileOrStrip: function getTileOrStrip(x, y, sample, callback) {
var numTilesPerRow = Math.ceil(this.getWidth() / this.getTileWidth());
var numTilesPerCol = Math.ceil(this.getHeight() / this.getTileHeight());
var index;
var tiles = this.tiles;
if (this.planarConfiguration === 1) {
index = y * numTilesPerRow + x;
} else if (this.planarConfiguration === 2) {
index = sample * numTilesPerRow * numTilesPerCol + y * numTilesPerRow + x;
}
if (tiles !== null && index in tiles) {
if (callback) {
return callback(null, { x: x, y: y, sample: sample, data: tiles[index] });
}
return tiles[index];
} else {
var offset, byteCount;
if (this.isTiled) {
offset = this.fileDirectory.TileOffsets[index];
byteCount = this.fileDirectory.TileByteCounts[index];
} else {
offset = this.fileDirectory.StripOffsets[index];
byteCount = this.fileDirectory.StripByteCounts[index];
}
var slice = this.dataView.buffer.slice(offset, offset + byteCount);
if (callback) {
return this.getDecoder().decodeBlockAsync(slice, function (error, data) {
if (!error && tiles !== null) {
tiles[index] = data;
}
callback(error, { x: x, y: y, sample: sample, data: data });
});
}
var block = this.getDecoder().decodeBlock(slice);
if (tiles !== null) {
tiles[index] = block;
}
return block;
}
},
_readRasterAsync: function _readRasterAsync(imageWindow, samples, valueArrays, interleave, callback, callbackError) {
var tileWidth = this.getTileWidth();
var tileHeight = this.getTileHeight();
var minXTile = Math.floor(imageWindow[0] / tileWidth);
var maxXTile = Math.ceil(imageWindow[2] / tileWidth);
var minYTile = Math.floor(imageWindow[1] / tileHeight);
var maxYTile = Math.ceil(imageWindow[3] / tileHeight);
var numTilesPerRow = Math.ceil(this.getWidth() / tileWidth);
var windowWidth = imageWindow[2] - imageWindow[0];
var windowHeight = imageWindow[3] - imageWindow[1];
var bytesPerPixel = this.getBytesPerPixel();
var imageWidth = this.getWidth();
var srcSampleOffsets = [];
var sampleReaders = [];
for (var i = 0; i < samples.length; ++i) {
if (this.planarConfiguration === 1) {
srcSampleOffsets.push(sum(this.fileDirectory.BitsPerSample, 0, samples[i]) / 8);
} else {
srcSampleOffsets.push(0);
}
sampleReaders.push(this.getReaderForSample(samples[i]));
}
var allStacked = false;
var unfinishedTiles = 0;
var littleEndian = this.littleEndian;
var globalError = null;
function onTileGot(error, tile) {
if (!error) {
var dataView = new DataView(tile.data);
var firstLine = tile.y * tileHeight;
var firstCol = tile.x * tileWidth;
var lastLine = (tile.y + 1) * tileHeight;
var lastCol = (tile.x + 1) * tileWidth;
var sampleIndex = tile.sample;
for (var y = Math.max(0, imageWindow[1] - firstLine); y < Math.min(tileHeight, tileHeight - (lastLine - imageWindow[3])); ++y) {
for (var x = Math.max(0, imageWindow[0] - firstCol); x < Math.min(tileWidth, tileWidth - (lastCol - imageWindow[2])); ++x) {
var pixelOffset = (y * tileWidth + x) * bytesPerPixel;
var value = sampleReaders[_sampleIndex].call(dataView, pixelOffset + srcSampleOffsets[_sampleIndex], littleEndian);
var windowCoordinate;
if (interleave) {
windowCoordinate = (y + firstLine - imageWindow[1]) * windowWidth * samples.length + (x + firstCol - imageWindow[0]) * samples.length + _sampleIndex;
valueArrays[windowCoordinate] = value;
} else {
windowCoordinate = (y + firstLine - imageWindow[1]) * windowWidth + x + firstCol - imageWindow[0];
valueArrays[_sampleIndex][windowCoordinate] = value;
}
}
}
} else {
globalError = error;
}
// check end condition and call callbacks
unfinishedTiles -= 1;
checkFinished();
}
function checkFinished() {
if (allStacked && unfinishedTiles === 0) {
if (globalError) {
callbackError(globalError);
} else {
callback(valueArrays);
}
}
}
for (var yTile = minYTile; yTile <= maxYTile; ++yTile) {
for (var xTile = minXTile; xTile <= maxXTile; ++xTile) {
for (var sampleIndex = 0; sampleIndex < samples.length; ++sampleIndex) {
var sample = samples[sampleIndex];
if (this.planarConfiguration === 2) {
bytesPerPixel = this.getSampleByteSize(sample);
}
var _sampleIndex = sampleIndex;
unfinishedTiles += 1;
this.getTileOrStrip(xTile, yTile, sample, onTileGot);
}
}
}
allStacked = true;
checkFinished();
},
_readRaster: function _readRaster(imageWindow, samples, valueArrays, interleave, callback, callbackError) {
try {
var tileWidth = this.getTileWidth();
var tileHeight = this.getTileHeight();
var minXTile = Math.floor(imageWindow[0] / tileWidth);
var maxXTile = Math.ceil(imageWindow[2] / tileWidth);
var minYTile = Math.floor(imageWindow[1] / tileHeight);
var maxYTile = Math.ceil(imageWindow[3] / tileHeight);
var numTilesPerRow = Math.ceil(this.getWidth() / tileWidth);
var windowWidth = imageWindow[2] - imageWindow[0];
var windowHeight = imageWindow[3] - imageWindow[1];
var bytesPerPixel = this.getBytesPerPixel();
var imageWidth = this.getWidth();
var srcSampleOffsets = [];
var sampleReaders = [];
for (var i = 0; i < samples.length; ++i) {
if (this.planarConfiguration === 1) {
srcSampleOffsets.push(sum(this.fileDirectory.BitsPerSample, 0, samples[i]) / 8);
} else {
srcSampleOffsets.push(0);
}
sampleReaders.push(this.getReaderForSample(samples[i]));
}
for (var yTile = minYTile; yTile < maxYTile; ++yTile) {
for (var xTile = minXTile; xTile < maxXTile; ++xTile) {
var firstLine = yTile * tileHeight;
var firstCol = xTile * tileWidth;
var lastLine = (yTile + 1) * tileHeight;
var lastCol = (xTile + 1) * tileWidth;
for (var sampleIndex = 0; sampleIndex < samples.length; ++sampleIndex) {
var sample = samples[sampleIndex];
if (this.planarConfiguration === 2) {
bytesPerPixel = this.getSampleByteSize(sample);
}
var tile = new DataView(this.getTileOrStrip(xTile, yTile, sample));
for (var y = Math.max(0, imageWindow[1] - firstLine); y < Math.min(tileHeight, tileHeight - (lastLine - imageWindow[3])); ++y) {
for (var x = Math.max(0, imageWindow[0] - firstCol); x < Math.min(tileWidth, tileWidth - (lastCol - imageWindow[2])); ++x) {
var pixelOffset = (y * tileWidth + x) * bytesPerPixel;
var value = sampleReaders[sampleIndex].call(tile, pixelOffset + srcSampleOffsets[sampleIndex], this.littleEndian);
var windowCoordinate;
if (interleave) {
windowCoordinate = (y + firstLine - imageWindow[1]) * windowWidth * samples.length + (x + firstCol - imageWindow[0]) * samples.length + sampleIndex;
valueArrays[windowCoordinate] = value;
} else {
windowCoordinate = (y + firstLine - imageWindow[1]) * windowWidth + x + firstCol - imageWindow[0];
valueArrays[sampleIndex][windowCoordinate] = value;
}
}
}
}
}
}
callback(valueArrays);
return valueArrays;
} catch (error) {
return callbackError(error);
}
},
/**
* This callback is called upon successful reading of a GeoTIFF image. The
* resulting arrays are passed as a single argument.
* @callback GeoTIFFImage~readCallback
* @param {(TypedArray|TypedArray[])} array the requested data as a either a
* single typed array or a list of
* typed arrays, depending on the
* 'interleave' option.
*/
/**
* This callback is called upon encountering an error while reading of a
* GeoTIFF image
* @callback GeoTIFFImage~readErrorCallback
* @param {Error} error the encountered error
*/
/**
* Reads raster data from the image. This function reads all selected samples
* into separate arrays of the correct type for that sample. When provided,
* only a subset of the raster is read for each sample.
*
* @param {Object} [options] optional parameters
* @param {Array} [options.window=whole image] the subset to read data from.
* @param {Array} [options.samples=all samples] the selection of samples to read from.
* @param {Boolean} [options.interleave=false] whether the data shall be read
* in one single array or separate
* arrays.
* @param {GeoTIFFImage~readCallback} [callback] the success callback. this
* parameter is mandatory for
* asynchronous decoders (some
* compression mechanisms).
* @param {GeoTIFFImage~readErrorCallback} [callbackError] the error callback
* @returns {(TypedArray|TypedArray[]|null)} in synchonous cases, the decoded
* array(s) is/are returned. In
* asynchronous cases, nothing is
* returned.
*/
readRasters: function readRasters() /* arguments are read via the 'arguments' object */{
// parse the arguments
var options, callback, callbackError;
switch (arguments.length) {
case 0:
break;
case 1:
if (typeof arguments[0] === "function") {
callback = arguments[0];
} else {
options = arguments[0];
}
break;
case 2:
if (typeof arguments[0] === "function") {
callback = arguments[0];
callbackError = arguments[1];
} else {
options = arguments[0];
callback = arguments[1];
}
break;
case 3:
options = arguments[0];
callback = arguments[1];
callbackError = arguments[2];
break;
default:
throw new Error("Invalid number of arguments passed.");
}
// set up default arguments
options = options || {};
callbackError = callbackError || function (error) {
console.error(error);
};
var imageWindow = options.window || [0, 0, this.getWidth(), this.getHeight()],
samples = options.samples,
interleave = options.interleave;
// check parameters
if (imageWindow[0] < 0 || imageWindow[1] < 0 || imageWindow[2] > this.getWidth() || imageWindow[3] > this.getHeight()) {
throw new Error("Select window is out of image bounds.");
} else if (imageWindow[0] > imageWindow[2] || imageWindow[1] > imageWindow[3]) {
throw new Error("Invalid subsets");
}
var imageWindowWidth = imageWindow[2] - imageWindow[0];
var imageWindowHeight = imageWindow[3] - imageWindow[1];
var numPixels = imageWindowWidth * imageWindowHeight;
var i;
if (!samples) {
samples = [];
for (i = 0; i < this.fileDirectory.SamplesPerPixel; ++i) {
samples.push(i);
}
} else {
for (i = 0; i < samples.length; ++i) {
if (samples[i] >= this.fileDirectory.SamplesPerPixel) {
throw new RangeError("Invalid sample index '" + samples[i] + "'.");
}
}
}
var valueArrays;
if (interleave) {
var format = Math.max.apply(null, this.fileDirectory.SampleFormat),
bitsPerSample = Math.max.apply(null, this.fileDirectory.BitsPerSample);
valueArrays = arrayForType(format, bitsPerSample, numPixels * samples.length);
} else {
valueArrays = [];
for (i = 0; i < samples.length; ++i) {
valueArrays.push(this.getArrayForSample(samples[i], numPixels));
}
}
// start reading data, sync or async
var decoder = this.getDecoder();
if (decoder.isAsync()) {
if (!callback) {
throw new Error("No callback specified for asynchronous raster reading.");
}
return this._readRasterAsync(imageWindow, samples, valueArrays, interleave, callback, callbackError);
} else {
callback = callback || function () {};
return this._readRaster(imageWindow, samples, valueArrays, interleave, callback, callbackError);
}
},
/**
* Returns an array of tiepoints.
* @returns {Object[]}
*/
getTiePoints: function getTiePoints() {
if (!this.fileDirectory.ModelTiepoint) {
return [];
}
var tiePoints = [];
for (var i = 0; i < this.fileDirectory.ModelTiepoint.length; i += 6) {
tiePoints.push({
i: this.fileDirectory.ModelTiepoint[i],
j: this.fileDirectory.ModelTiepoint[i + 1],
k: this.fileDirectory.ModelTiepoint[i + 2],
x: this.fileDirectory.ModelTiepoint[i + 3],
y: this.fileDirectory.ModelTiepoint[i + 4],
z: this.fileDirectory.ModelTiepoint[i + 5]
});
}
return tiePoints;
},
/**
* Returns the parsed GDAL metadata items.
* @returns {Object}
*/
getGDALMetadata: function getGDALMetadata() {
var metadata = {};
if (!this.fileDirectory.GDAL_METADATA) {
return null;
}
var xmlDom = globals.parseXml(this.fileDirectory.GDAL_METADATA);
var result = xmlDom.evaluate("GDALMetadata/Item", xmlDom, null, XPathResult.UNORDERED_NODE_SNAPSHOT_TYPE, null);
for (var i = 0; i < result.snapshotLength; ++i) {
var node = result.snapshotItem(i);
metadata[node.getAttribute("name")] = node.textContent;
}
return metadata;
}
};
module.exports = GeoTIFFImage;
},{"./compression/deflate.js":2,"./compression/lzw.js":3,"./compression/packbits.js":4,"./compression/raw.js":5,"./globals.js":8}],8:[function(require,module,exports){
"use strict";
var fieldTagNames = {
// TIFF Baseline
0x013B: 'Artist',
0x0102: 'BitsPerSample',
0x0109: 'CellLength',
0x0108: 'CellWidth',
0x0140: 'ColorMap',
0x0103: 'Compression',
0x8298: 'Copyright',
0x0132: 'DateTime',
0x0152: 'ExtraSamples',
0x010A: 'FillOrder',
0x0121: 'FreeByteCounts',
0x0120: 'FreeOffsets',
0x0123: 'GrayResponseCurve',
0x0122: 'GrayResponseUnit',
0x013C: 'HostComputer',
0x010E: 'ImageDescription',
0x0101: 'ImageLength',
0x0100: 'ImageWidth',
0x010F: 'Make',
0x0119: 'MaxSampleValue',
0x0118: 'MinSampleValue',
0x0110: 'Model',
0x00FE: 'NewSubfileType',
0x0112: 'Orientation',
0x0106: 'PhotometricInterpretation',
0x011C: 'PlanarConfiguration',
0x0128: 'ResolutionUnit',
0x0116: 'RowsPerStrip',
0x0115: 'SamplesPerPixel',
0x0131: 'Software',
0x0117: 'StripByteCounts',
0x0111: 'StripOffsets',
0x00FF: 'SubfileType',
0x0107: 'Threshholding',
0x011A: 'XResolution',
0x011B: 'YResolution',
// TIFF Extended
0x0146: 'BadFaxLines',
0x0147: 'CleanFaxData',
0x0157: 'ClipPath',
0x0148: 'ConsecutiveBadFaxLines',
0x01B1: 'Decode',
0x01B2: 'DefaultImageColor',
0x010D: 'DocumentName',
0x0150: 'DotRange',
0x0141: 'HalftoneHints',
0x015A: 'Indexed',
0x015B: 'JPEGTables',
0x011D: 'PageName',
0x0129: 'PageNumber',
0x013D: 'Predictor',
0x013F: 'PrimaryChromaticities',
0x0214: 'ReferenceBlackWhite',
0x0153: 'SampleFormat',
0x0154: 'SMinSampleValue',
0x0155: 'SMaxSampleValue',
0x022F: 'StripRowCounts',
0x014A: 'SubIFDs',
0x0124: 'T4Options',
0x0125: 'T6Options',
0x0145: 'TileByteCounts',
0x0143: 'TileLength',
0x0144: 'TileOffsets',
0x0142: 'TileWidth',
0x012D: 'TransferFunction',
0x013E: 'WhitePoint',
0x0158: 'XClipPathUnits',
0x011E: 'XPosition',
0x0211: 'YCbCrCoefficients',
0x0213: 'YCbCrPositioning',
0x0212: 'YCbCrSubSampling',
0x0159: 'YClipPathUnits',
0x011F: 'YPosition',
// EXIF
0x9202: 'ApertureValue',
0xA001: 'ColorSpace',
0x9004: 'DateTimeDigitized',
0x9003: 'DateTimeOriginal',
0x8769: 'Exif IFD',
0x9000: 'ExifVersion',
0x829A: 'ExposureTime',
0xA300: 'FileSource',
0x9209: 'Flash',
0xA000: 'FlashpixVersion',
0x829D: 'FNumber',
0xA420: 'ImageUniqueID',
0x9208: 'LightSource',
0x927C: 'MakerNote',
0x9201: 'ShutterSpeedValue',
0x9286: 'UserComment',
// IPTC
0x83BB: 'IPTC',
// ICC
0x8773: 'ICC Profile',
// XMP
0x02BC: 'XMP',
// GDAL
0xA480: 'GDAL_METADATA',
0xA481: 'GDAL_NODATA',
// Photoshop
0x8649: 'Photoshop',
// GeoTiff
0x830E: 'ModelPixelScale',
0x8482: 'ModelTiepoint',
0x85D8: 'ModelTransformation',
0x87AF: 'GeoKeyDirectory',
0x87B0: 'GeoDoubleParams',
0x87B1: 'GeoAsciiParams'
};
var key;
var fieldTags = {};
for (key in fieldTagNames) {
fieldTags[fieldTagNames[key]] = parseInt(key);
}
var arrayFields = [fieldTags.BitsPerSample, fieldTags.ExtraSamples, fieldTags.SampleFormat, fieldTags.StripByteCounts, fieldTags.StripOffsets, fieldTags.StripRowCounts, fieldTags.TileByteCounts, fieldTags.TileOffsets];
var fieldTypeNames = {
0x0001: 'BYTE',
0x0002: 'ASCII',
0x0003: 'SHORT',
0x0004: 'LONG',
0x0005: 'RATIONAL',
0x0006: 'SBYTE',
0x0007: 'UNDEFINED',
0x0008: 'SSHORT',
0x0009: 'SLONG',
0x000A: 'SRATIONAL',
0x000B: 'FLOAT',
0x000C: 'DOUBLE'
};
var fieldTypes = {};
for (key in fieldTypeNames) {
fieldTypes[fieldTypeNames[key]] = parseInt(key);
}
var geoKeyNames = {
1024: 'GTModelTypeGeoKey',
1025: 'GTRasterTypeGeoKey',
1026: 'GTCitationGeoKey',
2048: 'GeographicTypeGeoKey',
2049: 'GeogCitationGeoKey',
2050: 'GeogGeodeticDatumGeoKey',
2051: 'GeogPrimeMeridianGeoKey',
2052: 'GeogLinearUnitsGeoKey',
2053: 'GeogLinearUnitSizeGeoKey',
2054: 'GeogAngularUnitsGeoKey',
2055: 'GeogAngularUnitSizeGeoKey',
2056: 'GeogEllipsoidGeoKey',
2057: 'GeogSemiMajorAxisGeoKey',
2058: 'GeogSemiMinorAxisGeoKey',
2059: 'GeogInvFlatteningGeoKey',
2060: 'GeogAzimuthUnitsGeoKey',
2061: 'GeogPrimeMeridianLongGeoKey',
2062: 'GeogTOWGS84GeoKey',
3072: 'ProjectedCSTypeGeoKey',
3073: 'PCSCitationGeoKey',
3074: 'ProjectionGeoKey',
3075: 'ProjCoordTransGeoKey',
3076: 'ProjLinearUnitsGeoKey',
3077: 'ProjLinearUnitSizeGeoKey',
3078: 'ProjStdParallel1GeoKey',
3079: 'ProjStdParallel2GeoKey',
3080: 'ProjNatOriginLongGeoKey',
3081: 'ProjNatOriginLatGeoKey',
3082: 'ProjFalseEastingGeoKey',
3083: 'ProjFalseNorthingGeoKey',
3084: 'ProjFalseOriginLongGeoKey',
3085: 'ProjFalseOriginLatGeoKey',
3086: 'ProjFalseOriginEastingGeoKey',
3087: 'ProjFalseOriginNorthingGeoKey',
3088: 'ProjCenterLongGeoKey',
3089: 'ProjCenterLatGeoKey',
3090: 'ProjCenterEastingGeoKey',
3091: 'ProjCenterNorthingGeoKey',
3092: 'ProjScaleAtNatOriginGeoKey',
3093: 'ProjScaleAtCenterGeoKey',
3094: 'ProjAzimuthAngleGeoKey',
3095: 'ProjStraightVertPoleLongGeoKey',
3096: 'ProjRectifiedGridAngleGeoKey',
4096: 'VerticalCSTypeGeoKey',
4097: 'VerticalCitationGeoKey',
4098: 'VerticalDatumGeoKey',
4099: 'VerticalUnitsGeoKey'
};
var geoKeys = {};
for (key in geoKeyNames) {
geoKeys[geoKeyNames[key]] = parseInt(key);
}
var parseXml;
// node.js version
if (typeof window === "undefined") {
parseXml = function parseXml(xmlStr) {
// requires xmldom module
var DOMParser = require('xmldom').DOMParser;
return new DOMParser().parseFromString(xmlStr, "text/xml");
};
} else if (typeof window.DOMParser !== "undefined") {
parseXml = function parseXml(xmlStr) {
return new window.DOMParser().parseFromString(xmlStr, "text/xml");
};
} else if (typeof window.ActiveXObject !== "undefined" && new window.ActiveXObject("Microsoft.XMLDOM")) {
parseXml = function parseXml(xmlStr) {
var xmlDoc = new window.ActiveXObject("Microsoft.XMLDOM");
xmlDoc.async = "false";
xmlDoc.loadXML(xmlStr);
return xmlDoc;
};
}
module.exports = {
fieldTags: fieldTags,
fieldTagNames: fieldTagNames,
arrayFields: arrayFields,
fieldTypes: fieldTypes,
fieldTypeNames: fieldTypeNames,
geoKeys: geoKeys,
geoKeyNames: geoKeyNames,
parseXml: parseXml
};
},{"xmldom":"xmldom"}],9:[function(require,module,exports){
"use strict";
var GeoTIFF = require("./geotiff.js");
/**
* Main parsing function for GeoTIFF files.
* @param {(string|ArrayBuffer)} data Raw data to parse the GeoTIFF from.
* @param {Object} [options] further options.
* @param {Boolean} [options.cache=false] whether or not decoded tiles shall be cached.
* @returns {GeoTIFF} the parsed geotiff file.
*/
var parse = function parse(data, options) {
var rawData, i, strLen, view;
if (typeof data === "string" || data instanceof String) {
rawData = new ArrayBuffer(data.length * 2); // 2 bytes for each char
view = new Uint16Array(rawData);
for (i = 0, strLen = data.length; i < strLen; ++i) {
view[i] = data.charCodeAt(i);
}
} else if (data instanceof ArrayBuffer) {
rawData = data;
} else {
throw new Error("Invalid input data given.");
}
return new GeoTIFF(rawData, options);
};
if (typeof module !== "undefined" && typeof module.exports !== "undefined") {
module.exports.parse = parse;
}
if (typeof window !== "undefined") {
window["GeoTIFF"] = { parse: parse };
}
},{"./geotiff.js":6}]},{},[9]);
<!DOCTYPE html>
<meta charset="utf-8">
<style>
.states {
fill: #ccc;
stroke: #fff;
}
</style>
<body>
<div id="map"></div>
<script src="https://d3js.org/d3-color.v1.min.js"></script>
<script src="https://d3js.org/d3-format.v1.min.js"></script>
<script src="https://d3js.org/d3-interpolate.v1.min.js"></script>
<script src="https://d3js.org/d3-time.v1.min.js"></script>
<script src="https://d3js.org/d3-time-format.v2.min.js"></script>
<script src="https://d3js.org/d3-scale.v1.min.js"></script>
<script src="https://d3js.org/d3-zoom.v1.min.js"></script>
<script src="https://d3js.org/d3-drag.v1.min.js"></script>
<script src="https://d3js.org/d3-array.v1.min.js"></script>
<script src="https://d3js.org/d3-geo.v1.min.js"></script>
<script src="https://d3js.org/d3-selection.v1.min.js"></script>
<script src="https://d3js.org/d3-collection.v1.min.js"></script>
<script src="https://d3js.org/d3-dispatch.v1.min.js"></script>
<script src="https://d3js.org/d3-request.v1.min.js"></script>
<script src="http://d3js.org/topojson.v1.min.js"></script>
<script src="geotiff.js"></script>
<script src="https://npmcdn.com/d3-marching-squares@0.0.4"></script>
<script>
var width = 960,
height = 500;
var canvas = d3.select("#map").append("canvas")
.attr("width", width)
.attr("height", height);
var context = canvas.node().getContext("2d");
var projection = d3.geoOrthographic();
var path = d3.geoPath()
.projection(projection)
.context(context);
d3.request("sfctmp.tiff")
.responseType('arraybuffer')
.get(function(error, tiffData){
d3.json("world-110m.json", function(error, topojsonData) {
var tiff = GeoTIFF.parse(tiffData.response);
var image = tiff.getImage();
var rasters = image.readRasters();
var data = new Array(image.getHeight());
for (var j = 0; j<image.getHeight(); j++){
data[j] = new Array(image.getWidth());
for (var i = 0; i<image.getWidth(); i++){
data[j][i] = rasters[0][i + j*image.getWidth()];
}
}
var extent = d3.extent(rasters[0]);
var maxVal = 70.0;
var minVal = -75.0;
var graticule = d3.geoGraticule(), grid = graticule();
var intervals = d3.range(extent[0], extent[1], (maxVal-minVal)/20);
var colors = d3.ticks(0, 1, intervals.length).map(function(d){return d3.interpolatePlasma(d);});
geoTransform = [0, 0.500695, 0, 90, 0, -0.5]; //x-interval corrected to match borders
var bands = d3marchingsquares.isobands(data, geoTransform, intervals);
var countries = topojson.feature(topojsonData, topojsonData.objects.countries);
render();
canvas
.call(d3.drag().subject(dragsubject).on("drag", dragged));
var m0, o0;
// trick by using closure
function dragsubject() {
m0 = [d3.event.x, d3.event.y];
var proj = projection.rotate();
o0 = [-proj[0],-proj[1]];
return proj;
}
function dragged() {
var m1 = [d3.event.sourceEvent.pageX, d3.event.sourceEvent.pageY],
o1 = [o0[0] + (m0[0] - m1[0]) / 4, o0[1] + (m1[1] - m0[1]) / 4];
projection.rotate([-o1[0], -o1[1]]);
render();
}
function render() {
bands.features.forEach(function(d, i) {
context.beginPath();
context.fillStyle = colors[i];
path(d);
context.fill();
});
context.beginPath();
context.strokeStyle = "#000";
path(countries);
context.stroke();
// Style graticule
context.beginPath();
path(grid);
context.lineWidth = 0.5;
context.strokeStyle = "#ddd";
context.stroke();
}
});
});
// GeoTransform : According to GDAL
// Xgeo = GT(0) + Xpixel*GT(1) + Yline*GT(2)
// Ygeo = GT(3) + Xpixel*GT(4) + Yline*GT(5)
// In case of north up images, the GT(2) and GT(4) coefficients are zero, and the GT(1) is pixel width, and GT(5) is pixel height.
//The (GT(0),GT(3)) position is the top left corner of the top left pixel of the raster.
// so in our case 2 and 4 are zero => OK
// and 1 5 are a bit different, but x interval is corrected to match borders
// first pixel is at (0, 90)
</script>
id label rank x y cost target province modern
50001 Abodiacum 60 10.909 47.909 0 0 Five Germany
50002 Ad fl. Tigrim 60 42.191 37.341 0 0 Nine Turkey
50003 Ad Publicanos 60 6.374 45.671 0 0 Two France
50004 Ad Tricesimum 60 13.215 46.157 0 0 Four Italy
50005 Ad Aras 60 -0.977 38.736 0 0 One Spain
50006 Adramyttium 80 26.937 39.504 0 0 Seven Turkey
50007 Aeclanum 80 15.01 41.062 0 0 Four Italy
50008 Aelana 80 34.999 29.531 0 0 Nine Jordan
50009 Aequum Tuticum 70 15.074 41.257 0 0 Four Italy
50010 Aesernia 80 14.23 41.593 0 0 Four Italy
50011 Aesuris 70 -7.446 37.217 0 0 One Portugal
50012 Ara Agrippinensium 90 6.943 50.944 0 0 Two Germany
50013 Aguntum 80 12.819 46.839 0 0 Five Austria
50014 Ake-Ptolemais 80 35.077 32.926 0 0 Nine Israel
50015 Alba Fucens 80 13.411 42.079 0 0 Four Italy
50016 Albulae 70 -1.158 35.292 0 0 Eleven Algeria
50017 Alexandria 100 29.91 31.2 0 0 Ten Egypt
50019 Alexandria Troas 80 26.152 39.76 0 0 Seven Turkey
50020 Altinum 80 12.407 45.542 0 0 Four Italy
50021 Ammaedara 80 8.459 35.573 0 0 Eleven Tunisia
50022 Ancona 90 13.518 43.615 0 0 Four Italy
50023 Ancyra 90 32.873 39.947 0 0 Eight Turkey
50024 Antiochia 100 36.169 36.208 0 0 Nine Turkey
50025 Caesarea (Phrygia) 90 31.18 38.301 0 0 Eight Turkey
50026 Apamea 90 36.406 35.417 0 0 Nine Nine
50027 Apamea (Pisidia) 90 30.171 38.074 0 0 Seven Turkey
50028 Aphroditopolis 80 31.252 29.407 0 0 Ten Egypt
50029 Claudia Aprensis 90 27.066 40.976 0 0 Six Turkey
50030 Apulum 90 23.59 46.067 0 0 Six Romania
50031 Aquae Sextiae 80 5.441 43.534 0 0 Two France
50032 Aquae Sulis 70 -2.372 51.395 0 0 Three United Kingdom
50033 Aquae Terebellicae 70 -1.061 43.732 0 0 Two France
50034 Aquileia 90 13.364 45.767 0 0 Four Italy
50035 Aquincum 90 19.047 47.571 0 0 Five Hungary
50036 Arae Philaenorum 70 18.787 30.293 0 0 Ten Libya
50037 Arausio 80 4.809 44.137 0 0 Two France
50038 x 6 36.039 34.534 0 0 Nine Lebanon
50039 Archelais 80 34.048 38.384 0 0 Eight Turkey
50040 Arelate 90 4.627 43.687 0 0 Two France
50041 Argentorate 80 7.765 48.594 0 0 Two France
50042 Ariminum 80 12.563 44.059 0 0 Four Italy
50043 Arretium 90 11.862 43.47 0 0 Four Italy
50045 Arupium 70 15.29 44.829 0 0 Five Croatia
50046 Ascalon 90 34.546 31.669 0 0 Nine Israel
50047 Asculum 90 13.574 42.854 0 0 Four Italy
50048 Asturica 90 -6.049 42.462 0 0 One Spain
50049 Aternum 80 14.213 42.464 0 0 Four Italy
50050 Athenae 90 23.721 37.974 0 0 Seven Greece
50051 Aufidena 60 16.193 41.335 0 0 Four Italy
50052 Augusta Praetoria 80 7.313 45.736 0 0 Four Italy
50053 Augusta Raurica 80 7.727 47.544 0 0 Two Switzerland
50054 Augusta Suessionum 70 3.325 49.38 0 0 Two France
50055 Augusta Taurinorum 80 7.686 45.069 0 0 Four Italy
50056 Augusta Vindelicum 90 10.894 48.364 0 0 Five Germany
50057 Augustobona 70 4.063 48.307 0 0 Two France
50058 Augustobriga 70 -5.677 39.806 0 0 One Spain
50059 Augustodunum 80 4.283 46.967 0 0 Two France
50060 Auzia 80 3.685 36.148 0 0 Eleven Algeria
50061 Avaricum 90 2.405 47.081 0 0 Two France
50062 Aventicum 80 7.028 46.881 0 0 Two Switzerland
50063 Bagacum 70 3.81 50.303 0 0 Two France
50064 Banasa 80 -6.118 34.609 0 0 One Morocco
50065 Barcino 90 2.159 41.361 0 0 One Spain
50066 Barium 70 16.869 41.128 0 0 Four Italy
50067 Batnae 80 38.424 36.975 0 0 Nine Turkey
50068 Beneharnum 70 -0.436 43.332 0 0 Two France
50069 Beneventum 90 14.761 41.137 0 0 Four Italy
50070 Berenice 80 35.481 23.901 0 0 Ten Egypt
50072 Beroia 80 37.152 36.219 0 0 Nine Nine
50073 Berytus 90 35.521 33.898 0 0 Nine Lebanon
50074 Eleutheropolis 90 34.888 31.62 0 0 Nine Israel
50075 Bilbilis 80 -1.604 41.381 0 0 One Spain
50076 Claudiopolis 80 31.6 40.74 0 0 Eight Turkey
50077 Bonna 80 7.085 50.744 0 0 Two Germany
50078 Bononia 80 11.348 44.494 0 0 Four Italy
50079 Bononia (Moesia) 80 22.895 44.007 0 0 Six Bulgaria
50080 Bostra 90 36.484 32.517 0 0 Nine Nine
50081 Bovianum 80 14.473 41.486 0 0 Four Italy
50082 Bracara Augusta 90 -8.424 41.551 0 0 One Portugal
50083 Brigantium 70 9.725 47.495 0 0 Five Austria
50084 Flavium Brigantium 70 -8.397 43.37 0 0 One Spain
50085 Brigetio 80 18.145 47.737 0 0 Five Hungary
50086 Brundisium 80 17.938 40.635 0 0 Four Italy
50087 Bulla Regia 80 8.742 36.564 0 0 Eleven Tunisia
50088 Burdigala 90 -0.586 44.856 0 0 Two France
50089 Burnum 80 15.996 44.009 0 0 Five Croatia
50090 Burrio 80 -2.93 51.741 0 0 Three United Kingdom
50091 Cabilonnum 70 4.839 46.782 0 0 Two France
50092 Caeciliana 70 38.121 36.661 0 0 Nine Nine
50093 Caesaraugusta 90 -0.872 41.646 0 0 One Spain
50094 Caesarea Maritima 80 34.898 32.508 0 0 Nine Israel
50095 Caesarea (Cappadocia) 90 35.502 38.721 0 0 Eight Turkey
50096 Caesarodunum 80 0.701 47.383 0 0 Two France
50097 Calagurris 80 -1.966 42.303 0 0 One Spain
50098 Calleva 80 -1.075 51.375 0 0 Three United Kingdom
50099 Cambete 60 7.496 47.666 0 0 Two France
50100 Cambodunum 80 10.326 47.726 0 0 Five Germany
50101 Camulodunum 80 0.897 51.891 0 0 Three United Kingdom
50102 Canusium 80 16.065 41.221 0 0 Four Italy
50103 Capsa 80 8.789 34.412 0 0 Eleven Tunisia
50104 Capua 90 14.242 41.085 0 0 Four Italy
50105 Carnuntum 80 16.916 48.121 0 0 Five Austria
50106 Carrhae 80 39.023 36.875 0 0 Nine Turkey
50107 Carthago 100 10.312 36.846 0 0 Eleven Tunisia
50108 Carthago Nova 90 -0.992 37.605 0 0 One Spain
50109 Casinum 90 13.83 41.492 0 0 Four Italy
50110 Castrum Truentinum 80 13.905 42.897 0 0 Four Italy
50111 Castulo 80 -3.625 38.037 0 0 One Spain
50112 Catabathmus Maior 80 25.159 31.562 0 0 Ten Egypt
50113 Caudium 80 14.64 41.063 0 0 Four Italy
50114 Celeia 80 15.264 46.234 0 0 Five Slovenia
50115 Cenabum 80 1.915 47.909 0 0 Two France
50116 Cetium 70 15.622 48.204 0 0 Five Austria
50117 Chalcedon 80 29.03 40.993 0 0 Six Turkey
50118 Cibalae 80 18.8 45.275 0 0 Five Croatia
50119 Circesium 90 40.449 35.172 0 0 Nine Nine
50120 Cirta 90 6.593 36.362 0 0 Eleven Algeria
50121 Civitas Namnetum 70 -1.558 47.214 0 0 Two France
50122 Clusium 90 11.947 43.016 0 0 Four Italy
50123 Clysma 80 32.568 29.958 0 0 Ten Egypt
50124 Augusta Treverorum 90 6.681 49.761 0 0 Two Germany
50125 Ulpia Traiana Tricensimae 80 6.445 51.668 0 0 Two Germany
50126 Comana 80 36.33 38.337 0 0 Eight Turkey
50127 Comum 80 9.085 45.811 0 0 Four Italy
50128 Conimbriga 80 -8.499 40.085 0 0 One Portugal
50129 Constantinopolis 100 28.985 41.018 0 0 Six Turkey
50130 Coptos 100 32.805 26.006 0 0 Ten Egypt
50131 Corduba 100 -4.78 37.884 0 0 One Spain
50132 Corfinium 80 13.841 42.123 0 0 Four Italy
50133 Coriosopitum 70 -2.003 54.976 0 0 Three United Kingdom
50134 Cosa 80 11.288 42.406 0 0 Four Italy
50135 Cuicul 80 5.727 36.322 0 0 Eleven Algeria
50136 Cumae 80 14.045 40.853 0 0 Four Italy
50137 Curia 70 9.53 46.848 0 0 Five Switzerland
50138 Cyrene 90 21.867 32.824 0 0 Ten Libya
50139 Cyrrhus 80 36.915 36.781 0 0 Nine Nine
50140 Damascus 90 36.309 33.511 0 0 Nine Nine
50141 Darnis 80 22.641 32.768 0 0 Ten Libya
50142 Decetia 70 3.463 46.85 0 0 Two France
50143 Delphi 80 22.497 38.481 0 0 Seven Greece
50144 Dertona 80 8.864 44.896 0 0 Four Italy
50145 Dertosa 80 0.52 40.81 0 0 One Spain
50146 Deultum 80 27.306 42.401 0 0 Six Bulgaria
50147 Deva 80 -2.897 53.19 0 0 Three United Kingdom
50148 Diana Veteranorum 80 5.889 35.79 0 0 Eleven Algeria
50149 Dierna 80 22.402 44.708 0 0 Six Romania
50150 Thebai 80 32.652 25.701 0 0 Ten Egypt
50151 Doclea 80 19.28 42.479 0 0 Five Montenegro
50152 Domavium 80 19.381 44.141 0 0 Five Bosnia & Herzegovina
50153 Dorylaion 80 30.528 39.814 0 0 Seven Turkey
50154 Drobeta 80 22.659 44.635 0 0 Six Romania
50155 Dura 80 40.73 34.746 0 0 Nine Nine
50156 Durnonovaria 80 -2.435 50.71 0 0 Three United Kingdom
50157 Durocortorum 80 4.031 49.262 0 0 Two France
50158 Durostorum 80 27.26 44.116 0 0 Six Bulgaria
50159 Dyrrhachium 90 19.454 41.324 0 0 Six Albania
50160 Eburacum 90 -1.113 53.954 0 0 Three United Kingdom
50161 Edessa 90 38.794 37.159 0 0 Nine Turkey
50162 Eleusis 80 23.543 38.045 0 0 Seven Greece
50163 Emerita Augusta 90 -6.347 38.915 0 0 One Spain
50164 Emesa 80 36.716 34.734 0 0 Nine Nine
50165 Emmaus 80 34.989 31.838 0 0 Nine West Bank
50166 Emona 80 14.505 46.05 0 0 Four Slovenia
50167 Emporiae 80 3.1 42.15 0 0 One Spain
50168 Endidae 60 11.273 46.317 0 0 Four Italy
50169 Ephesus 100 27.348 37.939 0 0 Seven Turkey
50170 Epiphaneia 80 36.749 35.143 0 0 Nine Nine
50171 Fanum Fortunae 80 13.016 43.844 0 0 Four Italy
50172 Faventia 70 11.883 44.285 0 0 Four Italy
50173 Ferentinum 80 13.252 41.692 0 0 Four Italy
50174 Florentia 80 11.256 43.768 0 0 Four Italy
50175 Formiae 80 13.605 41.255 0 0 Four Italy
50176 Forum Iulii 80 6.731 43.441 0 0 Two France
50177 Fregellanum 60 13.512 41.545 0 0 Four Italy
50178 Gadara 80 35.733 32.061 0 0 Nine Jordan
50179 Gades 90 -6.293 36.529 0 0 One Spain
50180 Galacum 60 -2.592 54.171 0 0 Three United Kingdom
50181 Gaza 90 34.458 31.51 0 0 Nine Gaza Strip
50182 Genava 70 6.138 46.202 0 0 Two Switzerland
50183 Genua 70 8.933 44.406 0 0 Four Italy
50184 Germa 90 31.616 39.51 0 0 Seven Turkey
50185 Gesoriacum 70 1.614 50.724 0 0 Two France
50186 Glevum 80 -2.262 51.867 0 0 Three United Kingdom
50187 Hadrianoupolis 60 26.566 41.683 0 0 Six Turkey
50188 Hadrumetum 90 10.644 35.837 0 0 Eleven Tunisia
50189 Heliopolis 80 31.295 30.124 0 0 Ten Egypt
50190 Heliopolis (Baalbek) 90 36.203 34.014 0 0 Nine Lebanon
50191 Heraklea 80 21.345 41.025 0 0 Six Macedonia
50192 Herakleopolis 80 30.941 29.086 0 0 Ten Egypt
50193 Herdoniae 70 15.619 41.315 0 0 Four Italy
50194 Hermopolis Magna 90 30.804 27.778 0 0 Ten Egypt
50195 Hibis 80 30.553 25.437 0 0 Ten Egypt
50196 Hierakonpolis 70 30.477 31.018 0 0 Ten Egypt
50197 Hierasykaminos 70 32.683 23.068 0 0 Ten Egypt
50198 Hippo Regius 90 7.754 36.888 0 0 Eleven Algeria
50199 Hispalis 90 -5.997 37.382 0 0 One Spain
50200 Histria 80 28.768 44.552 0 0 Six Romania
50201 Iader 80 15.228 44.114 0 0 Five Croatia
50202 Iconium 80 32.512 37.866 0 0 Eight Turkey
50203 Ilerda 80 0.625 41.613 0 0 One Spain
50204 Ilium 80 26.265 39.947 0 0 Seven Turkey
50205 Interpromium 70 13.933 42.243 0 0 Four Italy
50206 Iol Caesarea 90 2.196 36.606 0 0 Eleven Algeria
50207 Isca 80 -2.966 51.618 0 0 Three United Kingdom
50208 Italica 80 -6.035 37.438 0 0 One Spain
50209 Iulia Concordia 80 12.843 45.756 0 0 Four Italy
50210 Iuliomagus 80 -0.548 47.458 0 0 Two France
50211 Iulium Carnicum 70 13.012 46.452 0 0 Four Italy
50212 Iuvavum 80 13.061 47.804 0 0 Five Austria
50213 Ierusalem 100 35.234 31.776 0 0 Nine West Bank
50214 Kallipolis 60 26.68 40.414 0 0 Six Turkey
50215 Kapitolias 70 35.857 32.61 0 0 Nine Jordan
50216 Katabolos 70 35.985 36.922 0 0 Eight Turkey
50217 Kellis 80 29.089 25.518 0 0 Ten Egypt
50218 Klaudianon 80 33.49 26.807 0 0 Ten Egypt
50219 Flaviopolis 70 32.197 40.806 0 0 Eight Turkey
50220 Lacobriga 70 -4.602 42.347 0 0 One Spain
50221 Lamasba 80 5.909 35.6 0 0 Eleven Algeria
50222 Lambaesis 90 6.262 35.489 0 0 Eleven Algeria
50223 Lampsacus 80 26.694 40.351 0 0 Seven Turkey
50224 Lancia 80 -5.415 42.533 0 0 One Spain
50225 Laodicea 80 35.785 35.521 0 0 Nine Nine
50226 Larinum 80 14.918 41.806 0 0 Four Italy
50227 Larissa 90 22.416 39.639 0 0 Seven Greece
50228 Lauriacum 80 14.465 48.22 0 0 Five Austria
50229 Legio VII 70 -5.571 42.605 0 0 One Spain
50230 Lepcis Magna 100 14.292 32.637 0 0 Eleven Libya
50231 Limonum 80 0.354 46.571 0 0 Two France
50232 Lindum 80 -0.541 53.237 0 0 Three United Kingdom
50233 Lixus 80 -6.111 35.209 0 0 One Morocco
50234 Loium 60 0.723 49.522 0 0 Two France
50235 Londinium 100 -0.083 51.52 0 0 Three United Kingdom
50236 Lousonna 60 6.631 46.518 0 0 Two Switzerland
50237 Luca 90 10.499 43.846 0 0 Four Italy
50238 Lugdunum Cananefatium 70 4.398 52.198 0 0 Two Netherlands
50239 Lugdunum Convenarum 80 0.559 43.038 0 0 Two France
50240 Luguvalium 80 -2.936 54.894 0 0 Three United Kingdom
50241 Luna 90 10.03 44.065 0 0 Four Italy
50242 Lutetia 70 2.34 48.85 0 0 Two France
50243 Lydda 90 34.892 31.965 0 0 Nine Israel
50244 Lykopolis 80 31.187 27.183 0 0 Ten Egypt
50245 Magnesia 80 27.526 37.859 0 0 Seven Turkey
50246 Mampsoukrenai 60 34.892 37.079 0 0 Eight Turkey
50247 Marcianopolis 90 27.437 43.315 0 0 Six Bulgaria
50248 Mariana 70 -2.926 38.558 0 0 One Spain
50249 Mamucio 70 -2.329 53.464 0 0 Three United Kingdom
50250 Massilia 80 5.363 43.305 0 0 Two France
50251 Mediolanum 100 9.187 45.463 0 0 Four Italy
50252 Mediolanum (Gaul) 80 -0.63 45.749 0 0 Two France
50253 Melitene 90 38.371 38.43 0 0 Eight Turkey
50254 Memphis 90 31.276 30.003 0 0 Ten Egypt
50255 Minturnae 90 13.768 41.241 0 0 Four Italy
50256 Misenum 80 14.084 40.785 0 0 Four Italy
50257 Mogontiacum 90 8.256 50.007 0 0 Two Germany
50258 Mounesis 70 30.606 24.683 0 0 Ten Egypt
50259 Mursa 80 18.673 45.549 0 0 Five Croatia
50260 Musti 80 9.135 36.341 0 0 Eleven Tunisia
50261 Mutina 80 10.924 44.646 0 0 Four Italy
50262 Myos Hormos 70 34.244 26.156 0 0 Ten Egypt
50263 Naissus 90 21.897 43.328 0 0 Six Serbia
50264 Narbo 90 3 43.197 0 0 Two France
50265 Narnia 80 12.515 42.519 0 0 Four Italy
50266 Narona 80 17.632 43.052 0 0 Five Croatia
50267 Naucratis 80 30.607 30.854 0 0 Ten Egypt
50268 Neapolis 90 14.233 40.84 0 0 Four Italy
50269 Nemausus 80 4.357 43.843 0 0 Two France
50270 Nemetacum 70 2.763 50.297 0 0 Two France
50271 Nicaea 90 29.723 40.436 0 0 Eight Turkey
50272 Nicomedia 90 29.924 40.77 0 0 Eight Turkey
50273 Nicopolis 80 20.735 39.007 0 0 Six Greece
50274 Nicopolis (Pontus) 80 38.146 40.151 0 0 Eight Turkey
50275 Nisibis 80 41.244 37.077 0 0 Nine Turkey
50276 Novae 80 25.385 43.615 0 0 Six Bulgaria
50277 Noviomagus 70 8.445 49.315 0 0 Two Germany
50278 Nuceria 80 14.673 40.742 0 0 Four Italy
50279 Ocriculum 80 12.466 42.411 0 0 Four Italy
50280 Odessus 80 27.908 43.211 0 0 Six Bulgaria
50281 Oea 90 13.174 32.897 0 0 Eleven Libya
50282 Oescus 80 24.472 43.707 0 0 Six Bulgaria
50283 Olisipo 80 -9.145 38.726 0 0 One Portugal
50284 Omboi 80 32.95 24.466 0 0 Ten Egypt
50285 Osca 80 -0.41 42.139 0 0 One Spain
50286 Ostia/Portus 90 12.287 41.754 0 0 Four Italy
50287 Ovilava 80 14.026 48.163 0 0 Five Austria
50288 Oxyrhynchus 80 30.626 28.672 0 0 Ten Egypt
50289 Palantia 60 -5.383 42.446 0 0 One Spain
50290 Palmyra 90 38.285 34.559 0 0 Nine Nine
50291 Paraetonium 80 27.225 31.356 0 0 Ten Egypt
50292 Parma 80 10.332 44.803 0 0 Four Italy
50293 Parthanum 60 11.085 47.491 0 0 Five Germany
50294 Patavium 90 11.876 45.409 0 0 Four Italy
50295 Pax Iulia 90 -7.851 37.997 0 0 One Portugal
50296 Pella 80 22.522 40.773 0 0 Six Greece
50297 Pelusium 90 32.567 31.043 0 0 Ten Egypt
50298 Penne Locos 60 6.917 46.397 0 0 Two Switzerland
50299 Perdices 70 5.367 35.845 0 0 Eleven Algeria
50300 Pergamum 90 27.181 39.14 0 0 Seven Turkey
50301 Perinthus 80 27.957 40.977 0 0 Six Turkey
50302 Petra 90 35.464 30.325 0 0 Nine Jordan
50303 Petuaria 70 -0.592 53.687 0 0 Three United Kingdom
50304 Philadelpheia 90 35.934 31.946 0 0 Nine Jordan
50305 Philippi 80 24.291 41.018 0 0 Six Greece
50306 Philippopolis 90 24.735 42.146 0 0 Six Bulgaria
50307 Pisae 90 10.396 43.715 0 0 Four Italy
50308 Pistoriae 80 10.892 43.934 0 0 Four Italy
50309 Placentia 90 9.698 45.051 0 0 Four Italy
50310 Poetovio 80 15.869 46.419 0 0 Five Slovenia
50311 Pola 80 13.84 44.869 0 0 Four Croatia
50312 Pompeii 80 14.484 40.748 0 0 Four Italy
50313 Pompelo 70 -1.652 42.8 0 0 One Spain
50314 Pons Aeni 70 12.118 47.881 0 0 Five Germany
50315 Pons Drusi 60 11.343 46.475 0 0 Four Italy
50316 Porolissum 80 23.194 47.168 0 0 Six Romania
50318 Potaissa 80 23.756 46.561 0 0 Six Romania
50319 Praetorium 70 15.968 31.286 0 0 Eleven Libya
50320 Ptolemais 90 20.95 32.707 0 0 Ten Libya
50321 Ptolemais Hermiou 80 31.804 26.477 0 0 Ten Egypt
50322 Puteoli 90 14.106 40.83 0 0 Four Italy
50323 Ravenna 90 12.212 44.423 0 0 Four Italy
50324 Reate 80 12.86 42.402 0 0 Four Italy
50325 Castra Regina 80 12.102 49.011 0 0 Five Germany
50326 Regium 80 15.643 38.108 0 0 Four Italy
50327 Roma 100 12.485 41.891 0 0 Four Italy
50328 Rusaddir 80 -2.94 35.283 0 0 One Spain
50329 Rusicade 80 6.912 36.885 0 0 Eleven Algeria
50330 Rutupiae 70 1.318 51.302 0 0 Three United Kingdom
50331 Sabratha 90 12.484 32.805 0 0 Eleven Libya
50332 Saguntum 80 -0.269 39.666 0 0 One Spain
50333 Sala 80 -6.81 34.005 0 0 One Morocco
50334 Saldae 80 5.071 36.762 0 0 Eleven Algeria
50335 Salernum 80 14.765 40.677 0 0 Four Italy
50336 Salona 90 16.5 43.531 0 0 Five Croatia
50337 Samarobriva 70 2.287 49.892 0 0 Two France
50338 Samosata 90 38.516 37.528 0 0 Nine Turkey
50339 Santicum 70 13.874 46.635 0 0 Five Austria
50340 Sardis 90 28.065 38.476 0 0 Seven Turkey
50341 Sarmizegethusa 80 22.784 45.522 0 0 Six Romania
50342 Satala 80 39.66 40.017 0 0 Eight Turkey
50343 Savaria 80 16.621 47.234 0 0 Five Hungary
50344 Scarbantia 80 16.599 47.69 0 0 Five Hungary
50345 Scodra 80 19.511 42.065 0 0 Five Albania
50346 Scythopolis 90 35.504 32.507 0 0 Nine Israel
50347 Sebasteia 90 37.032 39.748 0 0 Eight Turkey
50348 Segusio 70 7.011 45.122 0 0 Four Italy
50349 Senia 80 14.917 44.992 0 0 Five Croatia
50350 Serdica 90 23.333 42.73 0 0 Six Bulgaria
50351 Servitium 70 17.263 45.134 0 0 Five Bosnia & Herzegovina
50352 Sicca Veneria 80 8.706 36.176 0 0 Eleven Tunisia
50353 Side 90 31.398 36.775 0 0 Seven Turkey
50354 Siga 80 -1.466 35.257 0 0 Eleven Algeria
50355 Singara 90 41.861 36.328 0 0 Nine Iraq
50356 Singidunum 90 20.469 44.818 0 0 Six Serbia
50357 Sinuessa 80 13.83 41.161 0 0 Four Italy
50358 Sipontum 80 15.895 41.606 0 0 Four Italy
50359 Sirmium 90 19.609 44.965 0 0 Five Serbia
50360 Sisapo 70 -4.519 38.644 0 0 One Spain
50361 Siscia 90 16.37 45.482 0 0 Five Croatia
50362 Sitifis 90 5.394 36.192 0 0 Eleven Algeria
50363 Smyrna 90 27.141 38.427 0 0 Seven Turkey
50364 Soura 70 38.804 35.906 0 0 Nine Nine
50365 Spinis 60 -1.233 51.4 0 0 Three United Kingdom
50366 Spoletium 90 12.737 42.744 0 0 Four Italy
50367 Stobi 80 21.972 41.554 0 0 Six Macedonia
50368 Sufasar 80 2.507 36.194 0 0 Eleven Algeria
50369 Sufetula 80 9.128 35.257 0 0 Eleven Tunisia
50370 Summuntorium 70 10.789 48.639 0 0 Five Germany
50371 Summus Pyreneus (West) 60 -1.359 43.008 0 0 One Spain
50372 Summus Pyreneus (East) 60 -0.728 42.845 0 0 Two Spain
50373 Syene 80 32.905 24.095 0 0 Ten Egypt
50374 Tacape 90 10.098 33.882 0 0 Eleven Tunisia
50375 Taliata 70 22.148 44.46 0 0 Six Serbia
50376 Tabia 80 34.535 39.858 0 0 Eight Turkey
50377 Tarentum 90 17.239 40.468 0 0 Four Italy
50378 Tarracina 90 13.248 41.29 0 0 Four Italy
50379 Tarraco 100 1.23 41.115 0 0 One Spain
50380 Tarsus 90 34.901 36.915 0 0 Eight Turkey
50381 Teanum 80 14.055 41.254 0 0 Four Italy
50382 Terenouthis 70 30.816 30.431 0 0 Ten Egypt
50383 Tergeste 80 13.771 45.648 0 0 Four Italy
50384 Thagaste 80 7.983 36.29 0 0 Eleven Algeria
50385 Thamugadi 80 6.472 35.503 0 0 Eleven Algeria
50386 Thebae 80 23.318 38.321 0 0 Seven Greece
50387 Thelepte 80 8.596 34.986 0 0 Eleven Tunisia
50388 Thelseai 60 36.699 33.645 0 0 Nine Nine
50389 Thessalonica 90 22.966 40.635 0 0 Six Greece
50390 Theveste 80 8.143 35.409 0 0 Eleven Algeria
50391 Thuburnica 80 8.46 36.53 0 0 Eleven Tunisia
50392 Tibiscum 80 22.185 45.458 0 0 Six Romania
50393 Tibur 80 12.797 41.963 0 0 Four Italy
50394 Tubusuctu 80 4.834 36.668 0 0 Eleven Algeria
50395 Ticinum 70 9.156 45.185 0 0 Four Italy
50396 Tingi 90 -5.798 35.792 0 0 One Morocco
50398 Tolosa 80 1.434 43.616 0 0 Two France
50399 Tomis 80 28.643 44.188 0 0 Six Romania
50400 Tralles 80 27.84 37.86 0 0 Seven Turkey
50401 Trapezus 80 39.718 41.002 0 0 Eight Turkey
50402 Tridentum 80 11.118 46.066 0 0 Four Italy
50403 Troesmis 80 28.195 45.156 0 0 Six Romania
50404 Tyana 80 34.616 37.828 0 0 Eight Turkey
50405 Tyrus 90 35.198 33.277 0 0 Nine Lebanon
50406 Valentia 80 4.889 44.929 0 0 Two France
50407 Vappincum 70 6.033 44.546 0 0 Two France
50408 Veldidena 60 11.394 47.26 0 0 Five Austria
50409 Venonis 60 -1.299 52.487 0 0 Three United Kingdom
50410 Venusia 80 15.814 40.962 0 0 Four Italy
50411 Venta Icenorum 80 1.287 52.577 0 0 Three United Kingdom
50412 Venta 80 -1.323 51.068 0 0 Three United Kingdom
50413 Vercellae 80 8.416 45.33 0 0 Four Italy
50414 Verona 90 10.994 45.439 0 0 Four Italy
50415 Verulamium 80 -0.356 51.745 0 0 Three United Kingdom
50416 Vesontio 80 6.002 47.224 0 0 Two France
50417 Vibo Valentia 80 16.097 38.675 0 0 Four Italy
50418 Vienna 90 4.878 45.524 0 0 Two France
50419 Viminacium 80 21.233 44.736 0 0 Six Serbia
50420 Vindobona 80 16.373 48.21 0 0 Five Austria
50421 Viroconium 80 -2.649 52.66 0 0 Three United Kingdom
50422 Virovesca 70 -3.324 42.549 0 0 One Spain
50423 Virunum 90 14.415 46.702 0 0 Five Austria
50424 Vivisco 60 6.84 46.468 0 0 Two Switzerland
50425 Volsinii 80 11.985 42.644 0 0 Four Italy
50426 Volubilis 80 -5.558 34.085 0 0 One Morocco
50427 Zarai 80 5.683 35.799 0 0 Eleven Algeria
50428 Zeugma 80 37.875 37.059 0 0 Nine Turkey
50429 Lugdunum 100 4.818 45.758 0 0 Two France
50430 Heraclea Pontica 90 31.419 41.282 0 0 Eight Turkey
50431 Laodicea ad Lycum 90 29.116 37.842 0 0 Seven Turkey
50432 Boubastis 70 31.517 30.582 0 0 Ten Egypt
50434 Vorgium 70 -3.576 48.296 0 0 Two France
50435 Aginnum 80 0.627 44.203 0 0 Two France
50436 Cibyra 80 29.519 37.158 0 0 Seven Turkey
50437 Perge 90 30.856 36.967 0 0 Seven Turkey
50438 Phaselis 80 30.547 36.52 0 0 Seven Turkey
50439 Myra 80 29.995 36.244 0 0 Seven Turkey
50440 Patara 80 29.322 36.262 0 0 Seven Turkey
50441 Xanthos 80 29.331 36.36 0 0 Seven Turkey
50442 Amaseia 80 35.82 40.648 0 0 Eight Turkey
50443 Phiara 60 36.602 39.863 0 0 Eight Turkey
50444 Augustonemetum 80 3.077 45.775 0 0 Two France
50445 Augustoritum 80 1.248 45.833 0 0 Two France
50446 Amastris 80 32.38 41.748 0 0 Eight Turkey
50447 Attalea 80 30.7 36.894 0 0 Seven Turkey
50448 Ebusus 80 1.424 38.91 0 0 One Spain
50449 Thabraca 80 8.75 36.953 0 0 Eleven Tunisia
50450 Dianium 80 0.099 38.837 0 0 One Spain
50451 Olbia 80 9.501 40.929 0 0 Four Italy
50452 Paphos 90 32.414 34.758 0 0 Eight Eight
50453 Salamis 90 33.911 35.177 0 0 Eight Eight
50454 Seleukeia Pieria 90 35.934 36.119 0 0 Nine Turkey
50455 Syracusae 90 15.295 37.072 0 0 Four Italy
50456 Portus Pachyni 70 15.137 36.681 0 0 Four Italy
50458 Amisus 80 36.329 41.304 0 0 Eight Turkey
50459 Divodurum 70 6.186 49.123 0 0 Two France
50460 Condate 70 -1.69 48.129 0 0 Two France
50461 Rotomagus 70 1.097 49.448 0 0 Two France
50462 Iuliobona 70 0.537 49.525 0 0 Two France
50463 Iuliobriga 80 -4.112 43 0 0 One Spain
50464 Portus Blendium 70 -4.043 43.432 0 0 One Spain
50465 Dessobriga 60 -4.328 42.411 0 0 One Spain
50466 Lamia 80 22.442 38.902 0 0 Seven Greece
50467 Naupactus 80 21.831 38.399 0 0 Seven Greece
50468 Confluentes 70 7.585 50.357 0 0 Two Germany
50469 Lissus 80 19.663 41.785 0 0 Five Albania
50470 Salmantica 80 -5.664 40.964 0 0 One Spain
50471 Segedunum 60 -1.529 54.99 0 0 Three United Kingdom
50472 Ulpiana 80 21.192 42.598 0 0 Six Serbia
50473 Maiensis Statio 60 11.169 46.659 0 0 Four Italy
50474 Portus Magnus 70 -0.266 35.808 0 0 Eleven Algeria
50476 Colubraria 60 0.685 39.898 0 0 One Spain
50482 Igilgili 80 5.767 36.822 0 0 Eleven Algeria
50483 Metagonium Pr. 60 6.467 37.089 0 0 Eleven Algeria
50485 Galata 60 8.929 37.527 0 0 Eleven Tunisia
50486 Caralis 80 9.11 39.215 0 0 Four Italy
50487 Gallicum Fretum 60 9.159 41.387 0 0 Four France
50489 Ilva 70 10.24 42.743 0 0 Four Italy
50491 Thaenae 80 10.7 34.67 0 0 Eleven Tunisia
50492 Meninge 80 10.92 33.68 0 0 Eleven Tunisia
50493 Mercurii Pr. 60 11.013 37.062 0 0 Eleven Tunisia
50495 Clipea 70 11.11 36.84 0 0 Eleven Tunisia
50498 Caput Vada 60 11.16 35.23 0 0 Eleven Tunisia
50499 Cossyra 70 11.94 36.83 0 0 Eleven Italy
50501 Maritima 60 12.06 37.97 0 0 Four Italy
50502 Atria 70 12.055 45.054 0 0 Four Italy
50504 Brundulum 60 12.31 45.19 0 0 Four Italy
50505 Lilybaeum 80 12.437 37.798 0 0 Four Italy
50507 Selinus 90 12.825 37.583 0 0 Four Italy
50509 Tiliaventum (river) 60 13.1 45.64 0 0 Four Italy
50512 Melita 80 14.4 35.88 0 0 Four Malta
50513 Camarina 80 14.45 36.85 0 0 Four Italy
50515 Cephalae Pr. 60 15.21 32.37 0 0 Eleven Libya
50516 Messana 90 15.557 38.192 0 0 Four Italy
50518 Titius (river) 60 15.86 43.72 0 0 Five Croatia
50520 Salapia 70 16.02 41.39 0 0 Four Italy
50521 Heracleum Pr. 60 16.06 37.93 0 0 Four Italy
50523 Lokroi Epizephyrioi 80 16.26 38.24 0 0 Four Italy
50524 Lacinium Pr. 60 17.2 39.03 0 0 Four Italy
50527 Kallipolis-Anxa 70 17.99 40.06 0 0 Four Italy
50528 Epidaurum 80 18.22 42.58 0 0 Five Croatia
50529 Sallentinum Pr. 60 18.36 39.8 0 0 Four Italy
50530 Hydruntum 70 18.49 40.15 0 0 Four Italy
50531 Automalax 70 19.13 30.25 0 0 Ten Libya
50533 Acroceraunia Pr. 60 19.32 40.44 0 0 Six Albania
50534 Aulon 70 19.42 40.51 0 0 Six Albania
50535 Apollonia (Epirus) 90 19.43 40.77 0 0 Six Albania
50537 Corcyra 80 19.92 39.59 0 0 Six Greece
50538 Euesperides 80 20.079 32.135 0 0 Ten Libya
50539 Leucas 80 20.71 38.83 0 0 Six Greece
50540 Zacynthus 70 20.9 37.78 0 0 Seven Greece
50541 Ichthys Pr. 60 21.32 37.65 0 0 Seven Greece
50542 Alpheos (river) 60 21.45 37.61 0 0 Seven Greece
50544 Patrae 90 21.74 38.26 0 0 Seven Greece
50545 Apollonia-Sozousa 80 21.75 32.93 0 0 Ten Libya
50546 Akitas Pr. 60 21.88 36.72 0 0 Seven Greece
50547 Tainaron Pr. 80 22.48 36.39 0 0 Seven Greece
50548 Gythion 80 22.57 36.76 0 0 Seven Greece
50549 Corinthus 100 22.886 37.912 0 0 Seven Greece
50550 Isthmia 90 22.987 37.941 0 0 Seven Greece
50551 Chersonesos Akra 60 23.12 32.61 0 0 Ten Libya
50552 Malea Pr. 60 23.2 36.44 0 0 Seven Greece
50553 Petras Mikros 70 23.45 32.17 0 0 Ten Libya
50554 Kriou Metopon Pr. 60 23.58 35.27 0 0 Seven Greece
50555 Chalcis 90 23.59 38.46 0 0 Seven Greece
50556 Kimaros Pr. 60 23.6 35.63 0 0 Seven Greece
50557 Sounion Pr. 60 24.03 37.65 0 0 Seven Greece
50558 Kaudos 70 24.06 34.86 0 0 Seven Greece
50559 Athos Mons 60 24.22 40.26 0 0 Six Greece
50562 Geraistos 70 24.55 37.98 0 0 Seven Greece
50564 Thasos 80 24.71 40.78 0 0 Six Greece
50567 Kardamis 70 25.04 31.92 0 0 Ten Libya
50568 Petras Megas 70 25.09 31.75 0 0 Ten Libya
50569 Hephaistia 70 25.235 39.932 0 0 Six Greece
50573 Delos 70 25.27 37.4 0 0 Seven Greece
50577 Chersonasos 80 25.39 35.32 0 0 Seven Greece
50582 Kadiston Mons 60 25.77 35.34 0 0 Seven Greece
50586 Tenedos 60 26.051 39.817 0 0 Seven Turkey
50588 Chios 80 26.14 38.37 0 0 Seven Greece
50590 Sigeion 70 26.2 40.01 0 0 Seven Turkey
50592 Mytilene 80 26.31 39.21 0 0 Seven Greece
50593 Astypaleia 60 26.35 36.55 0 0 Seven Greece
50594 Sestus 80 26.417 40.228 0 0 Seven Turkey
50597 Samos 80 26.94 37.69 0 0 Seven Greece
50598 Trogilion Pr. 60 27.02 37.67 0 0 Seven Greece
50599 Parium 70 27.069 40.42 0 0 Seven Turkey
50602 Potidaion 70 27.21 35.51 0 0 Seven Greece
50603 Myndos 70 27.24 37.08 0 0 Seven Turkey
50604 Kos 70 27.29 36.89 0 0 Seven Greece
50606 Cnidus 80 27.37 36.69 0 0 Seven Turkey
50608 Halicarnassus 80 27.43 37.04 0 0 Seven Turkey
50609 Proconnesus 60 27.556 40.592 0 0 Six Turkey
50610 Bargylia 80 27.59 37.19 0 0 Seven Turkey
50611 Apollonia Pontica 80 27.696 42.417 0 0 Six Bulgaria
50612 Cyzicus 90 27.892 40.381 0 0 Seven Turkey
50613 Rhodos 80 28.23 36.44 0 0 Seven Greece
50614 Caunus 80 28.63 36.83 0 0 Seven Turkey
50617 Mouth of Pontus 60 29.124 41.212 0 0 Eight Turkey
50618 Salsovia 70 29.124 45.066 0 0 Six Romania
50619 Prusias 80 29.156 40.432 0 0 Eight Turkey
50620 Tyras 80 30.351 46.201 0 0 Twelve Ukraine
50621 Olbia (Borysthenes) 90 31.902 46.692 0 0 Twelve Ukraine
50622 Akamas Pr. 60 32.28 35.11 0 0 Eight Eight
50623 Kalos Limen 80 32.703 45.521 0 0 Twelve Ukraine
50624 Anemurium 60 32.8 36.02 0 0 Eight Turkey
50625 Amathous 80 33.13 34.71 0 0 Eight Eight
50626 Karambis Pr. 60 33.37 42.014 0 0 Eight Turkey
50627 Chersonesos 90 33.493 44.612 0 0 Twelve Ukraine
50628 Lapethos 80 33.173 35.33 0 0 Eight Eight
50630 Pedalion Pr. 60 34.08 34.96 0 0 Eight Eight
50631 Corycus 80 34.15 36.46 0 0 Eight Turkey
50632 Cinolis 60 34.164 41.963 0 0 Eight Turkey
50634 Kleides Pr. 60 34.59 35.7 0 0 Eight Eight
50636 Ioppe 60 34.751 32.055 0 0 Nine Israel
50637 Apollonia 80 34.816 32.213 0 0 Nine Israel
50639 Sinope 90 35.042 42.049 0 0 Eight Turkey
50641 Theodosia 80 35.379 45.046 0 0 Twelve Ukraine
50642 Pyramos (river) 60 35.56 36.57 0 0 Eight Turkey
50643 Byblos 80 35.64 34.12 0 0 Nine Lebanon
50644 Myriandros 80 36.19 36.59 0 0 Nine Turkey
50646 Pantikapaion 90 36.414 45.239 0 0 Twelve Ukraine
50647 Themiskyra 70 36.968 41.215 0 0 Eight Turkey
50648 Gorgippia 80 37.31 44.892 0 0 Twelve Russia
50649 Kotyora 70 37.875 41 0 0 Eight Turkey
50650 Tanais 80 39.258 47.268 0 0 Twelve Russia
50651 Dioscurias 90 41.003 42.993 0 0 Twelve Georgia
50652 Phasis 80 41.667 42.15 0 0 Twelve Georgia
50654 Raphia 80 34.252 31.289 0 0 Nine Gaza Strip
50658 Azotus Paralios 80 34.65 31.8 0 0 Nine Israel
50660 Apollonopolis Magna 80 32.875 24.983 0 0 Ten Egypt
50661 Krokodilopolis 80 30.839 29.317 0 0 Ten Egypt
50674 Latopolis 80 32.553 25.295 0 0 Ten Egypt
50677 Mons Porphyrites 60 33.347 27.208 0 0 Ten Egypt
50678 Mothis 80 28.949 25.509 0 0 Ten Egypt
50682 Ammon 80 25.544 29.205 0 0 Ten Egypt
50690 Oasis Parva 80 28.855 28.338 0 0 Ten Egypt
50700 Qasr Farafra 60 27.932 27.044 0 0 Ten Egypt
50713 Malaca 80 -4.422 36.715 0 0 One Spain
50714 Panormus 90 13.318 38.117 0 0 Four Italy
50715 Agrigentum 80 13.582 37.309 0 0 Four Italy
50716 Aleria 80 9.526 42.124 0 0 Four France
50717 Demetrias 90 22.917 39.303 0 0 Seven Greece
50718 Amphipolis 90 23.837 40.814 0 0 Six Greece
50719 Tripolis 90 35.85 34.431 0 0 Nine Lebanon
50720 Forum Appii 60 13.041 41.437 0 0 Four Italy
50721 x 6 -8.714 39.21 0 0 One Portugal
50725 Neapolis (Thrace) 80 24.468 40.95 0 0 Six Greece
50726 x 6 -8.673 39.219 0 0 One Portugal
50727 x 6 -6.114 38.965 0 0 One Spain
50730 x 6 -2.811 52.089 0 0 Three United Kingdom
50731 x 6 19.148 44.288 0 0 Five Bosnia & Herzegovina
50732 x 6 17.887 43.136 0 0 Five Bosnia & Herzegovina
50733 x 6 18.365 42.793 0 0 Five Bosnia & Herzegovina
50735 x 6 22.977 45.584 0 0 Six Romania
50736 x 6 17.891 45.404 0 0 Five Croatia
50737 x 6 18.488 45.279 0 0 Five Croatia
50738 x 6 15.391 46.36 0 0 Five Slovenia
50739 x 6 30.612 38.33 0 0 Eight Turkey
50741 Krane 80 20.568 38.224 0 0 Six Greece
50742 Horreum Margi 70 21.39 43.933 0 0 Six Serbia
50743 Boiodurum 60 13.454 48.574 0 0 Five Germany
50744 Toletum 80 -4.024 39.857 0 0 One Spain
50745 x 6 -7.681 37.942 0 0 One Portugal
50746 x 6 12.161 45.421 0 0 Four Italy
50747 x 6 13.128 46.371 0 0 Four Italy
50748 x 6 19.023 47.438 0 0 Five Hungary
50749 x 6 19.633 42.011 0 0 Five Albania
50750 x 6 19.657 41.078 0 0 Six Albania
50751 x 6 25.86 42.071 0 0 Six Bulgaria
50752 x 6 7.882 49.958 0 0 Two Germany
50753 x 6 15.694 44.366 0 0 Five Croatia
50754 x 6 11.625 44.821 0 0 Four Italy
50755 Selinous 70 23.685 39.14 0 0 Seven Greece
50756 Palma 80 2.65 39.567 0 0 One Spain
50757 x 6 23.499 46.021 0 0 Six Romania
50758 Samonion Pr. 60 26.254 35.281 0 0 Seven Greece
50759 Mouth of Witham 6 0.005 52.964 0 0 Three United Kingdom
50760 x 6 36.11 32.625 0 0 Nine Nine
50761 Populonium 80 10.496 42.996 0 0 Four Italy
50762 Palinurus Pr. 60 14.932 40.255 0 0 Four Italy
50763 x 6 11.644 46.783 0 0 Five Italy
50764 x 6 9.538 45.13 0 0 Four Italy
50765 x 6 10.39 43.805 0 0 Four Italy
50766 x 6 36.323 35.825 0 0 Nine Nine
50767 x 6 36.344 36.254 0 0 Nine Turkey
50768 x 6 17.626 47.688 0 0 Five Hungary
50769 x 6 27.96 44.699 0 0 Six Romania
50770 x 6 28.551 44.409 0 0 Six Romania
50771 x 6 36.763 35.274 0 0 Nine Nine
50772 x 6 9.13 45.024 0 0 Four Italy
50773 x 6 9.561 45.175 0 0 Four Italy
50774 x 6 2.024 46.081 0 0 Two France
50775 Nisyros 70 27.172 36.588 0 0 Seven Greece
50776 Amorgos 70 25.9 36.83 0 0 Seven Greece
50777 Anaphe 70 25.854 36.35 0 0 Seven Greece
50778 Andros 70 24.933 37.833 0 0 Seven Greece
50779 Ceos 70 24.333 37.617 0 0 Seven Greece
50780 Corseae 70 26.5 37.566 0 0 Seven Greece
50781 Cythnos 70 24.416 37.383 0 0 Seven Greece
50782 Donousa 70 25.8 37.1 0 0 Seven Greece
50783 Icaros 70 26.059 37.622 0 0 Seven Greece
50784 Imbros 70 25.844 40.161 0 0 Six Turkey
50785 Ios 70 25.333 36.717 0 0 Seven Greece
50787 Kimolos 70 24.55 36.8 0 0 Seven Greece
50788 Kinaros 70 26.289 36.98 0 0 Seven Greece
50791 Miletus 70 27.276 37.531 0 0 Seven Turkey
50793 Naxos 70 25.378 37.103 0 0 Seven Greece
50795 Patmos 70 26.558 37.316 0 0 Seven Greece
50796 Skyllaion Pr. 70 23.518 37.438 0 0 Seven Greece
50797 Siphnos 70 24.667 36.983 0 0 Seven Greece
50798 Syros 70 24.92 37.43 0 0 Seven Greece
50799 Telos 70 27.366 36.433 0 0 Seven Greece
50800 Tenos 70 25.166 37.533 0 0 Seven Greece
50801 Thera 70 25.433 36.417 0 0 Seven Greece
51817 x 6 -1.353 53.424 0 0 Three United Kingdom
51453 x 6 -0.145 51.457 0 0 Three United Kingdom
51649 x 6 -0.162 52.318 0 0 Three United Kingdom
51788 x 6 -0.379 52.709 0 0 Three United Kingdom
51791 x 6 1.462 52.774 0 0 Three United Kingdom
51783 x 6 0.758 52.713 0 0 Three United Kingdom
51610 x 6 0.471 51.726 0 0 Three United Kingdom
51801 x 6 -0.394 53.017 0 0 Three United Kingdom
51757 x 6 -3.411 52.589 0 0 Three United Kingdom
51634 x 6 0.862 51.866 0 0 Three United Kingdom
51763 x 6 0.686 52.691 0 0 Three United Kingdom
51586 x 6 -2.327 51.418 0 0 Three United Kingdom
51173 Moridunum 6 -4.332 51.850 0 0 Three United Kingdom
51373 x 6 -2.058 50.834 0 0 Three United Kingdom
51830 x 6 -1.913 53.263 0 0 Three United Kingdom
51670 x 6 -1.764 51.893 0 0 Three United Kingdom
51172 Ratae 6 -1.137 52.646 0 0 Three United Kingdom
51942 x 6 -1.827 55.401 0 0 Three United Kingdom
51735 x 6 0.656 52.310 0 0 Three United Kingdom
52225 x 6 -4.090 55.841 0 0 Three United Kingdom
51688 x 6 -1.409 52.083 0 0 Three United Kingdom
51767 x 6 0.772 52.753 0 0 Three United Kingdom
51481 x 6 0.573 51.085 0 0 Three United Kingdom
51920 x 6 -2.944 54.637 0 0 Three United Kingdom
51927 x 6 -1.607 54.982 0 0 Three United Kingdom
51799 x 6 -0.507 52.911 0 0 Three United Kingdom
51170 Durovernum 6 1.055 51.269 0 0 Three United Kingdom
51671 x 6 -1.888 52.240 0 0 Three United Kingdom
51893 x 6 -0.753 54.024 0 0 Three United Kingdom
51685 x 6 0.236 52.145 0 0 Three United Kingdom
51629 x 6 0.806 51.858 0 0 Three United Kingdom
51795 x 6 -0.388 52.769 0 0 Three United Kingdom
51911 x 6 -1.967 54.521 0 0 Three United Kingdom
51507 x 6 0.569 51.204 0 0 Three United Kingdom
51940 x 6 -3.431 55.138 0 0 Three United Kingdom
51839 x 6 -1.943 53.477 0 0 Three United Kingdom
51699 x 6 -2.690 52.280 0 0 Three United Kingdom
51648 x 6 0.012 51.886 0 0 Three United Kingdom
51766 x 6 0.722 52.645 0 0 Three United Kingdom
51177 Noviomagus 6 -0.785 50.834 0 0 Three United Kingdom
51811 x 6 -0.383 52.920 0 0 Three United Kingdom
52210 x 6 -2.003 55.778 0 0 Three United Kingdom
51829 x 6 -0.561 53.492 0 0 Three United Kingdom
51567 x 6 -0.163 51.522 0 0 Three United Kingdom
51175 Venta 6 -2.772 51.608 0 0 Three United Kingdom
51721 x 6 0.268 52.415 0 0 Three United Kingdom
51853 x 6 -0.313 53.497 0 0 Three United Kingdom
51468 x 6 -1.585 50.938 0 0 Three United Kingdom
51755 x 6 -2.118 52.597 0 0 Three United Kingdom
51608 x 6 -0.446 51.701 0 0 Three United Kingdom
51925 x 6 -2.882 54.933 0 0 Three United Kingdom
52212 x 6 -3.222 55.666 0 0 Three United Kingdom
51838 x 6 -1.743 53.329 0 0 Three United Kingdom
51740 x 6 -0.241 52.380 0 0 Three United Kingdom
51810 x 6 -0.281 52.912 0 0 Three United Kingdom
51915 x 6 -2.695 54.649 0 0 Three United Kingdom
51565 x 6 -1.112 51.454 0 0 Three United Kingdom
51802 x 6 -1.299 52.880 0 0 Three United Kingdom
51933 x 6 -2.284 54.926 0 0 Three United Kingdom
51376 x 6 -2.018 50.722 0 0 Three United Kingdom
51931 x 6 -2.533 54.982 0 0 Three United Kingdom
51919 x 6 -2.490 54.845 0 0 Three United Kingdom
51704 x 6 1.076 52.119 0 0 Three United Kingdom
51857 x 6 -1.872 53.930 0 0 Three United Kingdom
51667 x 6 0.857 51.963 0 0 Three United Kingdom
51522 x 6 -1.026 51.134 0 0 Three United Kingdom
51619 x 6 0.184 52.061 0 0 Three United Kingdom
51818 x 6 -2.500 53.095 0 0 Three United Kingdom
51895 x 6 -1.534 54.753 0 0 Three United Kingdom
51611 x 6 0.715 52.091 0 0 Three United Kingdom
51624 x 6 0.459 51.796 0 0 Three United Kingdom
51324 x 6 -2.460 50.629 0 0 Three United Kingdom
51917 x 6 -1.683 54.662 0 0 Three United Kingdom
51909 x 6 -2.788 54.733 0 0 Three United Kingdom
51705 x 6 1.297 52.156 0 0 Three United Kingdom
51875 x 6 -2.844 53.859 0 0 Three United Kingdom
51589 x 6 0.068 51.549 0 0 Three United Kingdom
51316 x 6 -3.685 50.499 0 0 Three United Kingdom
51403 x 6 -0.170 50.920 0 0 Three United Kingdom
51384 x 6 -0.798 50.786 0 0 Three United Kingdom
52211 x 6 -3.662 55.490 0 0 Three United Kingdom
51509 x 6 0.815 51.117 0 0 Three United Kingdom
51883 x 6 -0.884 54.002 0 0 Three United Kingdom
51937 x 6 -1.427 54.999 0 0 Three United Kingdom
51753 x 6 -2.281 52.559 0 0 Three United Kingdom
51573 x 6 -1.411 51.431 0 0 Three United Kingdom
51936 x 6 -1.571 54.928 0 0 Three United Kingdom
51531 x 6 0.520 51.381 0 0 Three United Kingdom
51693 x 6 0.844 52.295 0 0 Three United Kingdom
51638 x 6 -0.233 51.871 0 0 Three United Kingdom
51487 x 6 -2.526 51.203 0 0 Three United Kingdom
51715 x 6 0.912 51.893 0 0 Three United Kingdom
51789 x 6 -0.226 52.751 0 0 Three United Kingdom
51651 x 6 -2.523 51.907 0 0 Three United Kingdom
51375 x 6 -2.694 51.009 0 0 Three United Kingdom
51897 x 6 -0.237 54.090 0 0 Three United Kingdom
51512 x 6 1.048 51.087 0 0 Three United Kingdom
51749 x 6 -2.211 52.508 0 0 Three United Kingdom
51756 x 6 -3.525 52.493 0 0 Three United Kingdom
51444 x 6 0.026 50.919 0 0 Three United Kingdom
51748 x 6 -2.158 52.677 0 0 Three United Kingdom
51882 x 6 -0.711 53.885 0 0 Three United Kingdom
51392 x 6 -0.031 50.826 0 0 Three United Kingdom
51659 x 6 -2.653 52.079 0 0 Three United Kingdom
51729 x 6 -1.826 52.643 0 0 Three United Kingdom
51859 x 6 -2.550 53.816 0 0 Three United Kingdom
51679 x 6 -3.886 51.948 0 0 Three United Kingdom
51764 x 6 -3.431 52.523 0 0 Three United Kingdom
51514 x 6 0.997 51.090 0 0 Three United Kingdom
52209 x 6 -3.494 55.680 0 0 Three United Kingdom
51455 x 6 -0.529 50.950 0 0 Three United Kingdom
51792 x 6 -1.076 52.762 0 0 Three United Kingdom
51635 x 6 1.083 51.934 0 0 Three United Kingdom
51913 x 6 -2.556 54.628 0 0 Three United Kingdom
51537 x 6 -2.709 51.297 0 0 Three United Kingdom
51733 x 6 0.873 52.331 0 0 Three United Kingdom
51675 x 6 -3.402 52.255 0 0 Three United Kingdom
52229 x 6 -3.207 55.861 0 0 Three United Kingdom
51719 x 6 1.279 52.385 0 0 Three United Kingdom
51639 x 6 -0.184 51.971 0 0 Three United Kingdom
51773 x 6 -1.488 52.933 0 0 Three United Kingdom
51171 Cironium 6 -1.974 51.715 0 0 Three United Kingdom
51601 x 6 0.352 51.872 0 0 Three United Kingdom
51861 x 6 -2.659 53.549 0 0 Three United Kingdom
51399 x 6 -0.947 51.172 0 0 Three United Kingdom
51402 x 6 -0.210 50.846 0 0 Three United Kingdom
51176 Isca 6 -3.523 50.723 0 0 Three United Kingdom
51903 x 6 -2.586 54.401 0 0 Three United Kingdom
51596 x 6 -1.165 51.520 0 0 Three United Kingdom
51503 x 6 -1.163 51.089 0 0 Three United Kingdom
51386 x 6 -3.017 50.769 0 0 Three United Kingdom
51469 x 6 -1.358 50.982 0 0 Three United Kingdom
51617 x 6 -0.984 52.124 0 0 Three United Kingdom
51742 x 6 -0.524 52.407 0 0 Three United Kingdom
51518 x 6 -1.809 51.095 0 0 Three United Kingdom
51405 x 6 -2.190 51.076 0 0 Three United Kingdom
51865 x 6 -2.817 53.757 0 0 Three United Kingdom
51877 x 6 -1.273 53.885 0 0 Three United Kingdom
51587 x 6 -1.164 51.889 0 0 Three United Kingdom
51837 x 6 -2.586 53.361 0 0 Three United Kingdom
51807 x 6 -0.549 52.982 0 0 Three United Kingdom
51393 x 6 -0.062 51.471 0 0 Three United Kingdom
51815 x 6 -2.457 53.196 0 0 Three United Kingdom
51470 x 6 -1.374 50.952 0 0 Three United Kingdom
51941 x 6 -2.263 55.291 0 0 Three United Kingdom
51687 x 6 0.129 52.225 0 0 Three United Kingdom
51836 x 6 -2.664 53.305 0 0 Three United Kingdom
51739 x 6 1.010 52.462 0 0 Three United Kingdom
51547 x 6 1.273 51.293 0 0 Three United Kingdom
51669 x 6 1.070 52.133 0 0 Three United Kingdom
51480 x 6 0.530 51.014 0 0 Three United Kingdom
51887 x 6 -2.093 54.995 0 0 Three United Kingdom
51527 x 6 -0.857 51.215 0 0 Three United Kingdom
51485 x 6 -2.928 51.152 0 0 Three United Kingdom
51760 x 6 -1.494 52.561 0 0 Three United Kingdom
51821 x 6 -2.458 53.266 0 0 Three United Kingdom
51904 x 6 -2.740 54.334 0 0 Three United Kingdom
51577 x 6 -0.082 51.521 0 0 Three United Kingdom
51532 x 6 0.952 51.209 0 0 Three United Kingdom
51628 x 6 0.717 51.851 0 0 Three United Kingdom
51825 x 6 -3.012 53.301 0 0 Three United Kingdom
51686 x 6 0.451 52.086 0 0 Three United Kingdom
51690 x 6 0.601 52.091 0 0 Three United Kingdom
51554 x 6 -2.323 51.327 0 0 Three United Kingdom
51758 x 6 -0.369 52.562 0 0 Three United Kingdom
51708 x 6 -0.038 52.126 0 0 Three United Kingdom
51855 x 6 -1.050 53.958 0 0 Three United Kingdom
51785 x 6 0.495 52.948 0 0 Three United Kingdom
51678 x 6 -3.457 51.954 0 0 Three United Kingdom
51910 x 6 -1.671 54.443 0 0 Three United Kingdom
51926 x 6 -1.584 54.806 0 0 Three United Kingdom
51620 x 6 -0.504 51.754 0 0 Three United Kingdom
51939 x 6 -2.000 55.059 0 0 Three United Kingdom
51862 x 6 -0.564 53.673 0 0 Three United Kingdom
Display the source blob
Display the rendered blob
Raw
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Display the source blob
Display the rendered blob
Raw
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Display the source blob
Display the rendered blob
Raw
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment