Skip to content

Commit

Permalink
Merge pull request #25 from ronitjadhav/complex_polygons
Browse files Browse the repository at this point in the history
Adding Complex Polygons and Point Features with WebGL and Canvas Rendering
  • Loading branch information
jahow authored Nov 2, 2023
2 parents f11d375 + 5653bcd commit aa9aa69
Show file tree
Hide file tree
Showing 8 changed files with 414 additions and 101 deletions.
16 changes: 16 additions & 0 deletions cases/point-rendering/index.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
<!DOCTYPE html>
<html lang="en">

<head>
<meta charset="UTF-8">
<meta name="viewport" content="initial-scale=1.0, user-scalable=no, width=device-width">
<title>Point Rendering</title>
<link rel="stylesheet" href="../../style.css">
</head>

<body>
<div id="map" class="map"></div>
<script src="./main.js" type="module"></script>
</body>

</html>
158 changes: 93 additions & 65 deletions cases/vector-rendering/main.js → cases/point-rendering/main.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
/* eslint-disable no-console */
import GUI from 'lil-gui';
import GeoJSON from 'ol/format/GeoJSON.js';
import Layer from 'ol/layer/Layer.js';
import Link from 'ol/interaction/Link.js';
Expand All @@ -24,40 +25,34 @@ const source = new VectorSource();

const colors = ['#6ff05b', '#00AAFF', '#faa91e'];

const style = {
'fill-color': ['get', 'color'],
'stroke-color': 'gray',
'stroke-width': 0.5,
};
const gui = new GUI();

class WebGLLayer extends Layer {
/**
* @return {WebGLVectorLayerRenderer} The renderer.
*/
createRenderer() {
return new WebGLVectorLayerRenderer(this, {
style,
});
}
}
const link = new Link();

function useWebGL() {
map.getLayers().clear();
map.addLayer(new WebGLLayer({source}));
}
/**
* @type {import('ol/style/flat.js').FlatStyle & import('ol/style/literal.js').LiteralStyle}
*/
const style = {
// This has to be fixed upstream
// @ts-ignore
'circle-radius': ['get', 'radius'],
'circle-fill-color': ['get', 'color'],
'circle-stroke-color': 'gray',
'circle-stroke-width': 0.5,
};

function useCanvas() {
map.getLayers().clear();
map.addLayer(new VectorLayer({source, style}));
}
const gui_obj = {
'Feature count': 200000,
'Use WebGL': false,
'Radius': 4,
};

const link = new Link();
const useWebGLCheckbox = gui.add(gui_obj, 'Use WebGL');
const featureCountSlider = gui.add(gui_obj, 'Feature count', 100000, 500000);
const radiusMeasure = gui.add(gui_obj, 'Radius', 4, 40, 1);

