Skip to content

Commit

Permalink
added basic tests for clustertilelayer
Browse files Browse the repository at this point in the history
Signed-off-by: Tim Deubler <[email protected]>
  • Loading branch information
TerminalTim committed May 8, 2024
1 parent a005a24 commit 1ac678f
Show file tree
Hide file tree
Showing 4 changed files with 244 additions and 15 deletions.
29 changes: 17 additions & 12 deletions packages/core/src/layers/cluster/ClusterTileLayer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -103,33 +103,39 @@ export class ClusterTileLayer extends TileLayer {

super({
clusterRadius,
tileSize: 512,
...options,
providers
});

this.clusterMaxZoom = max - this.levelOffset;
this._dataProvider = dataProvider;

const featureUpdateListener = this.featureUpdateListener.bind(this);
this.featureUpdateListener = this.featureUpdateListener.bind(this);

const toggleProviderUpdateListener = ({type}) => {
['featuresAdd', 'featuresRemove'/* , 'tileInitialized'*/, 'tileDestroyed'].forEach((e) => {
if (type == 'layerAdd') {
dataProvider.addEventListener(e, featureUpdateListener);
} else {
dataProvider.removeEventListener(e, featureUpdateListener);
}
});
const toggleProviderListener = ({type}) => {
this.listenForDataUpdates(type == 'layerAdd');
};
this.addEventListener('layerAdd', toggleProviderUpdateListener);
this.addEventListener('layerRemove', toggleProviderUpdateListener);
this.addEventListener('layerAdd', toggleProviderListener);
this.addEventListener('layerRemove', toggleProviderListener);
}

listenForDataUpdates(active: boolean) {
['featuresAdd', 'featuresRemove'/* , 'tileInitialized'*/, 'tileDestroyed'].forEach((e) => {
if (active) {
this._dataProvider.addEventListener(e, this.featureUpdateListener);
} else {
this._dataProvider.removeEventListener(e, this.featureUpdateListener);
}
});
};

private featureUpdateListener(e) {
let {features, tiles} = e.detail;
const preventDuplicates = e.type == 'tileInitialized';
const operation = e.type == 'featuresAdd' ? CLUSTER_OPERATION.GROW : CLUSTER_OPERATION.SHRINK;
const updatedTiles = this._updateClusters(features, operation, preventDuplicates);

if (e.type == 'tileDestroyed') {
for (let tile of tiles) {
this._pendingClusterJobs.delete(tile.quadkey);
Expand Down Expand Up @@ -326,7 +332,6 @@ export class ClusterTileLayer extends TileLayer {
private _getCoveringTile(quadkey: string): string {
for (let [qk, jobs] of Array.from(this._pendingClusterJobs)) {
if (quadkey.indexOf(qk) == 0/* && jobs.size == 0*/) {
// console.log('::: WTF!!!', qk, 'covers', quadkey);
return qk;
}
}
Expand Down
11 changes: 11 additions & 0 deletions packages/tests/specs/core/layer/clusterTileLayer.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
{
"layers": [{
"id": "dataLayer",
"provider": {
"id": "dataProvider",
"type": "LocalProvider"
},
"min": 2,
"max": 20
}]
}
208 changes: 208 additions & 0 deletions packages/tests/specs/core/layer/clusterTileLayer.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,208 @@
/*
* Copyright (C) 2019-2022 HERE Europe B.V.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* SPDX-License-Identifier: Apache-2.0
* License-Filename: LICENSE
*/

import {prepare} from 'utils';
import dataset from './clusterTileLayer.json';
import {ClusterTileLayer} from '@here/xyz-maps-core';

describe('ClusterTileLayer', function() {
const expect = chai.expect;

let dataLayer;
let clusterLayer;
let clusterMaxZoom = 13;

before(async function() {
let preparedData = await prepare(dataset);
dataLayer = preparedData.getLayers('dataLayer');

clusterLayer = new ClusterTileLayer({
min: 2,
max: 20,
tileSize: 512,
clusterMaxZoom: clusterMaxZoom,
clusterRadius: 64,
provider: dataLayer.getProvider()
});

clusterLayer.listenForDataUpdates(true);

console.log(clusterLayer);
// [5.374586091665641, 51.955245165606556]
});
//
it('validate no clustered', ()=>{
let clusters = clusterLayer.getProvider(11).search({
point: {longitude: 5.595344540913686, latitude: 51.955245165606556},
radius: 100_000
});
expect(clusters).to.have.lengthOf(0);
});

it('add a feature, validate cluster with clusterSize 1', async () => {
dataLayer.addFeature({
id: 'F0',
type: 'Feature',
properties: {},
geometry: {'type': 'Point', 'coordinates': [5.595344540913686, 51.955245165606556]}
});

let clusters = clusterLayer.getProvider(10).search({
point: {longitude: 5.595344540913686, latitude: 51.955245165606556},
radius: 100_000
});
expect(clusters).to.have.lengthOf(1);
expect(clusters[0].properties.clusterSize).to.equal(1);
});

it('add another feature, validate clusters', async () => {
dataLayer.addFeature({
id: 'F1',
type: 'Feature',
properties: {},
geometry: {'type': 'Point', 'coordinates': [5.629676715081445, 51.955245165606556]}
});

let clusters = clusterLayer.getProvider(10).search({
point: {longitude: 5.595344540913686, latitude: 51.955245165606556},
radius: 100_000
});
expect(clusters).to.have.lengthOf(1);
expect(clusters[0].properties.clusterSize).to.equal(2);
});

it('add another feature, validate clusters', async () => {
dataLayer.addFeature({
id: 'F2',
type: 'Feature',
properties: {},
geometry: {'type': 'Point', 'coordinates': [5.664008889249146, 51.955245165606556]}
});

let clusters = clusterLayer.getProvider(10).search({
point: {longitude: 5.595344540913686, latitude: 51.955245165606556},
radius: 100_000
});
expect(clusters).to.have.lengthOf(1);
expect(clusters[0].properties.clusterSize).to.equal(3);
});

it('add feature close to existing cluster and we now have 2 clusters', async () => {
dataLayer.addFeature({
id: 'F3',
type: 'Feature',
properties: {},
geometry: {'type': 'Point', 'coordinates': [5.732673237584663, 51.955245165606556]}
});

let clusters = clusterLayer.getProvider(10).search({
point: {longitude: 5.595344540913686, latitude: 51.955245165606556},
radius: 100_000
});
expect(clusters).to.have.lengthOf(2);
});

it('validate clusters sizes', async () => {
let clusters = clusterLayer.getProvider(10).search({
point: {longitude: 5.595344540913686, latitude: 51.955245165606556},
radius: 100_000
});
expect(clusters[0].properties.clusterSize).to.equal(3);
expect(clusters[1].properties.clusterSize).to.equal(1);
});

it('validate cluster in zoomlevel +1', async () => {
dataLayer.addFeature({
id: 'F3',
type: 'Feature',
properties: {},
geometry: {'type': 'Point', 'coordinates': [5.732673237584663, 51.955245165606556]}
});

let clusters = clusterLayer.getProvider(11).search({
point: {longitude: 5.595344540913686, latitude: 51.955245165606556},
radius: 100_000
});
expect(clusters).to.have.lengthOf(3);
});
it('validate clusters sizes in zoomlevel +1', async () => {
let clusters = clusterLayer.getProvider(11).search({
point: {longitude: 5.595344540913686, latitude: 51.955245165606556},
radius: 100_000
});
expect(clusters[0].properties.clusterSize).to.equal(2);
expect(clusters[1].properties.clusterSize).to.equal(1);
expect(clusters[2].properties.clusterSize).to.equal(1);
});

it('validate cluster in zoomlevel +2', async () => {
dataLayer.addFeature({
id: 'F3',
type: 'Feature',
properties: {},
geometry: {'type': 'Point', 'coordinates': [5.732673237584663, 51.955245165606556]}
});

let clusters = clusterLayer.getProvider(12).search({
point: {longitude: 5.595344540913686, latitude: 51.955245165606556},
radius: 100_000
});
expect(clusters).to.have.lengthOf(4);
});
it('validate clusters sizes in zoomlevel +2', async () => {
let clusters = clusterLayer.getProvider(12).search({
point: {longitude: 5.595344540913686, latitude: 51.955245165606556},
radius: 100_000
});
expect(clusters[0].properties.clusterSize).to.equal(1);
expect(clusters[1].properties.clusterSize).to.equal(1);
expect(clusters[2].properties.clusterSize).to.equal(1);
expect(clusters[3].properties.clusterSize).to.equal(1);
});

it('validate cluster in zoomlevel -1', async () => {
let clusters = clusterLayer.getProvider(9).search({
point: {longitude: 5.595344540913686, latitude: 51.955245165606556},
radius: 100_000
});
expect(clusters).to.have.lengthOf(1);
});
it('validate clusters sizes in zoomlevel -1', async () => {
let clusters = clusterLayer.getProvider(9).search({
point: {longitude: 5.595344540913686, latitude: 51.955245165606556},
radius: 100_000
});
expect(clusters[0].properties.clusterSize).to.equal(4);
});

it('validate cluster in zoomlevel -2', async () => {
let clusters = clusterLayer.getProvider(8).search({
point: {longitude: 5.595344540913686, latitude: 51.955245165606556},
radius: 100_000
});
expect(clusters).to.have.lengthOf(1);
});
it('validate clusters sizes in zoomlevel -2', async () => {
let clusters = clusterLayer.getProvider(8).search({
point: {longitude: 5.595344540913686, latitude: 51.955245165606556},
radius: 100_000
});
expect(clusters[0].properties.clusterSize).to.equal(4);
});
});
11 changes: 8 additions & 3 deletions packages/tests/src/utils/prepareData.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,11 +20,10 @@
import environments from 'environments';
// @ts-ignore
import credentials from 'credentials';
import {TileLayer, FeatureProvider} from '@here/xyz-maps-core';
import {GeoJSONFeature, ClusterTileLayer, TileLayer, FeatureProvider} from '@here/xyz-maps-core';
import * as XYZMapsCore from '@here/xyz-maps-core';
import {TestLocalProvider, TestProvider} from '../TestProvider';
import {spacePool} from '../runner';
import {GeoJSONFeature} from '@here/xyz-maps-core';
import TileProvider from '@here/xyz-maps-core/src/providers/TileProvider/TileProvider';


Expand Down Expand Up @@ -120,6 +119,7 @@ type ProviderSetup = {
type LayerSetup = {
id: string;
provider: ProviderSetup;
type?: 'TileLayer'|'ClusterTileLayer'
min: number;
max: number;
data?: {
Expand All @@ -138,6 +138,9 @@ export default async function prepare(dataset: MapSetup) {
let featuresToUpdateRP = {};
let linkLayerId;


const supportedLayerTypes = {'TileLayer': TileLayer, 'ClusterTileLayer': ClusterTileLayer};

if (dataset && dataset.layers) {
let ts = (new Date()).getTime().toString();
for (let l of dataset.layers) {
Expand All @@ -152,7 +155,9 @@ export default async function prepare(dataset: MapSetup) {
delete layerConfig['data'];
delete layerConfig['clear'];

let layer = new TileLayer(layerConfig);
const LayerClass: typeof TileLayer = supportedLayerTypes[l.type]||TileLayer;

let layer = new LayerClass(layerConfig);

preparedData.addLayer(layer);

Expand Down

0 comments on commit 1ac678f

Please sign in to comment.