Introduce MixedGeometryBatch for webgl rendering
This class keeps an up-to-date list of line, polygon and point geometries to render as well as vertices counts, geometries count, rings count etc.
This commit is contained in:
@@ -0,0 +1,336 @@
|
|||||||
|
/**
|
||||||
|
* @module ol/render/webgl/MixedGeometryBatch
|
||||||
|
*/
|
||||||
|
import {getUid} from '../../util.js';
|
||||||
|
import GeometryType from '../../geom/GeometryType.js';
|
||||||
|
import WebGLArrayBuffer from '../../webgl/Buffer.js';
|
||||||
|
import {ARRAY_BUFFER, DYNAMIC_DRAW, ELEMENT_ARRAY_BUFFER} from '../../webgl.js';
|
||||||
|
import {create as createTransform} from '../../transform.js';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @typedef {Object} GeometryBatchItem Object that holds a reference to a feature as well as the raw coordinates of its various geometries
|
||||||
|
* @property {import("../../Feature").default} feature Feature
|
||||||
|
* @property {Object<string, *>} properties Feature properties
|
||||||
|
* @property {Array<Array<number>>} flatCoordss Array of flat coordinates arrays, one for each geometry related to the feature
|
||||||
|
* @property {number} [verticesCount] Only defined for linestring and polygon batches
|
||||||
|
* @property {number} [ringsCount] Only defined for polygon batches
|
||||||
|
* @property {Array<Array<number>>} [ringsVerticesCounts] Array of vertices counts in each ring for each geometry; only defined for polygons batches
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @typedef {Object} AbstractGeometryBatch
|
||||||
|
* @abstract
|
||||||
|
* @property {Object<string, GeometryBatchItem>} entries Dictionary of all entries in the batch with associated computed values.
|
||||||
|
* One entry corresponds to one feature. Key is feature uid.
|
||||||
|
* @property {number} geometriesCount Amount of geometries in the batch.
|
||||||
|
* @property {Float32Array} renderInstructions Render instructions for polygons are structured like so:
|
||||||
|
* [ numberOfRings, numberOfVerticesInRing0, ..., numberOfVerticesInRingN, x0, y0, customAttr0, ..., xN, yN, customAttrN, numberOfRings,... ]
|
||||||
|
* @property {WebGLArrayBuffer} verticesBuffer
|
||||||
|
* @property {WebGLArrayBuffer} indicesBuffer
|
||||||
|
* @property {import("../../transform.js").Transform} renderInstructionsTransform Converts world space coordinates to screen space; applies to the rendering instructions
|
||||||
|
* @property {import("../../transform.js").Transform} verticesBufferTransform Converts world space coordinates to screen space; applies to the webgl vertices buffer
|
||||||
|
* @property {import("../../transform.js").Transform} invertVerticesBufferTransform Screen space to world space; applies to the webgl vertices buffer
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @typedef {Object} PolygonGeometryBatch A geometry batch specific to polygons
|
||||||
|
* @extends {AbstractGeometryBatch}
|
||||||
|
* @property {number} verticesCount Amount of vertices from geometries in the batch.
|
||||||
|
* @property {number} ringsCount How many outer and inner rings in this batch.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @typedef {Object} LineStringGeometryBatch A geometry batch specific to lines
|
||||||
|
* @extends {AbstractGeometryBatch}
|
||||||
|
* @property {number} verticesCount Amount of vertices from geometries in the batch.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @typedef {Object} PointGeometryBatch A geometry batch specific to points
|
||||||
|
* @extends {AbstractGeometryBatch}
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @classdesc This class is used to group several geometries of various types together for faster rendering.
|
||||||
|
* Three inner batches are maintained for polygons, lines and points. Each time a feature is added, changed or removed
|
||||||
|
* from the batch, these inner batches are modified accordingly in order to keep them up-to-date.
|
||||||
|
*
|
||||||
|
* A feature can be present in several inner batches, for example a polygon geometry will be present in the polygon batch
|
||||||
|
* and its linar rings will be present in the line batch. Multi geometries are also broken down into individual geometries
|
||||||
|
* and added to the corresponding batches in a recursive manner.
|
||||||
|
*
|
||||||
|
* Corresponding {@link module:ol/render/webgl/BatchRenderer} instances are then used to generate the render instructions
|
||||||
|
* and WebGL buffers (vertices and indices) for each inner batches; render instructions are stored on the inner batches,
|
||||||
|
* alongside the transform used to convert world coords to screen coords at the time these instructions were generated.
|
||||||
|
* The resulting WebGL buffers are stored on the batches as well.
|
||||||
|
*
|
||||||
|
* An important aspect of geometry batches is that there is no guarantee that render instructions and WebGL buffers
|
||||||
|
* are synchronized, i.e. render instructions can describe a new state while WebGL buffers might not have been written yet.
|
||||||
|
* This is why two world-to-screen transforms are stored on each batch: one for the render instructions and one for
|
||||||
|
* the WebGL buffers.
|
||||||
|
*/
|
||||||
|
class MixedGeometryBatch {
|
||||||
|
constructor() {
|
||||||
|
/**
|
||||||
|
* @type {PolygonGeometryBatch}
|
||||||
|
*/
|
||||||
|
this.polygonBatch = {
|
||||||
|
entries: {},
|
||||||
|
geometriesCount: 0,
|
||||||
|
verticesCount: 0,
|
||||||
|
ringsCount: 0,
|
||||||
|
renderInstructions: new Float32Array(0),
|
||||||
|
verticesBuffer: new WebGLArrayBuffer(ARRAY_BUFFER, DYNAMIC_DRAW),
|
||||||
|
indicesBuffer: new WebGLArrayBuffer(ELEMENT_ARRAY_BUFFER, DYNAMIC_DRAW),
|
||||||
|
renderInstructionsTransform: createTransform(),
|
||||||
|
verticesBufferTransform: createTransform(),
|
||||||
|
invertVerticesBufferTransform: createTransform(),
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @type {PointGeometryBatch}
|
||||||
|
*/
|
||||||
|
this.pointBatch = {
|
||||||
|
entries: {},
|
||||||
|
geometriesCount: 0,
|
||||||
|
renderInstructions: new Float32Array(0),
|
||||||
|
verticesBuffer: new WebGLArrayBuffer(ARRAY_BUFFER, DYNAMIC_DRAW),
|
||||||
|
indicesBuffer: new WebGLArrayBuffer(ELEMENT_ARRAY_BUFFER, DYNAMIC_DRAW),
|
||||||
|
renderInstructionsTransform: createTransform(),
|
||||||
|
verticesBufferTransform: createTransform(),
|
||||||
|
invertVerticesBufferTransform: createTransform(),
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @type {LineStringGeometryBatch}
|
||||||
|
*/
|
||||||
|
this.lineStringBatch = {
|
||||||
|
entries: {},
|
||||||
|
geometriesCount: 0,
|
||||||
|
verticesCount: 0,
|
||||||
|
renderInstructions: new Float32Array(0),
|
||||||
|
verticesBuffer: new WebGLArrayBuffer(ARRAY_BUFFER, DYNAMIC_DRAW),
|
||||||
|
indicesBuffer: new WebGLArrayBuffer(ELEMENT_ARRAY_BUFFER, DYNAMIC_DRAW),
|
||||||
|
renderInstructionsTransform: createTransform(),
|
||||||
|
verticesBufferTransform: createTransform(),
|
||||||
|
invertVerticesBufferTransform: createTransform(),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {import("../../Feature").default[]} features
|
||||||
|
*/
|
||||||
|
addFeatures(features) {
|
||||||
|
for (let i = 0; i < features.length; i++) {
|
||||||
|
this.addFeature(features[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {import("../../Feature").default} feature
|
||||||
|
*/
|
||||||
|
addFeature(feature) {
|
||||||
|
const geometry = feature.getGeometry();
|
||||||
|
if (!geometry) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
this.addGeometry_(geometry, feature);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {import("../../Feature").default} feature
|
||||||
|
* @return {GeometryBatchItem}
|
||||||
|
* @private
|
||||||
|
*/
|
||||||
|
addFeatureEntryInPointBatch_(feature) {
|
||||||
|
const uid = getUid(feature);
|
||||||
|
if (!(uid in this.pointBatch.entries)) {
|
||||||
|
this.pointBatch.entries[uid] = {
|
||||||
|
feature: feature,
|
||||||
|
properties: feature.getProperties(),
|
||||||
|
flatCoordss: [],
|
||||||
|
};
|
||||||
|
}
|
||||||
|
return this.pointBatch.entries[uid];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {import("../../Feature").default} feature
|
||||||
|
* @return {GeometryBatchItem}
|
||||||
|
* @private
|
||||||
|
*/
|
||||||
|
addFeatureEntryInLineStringBatch_(feature) {
|
||||||
|
const uid = getUid(feature);
|
||||||
|
if (!(uid in this.lineStringBatch.entries)) {
|
||||||
|
this.lineStringBatch.entries[uid] = {
|
||||||
|
feature: feature,
|
||||||
|
properties: feature.getProperties(),
|
||||||
|
flatCoordss: [],
|
||||||
|
verticesCount: 0,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
return this.lineStringBatch.entries[uid];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {import("../../Feature").default} feature
|
||||||
|
* @return {GeometryBatchItem}
|
||||||
|
* @private
|
||||||
|
*/
|
||||||
|
addFeatureEntryInPolygonBatch_(feature) {
|
||||||
|
const uid = getUid(feature);
|
||||||
|
if (!(uid in this.polygonBatch.entries)) {
|
||||||
|
this.polygonBatch.entries[uid] = {
|
||||||
|
feature: feature,
|
||||||
|
properties: feature.getProperties(),
|
||||||
|
flatCoordss: [],
|
||||||
|
verticesCount: 0,
|
||||||
|
ringsCount: 0,
|
||||||
|
ringsVerticesCounts: [],
|
||||||
|
};
|
||||||
|
}
|
||||||
|
return this.polygonBatch.entries[uid];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {import("../../Feature").default} feature
|
||||||
|
* @private
|
||||||
|
*/
|
||||||
|
clearFeatureEntryInPointBatch_(feature) {
|
||||||
|
const entry = this.pointBatch.entries[getUid(feature)];
|
||||||
|
if (!entry) return;
|
||||||
|
this.pointBatch.geometriesCount -= entry.flatCoordss.length;
|
||||||
|
delete this.pointBatch.entries[getUid(feature)];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {import("../../Feature").default} feature
|
||||||
|
* @private
|
||||||
|
*/
|
||||||
|
clearFeatureEntryInLineStringBatch_(feature) {
|
||||||
|
const entry = this.lineStringBatch.entries[getUid(feature)];
|
||||||
|
if (!entry) return;
|
||||||
|
this.lineStringBatch.verticesCount -= entry.verticesCount;
|
||||||
|
this.lineStringBatch.geometriesCount -= entry.flatCoordss.length;
|
||||||
|
delete this.lineStringBatch.entries[getUid(feature)];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {import("../../Feature").default} feature
|
||||||
|
* @private
|
||||||
|
*/
|
||||||
|
clearFeatureEntryInPolygonBatch_(feature) {
|
||||||
|
const entry = this.polygonBatch.entries[getUid(feature)];
|
||||||
|
if (!entry) return;
|
||||||
|
this.polygonBatch.verticesCount -= entry.verticesCount;
|
||||||
|
this.polygonBatch.ringsCount -= entry.ringsCount;
|
||||||
|
this.polygonBatch.geometriesCount -= entry.flatCoordss.length;
|
||||||
|
delete this.polygonBatch.entries[getUid(feature)];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {import("../../geom").Geometry} geometry
|
||||||
|
* @param {import("../../Feature").default} feature
|
||||||
|
* @private
|
||||||
|
*/
|
||||||
|
addGeometry_(geometry, feature) {
|
||||||
|
const type = geometry.getType();
|
||||||
|
let flatCoords;
|
||||||
|
let verticesCount;
|
||||||
|
let batchEntry;
|
||||||
|
switch (type) {
|
||||||
|
case GeometryType.GEOMETRY_COLLECTION:
|
||||||
|
geometry
|
||||||
|
.getGeometries()
|
||||||
|
.map((geom) => this.addGeometry_(geom, feature));
|
||||||
|
break;
|
||||||
|
case GeometryType.MULTI_POLYGON:
|
||||||
|
geometry
|
||||||
|
.getPolygons()
|
||||||
|
.map((polygon) => this.addGeometry_(polygon, feature));
|
||||||
|
break;
|
||||||
|
case GeometryType.MULTI_LINE_STRING:
|
||||||
|
geometry
|
||||||
|
.getLineStrings()
|
||||||
|
.map((line) => this.addGeometry_(line, feature));
|
||||||
|
break;
|
||||||
|
case GeometryType.MULTI_POINT:
|
||||||
|
geometry.getPoints().map((point) => this.addGeometry_(point, feature));
|
||||||
|
break;
|
||||||
|
case GeometryType.POLYGON:
|
||||||
|
batchEntry = this.addFeatureEntryInPolygonBatch_(feature);
|
||||||
|
flatCoords = geometry.getFlatCoordinates();
|
||||||
|
verticesCount = flatCoords.length / 2;
|
||||||
|
const ringsCount = geometry.getLinearRingCount();
|
||||||
|
const ringsVerticesCount = geometry
|
||||||
|
.getEnds()
|
||||||
|
.map((end, ind, arr) =>
|
||||||
|
ind > 0 ? (end - arr[ind - 1]) / 2 : end / 2
|
||||||
|
);
|
||||||
|
this.polygonBatch.verticesCount += verticesCount;
|
||||||
|
this.polygonBatch.ringsCount += ringsCount;
|
||||||
|
this.polygonBatch.geometriesCount++;
|
||||||
|
batchEntry.flatCoordss.push(flatCoords);
|
||||||
|
batchEntry.ringsVerticesCounts.push(ringsVerticesCount);
|
||||||
|
batchEntry.verticesCount += verticesCount;
|
||||||
|
batchEntry.ringsCount += ringsCount;
|
||||||
|
geometry
|
||||||
|
.getLinearRings()
|
||||||
|
.map((ring) => this.addGeometry_(ring, feature));
|
||||||
|
break;
|
||||||
|
case GeometryType.POINT:
|
||||||
|
batchEntry = this.addFeatureEntryInPointBatch_(feature);
|
||||||
|
flatCoords = geometry.getFlatCoordinates();
|
||||||
|
this.pointBatch.geometriesCount++;
|
||||||
|
batchEntry.flatCoordss.push(flatCoords);
|
||||||
|
break;
|
||||||
|
case GeometryType.LINE_STRING:
|
||||||
|
case GeometryType.LINEAR_RING:
|
||||||
|
batchEntry = this.addFeatureEntryInLineStringBatch_(feature);
|
||||||
|
flatCoords = geometry.getFlatCoordinates();
|
||||||
|
verticesCount = flatCoords.length / 2;
|
||||||
|
this.lineStringBatch.verticesCount += verticesCount;
|
||||||
|
this.lineStringBatch.geometriesCount++;
|
||||||
|
batchEntry.flatCoordss.push(flatCoords);
|
||||||
|
batchEntry.verticesCount += verticesCount;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {import("../../Feature").default} feature
|
||||||
|
*/
|
||||||
|
changeFeature(feature) {
|
||||||
|
this.clearFeatureEntryInPointBatch_(feature);
|
||||||
|
this.clearFeatureEntryInPolygonBatch_(feature);
|
||||||
|
this.clearFeatureEntryInLineStringBatch_(feature);
|
||||||
|
const geometry = feature.getGeometry();
|
||||||
|
if (!geometry) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
this.addGeometry_(geometry, feature);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {import("../../Feature").default} feature
|
||||||
|
*/
|
||||||
|
removeFeature(feature) {
|
||||||
|
this.clearFeatureEntryInPointBatch_(feature);
|
||||||
|
this.clearFeatureEntryInPolygonBatch_(feature);
|
||||||
|
this.clearFeatureEntryInLineStringBatch_(feature);
|
||||||
|
}
|
||||||
|
|
||||||
|
clear() {
|
||||||
|
this.polygonBatch.entries = {};
|
||||||
|
this.polygonBatch.geometriesCount = 0;
|
||||||
|
this.polygonBatch.verticesCount = 0;
|
||||||
|
this.polygonBatch.ringsCount = 0;
|
||||||
|
this.lineStringBatch.entries = {};
|
||||||
|
this.lineStringBatch.geometriesCount = 0;
|
||||||
|
this.lineStringBatch.verticesCount = 0;
|
||||||
|
this.pointBatch.entries = {};
|
||||||
|
this.pointBatch.geometriesCount = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export default MixedGeometryBatch;
|
||||||
@@ -0,0 +1,778 @@
|
|||||||
|
import Feature from '../../../../../../src/ol/Feature.js';
|
||||||
|
import Point from '../../../../../../src/ol/geom/Point.js';
|
||||||
|
import MixedGeometryBatch from '../../../../../../src/ol/render/webgl/MixedGeometryBatch.js';
|
||||||
|
import LineString from '../../../../../../src/ol/geom/LineString.js';
|
||||||
|
import {getUid} from '../../../../../../src/ol/index.js';
|
||||||
|
import Polygon from '../../../../../../src/ol/geom/Polygon.js';
|
||||||
|
import LinearRing from '../../../../../../src/ol/geom/LinearRing.js';
|
||||||
|
import MultiPolygon from '../../../../../../src/ol/geom/MultiPolygon.js';
|
||||||
|
import GeometryCollection from '../../../../../../src/ol/geom/GeometryCollection.js';
|
||||||
|
import MultiLineString from '../../../../../../src/ol/geom/MultiLineString.js';
|
||||||
|
import MultiPoint from '../../../../../../src/ol/geom/MultiPoint.js';
|
||||||
|
|
||||||
|
describe('MixedGeometryBatch', function () {
|
||||||
|
let mixedBatch;
|
||||||
|
|
||||||
|
beforeEach(() => {
|
||||||
|
mixedBatch = new MixedGeometryBatch();
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('#addFeatures', () => {
|
||||||
|
let features, spy;
|
||||||
|
beforeEach(() => {
|
||||||
|
features = [new Feature(), new Feature(), new Feature()];
|
||||||
|
spy = sinon.spy(mixedBatch, 'addFeature');
|
||||||
|
mixedBatch.addFeatures(features);
|
||||||
|
});
|
||||||
|
it('calls addFeature for each feature', () => {
|
||||||
|
expect(spy.callCount).to.be(3);
|
||||||
|
expect(spy.args[0][0]).to.be(features[0]);
|
||||||
|
expect(spy.args[1][0]).to.be(features[1]);
|
||||||
|
expect(spy.args[2][0]).to.be(features[2]);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('features with Point geometries', () => {
|
||||||
|
let geometry1, feature1, geometry2, feature2;
|
||||||
|
|
||||||
|
beforeEach(() => {
|
||||||
|
geometry1 = new Point([0, 1]);
|
||||||
|
feature1 = new Feature({
|
||||||
|
geometry: geometry1,
|
||||||
|
prop1: 'abcd',
|
||||||
|
prop2: 'efgh',
|
||||||
|
});
|
||||||
|
geometry2 = new Point([2, 3]);
|
||||||
|
feature2 = new Feature({
|
||||||
|
geometry: geometry2,
|
||||||
|
prop3: '1234',
|
||||||
|
prop4: '5678',
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('#addFeature', () => {
|
||||||
|
beforeEach(() => {
|
||||||
|
mixedBatch.addFeature(feature1);
|
||||||
|
mixedBatch.addFeature(feature2);
|
||||||
|
});
|
||||||
|
it('puts the geometries in the point batch', () => {
|
||||||
|
const keys = Object.keys(mixedBatch.pointBatch.entries);
|
||||||
|
const uid1 = getUid(feature1);
|
||||||
|
const uid2 = getUid(feature2);
|
||||||
|
expect(keys).to.eql([uid1, uid2]);
|
||||||
|
expect(mixedBatch.pointBatch.entries[uid1]).to.eql({
|
||||||
|
feature: feature1,
|
||||||
|
properties: feature1.getProperties(),
|
||||||
|
flatCoordss: [[0, 1]],
|
||||||
|
});
|
||||||
|
expect(mixedBatch.pointBatch.entries[uid2]).to.eql({
|
||||||
|
feature: feature2,
|
||||||
|
properties: feature2.getProperties(),
|
||||||
|
flatCoordss: [[2, 3]],
|
||||||
|
});
|
||||||
|
});
|
||||||
|
it('computes the geometries count', () => {
|
||||||
|
expect(mixedBatch.pointBatch.geometriesCount).to.be(2);
|
||||||
|
});
|
||||||
|
it('leaves other batches untouched', () => {
|
||||||
|
expect(Object.keys(mixedBatch.polygonBatch.entries)).to.have.length(0);
|
||||||
|
expect(Object.keys(mixedBatch.lineStringBatch.entries)).to.have.length(
|
||||||
|
0
|
||||||
|
);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('#changeFeature', () => {
|
||||||
|
beforeEach(() => {
|
||||||
|
mixedBatch.addFeature(feature1);
|
||||||
|
mixedBatch.addFeature(feature2);
|
||||||
|
});
|
||||||
|
describe('modifying geometry and props', () => {
|
||||||
|
beforeEach(() => {
|
||||||
|
feature1.set('prop1', 'changed');
|
||||||
|
geometry1.setCoordinates([100, 101]);
|
||||||
|
mixedBatch.changeFeature(feature1);
|
||||||
|
});
|
||||||
|
it('updates the modified properties and geometry in the point batch', () => {
|
||||||
|
const entry = mixedBatch.pointBatch.entries[getUid(feature1)];
|
||||||
|
expect(entry.properties.prop1).to.eql('changed');
|
||||||
|
});
|
||||||
|
it('keeps geometry count the same', () => {
|
||||||
|
expect(mixedBatch.pointBatch.geometriesCount).to.be(2);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
describe('changing the geometry', () => {
|
||||||
|
let newGeom;
|
||||||
|
beforeEach(() => {
|
||||||
|
newGeom = new Point([40, 41]);
|
||||||
|
feature1.setGeometry(newGeom);
|
||||||
|
mixedBatch.changeFeature(feature1);
|
||||||
|
});
|
||||||
|
it('updates the geometry in the point batch', () => {
|
||||||
|
const entry = mixedBatch.pointBatch.entries[getUid(feature1)];
|
||||||
|
expect(entry.flatCoordss).to.eql([[40, 41]]);
|
||||||
|
});
|
||||||
|
it('keeps geometry count the same', () => {
|
||||||
|
expect(mixedBatch.pointBatch.geometriesCount).to.be(2);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('#removeFeature', () => {
|
||||||
|
beforeEach(() => {
|
||||||
|
mixedBatch.addFeature(feature1);
|
||||||
|
mixedBatch.addFeature(feature2);
|
||||||
|
mixedBatch.removeFeature(feature1);
|
||||||
|
});
|
||||||
|
it('clears the entry related to this feature', () => {
|
||||||
|
const keys = Object.keys(mixedBatch.pointBatch.entries);
|
||||||
|
expect(keys).to.not.contain(getUid(feature1));
|
||||||
|
});
|
||||||
|
it('recompute geometry count', () => {
|
||||||
|
expect(mixedBatch.pointBatch.geometriesCount).to.be(1);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('features with LineString geometries', () => {
|
||||||
|
let geometry1, feature1, geometry2, feature2;
|
||||||
|
|
||||||
|
beforeEach(() => {
|
||||||
|
geometry1 = new LineString([
|
||||||
|
[0, 1],
|
||||||
|
[2, 3],
|
||||||
|
[4, 5],
|
||||||
|
[6, 7],
|
||||||
|
]);
|
||||||
|
feature1 = new Feature({
|
||||||
|
geometry: geometry1,
|
||||||
|
prop1: 'abcd',
|
||||||
|
prop2: 'efgh',
|
||||||
|
});
|
||||||
|
geometry2 = new LineString([
|
||||||
|
[8, 9],
|
||||||
|
[10, 11],
|
||||||
|
[12, 13],
|
||||||
|
]);
|
||||||
|
feature2 = new Feature({
|
||||||
|
geometry: geometry2,
|
||||||
|
prop3: '1234',
|
||||||
|
prop4: '5678',
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('#addFeature', () => {
|
||||||
|
beforeEach(() => {
|
||||||
|
mixedBatch.addFeature(feature1);
|
||||||
|
mixedBatch.addFeature(feature2);
|
||||||
|
});
|
||||||
|
it('puts the geometries in the linestring batch', () => {
|
||||||
|
const keys = Object.keys(mixedBatch.lineStringBatch.entries);
|
||||||
|
const uid1 = getUid(feature1);
|
||||||
|
const uid2 = getUid(feature2);
|
||||||
|
expect(keys).to.eql([uid1, uid2]);
|
||||||
|
expect(mixedBatch.lineStringBatch.entries[uid1]).to.eql({
|
||||||
|
feature: feature1,
|
||||||
|
properties: feature1.getProperties(),
|
||||||
|
flatCoordss: [[0, 1, 2, 3, 4, 5, 6, 7]],
|
||||||
|
verticesCount: 4,
|
||||||
|
});
|
||||||
|
expect(mixedBatch.lineStringBatch.entries[uid2]).to.eql({
|
||||||
|
feature: feature2,
|
||||||
|
properties: feature2.getProperties(),
|
||||||
|
flatCoordss: [[8, 9, 10, 11, 12, 13]],
|
||||||
|
verticesCount: 3,
|
||||||
|
});
|
||||||
|
});
|
||||||
|
it('computes the aggregated metrics on all geoms', () => {
|
||||||
|
expect(mixedBatch.lineStringBatch.verticesCount).to.be(7);
|
||||||
|
expect(mixedBatch.lineStringBatch.geometriesCount).to.be(2);
|
||||||
|
});
|
||||||
|
it('leaves other batches untouched', () => {
|
||||||
|
expect(Object.keys(mixedBatch.polygonBatch.entries)).to.have.length(0);
|
||||||
|
expect(Object.keys(mixedBatch.pointBatch.entries)).to.have.length(0);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('#changeFeature', () => {
|
||||||
|
beforeEach(() => {
|
||||||
|
mixedBatch.addFeature(feature1);
|
||||||
|
mixedBatch.addFeature(feature2);
|
||||||
|
});
|
||||||
|
describe('modifying geometry and props', () => {
|
||||||
|
beforeEach(() => {
|
||||||
|
feature1.set('prop1', 'changed');
|
||||||
|
geometry1.appendCoordinate([100, 101]);
|
||||||
|
geometry1.appendCoordinate([102, 103]);
|
||||||
|
mixedBatch.changeFeature(feature1);
|
||||||
|
});
|
||||||
|
it('updates the modified properties and geometry in the linestring batch', () => {
|
||||||
|
const entry = mixedBatch.lineStringBatch.entries[getUid(feature1)];
|
||||||
|
expect(entry.properties.prop1).to.eql('changed');
|
||||||
|
expect(entry.verticesCount).to.eql(6);
|
||||||
|
expect(entry.flatCoordss).to.eql([
|
||||||
|
[0, 1, 2, 3, 4, 5, 6, 7, 100, 101, 102, 103],
|
||||||
|
]);
|
||||||
|
});
|
||||||
|
it('updates the aggregated metrics on all geoms', () => {
|
||||||
|
expect(mixedBatch.lineStringBatch.verticesCount).to.be(9);
|
||||||
|
expect(mixedBatch.lineStringBatch.geometriesCount).to.be(2);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
describe('changing the geometry', () => {
|
||||||
|
let newGeom;
|
||||||
|
beforeEach(() => {
|
||||||
|
newGeom = new LineString([
|
||||||
|
[40, 41],
|
||||||
|
[42, 43],
|
||||||
|
]);
|
||||||
|
feature1.setGeometry(newGeom);
|
||||||
|
mixedBatch.changeFeature(feature1);
|
||||||
|
});
|
||||||
|
it('updates the geometry in the linestring batch', () => {
|
||||||
|
const entry = mixedBatch.lineStringBatch.entries[getUid(feature1)];
|
||||||
|
expect(entry.flatCoordss).to.eql([[40, 41, 42, 43]]);
|
||||||
|
});
|
||||||
|
it('updates the aggregated metrics on all geoms', () => {
|
||||||
|
expect(mixedBatch.lineStringBatch.verticesCount).to.be(5);
|
||||||
|
expect(mixedBatch.lineStringBatch.geometriesCount).to.be(2);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('#removeFeature', () => {
|
||||||
|
beforeEach(() => {
|
||||||
|
mixedBatch.addFeature(feature1);
|
||||||
|
mixedBatch.addFeature(feature2);
|
||||||
|
mixedBatch.removeFeature(feature1);
|
||||||
|
});
|
||||||
|
it('clears the entry related to this feature', () => {
|
||||||
|
const keys = Object.keys(mixedBatch.lineStringBatch.entries);
|
||||||
|
expect(keys).to.not.contain(getUid(feature1));
|
||||||
|
});
|
||||||
|
it('updates the aggregated metrics on all geoms', () => {
|
||||||
|
expect(mixedBatch.lineStringBatch.verticesCount).to.be(3);
|
||||||
|
expect(mixedBatch.lineStringBatch.geometriesCount).to.be(1);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('features with Polygon geometries', () => {
|
||||||
|
let geometry1, feature1, geometry2, feature2;
|
||||||
|
|
||||||
|
beforeEach(() => {
|
||||||
|
geometry1 = new Polygon([
|
||||||
|
[
|
||||||
|
[0, 1],
|
||||||
|
[2, 3],
|
||||||
|
[4, 5],
|
||||||
|
[6, 7],
|
||||||
|
],
|
||||||
|
[
|
||||||
|
[20, 21],
|
||||||
|
[22, 23],
|
||||||
|
[24, 25],
|
||||||
|
],
|
||||||
|
]);
|
||||||
|
feature1 = new Feature({
|
||||||
|
geometry: geometry1,
|
||||||
|
prop1: 'abcd',
|
||||||
|
prop2: 'efgh',
|
||||||
|
});
|
||||||
|
geometry2 = new Polygon([
|
||||||
|
[
|
||||||
|
[8, 9],
|
||||||
|
[10, 11],
|
||||||
|
[12, 13],
|
||||||
|
],
|
||||||
|
[
|
||||||
|
[30, 31],
|
||||||
|
[32, 33],
|
||||||
|
[34, 35],
|
||||||
|
],
|
||||||
|
[
|
||||||
|
[40, 41],
|
||||||
|
[42, 43],
|
||||||
|
[44, 45],
|
||||||
|
[46, 47],
|
||||||
|
],
|
||||||
|
]);
|
||||||
|
feature2 = new Feature({
|
||||||
|
geometry: geometry2,
|
||||||
|
prop3: '1234',
|
||||||
|
prop4: '5678',
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('#addFeature', () => {
|
||||||
|
beforeEach(() => {
|
||||||
|
mixedBatch.addFeature(feature1);
|
||||||
|
mixedBatch.addFeature(feature2);
|
||||||
|
});
|
||||||
|
it('puts the polygons in the polygon batch', () => {
|
||||||
|
const keys = Object.keys(mixedBatch.polygonBatch.entries);
|
||||||
|
const uid1 = getUid(feature1);
|
||||||
|
const uid2 = getUid(feature2);
|
||||||
|
expect(keys).to.eql([uid1, uid2]);
|
||||||
|
expect(mixedBatch.polygonBatch.entries[uid1]).to.eql({
|
||||||
|
feature: feature1,
|
||||||
|
properties: feature1.getProperties(),
|
||||||
|
flatCoordss: [[0, 1, 2, 3, 4, 5, 6, 7, 20, 21, 22, 23, 24, 25]],
|
||||||
|
verticesCount: 7,
|
||||||
|
ringsCount: 2,
|
||||||
|
ringsVerticesCounts: [[4, 3]],
|
||||||
|
});
|
||||||
|
expect(mixedBatch.polygonBatch.entries[uid2]).to.eql({
|
||||||
|
feature: feature2,
|
||||||
|
properties: feature2.getProperties(),
|
||||||
|
flatCoordss: [
|
||||||
|
[
|
||||||
|
8, 9, 10, 11, 12, 13, 30, 31, 32, 33, 34, 35, 40, 41, 42, 43, 44,
|
||||||
|
45, 46, 47,
|
||||||
|
],
|
||||||
|
],
|
||||||
|
verticesCount: 10,
|
||||||
|
ringsCount: 3,
|
||||||
|
ringsVerticesCounts: [[3, 3, 4]],
|
||||||
|
});
|
||||||
|
});
|
||||||
|
it('computes the aggregated metrics on all polygons', () => {
|
||||||
|
expect(mixedBatch.polygonBatch.verticesCount).to.be(17);
|
||||||
|
expect(mixedBatch.polygonBatch.geometriesCount).to.be(2);
|
||||||
|
expect(mixedBatch.polygonBatch.ringsCount).to.be(5);
|
||||||
|
});
|
||||||
|
it('puts the linear rings in the linestring batch', () => {
|
||||||
|
const keys = Object.keys(mixedBatch.lineStringBatch.entries);
|
||||||
|
expect(keys).to.eql([getUid(feature1), getUid(feature2)]);
|
||||||
|
expect(mixedBatch.lineStringBatch.entries[getUid(feature1)]).to.eql({
|
||||||
|
feature: feature1,
|
||||||
|
properties: feature1.getProperties(),
|
||||||
|
flatCoordss: [
|
||||||
|
[0, 1, 2, 3, 4, 5, 6, 7],
|
||||||
|
[20, 21, 22, 23, 24, 25],
|
||||||
|
],
|
||||||
|
verticesCount: 7,
|
||||||
|
});
|
||||||
|
expect(mixedBatch.lineStringBatch.entries[getUid(feature2)]).to.eql({
|
||||||
|
feature: feature2,
|
||||||
|
properties: feature2.getProperties(),
|
||||||
|
flatCoordss: [
|
||||||
|
[8, 9, 10, 11, 12, 13],
|
||||||
|
[30, 31, 32, 33, 34, 35],
|
||||||
|
[40, 41, 42, 43, 44, 45, 46, 47],
|
||||||
|
],
|
||||||
|
verticesCount: 10,
|
||||||
|
});
|
||||||
|
});
|
||||||
|
it('computes the aggregated metrics on all linestrings', () => {
|
||||||
|
expect(mixedBatch.lineStringBatch.verticesCount).to.be(17);
|
||||||
|
expect(mixedBatch.lineStringBatch.geometriesCount).to.be(5);
|
||||||
|
});
|
||||||
|
it('leaves point batch untouched', () => {
|
||||||
|
expect(Object.keys(mixedBatch.pointBatch.entries)).to.have.length(0);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('#changeFeature', () => {
|
||||||
|
beforeEach(() => {
|
||||||
|
mixedBatch.addFeature(feature1);
|
||||||
|
mixedBatch.addFeature(feature2);
|
||||||
|
});
|
||||||
|
describe('modifying geometry and props', () => {
|
||||||
|
beforeEach(() => {
|
||||||
|
feature1.set('prop1', 'changed');
|
||||||
|
geometry1.appendLinearRing(
|
||||||
|
new LinearRing([
|
||||||
|
[201, 202],
|
||||||
|
[203, 204],
|
||||||
|
[205, 206],
|
||||||
|
[207, 208],
|
||||||
|
])
|
||||||
|
);
|
||||||
|
mixedBatch.changeFeature(feature1);
|
||||||
|
});
|
||||||
|
it('updates the modified properties and geometry in the polygon batch', () => {
|
||||||
|
const entry = mixedBatch.polygonBatch.entries[getUid(feature1)];
|
||||||
|
expect(entry.properties.prop1).to.eql('changed');
|
||||||
|
expect(entry.verticesCount).to.eql(11);
|
||||||
|
expect(entry.ringsCount).to.eql(3);
|
||||||
|
expect(entry.ringsVerticesCounts).to.eql([[4, 3, 4]]);
|
||||||
|
});
|
||||||
|
it('updates the aggregated metrics on all geoms', () => {
|
||||||
|
expect(mixedBatch.polygonBatch.verticesCount).to.be(21);
|
||||||
|
expect(mixedBatch.polygonBatch.geometriesCount).to.be(2);
|
||||||
|
expect(mixedBatch.polygonBatch.ringsCount).to.be(6);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
describe('changing the geometry', () => {
|
||||||
|
let newGeom;
|
||||||
|
beforeEach(() => {
|
||||||
|
newGeom = new Polygon([
|
||||||
|
[
|
||||||
|
[201, 202],
|
||||||
|
[203, 204],
|
||||||
|
[205, 206],
|
||||||
|
[207, 208],
|
||||||
|
],
|
||||||
|
]);
|
||||||
|
feature1.setGeometry(newGeom);
|
||||||
|
mixedBatch.changeFeature(feature1);
|
||||||
|
});
|
||||||
|
it('updates the geometry in the polygon batch', () => {
|
||||||
|
const entry = mixedBatch.polygonBatch.entries[getUid(feature1)];
|
||||||
|
expect(entry.feature).to.be(feature1);
|
||||||
|
expect(entry.verticesCount).to.eql(4);
|
||||||
|
expect(entry.ringsCount).to.eql(1);
|
||||||
|
expect(entry.ringsVerticesCounts).to.eql([[4]]);
|
||||||
|
expect(entry.flatCoordss).to.eql([
|
||||||
|
[201, 202, 203, 204, 205, 206, 207, 208],
|
||||||
|
]);
|
||||||
|
});
|
||||||
|
it('updates the aggregated metrics on all geoms', () => {
|
||||||
|
expect(mixedBatch.polygonBatch.verticesCount).to.be(14);
|
||||||
|
expect(mixedBatch.polygonBatch.geometriesCount).to.be(2);
|
||||||
|
expect(mixedBatch.polygonBatch.ringsCount).to.be(4);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('#removeFeature', () => {
|
||||||
|
beforeEach(() => {
|
||||||
|
mixedBatch.addFeature(feature1);
|
||||||
|
mixedBatch.addFeature(feature2);
|
||||||
|
mixedBatch.removeFeature(feature1);
|
||||||
|
});
|
||||||
|
it('clears the entry related to this feature', () => {
|
||||||
|
const keys = Object.keys(mixedBatch.polygonBatch.entries);
|
||||||
|
expect(keys).to.not.contain(getUid(feature1));
|
||||||
|
});
|
||||||
|
it('updates the aggregated metrics on all geoms', () => {
|
||||||
|
expect(mixedBatch.polygonBatch.verticesCount).to.be(10);
|
||||||
|
expect(mixedBatch.polygonBatch.geometriesCount).to.be(1);
|
||||||
|
expect(mixedBatch.polygonBatch.ringsCount).to.be(3);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('feature with nested geometries (collection, multi)', () => {
|
||||||
|
let feature, geomCollection, multiPolygon, multiPoint, multiLine;
|
||||||
|
|
||||||
|
beforeEach(() => {
|
||||||
|
multiPoint = new MultiPoint([
|
||||||
|
[101, 102],
|
||||||
|
[201, 202],
|
||||||
|
[301, 302],
|
||||||
|
]);
|
||||||
|
multiLine = new MultiLineString([
|
||||||
|
[
|
||||||
|
[0, 1],
|
||||||
|
[2, 3],
|
||||||
|
[4, 5],
|
||||||
|
[6, 7],
|
||||||
|
],
|
||||||
|
[
|
||||||
|
[8, 9],
|
||||||
|
[10, 11],
|
||||||
|
[12, 13],
|
||||||
|
],
|
||||||
|
]);
|
||||||
|
multiPolygon = new MultiPolygon([
|
||||||
|
[
|
||||||
|
[
|
||||||
|
[0, 1],
|
||||||
|
[2, 3],
|
||||||
|
[4, 5],
|
||||||
|
[6, 7],
|
||||||
|
],
|
||||||
|
[
|
||||||
|
[20, 21],
|
||||||
|
[22, 23],
|
||||||
|
[24, 25],
|
||||||
|
],
|
||||||
|
],
|
||||||
|
[
|
||||||
|
[
|
||||||
|
[8, 9],
|
||||||
|
[10, 11],
|
||||||
|
[12, 13],
|
||||||
|
],
|
||||||
|
[
|
||||||
|
[30, 31],
|
||||||
|
[32, 33],
|
||||||
|
[34, 35],
|
||||||
|
],
|
||||||
|
[
|
||||||
|
[40, 41],
|
||||||
|
[42, 43],
|
||||||
|
[44, 45],
|
||||||
|
[46, 47],
|
||||||
|
],
|
||||||
|
],
|
||||||
|
]);
|
||||||
|
geomCollection = new GeometryCollection([
|
||||||
|
multiPolygon,
|
||||||
|
multiLine,
|
||||||
|
multiPoint,
|
||||||
|
]);
|
||||||
|
feature = new Feature({
|
||||||
|
geometry: geomCollection,
|
||||||
|
prop3: '1234',
|
||||||
|
prop4: '5678',
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('#addFeature', () => {
|
||||||
|
beforeEach(() => {
|
||||||
|
mixedBatch.addFeature(feature);
|
||||||
|
});
|
||||||
|
it('puts the polygons in the polygon batch', () => {
|
||||||
|
const uid = getUid(feature);
|
||||||
|
expect(mixedBatch.polygonBatch.entries[uid]).to.eql({
|
||||||
|
feature: feature,
|
||||||
|
properties: feature.getProperties(),
|
||||||
|
flatCoordss: [
|
||||||
|
[0, 1, 2, 3, 4, 5, 6, 7, 20, 21, 22, 23, 24, 25],
|
||||||
|
[
|
||||||
|
8, 9, 10, 11, 12, 13, 30, 31, 32, 33, 34, 35, 40, 41, 42, 43, 44,
|
||||||
|
45, 46, 47,
|
||||||
|
],
|
||||||
|
],
|
||||||
|
verticesCount: 17,
|
||||||
|
ringsCount: 5,
|
||||||
|
ringsVerticesCounts: [
|
||||||
|
[4, 3],
|
||||||
|
[3, 3, 4],
|
||||||
|
],
|
||||||
|
});
|
||||||
|
});
|
||||||
|
it('puts the polygon rings and linestrings in the linestring batch', () => {
|
||||||
|
const uid = getUid(feature);
|
||||||
|
expect(mixedBatch.lineStringBatch.entries[uid]).to.eql({
|
||||||
|
feature: feature,
|
||||||
|
properties: feature.getProperties(),
|
||||||
|
flatCoordss: [
|
||||||
|
[0, 1, 2, 3, 4, 5, 6, 7],
|
||||||
|
[20, 21, 22, 23, 24, 25],
|
||||||
|
[8, 9, 10, 11, 12, 13],
|
||||||
|
[30, 31, 32, 33, 34, 35],
|
||||||
|
[40, 41, 42, 43, 44, 45, 46, 47],
|
||||||
|
[0, 1, 2, 3, 4, 5, 6, 7],
|
||||||
|
[8, 9, 10, 11, 12, 13],
|
||||||
|
],
|
||||||
|
verticesCount: 24,
|
||||||
|
});
|
||||||
|
});
|
||||||
|
it('puts the points in the linestring batch', () => {
|
||||||
|
const uid = getUid(feature);
|
||||||
|
expect(mixedBatch.pointBatch.entries[uid]).to.eql({
|
||||||
|
feature: feature,
|
||||||
|
properties: feature.getProperties(),
|
||||||
|
flatCoordss: [
|
||||||
|
[101, 102],
|
||||||
|
[201, 202],
|
||||||
|
[301, 302],
|
||||||
|
],
|
||||||
|
});
|
||||||
|
});
|
||||||
|
it('computes the aggregated metrics on all polygons', () => {
|
||||||
|
expect(mixedBatch.polygonBatch.verticesCount).to.be(17);
|
||||||
|
expect(mixedBatch.polygonBatch.geometriesCount).to.be(2);
|
||||||
|
expect(mixedBatch.polygonBatch.ringsCount).to.be(5);
|
||||||
|
});
|
||||||
|
it('computes the aggregated metrics on all linestring', () => {
|
||||||
|
expect(mixedBatch.lineStringBatch.verticesCount).to.be(24);
|
||||||
|
expect(mixedBatch.lineStringBatch.geometriesCount).to.be(7);
|
||||||
|
});
|
||||||
|
it('computes the aggregated metrics on all points', () => {
|
||||||
|
expect(mixedBatch.pointBatch.geometriesCount).to.be(3);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('#changeFeature', () => {
|
||||||
|
beforeEach(() => {
|
||||||
|
mixedBatch.addFeature(feature);
|
||||||
|
});
|
||||||
|
describe('modifying geometry', () => {
|
||||||
|
beforeEach(() => {
|
||||||
|
multiLine.appendLineString(
|
||||||
|
new LineString([
|
||||||
|
[500, 501],
|
||||||
|
[502, 503],
|
||||||
|
[504, 505],
|
||||||
|
[506, 507],
|
||||||
|
])
|
||||||
|
);
|
||||||
|
multiPolygon.appendPolygon(
|
||||||
|
new Polygon([
|
||||||
|
[
|
||||||
|
[201, 202],
|
||||||
|
[203, 204],
|
||||||
|
[205, 206],
|
||||||
|
[207, 208],
|
||||||
|
[209, 210],
|
||||||
|
],
|
||||||
|
])
|
||||||
|
);
|
||||||
|
mixedBatch.changeFeature(feature);
|
||||||
|
});
|
||||||
|
it('updates the geometries in the polygon batch', () => {
|
||||||
|
const entry = mixedBatch.polygonBatch.entries[getUid(feature)];
|
||||||
|
expect(entry).to.eql({
|
||||||
|
feature: feature,
|
||||||
|
properties: feature.getProperties(),
|
||||||
|
flatCoordss: [
|
||||||
|
[0, 1, 2, 3, 4, 5, 6, 7, 20, 21, 22, 23, 24, 25],
|
||||||
|
[
|
||||||
|
8, 9, 10, 11, 12, 13, 30, 31, 32, 33, 34, 35, 40, 41, 42, 43,
|
||||||
|
44, 45, 46, 47,
|
||||||
|
],
|
||||||
|
[201, 202, 203, 204, 205, 206, 207, 208, 209, 210],
|
||||||
|
],
|
||||||
|
verticesCount: 22,
|
||||||
|
ringsCount: 6,
|
||||||
|
ringsVerticesCounts: [[4, 3], [3, 3, 4], [5]],
|
||||||
|
});
|
||||||
|
});
|
||||||
|
it('updates the geometries in the linestring batch', () => {
|
||||||
|
const entry = mixedBatch.lineStringBatch.entries[getUid(feature)];
|
||||||
|
expect(entry).to.eql({
|
||||||
|
feature: feature,
|
||||||
|
properties: feature.getProperties(),
|
||||||
|
flatCoordss: [
|
||||||
|
[0, 1, 2, 3, 4, 5, 6, 7],
|
||||||
|
[20, 21, 22, 23, 24, 25],
|
||||||
|
[8, 9, 10, 11, 12, 13],
|
||||||
|
[30, 31, 32, 33, 34, 35],
|
||||||
|
[40, 41, 42, 43, 44, 45, 46, 47],
|
||||||
|
[201, 202, 203, 204, 205, 206, 207, 208, 209, 210],
|
||||||
|
[0, 1, 2, 3, 4, 5, 6, 7],
|
||||||
|
[8, 9, 10, 11, 12, 13],
|
||||||
|
[500, 501, 502, 503, 504, 505, 506, 507],
|
||||||
|
],
|
||||||
|
verticesCount: 33,
|
||||||
|
});
|
||||||
|
});
|
||||||
|
it('updates the aggregated metrics on the polygon batch', () => {
|
||||||
|
expect(mixedBatch.polygonBatch.verticesCount).to.be(22);
|
||||||
|
expect(mixedBatch.polygonBatch.geometriesCount).to.be(3);
|
||||||
|
expect(mixedBatch.polygonBatch.ringsCount).to.be(6);
|
||||||
|
});
|
||||||
|
it('updates the aggregated metrics on the linestring batch', () => {
|
||||||
|
expect(mixedBatch.lineStringBatch.verticesCount).to.be(33);
|
||||||
|
expect(mixedBatch.lineStringBatch.geometriesCount).to.be(9);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
describe('changing the geometry', () => {
|
||||||
|
beforeEach(() => {
|
||||||
|
feature.setGeometry(
|
||||||
|
new Polygon([
|
||||||
|
[
|
||||||
|
[201, 202],
|
||||||
|
[203, 204],
|
||||||
|
[205, 206],
|
||||||
|
[207, 208],
|
||||||
|
],
|
||||||
|
])
|
||||||
|
);
|
||||||
|
mixedBatch.changeFeature(feature);
|
||||||
|
});
|
||||||
|
it('updates the geometries in the polygon batch', () => {
|
||||||
|
const entry = mixedBatch.polygonBatch.entries[getUid(feature)];
|
||||||
|
expect(entry).to.eql({
|
||||||
|
feature: feature,
|
||||||
|
properties: feature.getProperties(),
|
||||||
|
flatCoordss: [[201, 202, 203, 204, 205, 206, 207, 208]],
|
||||||
|
verticesCount: 4,
|
||||||
|
ringsCount: 1,
|
||||||
|
ringsVerticesCounts: [[4]],
|
||||||
|
});
|
||||||
|
});
|
||||||
|
it('updates the geometries in the linestring batch', () => {
|
||||||
|
const entry = mixedBatch.lineStringBatch.entries[getUid(feature)];
|
||||||
|
expect(entry).to.eql({
|
||||||
|
feature: feature,
|
||||||
|
properties: feature.getProperties(),
|
||||||
|
flatCoordss: [[201, 202, 203, 204, 205, 206, 207, 208]],
|
||||||
|
verticesCount: 4,
|
||||||
|
});
|
||||||
|
});
|
||||||
|
it('updates the aggregated metrics on the polygon batch', () => {
|
||||||
|
expect(mixedBatch.polygonBatch.verticesCount).to.be(4);
|
||||||
|
expect(mixedBatch.polygonBatch.geometriesCount).to.be(1);
|
||||||
|
expect(mixedBatch.polygonBatch.ringsCount).to.be(1);
|
||||||
|
});
|
||||||
|
it('updates the aggregated metrics on the linestring batch', () => {
|
||||||
|
expect(mixedBatch.lineStringBatch.verticesCount).to.be(4);
|
||||||
|
expect(mixedBatch.lineStringBatch.geometriesCount).to.be(1);
|
||||||
|
});
|
||||||
|
it('updates the aggregated metrics on the point batch', () => {
|
||||||
|
const keys = Object.keys(mixedBatch.pointBatch.entries);
|
||||||
|
expect(keys).to.not.contain(getUid(feature));
|
||||||
|
expect(mixedBatch.pointBatch.geometriesCount).to.be(0);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('#removeFeature', () => {
|
||||||
|
beforeEach(() => {
|
||||||
|
mixedBatch.addFeature(feature);
|
||||||
|
mixedBatch.removeFeature(feature);
|
||||||
|
});
|
||||||
|
it('clears all entries in the polygon batch', () => {
|
||||||
|
const keys = Object.keys(mixedBatch.polygonBatch.entries);
|
||||||
|
expect(keys).to.have.length(0);
|
||||||
|
expect(mixedBatch.polygonBatch.verticesCount).to.be(0);
|
||||||
|
expect(mixedBatch.polygonBatch.geometriesCount).to.be(0);
|
||||||
|
expect(mixedBatch.polygonBatch.ringsCount).to.be(0);
|
||||||
|
});
|
||||||
|
it('clears all entries in the linestring batch', () => {
|
||||||
|
const keys = Object.keys(mixedBatch.lineStringBatch.entries);
|
||||||
|
expect(keys).to.have.length(0);
|
||||||
|
expect(mixedBatch.lineStringBatch.verticesCount).to.be(0);
|
||||||
|
expect(mixedBatch.lineStringBatch.geometriesCount).to.be(0);
|
||||||
|
});
|
||||||
|
it('clears all entries in the point batch', () => {
|
||||||
|
const keys = Object.keys(mixedBatch.pointBatch.entries);
|
||||||
|
expect(keys).to.have.length(0);
|
||||||
|
expect(mixedBatch.pointBatch.geometriesCount).to.be(0);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('#clear', () => {
|
||||||
|
beforeEach(() => {
|
||||||
|
const feature1 = new Feature(
|
||||||
|
new Polygon([
|
||||||
|
[
|
||||||
|
[201, 202],
|
||||||
|
[203, 204],
|
||||||
|
[205, 206],
|
||||||
|
[207, 208],
|
||||||
|
],
|
||||||
|
])
|
||||||
|
);
|
||||||
|
const feature2 = new Feature(new Point([201, 202]));
|
||||||
|
mixedBatch.addFeature(feature1);
|
||||||
|
mixedBatch.addFeature(feature2);
|
||||||
|
mixedBatch.clear();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('clears polygon batch', () => {
|
||||||
|
expect(Object.keys(mixedBatch.polygonBatch.entries)).to.have.length(0);
|
||||||
|
expect(mixedBatch.polygonBatch.geometriesCount).to.be(0);
|
||||||
|
expect(mixedBatch.polygonBatch.verticesCount).to.be(0);
|
||||||
|
expect(mixedBatch.polygonBatch.ringsCount).to.be(0);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('clears linestring batch', () => {
|
||||||
|
expect(Object.keys(mixedBatch.lineStringBatch.entries)).to.have.length(0);
|
||||||
|
expect(mixedBatch.lineStringBatch.geometriesCount).to.be(0);
|
||||||
|
expect(mixedBatch.lineStringBatch.verticesCount).to.be(0);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('clears point batch', () => {
|
||||||
|
expect(Object.keys(mixedBatch.pointBatch.entries)).to.have.length(0);
|
||||||
|
expect(mixedBatch.pointBatch.geometriesCount).to.be(0);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
Reference in New Issue
Block a user