Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add back & document cluster featureformat #1505

Merged
merged 2 commits into from
Sep 27, 2024
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
46 changes: 45 additions & 1 deletion lib/layer/featureFormats.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,7 @@ The layer.params.fields[] property values will be added to the layer.featureFiel
export function wkt(layer, features) {

if (!Array.isArray(features)) return;

const formatWKT = new ol.format.WKT

mapp.layer.featureFields.reset(layer);
Expand Down Expand Up @@ -147,3 +147,47 @@ export function wkt_properties(layer, features) {

mapp.layer.featureFields.process(layer);
}


/**
* @function cluster

* @description
* The cluster function processes an array of feature data and returns an array of OpenLayers features to be added to the layer source.
* It creates Point geometries from coordinate pairs, extracts count and ID information, and assigns additional properties based on the layer's field definitions.
* The function also tracks the maximum count across all features in the layer.max_size property.
* @param {Object} layer A layer object, likely an OpenLayers layer.
* @param {Array} features An array of feature data, where each feature is represented as an array.
* @property {number} layer.max_size The maximum count across all features.
* @property {Object} layer.params
* @property {Array} layer.params.fields Array of field names for additional feature properties.
* @returns {Array} Array of OpenLayers Feature objects.
*/
export function cluster(layer, features) {

layer.max_size = 1

return features.map((vals, i) => {

const geometry = new ol.geom.Point(vals.shift())

const count = vals.shift()

layer.max_size = layer.max_size > count ? layer.max_size : count;

const id = vals.shift()

const properties = { count }

layer.params.fields.forEach((field, i) => {
properties[field] = vals[i]
})

return new ol.Feature({
id,
geometry,
...properties
})

})
}
12 changes: 6 additions & 6 deletions lib/layer/format/vector.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -124,7 +124,7 @@ export default function vector(layer) {

clearTimeout(layer.timeout)

layer.timeout = setTimeout(()=>layer.reload(), 100)
layer.timeout = setTimeout(() => layer.reload(), 100)
})
}

Expand Down Expand Up @@ -267,13 +267,13 @@ function clusterConfig(layer) {
return;
};

// Check if distance is defined as <1 and layer is a format wkt
if (layer.cluster.distance < 1) {
// Check if distance is defined as <1 and layer is a format wkt
if (layer.cluster.distance < 1) {

console.warn(`Layer: ${layer.key}, cluster.distance is less than 1 [pixel]. The cluster config will be removed.`)

// Remove the cluster object
delete layer.cluster;
delete layer.cluster;
return;
}

Expand All @@ -284,7 +284,7 @@ function clusterConfig(layer) {
if (typeof layer.cluster.resolution === 'number') {
// Assign resolution as float.
layer.params.resolution = parseFloat(layer.cluster.resolution);
}
}
// Otherwise, warn and return.
else {
console.warn(`Layer: ${layer.key}, cluster.resolution must be a number.`)
Expand Down
8 changes: 5 additions & 3 deletions tests/browser/local.test.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,8 @@ import { ui_elementsTest } from '../lib/ui/elements/_elements.test.mjs';

import { ui_layers } from '../lib/ui/layers/_layers.test.mjs';
import { entriesTest } from '../lib/ui/locations/entries/_entries.test.mjs';
import {uiTest} from '../lib/ui/_ui.test.mjs';

import { uiTest } from '../lib/ui/_ui.test.mjs';
import { formatTest } from '../lib/layer/format/_format.test.mjs';
//API Tests
await workspaceTest();
await queryTest();
Expand Down Expand Up @@ -52,4 +52,6 @@ await entriesTest.geometryTest(mapview);

await ui_layers.filtersTest(mapview);

await uiTest.Tabview();
await uiTest.Tabview();

await formatTest.vectorTest(mapview);
5 changes: 5 additions & 0 deletions tests/lib/layer/format/_format.test.mjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
import { vectorTest } from './vector.test.mjs';

export const formatTest = {
vectorTest
}
107 changes: 107 additions & 0 deletions tests/lib/layer/format/vector.test.mjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,107 @@
/**
* This is the vector module used to test /lib/layer/format/vector
* @module layer/format/vector
*/

/**
* This is the entry point function for the vector test module.
* @function vectorTest
* @param {object} mapview
*/
export async function vectorTest(mapview) {
codi.describe('Layer Format: Vector', async () => {

/**
* ### Should be able to create a cluster layer
* 1. It takes layer params.
* 2. Decorates the layer.
* 3. We then give the vector function the layer.
* 4. We expect the format of the layer to change to 'cluster'
* @function it
*/
codi.it('Should create a cluster layer', async () => {
const layer_params = {
mapview: mapview,
'key': 'cluster_test',
'display': true,
'group': 'layer',
'format': 'wkt', //This should change to cluster when used in the vector function
'dbs': 'NEON',
'table': 'test.scratch',
'srid': '3857',
'geom': 'geom_3857',
'qID': 'id',
'cluster': {
'resolution': 0.005,
'hexgrid': true
},
'infoj': [
{
'type': 'pin',
'label': 'ST_PointOnSurface',
'field': 'pin',
'fieldfx': 'ARRAY[ST_X(ST_PointOnSurface(geom_3857)),ST_Y(ST_PointOnSurface(geom_3857))]'
}
],
'style': {
'default': {
'icon': {
'type': 'dot',
'fillColor': '#13336B'
}
},
'cluster': {
'icon': {
'type': 'target',
'fillColor': '#E6FFFF',
'layers': {
'1': '#13336B',
'0.85': '#E6FFFF'
}
}
},
'highlight': {
'scale': 1.3
},
'theme': {
'title': 'theme_1',
'type': 'graduated',
'field': 'test_template_style',
'graduated_breaks': 'greater_than',
'template': {
'key': 'test_template_style',
'template': '100-99',
'value_only': true
},
'cat_arr': [
{
'value': 0,
'label': '0 to 5%',
'style': {
'icon': {
'fillColor': '#ffffcc',
'fillOpacity': 0.8
}
}
}
]
}
}
}

//Decorating layer
const layer = await mapp.layer.decorate(layer_params);

//Passing the layer to the format method
mapp.layer.formats.vector(layer);

//Showing the layer
layer.show();
codi.assertTrue(typeof layer.show === 'function', 'The layer should have a show function');
codi.assertTrue(typeof layer.reload === 'function', 'The layer should have a reload function');
codi.assertTrue(typeof layer.setSource === 'function', 'The layer should have a setSource function');
codi.assertTrue(layer.format === 'cluster', 'The layer should have the format cluster');
layer.hide();
});
});
}
3 changes: 2 additions & 1 deletion tests/workspace.json
Original file line number Diff line number Diff line change
Expand Up @@ -310,7 +310,8 @@
"src": "file:/tests/assets/layers/location_mock/layer.json"
}
]
}
},
"cluster_test": {}
}
}
}
Loading