Skip to content

Commit

Permalink
Merge pull request #39 from ronitjadhav/vector_tiles
Browse files Browse the repository at this point in the history
Added Vector Tiles Rendering
  • Loading branch information
jahow authored Nov 29, 2023
2 parents 439229a + bfe1f53 commit e679647
Show file tree
Hide file tree
Showing 3 changed files with 316 additions and 0 deletions.
16 changes: 16 additions & 0 deletions cases/vector-tiles-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>Vector Tiles 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>
297 changes: 297 additions & 0 deletions cases/vector-tiles-rendering/main.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,297 @@
/* eslint-disable no-console */
import BaseTileLayer from 'ol/layer/BaseTile.js';
import GUI from 'lil-gui';
import GeoJSON from 'ol/format/GeoJSON.js';
import Link from 'ol/interaction/Link.js';
import Map from 'ol/Map.js';
import VectorTileLayer from 'ol/layer/VectorTile.js';
import VectorTileSource from 'ol/source/VectorTile.js';
import View from 'ol/View.js';
import WebGLVectorTileLayerRenderer from 'ol/renderer/webgl/VectorTileLayer.js';
import {transformExtent, useGeographic} from 'ol/proj.js';

useGeographic();

const map = new Map({
layers: [],
target: 'map',
view: new View({
center: [0, 0],
zoom: 0,
}),
});

const source = new VectorTileSource({
url: '{z}/{x}/{y}',
// @ts-ignore
tileLoadFunction: (tile) => tileLoadFunction(tile),
maxZoom: 15,
});

const format = new GeoJSON({featureProjection: map.getView().getProjection()});

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

const gui = new GUI();

const link = new Link();

/**
*
* @type {import('ol/style/flat.js').FlatStyle & import('ol/style/literal.js').LiteralStyle}
*/
const style = {
'fill-color': ['get', 'color'],
'stroke-color': ['get', 'color'],
'stroke-width': 2,
'circle-radius': 7,
'circle-fill-color': ['get', 'color'],
'circle-stroke-color': 'gray',
'circle-stroke-width': 0.5,
};

const gui_obj = {
'Use WebGL': false,
'Feature count': 500,
'Toggle Performance Tracking': false, // New property for the performance tracking button
};

const useWebGLCheckbox = gui.add(gui_obj, 'Use WebGL');
const featureCountSlider = gui.add(gui_obj, 'Feature count', 500, 10000, 500);

useWebGLCheckbox.onChange((/** @type {any} */ value) => {
link.update('renderer', value ? 'webgl' : 'canvas');
value ? useWebGL() : useCanvas();
});

featureCountSlider.onFinishChange(() => {
link.update('count', featureCountSlider.getValue());
source.refresh();
// workaround required for webgl renderer; see https://github.com/openlayers/openlayers/issues/15213
// @ts-ignore
source.setKey(Date.now().toString());
});

const initialCount = link.track('count', (newCount) => {
// workaround required for webgl renderer; see https://github.com/openlayers/openlayers/issues/15213
// @ts-ignore
source.setKey(Date.now().toString());
source.refresh();
});

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

/**
* @extends {BaseTileLayer<VectorTileSource, WebGLVectorTileLayerRenderer>}
*/

class WebGLVectorTileLayer extends BaseTileLayer {
createRenderer() {
return new WebGLVectorTileLayerRenderer(this, {
style,
});
}
}

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

function useCanvas() {
map.getLayers().clear();
map.addLayer(
new VectorTileLayer({
source,
// @ts-ignore
style: style,
})
);
}

/**
* @param {number} numVertices
* @param {any} bbox
* @param {any} countPoints
* @param {number} countPolygons
* @param {number} countLines
*/