const webglToggle = /** @type {HTMLInputElement} */ (
document.getElementById('renderer')
);
webglToggle.addEventListener('change', function () {
if (webglToggle.checked) {
useWebGLCheckbox.onChange((/** @type {boolean} */ value) => {
if (value) {
link.update('renderer', 'webgl');
useWebGL();
} else {
Expand All @@ -66,63 +61,82 @@ webglToggle.addEventListener('change', function () {
}
});

featureCountSlider.onFinishChange(() => {
link.update('count', featureCountSlider.getValue());
resetData(parseInt(featureCountSlider.getValue()), gui_obj.Radius);
});

radiusMeasure.onFinishChange(() => {
link.update('radius', radiusMeasure.getValue());
resetData(gui_obj['Feature count'], gui_obj.Radius);
});

const initialRenderer = link.track('renderer', (newRenderer) => {
if (newRenderer === 'webgl') {
webglToggle.checked = true;
gui_obj['Use WebGL'] = true;
useWebGLCheckbox.listen();
useWebGL();
} else {
webglToggle.checked = false;
useCanvas();
gui_obj['Use WebGL'] = false;
useWebGLCheckbox.listen();
}
});
webglToggle.checked = initialRenderer === 'webgl';

const countSelect = /** @type {HTMLSelectElement} */ (
document.getElementById('count')
);
countSelect.addEventListener('change', function () {
link.update('count', countSelect.value);
resetData(parseInt(countSelect.value));
});

const initialCount = link.track('count', (newCount) => {
resetData(parseInt(newCount));
resetData(parseInt(newCount), parseInt(radiusMeasure.getValue()));
});

const initialRadius = link.track('radius', (newRadius) => {
resetData(parseInt(featureCountSlider.getValue()), parseInt(newRadius));
});
if (initialCount) {
countSelect.value = initialCount;
}

map.addInteraction(link);

class WebGLLayer extends Layer {
/**
* @return {WebGLVectorLayerRenderer} The renderer.
*/
createRenderer() {
return new WebGLVectorLayerRenderer(this, {
style,
});
}
}

function useWebGL() {
map.getLayers().clear();
map.addLayer(new WebGLLayer({source}));
}

function useCanvas() {
map.getLayers().clear();
map.addLayer(new VectorLayer({source, style}));
}

/**
* @param {number} count The number of features to create.
* @return {import('geojson').FeatureCollection} The features.
* @param {number} count
* @param {number} radius
*/
function makeData(count) {
const size = 180 / Math.floor(Math.sqrt(count / 2));

function makeData(count, radius) {
const size = 400 / Math.floor(Math.sqrt(count / 2));
/**
* @type {Array<import('geojson').Feature>}
*/
const features = [];
for (let lon = -180; lon < 180 - size / 4; lon += size) {
for (let lat = -90; lat < 90 - size / 4; lat += size) {
const buffer = (0.1 + Math.random() * 0.1) * size;
const buffer = (0.3 + Math.random() * 0.2) * size * (radius / 5); // Increase the buffer for larger points
features.push({
type: 'Feature',
properties: {
color: colors[Math.floor(Math.random() * colors.length)],
radius,
},
geometry: {
type: 'Polygon',
coordinates: [
[
[lon + buffer, lat + buffer],
[lon + size - buffer, lat + buffer],
[lon + size - buffer, lat + size - buffer],
[lon + buffer, lat + size - buffer],
[lon + buffer, lat + buffer],
],
],
type: 'Point',
coordinates: [lon + buffer, lat + buffer],
},
});
}
Expand All @@ -135,7 +149,7 @@ function makeData(count) {

const format = new GeoJSON();
/**
* @param {import('geojson').FeatureCollection} data The GeoJSON data.
* @param {{features: Array<import('geojson').Feature>, type: string}} data The GeoJSON data.
* @return {Array<import('ol/Feature.js').default>} The features.
*/
function parseFeatures(data) {
Expand All @@ -156,10 +170,12 @@ async function addFeatures(features) {

/**
* @param {number} count The number of features to create.
* @param {number} numVertices
*/
function resetData(count) {

function resetData(count, numVertices) {
source.clear();
const data = makeData(count);
const data = makeData(count, numVertices);
const features = parseFeatures(data);
addFeatures(features);
console.time('first render');
Expand All @@ -168,10 +184,22 @@ function resetData(count) {
function main() {
const count = initialCount
? parseInt(initialCount)
: parseInt(countSelect.value);
resetData(count);
: parseInt(featureCountSlider.getValue());
const radius = initialRadius
? parseInt(initialRadius)
: parseInt(radiusMeasure.getValue());

resetData(count, radius);

gui_obj['Feature count'] = count;
gui_obj.Radius = radius;
featureCountSlider.listen();
radiusMeasure.listen();

gui_obj['Use WebGL'] = initialRenderer === 'webgl';
useWebGLCheckbox.listen();

if (initialRenderer === 'webgl') {
if (gui_obj['Use WebGL']) {
useWebGL();
} else {
useCanvas();
Expand Down
16 changes: 16 additions & 0 deletions cases/polygon-rendering/index.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
<!DOCTYPE html>
<html lang="en">

<head>
<meta charset="UTF-8">
<meta name="viewport" content="initial-scale=1.0, user-scalable=no, width=device-width">
<title>Polygon Rendering</title>
<link rel="stylesheet" href="../../style.css">
</head>

<body>
<div id="map" class="map"></div>
<script src="./main.js" type="module"></script>
</body>

</html>
Loading

0 comments on commit aa9aa69

Please sign in to comment.