|
|
@@ -2,185 +2,252 @@
|
|
|
<script src="ogc-parser.js"></script>
|
|
|
<script>
|
|
|
/* global ogcParser */
|
|
|
-function wait(ms = 0) {
|
|
|
- return new Promise((resolve) => {
|
|
|
- setTimeout(resolve, ms);
|
|
|
- });
|
|
|
+function wait( ms = 0 ) {
|
|
|
+
|
|
|
+ return new Promise( ( resolve ) => {
|
|
|
+
|
|
|
+ setTimeout( resolve, ms );
|
|
|
+
|
|
|
+ } );
|
|
|
+
|
|
|
}
|
|
|
|
|
|
// # need to draw to 2nd canvas, then shave off non perfect pixels
|
|
|
|
|
|
async function main() {
|
|
|
- const ctx = document.querySelector('canvas').getContext('2d');
|
|
|
- ctx.canvas.width = 2048;
|
|
|
- ctx.canvas.height = 2048;
|
|
|
- ctx.fillStyle = '#444';
|
|
|
- ctx.fillRect(0, 0, ctx.canvas.width, ctx.canvas.height);
|
|
|
- ctx.translate(ctx.canvas.width / 2, ctx.canvas.height / 2);
|
|
|
- ctx.scale(ctx.canvas.width / 360, ctx.canvas.height / -180);
|
|
|
-
|
|
|
- function setColor(color) {
|
|
|
- ctx.fillStyle = color;
|
|
|
- ctx.strokeStyle = color;
|
|
|
- }
|
|
|
-
|
|
|
- const handlers = {
|
|
|
- point,
|
|
|
- lineString,
|
|
|
- polygon,
|
|
|
- multiPoint,
|
|
|
- multiLineString,
|
|
|
- multiPolygon,
|
|
|
- };
|
|
|
-
|
|
|
- function point(d) {
|
|
|
- ctx.fillRect(...d.point, 1, 1);
|
|
|
- }
|
|
|
-
|
|
|
- function setPathFromPoints(points, backward = false) {
|
|
|
- if (backward) {
|
|
|
- const numPoints = points.length / 2;
|
|
|
- const lastPoint = numPoints - 1;
|
|
|
- ctx.moveTo(...points.slice(lastPoint * 2, lastPoint * 2 + 2));
|
|
|
- for (let i = lastPoint - 1; i >= 0; i -= 2) {
|
|
|
- ctx.lineTo(...points.slice(i * 2, i * 2 + 2));
|
|
|
- }
|
|
|
- } else {
|
|
|
- ctx.moveTo(...points.slice(0, 2));
|
|
|
- for (let i = 2; i < points.length; i += 2) {
|
|
|
- ctx.lineTo(...points.slice(i, i + 2));
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- function stroke(ctx) {
|
|
|
- ctx.save();
|
|
|
- ctx.setTransform(1, 0, 0, 1, 0, 0);
|
|
|
- ctx.stroke();
|
|
|
- ctx.restore();
|
|
|
- }
|
|
|
-
|
|
|
- function lineString(d) {
|
|
|
- ctx.beginPath();
|
|
|
- setPathFromPoints(d.points);
|
|
|
- stroke(ctx);
|
|
|
- }
|
|
|
-
|
|
|
- function polygon(d) {
|
|
|
- ctx.beginPath();
|
|
|
- d.rings.forEach((ring, ndx) => {
|
|
|
- setPathFromPoints(ring, ndx !== 0);
|
|
|
- ctx.closePath();
|
|
|
- });
|
|
|
- ctx.fill();
|
|
|
- stroke(ctx);
|
|
|
- }
|
|
|
-
|
|
|
- function multiPoint(d) {
|
|
|
- for (let i = 0; i < d.points.length; i += 2) {
|
|
|
- ctx.fillRect(...d.points.slice(i, i + 2));
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- function multiLineString(d) {
|
|
|
- d.lineStrings.forEach((lineString) => {
|
|
|
- ctx.beginPath();
|
|
|
- setPathFromPoints(lineString);
|
|
|
- stroke(ctx);
|
|
|
- });
|
|
|
- }
|
|
|
-
|
|
|
- function multiPolygon(d) {
|
|
|
- d.polygons.forEach((polygon) => {
|
|
|
- ctx.beginPath();
|
|
|
- polygon.forEach((ring, ndx) => {
|
|
|
- setPathFromPoints(ring, ndx !== 0);
|
|
|
- });
|
|
|
- ctx.fill();
|
|
|
- stroke(ctx);
|
|
|
- });
|
|
|
- }
|
|
|
-
|
|
|
- const colors = {};
|
|
|
-
|
|
|
- const req = await fetch('level1.json');
|
|
|
- const areas = await req.json();
|
|
|
- const min = [Number.MAX_VALUE, Number.MAX_VALUE];
|
|
|
- const max = [Number.MIN_VALUE, Number.MIN_VALUE];
|
|
|
- console.log('num areas:', areas.length);
|
|
|
- for (let ndx = 0; ndx < areas.length; ++ndx) {
|
|
|
- const area = areas[ndx];
|
|
|
- try {
|
|
|
- const buf = new Uint8Array(base64ToUint8Array(area.geom));
|
|
|
- area.geom = ogcParser.parse(buf);
|
|
|
- } catch (e) {
|
|
|
- console.log('ERROR:', e);
|
|
|
- console.log(JSON.stringify(area, null, 2));
|
|
|
- throw e;
|
|
|
- }
|
|
|
-
|
|
|
- if (!colors[area.NAME_0]) {
|
|
|
- colors[area.NAME_0] = rgb(r(), r(), r());
|
|
|
- }
|
|
|
-
|
|
|
- const color = colors[area.NAME_0];
|
|
|
-
|
|
|
- console.log(ndx, area.NAME_0);
|
|
|
-
|
|
|
- area.geom.primitives.forEach((primitive) => {
|
|
|
- const fn = handlers[primitive.type];
|
|
|
- setColor(color);
|
|
|
- fn(primitive);
|
|
|
- });
|
|
|
-
|
|
|
- min[0] = Math.min(min[0], area.geom.envelope[0]);
|
|
|
- min[0] = Math.min(min[0], area.geom.envelope[1]);
|
|
|
- min[1] = Math.min(min[1], area.geom.envelope[2]);
|
|
|
- min[1] = Math.min(min[1], area.geom.envelope[3]);
|
|
|
-
|
|
|
- max[0] = Math.max(max[0], area.geom.envelope[0]);
|
|
|
- max[0] = Math.max(max[0], area.geom.envelope[1]);
|
|
|
- max[1] = Math.max(max[1], area.geom.envelope[2]);
|
|
|
- max[1] = Math.max(max[1], area.geom.envelope[3]);
|
|
|
-
|
|
|
- if (ndx % 100 === 99) {
|
|
|
- await wait();
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- console.log('min', min);
|
|
|
- console.log('max', max);
|
|
|
+
|
|
|
+ const ctx = document.querySelector( 'canvas' ).getContext( '2d' );
|
|
|
+ ctx.canvas.width = 2048;
|
|
|
+ ctx.canvas.height = 2048;
|
|
|
+ ctx.fillStyle = '#444';
|
|
|
+ ctx.fillRect( 0, 0, ctx.canvas.width, ctx.canvas.height );
|
|
|
+ ctx.translate( ctx.canvas.width / 2, ctx.canvas.height / 2 );
|
|
|
+ ctx.scale( ctx.canvas.width / 360, ctx.canvas.height / - 180 );
|
|
|
+
|
|
|
+ function setColor( color ) {
|
|
|
+
|
|
|
+ ctx.fillStyle = color;
|
|
|
+ ctx.strokeStyle = color;
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+ const handlers = {
|
|
|
+ point,
|
|
|
+ lineString,
|
|
|
+ polygon,
|
|
|
+ multiPoint,
|
|
|
+ multiLineString,
|
|
|
+ multiPolygon,
|
|
|
+ };
|
|
|
+
|
|
|
+ function point( d ) {
|
|
|
+
|
|
|
+ ctx.fillRect( ...d.point, 1, 1 );
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+ function setPathFromPoints( points, backward = false ) {
|
|
|
+
|
|
|
+ if ( backward ) {
|
|
|
+
|
|
|
+ const numPoints = points.length / 2;
|
|
|
+ const lastPoint = numPoints - 1;
|
|
|
+ ctx.moveTo( ...points.slice( lastPoint * 2, lastPoint * 2 + 2 ) );
|
|
|
+ for ( let i = lastPoint - 1; i >= 0; i -= 2 ) {
|
|
|
+
|
|
|
+ ctx.lineTo( ...points.slice( i * 2, i * 2 + 2 ) );
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+ } else {
|
|
|
+
|
|
|
+ ctx.moveTo( ...points.slice( 0, 2 ) );
|
|
|
+ for ( let i = 2; i < points.length; i += 2 ) {
|
|
|
+
|
|
|
+ ctx.lineTo( ...points.slice( i, i + 2 ) );
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+ function stroke( ctx ) {
|
|
|
+
|
|
|
+ ctx.save();
|
|
|
+ ctx.setTransform( 1, 0, 0, 1, 0, 0 );
|
|
|
+ ctx.stroke();
|
|
|
+ ctx.restore();
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+ function lineString( d ) {
|
|
|
+
|
|
|
+ ctx.beginPath();
|
|
|
+ setPathFromPoints( d.points );
|
|
|
+ stroke( ctx );
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+ function polygon( d ) {
|
|
|
+
|
|
|
+ ctx.beginPath();
|
|
|
+ d.rings.forEach( ( ring, ndx ) => {
|
|
|
+
|
|
|
+ setPathFromPoints( ring, ndx !== 0 );
|
|
|
+ ctx.closePath();
|
|
|
+
|
|
|
+ } );
|
|
|
+ ctx.fill();
|
|
|
+ stroke( ctx );
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+ function multiPoint( d ) {
|
|
|
+
|
|
|
+ for ( let i = 0; i < d.points.length; i += 2 ) {
|
|
|
+
|
|
|
+ ctx.fillRect( ...d.points.slice( i, i + 2 ) );
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+ function multiLineString( d ) {
|
|
|
+
|
|
|
+ d.lineStrings.forEach( ( lineString ) => {
|
|
|
+
|
|
|
+ ctx.beginPath();
|
|
|
+ setPathFromPoints( lineString );
|
|
|
+ stroke( ctx );
|
|
|
+
|
|
|
+ } );
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+ function multiPolygon( d ) {
|
|
|
+
|
|
|
+ d.polygons.forEach( ( polygon ) => {
|
|
|
+
|
|
|
+ ctx.beginPath();
|
|
|
+ polygon.forEach( ( ring, ndx ) => {
|
|
|
+
|
|
|
+ setPathFromPoints( ring, ndx !== 0 );
|
|
|
+
|
|
|
+ } );
|
|
|
+ ctx.fill();
|
|
|
+ stroke( ctx );
|
|
|
+
|
|
|
+ } );
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+ const colors = {};
|
|
|
+
|
|
|
+ const req = await fetch( 'level1.json' );
|
|
|
+ const areas = await req.json();
|
|
|
+ const min = [ Number.MAX_VALUE, Number.MAX_VALUE ];
|
|
|
+ const max = [ Number.MIN_VALUE, Number.MIN_VALUE ];
|
|
|
+ console.log( 'num areas:', areas.length );
|
|
|
+ for ( let ndx = 0; ndx < areas.length; ++ ndx ) {
|
|
|
+
|
|
|
+ const area = areas[ ndx ];
|
|
|
+ try {
|
|
|
+
|
|
|
+ const buf = new Uint8Array( base64ToUint8Array( area.geom ) );
|
|
|
+ area.geom = ogcParser.parse( buf );
|
|
|
+
|
|
|
+ } catch ( e ) {
|
|
|
+
|
|
|
+ console.log( 'ERROR:', e );
|
|
|
+ console.log( JSON.stringify( area, null, 2 ) );
|
|
|
+ throw e;
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+ if ( ! colors[ area.NAME_0 ] ) {
|
|
|
+
|
|
|
+ colors[ area.NAME_0 ] = rgb( r(), r(), r() );
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+ const color = colors[ area.NAME_0 ];
|
|
|
+
|
|
|
+ console.log( ndx, area.NAME_0 );
|
|
|
+
|
|
|
+ area.geom.primitives.forEach( ( primitive ) => {
|
|
|
+
|
|
|
+ const fn = handlers[ primitive.type ];
|
|
|
+ setColor( color );
|
|
|
+ fn( primitive );
|
|
|
+
|
|
|
+ } );
|
|
|
+
|
|
|
+ min[ 0 ] = Math.min( min[ 0 ], area.geom.envelope[ 0 ] );
|
|
|
+ min[ 0 ] = Math.min( min[ 0 ], area.geom.envelope[ 1 ] );
|
|
|
+ min[ 1 ] = Math.min( min[ 1 ], area.geom.envelope[ 2 ] );
|
|
|
+ min[ 1 ] = Math.min( min[ 1 ], area.geom.envelope[ 3 ] );
|
|
|
+
|
|
|
+ max[ 0 ] = Math.max( max[ 0 ], area.geom.envelope[ 0 ] );
|
|
|
+ max[ 0 ] = Math.max( max[ 0 ], area.geom.envelope[ 1 ] );
|
|
|
+ max[ 1 ] = Math.max( max[ 1 ], area.geom.envelope[ 2 ] );
|
|
|
+ max[ 1 ] = Math.max( max[ 1 ], area.geom.envelope[ 3 ] );
|
|
|
+
|
|
|
+ if ( ndx % 100 === 99 ) {
|
|
|
+
|
|
|
+ await wait();
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+ console.log( 'min', min );
|
|
|
+ console.log( 'max', max );
|
|
|
+
|
|
|
}
|
|
|
|
|
|
-function r(min, max) {
|
|
|
- if (min === undefined) {
|
|
|
- min = 0;
|
|
|
- max = 1;
|
|
|
- } else if (max === undefined){
|
|
|
- max = min;
|
|
|
- min = 0;
|
|
|
- }
|
|
|
- return min + Math.random() * (max - min);
|
|
|
+function r( min, max ) {
|
|
|
+
|
|
|
+ if ( min === undefined ) {
|
|
|
+
|
|
|
+ min = 0;
|
|
|
+ max = 1;
|
|
|
+
|
|
|
+ } else if ( max === undefined ) {
|
|
|
+
|
|
|
+ max = min;
|
|
|
+ min = 0;
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+ return min + Math.random() * ( max - min );
|
|
|
+
|
|
|
}
|
|
|
|
|
|
-function rgb(r, g, b) {
|
|
|
- return `rgb(${r * 255 | 0},${g * 255 | 0},${b * 255 | 0})`;
|
|
|
+function rgb( r, g, b ) {
|
|
|
+
|
|
|
+ return `rgb(${r * 255 | 0},${g * 255 | 0},${b * 255 | 0})`;
|
|
|
+
|
|
|
}
|
|
|
|
|
|
// function hsl(h, s, l) {
|
|
|
// return `hsl(${h * 360 | 0},${s * 100 | 0}%,${l * 100 | 0}%)`;
|
|
|
// }
|
|
|
|
|
|
-function base64ToUint8Array(base64) {
|
|
|
- const raw = window.atob(base64);
|
|
|
- const rawLength = raw.length;
|
|
|
- const array = new Uint8Array(new ArrayBuffer(rawLength));
|
|
|
+function base64ToUint8Array( base64 ) {
|
|
|
+
|
|
|
+ const raw = window.atob( base64 );
|
|
|
+ const rawLength = raw.length;
|
|
|
+ const array = new Uint8Array( new ArrayBuffer( rawLength ) );
|
|
|
+
|
|
|
+ for ( let i = 0; i < rawLength; ++ i ) {
|
|
|
+
|
|
|
+ array[ i ] = raw.charCodeAt( i );
|
|
|
+
|
|
|
+ }
|
|
|
|
|
|
- for(let i = 0; i < rawLength; ++i) {
|
|
|
- array[i] = raw.charCodeAt(i);
|
|
|
- }
|
|
|
+ return array;
|
|
|
|
|
|
- return array;
|
|
|
}
|
|
|
|
|
|
main();
|