| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531 |
- function cell2Polygons(cell, x, y, settings) {
- var polygons = [];
- cell.polygons.forEach(function(p) {
- p.forEach(function(pp) {
- pp[0] += x;
- pp[1] += y;
- });
- if (settings.linearRing)
- p.push(p[0]);
- polygons.push(p);
- });
- return polygons;
- }
- function entry_coordinate(x, y, mode, path) {
- if (mode === 0) { /* down */
- x += 1;
- y += path[0][1];
- } else if (mode === 1) { /* left */
- x += path[0][0];
- } else if (mode === 2) { /* up */
- y += path[0][1];
- } else if (mode === 3) { /* right */
- x += path[0][0];
- y += 1;
- }
- return [ x, y ];
- }
- function skip_coordinate(x, y, mode) {
- if (mode === 0) { /* down */
- x++;
- } else if (mode === 1) { /* left */
- /* do nothing */
- } else if (mode === 2) { /* up */
- y++;
- } else if (mode === 3) { /* right */
- x++;
- y++;
- }
- return [ x, y ];
- }
- function requireFrame(data, lowerBound, upperBound) {
- var frameRequired,
- cols,
- rows,
- i,
- j;
- frameRequired = true;
- cols = data[0].length;
- rows = data.length;
- for (j = 0; j < rows; j++) {
- if ((data[j][0] < lowerBound) ||
- (data[j][0] > upperBound) ||
- (data[j][cols - 1] < lowerBound) ||
- (data[j][cols - 1] > upperBound)) {
- frameRequired = false;
- break;
- }
- }
- if ((frameRequired) &&
- ((data[rows - 1][0] < lowerBound) ||
- (data[rows - 1][0] > upperBound) ||
- (data[rows - 1][cols - 1] < lowerBound) ||
- (data[rows - 1][cols - 1] > upperBound))) {
- frameRequired = false;
- }
- if (frameRequired)
- for (i = 0; i < cols - 1; i++) {
- if ((data[0][i] < lowerBound) ||
- (data[0][i] > upperBound) ||
- (data[rows - 1][i] < lowerBound) ||
- (data[rows - 1][i] > upperBound)) {
- frameRequired = false;
- break;
- }
- }
- return frameRequired;
- }
- function requireLineFrame(data, threshold) {
- var frameRequired,
- cols,
- rows,
- i,
- j;
- frameRequired = true;
- cols = data[0].length;
- rows = data.length;
- for (j = 0; j < rows; j++) {
- if ((data[j][0] >= threshold) ||
- (data[j][cols - 1] >= threshold)) {
- frameRequired = false;
- break;
- }
- }
- if ((frameRequired) &&
- ((data[rows - 1][0] >= threshold) ||
- (data[rows - 1][cols - 1] >= threshold))) {
- frameRequired = false;
- }
- if (frameRequired)
- for (i = 0; i < cols - 1; i++) {
- if ((data[0][i] >= threshold) ||
- (data[rows - 1][i] > threshold)) {
- frameRequired = false;
- break;
- }
- }
- return frameRequired;
- }
- function traceBandPaths(data, cellGrid, settings) {
- var nextedge,
- path,
- e,
- ee,
- s,
- ve,
- enter,
- x,
- y,
- finalized,
- origin,
- cc,
- dir,
- count,
- point,
- found_entry;
- var polygons = [];
- var rows = data.length - 1;
- var cols = data[0].length - 1;
- /*
- * directions for out-of-grid moves are:
- * 0 ... "down",
- * 1 ... "left",
- * 2 ... "up",
- * 3 ... "right"
- */
- var valid_entries = [ ['rt', 'rb'], /* down */
- ['br', 'bl'], /* left */
- ['lb', 'lt'], /* up */
- ['tl', 'tr'] /* right */
- ];
- var add_x = [ 0, -1, 0, 1 ];
- var add_y = [ -1, 0, 1, 0 ];
- var available_starts = [ 'bl', 'lb', 'lt', 'tl', 'tr', 'rt', 'rb', 'br' ];
- var entry_dir = {
- bl: 1, br: 1,
- lb: 2, lt: 2,
- tl: 3, tr: 3,
- rt: 0, rb: 0
- };
- if (requireFrame(data, settings.minV, settings.maxV)) {
- if (settings.linearRing)
- polygons.push([ [0, 0], [0, rows], [cols, rows], [cols, 0], [0, 0] ]);
- else
- polygons.push([ [0, 0], [0, rows], [cols, rows], [cols, 0] ]);
- }
- /* finally, start tracing back first polygon(s) */
- cellGrid.forEach(function(a, i) {
- a.forEach(function(cell, j) {
- nextedge = null;
- /* trace paths for all available edges that go through this cell */
- for (e = 0; e < 8; e++) {
- nextedge = available_starts[e];
- if (typeof cell.edges[nextedge] !== 'object')
- continue;
- /* start a new, full path */
- path = [];
- ee = cell.edges[nextedge];
- enter = nextedge;
- x = i;
- y = j;
- finalized = false;
- origin = [ i + ee.path[0][0], j + ee.path[0][1] ];
- /* add start coordinate */
- path.push(origin);
- /* start traceback */
- while (!finalized) {
- cc = cellGrid[x][y];
- if (typeof cc.edges[enter] !== 'object')
- break;
- ee = cc.edges[enter];
- /* remove edge from cell */
- delete cc.edges[enter];
- /* add last point of edge to path arra, since we extend a polygon */
- point = ee.path[1];
- point[0] += x;
- point[1] += y;
- path.push(point);
- enter = ee.move.enter;
- x = x + ee.move.x;
- y = y + ee.move.y;
- /* handle out-of-grid moves */
- if ((typeof cellGrid[x] === 'undefined') ||
- (typeof cellGrid[x][y] === 'undefined')) {
- dir = 0;
- count = 0;
- if (x === cols) {
- x--;
- dir = 0; /* move downwards */
- } else if (x < 0) {
- x++;
- dir = 2; /* move upwards */
- } else if (y === rows) {
- y--;
- dir = 3; /* move right */
- } else if (y < 0) {
- y++;
- dir = 1; /* move left */
- } else {
- throw new Error('Left the grid somewhere in the interior!');
- }
- if ((x === i) && (y === j) && (dir === entry_dir[nextedge])) {
- finalized = true;
- enter = nextedge;
- break;
- }
- while (1) {
- found_entry = false;
- if (count > 4)
- throw new Error('Direction change counter overflow! This should never happen!');
- if (!((typeof cellGrid[x] === 'undefined') ||
- (typeof cellGrid[x][y] === 'undefined'))) {
- cc = cellGrid[x][y];
- /* check for re-entry */
- for (s = 0; s < valid_entries[dir].length; s++) {
- ve = valid_entries[dir][s];
- if (typeof cc.edges[ve] === 'object') {
- /* found re-entry */
- ee = cc.edges[ve];
- path.push(entry_coordinate(x, y, dir, ee.path));
- enter = ve;
- found_entry = true;
- break;
- }
- }
- }
- if (found_entry) {
- break;
- } else {
- path.push(skip_coordinate(x, y, dir));
- x += add_x[dir];
- y += add_y[dir];
- /* change direction if we'e moved out of grid again */
- if ((typeof cellGrid[x] === 'undefined') ||
- (typeof cellGrid[x][y] === 'undefined')) {
- if (((dir === 0) && (y < 0)) ||
- ((dir === 1) && (x < 0)) ||
- ((dir === 2) && (y === rows)) ||
- ((dir === 3) && (x === cols))) {
- x -= add_x[dir];
- y -= add_y[dir];
- dir = (dir + 1) % 4;
- count++;
- }
- }
- if ((x === i) && (y === j) && (dir === entry_dir[nextedge])) {
- /* we are back where we started off, so finalize the polygon */
- finalized = true;
- enter = nextedge;
- break;
- }
- }
- }
- }
- }
- if ((settings.linearRing) &&
- ((path[path.length - 1][0] !== origin[0]) ||
- (path[path.length - 1][1] !== origin[1])))
- path.push(origin);
- polygons.push(path);
- } /* end forall entry sites */
- }); /* end foreach i */
- }); /* end foreach j */
- return polygons;
- }
- function traceLinePaths(data, cellGrid, settings) {
- var nextedge,
- e,
- ee,
- cc,
- path,
- enter,
- x,
- y,
- finalized,
- origin,
- point,
- dir,
- count,
- found_entry,
- ve;
- var polygons = [];
- var rows = data.length - 1;
- var cols = data[0].length - 1;
- /*
- * directions for out-of-grid moves are:
- * 0 ... "down",
- * 1 ... "left",
- * 2 ... "up",
- * 3 ... "right"
- */
- var valid_entries = [ 'right', /* down */
- 'bottom', /* left */
- 'left', /* up */
- 'top' /* right */
- ];
- var add_x = [ 0, -1, 0, 1 ];
- var add_y = [ -1, 0, 1, 0 ];
- var entry_dir = {
- bottom: 1,
- left: 2,
- top: 3,
- right: 0
- };
- /* first, detect whether we need any outer frame */
- if (!settings.noFrame)
- if (requireLineFrame(data, settings.threshold)) {
- if (settings.linearRing)
- polygons.push([ [0, 0], [0, rows], [cols, rows], [cols, 0], [0, 0] ]);
- else
- polygons.push([ [0, 0], [0, rows], [cols, rows], [cols, 0] ]);
- }
- /* finally, start tracing back first polygon(s) */
- cellGrid.forEach(function(a, i) {
- a.forEach(function(cell, j) {
- nextedge = null;
- /* trace paths for all available edges that go through this cell */
- for (e = 0; e < 4; e++) {
- nextedge = valid_entries[e];
- if (typeof cell.edges[nextedge] !== 'object')
- continue;
- /* start a new, full path */
- path = [];
- ee = cell.edges[nextedge];
- enter = nextedge;
- x = i;
- y = j;
- finalized = false;
- origin = [ i + ee.path[0][0], j + ee.path[0][1] ];
- /* add start coordinate */
- path.push(origin);
- /* start traceback */
- while (!finalized) {
- cc = cellGrid[x][y];
- if (typeof cc.edges[enter] !== 'object')
- break;
- ee = cc.edges[enter];
- /* remove edge from cell */
- delete cc.edges[enter];
- /* add last point of edge to path arra, since we extend a polygon */
- point = ee.path[1];
- point[0] += x;
- point[1] += y;
- path.push(point);
- enter = ee.move.enter;
- x = x + ee.move.x;
- y = y + ee.move.y;
- /* handle out-of-grid moves */
- if ((typeof cellGrid[x] === 'undefined') ||
- (typeof cellGrid[x][y] === 'undefined')) {
- if (!settings.linearRing)
- break;
- dir = 0;
- count = 0;
- if (x === cols) {
- x--;
- dir = 0; /* move downwards */
- } else if (x < 0) {
- x++;
- dir = 2; /* move upwards */
- } else if (y === rows) {
- y--;
- dir = 3; /* move right */
- } else if (y < 0) {
- y++;
- dir = 1; /* move left */
- }
- if ((x === i) && (y === j) && (dir === entry_dir[nextedge])) {
- finalized = true;
- enter = nextedge;
- break;
- }
- while (1) {
- found_entry = false;
- if (count > 4)
- throw new Error('Direction change counter overflow! This should never happen!');
- if (!((typeof cellGrid[x] === 'undefined') ||
- (typeof cellGrid[x][y] === 'undefined'))) {
- cc = cellGrid[x][y];
- /* check for re-entry */
- ve = valid_entries[dir];
- if (typeof cc.edges[ve] === 'object') {
- /* found re-entry */
- ee = cc.edges[ve];
- path.push(entry_coordinate(x, y, dir, ee.path));
- enter = ve;
- found_entry = true;
- break;
- }
- }
- if (found_entry) {
- break;
- } else {
- path.push(skip_coordinate(x, y, dir));
- x += add_x[dir];
- y += add_y[dir];
- /* change direction if we'e moved out of grid again */
- if ((typeof cellGrid[x] === 'undefined') ||
- (typeof cellGrid[x][y] === 'undefined')) {
- if (((dir === 0) && (y < 0)) ||
- ((dir === 1) && (x < 0)) ||
- ((dir === 2) && (y === rows)) ||
- ((dir === 3) && (x === cols))) {
- x -= add_x[dir];
- y -= add_y[dir];
- dir = (dir + 1) % 4;
- count++;
- }
- }
- if ((x === i) && (y === j) && (dir === entry_dir[nextedge])) {
- /* we are back where we started off, so finalize the polygon */
- finalized = true;
- enter = nextedge;
- break;
- }
- }
- }
- }
- }
- if ((settings.linearRing) &&
- ((path[path.length - 1][0] !== origin[0]) ||
- (path[path.length - 1][1] !== origin[1])))
- path.push(origin);
- polygons.push(path);
- } /* end forall entry sites */
- }); /* end foreach i */
- }); /* end foreach j */
- return polygons;
- }
- export {cell2Polygons, traceBandPaths, traceLinePaths};
|