diff --git a/README.md b/README.md index 1965e0e6..5d644be6 100644 --- a/README.md +++ b/README.md @@ -63,16 +63,17 @@ Returns the zoom on which the cluster expands into several children (useful for ## Options -| Option | Default | Description | -|------------|---------|-------------------------------------------------------------------| -| minZoom | 0 | Minimum zoom level at which clusters are generated. | -| maxZoom | 16 | Maximum zoom level at which clusters are generated. | -| minPoints | 2 | Minimum number of points to form a cluster. | -| radius | 40 | Cluster radius, in pixels. | -| extent | 512 | (Tiles) Tile extent. Radius is calculated relative to this value. | -| nodeSize | 64 | Size of the KD-tree leaf node. Affects performance. | -| log | false | Whether timing info should be logged. | -| generateId | false | Whether to generate ids for input features in vector tiles. | +| Option | Default | Description | +|------------|--------------|-------------------------------------------------------------------------------------| +| minZoom | 0 | Minimum zoom level at which clusters are generated. | +| maxZoom | 16 | Maximum zoom level at which clusters are generated. | +| minPoints | 2 | Minimum number of points to form a cluster. | +| radius | 40 | Cluster radius, in pixels. | +| extent | 512 | (Tiles) Tile extent. Radius is calculated relative to this value. | +| nodeSize | 64 | Size of the KD-tree leaf node. Affects performance. | +| arrayType | Float32Array | TypedArray to use for storing coordinate values. Affects accuracy for small radius. | +| log | false | Whether timing info should be logged. | +| generateId | false | Whether to generate ids for input features in vector tiles. | ### Property map/reduce options diff --git a/index.js b/index.js index 4dce8d36..671cbebd 100644 --- a/index.js +++ b/index.js @@ -8,6 +8,7 @@ const defaultOptions = { radius: 40, // cluster radius in pixels extent: 512, // tile extent (radius is calculated relative to it) nodeSize: 64, // size of the KD-tree leaf node, affects performance + arrayType: Float32Array, // TypedArray to use for storing coordinate values, affects accuracy for small radius log: false, // whether to log timing info // whether to generate numeric ids for input features (in vector tiles) @@ -34,6 +35,7 @@ export default class Supercluster { this.trees = new Array(this.options.maxZoom + 1); this.stride = this.options.reduce ? 7 : 6; this.clusterProps = []; + this.coordinateRoundFn = this.options.arrayType === Float32Array ? fround : (x => x); } load(points) { @@ -54,8 +56,8 @@ export default class Supercluster { if (!p.geometry) continue; const [lng, lat] = p.geometry.coordinates; - const x = fround(lngX(lng)); - const y = fround(latY(lat)); + const x = this.coordinateRoundFn(lngX(lng)); + const y = this.coordinateRoundFn(latY(lat)); // store internal point/cluster data in flat numeric arrays for performance data.push( x, y, // projected point coordinates @@ -220,7 +222,7 @@ export default class Supercluster { } _createTree(data) { - const tree = new KDBush(data.length / this.stride | 0, this.options.nodeSize, Float32Array); + const tree = new KDBush(data.length / this.stride | 0, this.options.nodeSize, this.options.arrayType); for (let i = 0; i < data.length; i += this.stride) tree.add(data[i], data[i + 1]); tree.finish(); tree.data = data; diff --git a/test/test.js b/test/test.js index 5fb05107..a2c4fe83 100644 --- a/test/test.js +++ b/test/test.js @@ -179,3 +179,31 @@ test('does not throw on zero items', () => { assert.deepEqual(index.getClusters([-180, -85, 180, 85], 0), []); }); }); + +test('very close points which shouldn\'t cluster, are clustered when using Float32Array', () => { + const index = new Supercluster({ + maxZoom: 22, + extent: 8192, + radius: 4, + arrayType: Float32Array + }).load([ + {type: 'Feature', geometry: {type: 'Point', coordinates: [-1.426798, 53.943034]}}, + {type: 'Feature', geometry: {type: 'Point', coordinates: [-1.426799, 53.943034]}} + ]); + + assert.equal(index.trees[22].ids.length, 1); +}); + +test('very close points which shouldn\'t cluster, are not clustered when using Float64Array', () => { + const index = new Supercluster({ + maxZoom: 22, + extent: 8192, + radius: 4, + arrayType: Float64Array + }).load([ + {type: 'Feature', geometry: {type: 'Point', coordinates: [-1.426798, 53.943034]}}, + {type: 'Feature', geometry: {type: 'Point', coordinates: [-1.426799, 53.943034]}} + ]); + + assert.equal(index.trees[22].ids.length, 2); +});