function makeData(countPoints, countPolygons, countLines, numVertices, bbox) {
/**
* @type {Array<import('geojson').Feature>}
*/
const features = [];
const width = bbox[2] - bbox[0];
const height = bbox[3] - bbox[1];
const centerLon = bbox[0] + width / 2;
const centerLat = bbox[1] + height / 2;

// Calculate the size based on the count and the bounding box area
const gridSpacing =
(width + height) / 4 / (Math.ceil(Math.sqrt(countPoints)) + 1);

// Generate polygons on the left bottom corner
for (let lon = bbox[0] + gridSpacing; lon < centerLon; lon += gridSpacing) {
for (let lat = bbox[1] + gridSpacing; lat < centerLat; lat += gridSpacing) {
const buffer = (0.3 + Math.random() * 0.2) * gridSpacing;

const angleStep = (2 * Math.PI) / numVertices;

const polygonCoordinates = [];
for (let i = 0; i < numVertices; i++) {
const angle = i * angleStep;
const x = lon + buffer * Math.cos(angle);
const y = lat + buffer * Math.sin(angle);
polygonCoordinates.push([x, y]);
}
polygonCoordinates.push(polygonCoordinates[0]);

features.push({
type: 'Feature',
properties: {
color: colors[Math.floor(Math.random() * colors.length)],
},
geometry: {
type: 'Polygon',
coordinates: [polygonCoordinates],
},
});
}
}

// outer boundary
features.push({
type: 'Feature',
properties: {
color: colors[Math.floor(Math.random() * colors.length)],
},
geometry: {
type: 'LineString',
coordinates: [
[bbox[0], bbox[1]],
[bbox[2], bbox[1]],
[bbox[2], bbox[3]],
[bbox[0], bbox[3]],
[bbox[0], bbox[1]],
],
},
});

// Generate points on the right top corner
for (let lon = centerLon + gridSpacing; lon < bbox[2]; lon += gridSpacing) {
for (let lat = bbox[1] + gridSpacing; lat < centerLat; lat += gridSpacing) {
const point = [lon, lat];

features.push({
type: 'Feature',
properties: {
color: colors[Math.floor(Math.random() * colors.length)],
},
geometry: {
type: 'Point',
coordinates: point,
},
});
}
}

const curveComplexity = 2;
const periodCount = 6;
const periodWidth = (width - gridSpacing * 2) / periodCount;
const periodHeight = height / 20;
const latitudeSpacing = (height / 2 - periodHeight * 2) / countLines;

/**
* @type {Array<any>}
*/
let singleCurve = []; // Create a singleCurve array outside the loop

for (let j = 0; j < countLines; j++) {
const coordinates = [];
for (let i = 0; i < periodCount; i++) {
const startLon = bbox[0] + i * periodWidth + gridSpacing;
const startLat = centerLat + periodHeight + j * latitudeSpacing; // Change the starting latitude to be above the center

singleCurve = []; // Clear the array

for (let i = 0; i < curveComplexity; i++) {
const ratio = i / curveComplexity;
const longitude = startLon + ratio * periodWidth;
const latitude =
startLat + Math.cos(ratio * Math.PI * 2) * periodHeight * 0.5;
singleCurve = singleCurve.concat([[longitude, latitude]]);
}
coordinates.push(...singleCurve);
}
features.push({
type: 'Feature',
properties: {
color: colors[Math.floor(Math.random() * colors.length)],
},
geometry: {
type: 'LineString',
coordinates,
},
});
}

return {
type: 'FeatureCollection',
features,
};
}

/**
* @param {import("ol/VectorTile.js").default} tile
*/

function tileLoadFunction(tile) {
// source.clear();
const totalFeatureCount = featureCountSlider.getValue();
const countPoints = Math.floor(totalFeatureCount / 3);
const countPolygons = Math.floor(totalFeatureCount / 3);
const countLines = totalFeatureCount - countPoints - countPolygons;
const tileGrid = source.getTileGrid();
let extent = tileGrid
? tileGrid.getTileCoordExtent(tile.tileCoord)
: [0, 0, 0, 0];
extent = transformExtent(extent, 'EPSG:3857', 'EPSG:4326');
const numVertices = 5;
const data = makeData(
countPoints,
countPolygons,
countLines,
numVertices,
extent
);
const features = format.readFeatures(data);
tile.setFeatures(features);
}

function main() {
gui_obj['Feature count'] = initialCount
? parseInt(initialCount)
: parseInt(featureCountSlider.getValue());
featureCountSlider.listen();
gui_obj['Use WebGL'] = initialRenderer === 'webgl';
useWebGLCheckbox.listen();

if (gui_obj['Use WebGL']) {
useWebGL();
} else {
useCanvas();
}
}

main();
3 changes: 3 additions & 0 deletions index.html
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,9 @@
<li>
<a href="cases/line-rendering/">Line Rendering</a>
</li>
<li>
<a href="cases/vector-tiles-rendering/">Vector Tiles Rendering</a>
</li>
</ul>
</body>

Expand Down

0 comments on commit e679647

Please sign in to comment.