1034 lines
30 KiB
JavaScript
1034 lines
30 KiB
JavaScript
import Circle from '../../../../../src/ol/geom/Circle.js';
|
|
import Feature from '../../../../../src/ol/Feature.js';
|
|
import GeoJSON from '../../../../../src/ol/format/GeoJSON.js';
|
|
import GeometryCollection from '../../../../../src/ol/geom/GeometryCollection.js';
|
|
import LineString from '../../../../../src/ol/geom/LineString.js';
|
|
import LinearRing from '../../../../../src/ol/geom/LinearRing.js';
|
|
import MultiPolygon from '../../../../../src/ol/geom/MultiPolygon.js';
|
|
import Point from '../../../../../src/ol/geom/Point.js';
|
|
import Polygon from '../../../../../src/ol/geom/Polygon.js';
|
|
import {
|
|
Projection,
|
|
fromLonLat,
|
|
get as getProjection,
|
|
toLonLat,
|
|
transform,
|
|
} from '../../../../../src/ol/proj.js';
|
|
import {equals} from '../../../../../src/ol/extent.js';
|
|
|
|
describe('ol.format.GeoJSON', function () {
|
|
let format;
|
|
beforeEach(function () {
|
|
format = new GeoJSON();
|
|
});
|
|
|
|
const pointGeoJSON = {
|
|
'type': 'Feature',
|
|
'geometry': {
|
|
'type': 'Point',
|
|
'coordinates': [102.0, 0.5],
|
|
},
|
|
'properties': {
|
|
'prop0': 'value0',
|
|
},
|
|
};
|
|
|
|
const nullGeometryGeoJSON = {
|
|
'type': 'Feature',
|
|
'geometry': null,
|
|
'properties': {
|
|
'prop0': 'value0',
|
|
},
|
|
};
|
|
|
|
const zeroIdGeoJSON = {
|
|
'type': 'Feature',
|
|
'id': 0,
|
|
'geometry': null,
|
|
'properties': {
|
|
'prop0': 'value0',
|
|
},
|
|
};
|
|
|
|
const lineStringGeoJSON = {
|
|
'type': 'Feature',
|
|
'geometry': {
|
|
'type': 'LineString',
|
|
'coordinates': [
|
|
[102.0, 0.0],
|
|
[103.0, 1.0],
|
|
[104.0, 0.0],
|
|
[105.0, 1.0],
|
|
],
|
|
},
|
|
'properties': {
|
|
'prop0': 'value0',
|
|
'prop1': 0.0,
|
|
},
|
|
};
|
|
|
|
const polygonGeoJSON = {
|
|
'type': 'Feature',
|
|
'geometry': {
|
|
'type': 'Polygon',
|
|
'coordinates': [
|
|
[
|
|
[100.0, 0.0],
|
|
[100.0, 1.0],
|
|
[101.0, 1.0],
|
|
[101.0, 0.0],
|
|
],
|
|
],
|
|
},
|
|
'properties': {
|
|
'prop0': 'value0',
|
|
'prop1': {'this': 'that'},
|
|
},
|
|
};
|
|
|
|
const featureCollectionGeoJSON = {
|
|
'type': 'FeatureCollection',
|
|
'features': [pointGeoJSON, lineStringGeoJSON, polygonGeoJSON],
|
|
};
|
|
|
|
const data = {
|
|
'type': 'FeatureCollection',
|
|
'features': [
|
|
{
|
|
'type': 'Feature',
|
|
'properties': {
|
|
'LINK_ID': 573730499,
|
|
'RP_TYPE': 14,
|
|
'RP_FUNC': 0,
|
|
'DIRECTION': 2,
|
|
'LOGKOD': '',
|
|
'CHANGED': '',
|
|
'USERID': '',
|
|
'ST_NAME': '',
|
|
'L_REFADDR': '',
|
|
'L_NREFADDR': '',
|
|
'R_REFADDR': '',
|
|
'R_NREFADDR': '',
|
|
'SPEED_CAT': '7',
|
|
'ZIPCODE': '59330',
|
|
'SHAPE_LEN': 46.3826,
|
|
},
|
|
'geometry': {
|
|
'type': 'LineString',
|
|
'coordinates': [
|
|
[1549497.66985, 6403707.96],
|
|
[1549491.1, 6403710.1],
|
|
[1549488.03995, 6403716.7504],
|
|
[1549488.5401, 6403724.5504],
|
|
[1549494.37985, 6403733.54],
|
|
[1549499.6799, 6403738.0504],
|
|
[1549506.22, 6403739.2504],
|
|
],
|
|
},
|
|
},
|
|
{
|
|
'type': 'Feature',
|
|
'properties': {
|
|
'LINK_ID': 30760556,
|
|
'RP_TYPE': 12,
|
|
'RP_FUNC': 1,
|
|
'DIRECTION': 0,
|
|
'LOGKOD': '',
|
|
'CHANGED': '',
|
|
'USERID': '',
|
|
'ST_NAME': 'BRUNNSGATAN',
|
|
'L_REFADDR': '24',
|
|
'L_NREFADDR': '16',
|
|
'R_REFADDR': '',
|
|
'R_NREFADDR': '',
|
|
'SPEED_CAT': '7',
|
|
'ZIPCODE': '59330',
|
|
'SHAPE_LEN': 70.3106,
|
|
},
|
|
'geometry': {
|
|
'type': 'LineString',
|
|
'coordinates': [
|
|
[1549754.2769, 6403854.8024],
|
|
[1549728.45985, 6403920.2],
|
|
],
|
|
},
|
|
},
|
|
],
|
|
};
|
|
|
|
describe('#readFeature', function () {
|
|
it('can read a single point feature', function () {
|
|
const feature = format.readFeature(pointGeoJSON);
|
|
expect(feature).to.be.an(Feature);
|
|
const geometry = feature.getGeometry();
|
|
expect(geometry).to.be.an(Point);
|
|
expect(geometry.getCoordinates()).to.eql([102.0, 0.5]);
|
|
expect(feature.get('prop0')).to.be('value0');
|
|
});
|
|
|
|
it('can read a single point geometry as a feature', function () {
|
|
const feature = format.readFeature(pointGeoJSON.geometry);
|
|
expect(feature).to.be.an(Feature);
|
|
const geometry = feature.getGeometry();
|
|
expect(geometry).to.be.an(Point);
|
|
expect(geometry.getCoordinates()).to.eql([102.0, 0.5]);
|
|
});
|
|
|
|
it('can read a single line string feature', function () {
|
|
const feature = format.readFeature(lineStringGeoJSON);
|
|
expect(feature).to.be.an(Feature);
|
|
const geometry = feature.getGeometry();
|
|
expect(geometry).to.be.an(LineString);
|
|
expect(geometry.getCoordinates()).to.eql([
|
|
[102.0, 0.0],
|
|
[103.0, 1.0],
|
|
[104.0, 0.0],
|
|
[105.0, 1.0],
|
|
]);
|
|
expect(feature.get('prop0')).to.be('value0');
|
|
expect(feature.get('prop1')).to.be(0.0);
|
|
});
|
|
|
|
it('can read a single polygon feature', function () {
|
|
const feature = format.readFeature(polygonGeoJSON);
|
|
expect(feature).to.be.an(Feature);
|
|
const geometry = feature.getGeometry();
|
|
expect(geometry).to.be.an(Polygon);
|
|
expect(geometry.getCoordinates()).to.eql([
|
|
[
|
|
[100.0, 0.0],
|
|
[100.0, 1.0],
|
|
[101.0, 1.0],
|
|
[101.0, 0.0],
|
|
],
|
|
]);
|
|
expect(feature.get('prop0')).to.be('value0');
|
|
expect(feature.get('prop1')).to.eql({'this': 'that'});
|
|
});
|
|
|
|
it('can read a feature with null geometry', function () {
|
|
const feature = format.readFeature(nullGeometryGeoJSON);
|
|
expect(feature).to.be.an(Feature);
|
|
const geometry = feature.getGeometry();
|
|
expect(geometry).to.eql(null);
|
|
expect(feature.get('prop0')).to.be('value0');
|
|
});
|
|
|
|
it('can read a feature with id equal to 0', function () {
|
|
const feature = format.readFeature(zeroIdGeoJSON);
|
|
expect(feature).to.be.an(Feature);
|
|
expect(feature.getId()).to.be(0);
|
|
});
|
|
|
|
it('can read a feature collection', function () {
|
|
const features = format.readFeatures(featureCollectionGeoJSON);
|
|
expect(features).to.have.length(3);
|
|
expect(features[0].getGeometry()).to.be.an(Point);
|
|
expect(features[1].getGeometry()).to.be.an(LineString);
|
|
expect(features[2].getGeometry()).to.be.an(Polygon);
|
|
});
|
|
|
|
it('can read and transform a point', function () {
|
|
const feature = format.readFeatures(pointGeoJSON, {
|
|
featureProjection: 'EPSG:3857',
|
|
});
|
|
expect(feature[0].getGeometry()).to.be.an(Point);
|
|
expect(feature[0].getGeometry().getCoordinates()).to.eql(
|
|
transform([102.0, 0.5], 'EPSG:4326', 'EPSG:3857')
|
|
);
|
|
});
|
|
|
|
it('uses featureProjection passed to the constructor', function () {
|
|
const format = new GeoJSON({featureProjection: 'EPSG:3857'});
|
|
const feature = format.readFeatures(pointGeoJSON);
|
|
expect(feature[0].getGeometry()).to.be.an(Point);
|
|
expect(feature[0].getGeometry().getCoordinates()).to.eql(
|
|
transform([102.0, 0.5], 'EPSG:4326', 'EPSG:3857')
|
|
);
|
|
});
|
|
|
|
it('gives precedence to options passed to the read method', function () {
|
|
const format = new GeoJSON({featureProjection: 'EPSG:1234'});
|
|
const feature = format.readFeatures(pointGeoJSON, {
|
|
featureProjection: 'EPSG:3857',
|
|
});
|
|
expect(feature[0].getGeometry()).to.be.an(Point);
|
|
expect(feature[0].getGeometry().getCoordinates()).to.eql(
|
|
transform([102.0, 0.5], 'EPSG:4326', 'EPSG:3857')
|
|
);
|
|
});
|
|
|
|
it('can read and transform a feature collection', function () {
|
|
const features = format.readFeatures(featureCollectionGeoJSON, {
|
|
featureProjection: 'EPSG:3857',
|
|
});
|
|
expect(features[0].getGeometry()).to.be.an(Point);
|
|
expect(features[0].getGeometry().getCoordinates()).to.eql(
|
|
transform([102.0, 0.5], 'EPSG:4326', 'EPSG:3857')
|
|
);
|
|
expect(features[1].getGeometry().getCoordinates()).to.eql([
|
|
transform([102.0, 0.0], 'EPSG:4326', 'EPSG:3857'),
|
|
transform([103.0, 1.0], 'EPSG:4326', 'EPSG:3857'),
|
|
transform([104.0, 0.0], 'EPSG:4326', 'EPSG:3857'),
|
|
transform([105.0, 1.0], 'EPSG:4326', 'EPSG:3857'),
|
|
]);
|
|
expect(features[2].getGeometry().getCoordinates()).to.eql([
|
|
[
|
|
transform([100.0, 0.0], 'EPSG:4326', 'EPSG:3857'),
|
|
transform([100.0, 1.0], 'EPSG:4326', 'EPSG:3857'),
|
|
transform([101.0, 1.0], 'EPSG:4326', 'EPSG:3857'),
|
|
transform([101.0, 0.0], 'EPSG:4326', 'EPSG:3857'),
|
|
],
|
|
]);
|
|
});
|
|
|
|
it('can create a feature with a specific geometryName', function () {
|
|
const feature = new GeoJSON({geometryName: 'the_geom'}).readFeature(
|
|
pointGeoJSON
|
|
);
|
|
expect(feature.getGeometryName()).to.be('the_geom');
|
|
expect(feature.getGeometry()).to.be.an(Point);
|
|
});
|
|
|
|
it('transforms tile pixel coordinates', function () {
|
|
const geojson = {
|
|
type: 'Feature',
|
|
geometry: {
|
|
type: 'Point',
|
|
coordinates: [1024, 1024],
|
|
},
|
|
};
|
|
const format = new GeoJSON({
|
|
dataProjection: new Projection({
|
|
code: '',
|
|
units: 'tile-pixels',
|
|
extent: [0, 0, 4096, 4096],
|
|
}),
|
|
});
|
|
const feature = format.readFeature(geojson, {
|
|
extent: [-180, -90, 180, 90],
|
|
featureProjection: 'EPSG:3857',
|
|
});
|
|
expect(feature.getGeometry().getCoordinates()).to.eql([-135, 45]);
|
|
});
|
|
});
|
|
|
|
describe('#readFeatures', function () {
|
|
it('parses feature collection', function () {
|
|
const str = JSON.stringify(data);
|
|
const array = format.readFeatures(str);
|
|
|
|
expect(array.length).to.be(2);
|
|
|
|
const first = array[0];
|
|
expect(first).to.be.a(Feature);
|
|
expect(first.get('LINK_ID')).to.be(573730499);
|
|
const firstGeom = first.getGeometry();
|
|
expect(firstGeom).to.be.a(LineString);
|
|
|
|
const second = array[1];
|
|
expect(second).to.be.a(Feature);
|
|
expect(second.get('ST_NAME')).to.be('BRUNNSGATAN');
|
|
const secondGeom = second.getGeometry();
|
|
expect(secondGeom).to.be.a(LineString);
|
|
});
|
|
|
|
it('can parse a polygon geometry as an array of one feature', function () {
|
|
const features = format.readFeatures(polygonGeoJSON);
|
|
expect(features).to.be.an(Array);
|
|
expect(features).to.have.length(1);
|
|
const geometry = features[0].getGeometry();
|
|
expect(geometry).to.be.an(Polygon);
|
|
});
|
|
|
|
it('parses countries.geojson', function (done) {
|
|
afterLoadText(
|
|
'spec/ol/format/geojson/countries.geojson',
|
|
function (text) {
|
|
const result = format.readFeatures(text);
|
|
expect(result.length).to.be(179);
|
|
|
|
const first = result[0];
|
|
expect(first).to.be.a(Feature);
|
|
expect(first.get('name')).to.be('Afghanistan');
|
|
expect(first.getId()).to.be('AFG');
|
|
const firstGeom = first.getGeometry();
|
|
expect(firstGeom).to.be.a(Polygon);
|
|
expect(
|
|
equals(firstGeom.getExtent(), [
|
|
60.52843,
|
|
29.318572,
|
|
75.158028,
|
|
38.486282,
|
|
])
|
|
).to.be(true);
|
|
|
|
const last = result[178];
|
|
expect(last).to.be.a(Feature);
|
|
expect(last.get('name')).to.be('Zimbabwe');
|
|
expect(last.getId()).to.be('ZWE');
|
|
const lastGeom = last.getGeometry();
|
|
expect(lastGeom).to.be.a(Polygon);
|
|
expect(
|
|
equals(lastGeom.getExtent(), [
|
|
25.264226,
|
|
-22.271612,
|
|
32.849861,
|
|
-15.507787,
|
|
])
|
|
).to.be(true);
|
|
done();
|
|
}
|
|
);
|
|
});
|
|
|
|
it('generates an array of features for Feature', function () {
|
|
const format = new GeoJSON();
|
|
const json = {
|
|
type: 'Feature',
|
|
properties: {
|
|
bam: 'baz',
|
|
},
|
|
geometry: {
|
|
type: 'LineString',
|
|
coordinates: [
|
|
[1, 2],
|
|
[3, 4],
|
|
],
|
|
},
|
|
};
|
|
const features = format.readFeatures(json);
|
|
|
|
expect(features.length).to.be(1);
|
|
|
|
const first = features[0];
|
|
expect(first).to.be.a(Feature);
|
|
expect(first.get('bam')).to.be('baz');
|
|
expect(first.getGeometry()).to.be.a(LineString);
|
|
|
|
expect(format.readProjection(json)).to.be(getProjection('EPSG:4326'));
|
|
});
|
|
});
|
|
|
|
describe('#readGeometry', function () {
|
|
it('parses point', function () {
|
|
const str = JSON.stringify({
|
|
type: 'Point',
|
|
coordinates: [10, 20],
|
|
});
|
|
|
|
const obj = format.readGeometry(str);
|
|
expect(obj).to.be.a(Point);
|
|
expect(obj.getCoordinates()).to.eql([10, 20]);
|
|
expect(obj.getLayout()).to.eql('XY');
|
|
});
|
|
|
|
it('parses linestring', function () {
|
|
const str = JSON.stringify({
|
|
type: 'LineString',
|
|
coordinates: [
|
|
[10, 20],
|
|
[30, 40],
|
|
],
|
|
});
|
|
|
|
const obj = format.readGeometry(str);
|
|
expect(obj).to.be.a(LineString);
|
|
expect(obj.getCoordinates()).to.eql([
|
|
[10, 20],
|
|
[30, 40],
|
|
]);
|
|
expect(obj.getLayout()).to.eql('XY');
|
|
});
|
|
|
|
it('parses XYZ linestring', function () {
|
|
const str = JSON.stringify({
|
|
type: 'LineString',
|
|
coordinates: [
|
|
[10, 20, 1534],
|
|
[30, 40, 1420],
|
|
],
|
|
});
|
|
|
|
const obj = format.readGeometry(str);
|
|
expect(obj).to.be.a(LineString);
|
|
expect(obj.getLayout()).to.eql('XYZ');
|
|
expect(obj.getCoordinates()).to.eql([
|
|
[10, 20, 1534],
|
|
[30, 40, 1420],
|
|
]);
|
|
});
|
|
|
|
it('parses polygon', function () {
|
|
const outer = [
|
|
[0, 0],
|
|
[10, 0],
|
|
[10, 10],
|
|
[0, 10],
|
|
[0, 0],
|
|
];
|
|
const inner1 = [
|
|
[1, 1],
|
|
[2, 1],
|
|
[2, 2],
|
|
[1, 2],
|
|
[1, 1],
|
|
];
|
|
const inner2 = [
|
|
[8, 8],
|
|
[9, 8],
|
|
[9, 9],
|
|
[8, 9],
|
|
[8, 8],
|
|
];
|
|
const str = JSON.stringify({
|
|
type: 'Polygon',
|
|
coordinates: [outer, inner1, inner2],
|
|
});
|
|
|
|
const obj = format.readGeometry(str);
|
|
expect(obj).to.be.a(Polygon);
|
|
expect(obj.getLayout()).to.eql('XY');
|
|
const rings = obj.getLinearRings();
|
|
expect(rings.length).to.be(3);
|
|
expect(rings[0]).to.be.a(LinearRing);
|
|
expect(rings[1]).to.be.a(LinearRing);
|
|
expect(rings[2]).to.be.a(LinearRing);
|
|
});
|
|
|
|
it('parses geometry collection', function () {
|
|
const str = JSON.stringify({
|
|
type: 'GeometryCollection',
|
|
geometries: [
|
|
{type: 'Point', coordinates: [10, 20]},
|
|
{
|
|
type: 'LineString',
|
|
coordinates: [
|
|
[30, 40],
|
|
[50, 60],
|
|
],
|
|
},
|
|
],
|
|
});
|
|
|
|
const geometryCollection = format.readGeometry(str);
|
|
expect(geometryCollection).to.be.an(GeometryCollection);
|
|
const array = geometryCollection.getGeometries();
|
|
expect(array.length).to.be(2);
|
|
expect(array[0]).to.be.a(Point);
|
|
expect(array[0].getLayout()).to.eql('XY');
|
|
expect(array[1]).to.be.a(LineString);
|
|
expect(array[1].getLayout()).to.eql('XY');
|
|
});
|
|
});
|
|
|
|
describe('#readProjection', function () {
|
|
it('reads named crs from top-level object', function () {
|
|
const json = {
|
|
type: 'FeatureCollection',
|
|
crs: {
|
|
type: 'name',
|
|
properties: {
|
|
name: 'EPSG:3857',
|
|
},
|
|
},
|
|
features: [
|
|
{
|
|
type: 'Feature',
|
|
properties: {
|
|
foo: 'bar',
|
|
},
|
|
geometry: {
|
|
type: 'Point',
|
|
coordinates: [1, 2],
|
|
},
|
|
},
|
|
{
|
|
type: 'Feature',
|
|
properties: {
|
|
bam: 'baz',
|
|
},
|
|
geometry: {
|
|
type: 'LineString',
|
|
coordinates: [
|
|
[1, 2],
|
|
[3, 4],
|
|
],
|
|
},
|
|
},
|
|
],
|
|
};
|
|
const features = format.readFeatures(json);
|
|
|
|
expect(features.length).to.be(2);
|
|
|
|
const first = features[0];
|
|
expect(first).to.be.a(Feature);
|
|
expect(first.get('foo')).to.be('bar');
|
|
expect(first.getGeometry()).to.be.a(Point);
|
|
|
|
const second = features[1];
|
|
expect(second).to.be.a(Feature);
|
|
expect(second.get('bam')).to.be('baz');
|
|
expect(second.getGeometry()).to.be.a(LineString);
|
|
|
|
expect(format.readProjection(json)).to.be(getProjection('EPSG:3857'));
|
|
});
|
|
|
|
it('accepts null crs', function () {
|
|
const json = {
|
|
type: 'FeatureCollection',
|
|
crs: null,
|
|
features: [
|
|
{
|
|
type: 'Feature',
|
|
properties: {
|
|
foo: 'bar',
|
|
},
|
|
geometry: {
|
|
type: 'Point',
|
|
coordinates: [1, 2],
|
|
},
|
|
},
|
|
{
|
|
type: 'Feature',
|
|
properties: {
|
|
bam: 'baz',
|
|
},
|
|
geometry: {
|
|
type: 'LineString',
|
|
coordinates: [
|
|
[1, 2],
|
|
[3, 4],
|
|
],
|
|
},
|
|
},
|
|
],
|
|
};
|
|
const features = format.readFeatures(json);
|
|
|
|
expect(features.length).to.be(2);
|
|
|
|
const first = features[0];
|
|
expect(first).to.be.a(Feature);
|
|
expect(first.get('foo')).to.be('bar');
|
|
expect(first.getGeometry()).to.be.a(Point);
|
|
|
|
const second = features[1];
|
|
expect(second).to.be.a(Feature);
|
|
expect(second.get('bam')).to.be('baz');
|
|
expect(second.getGeometry()).to.be.a(LineString);
|
|
|
|
expect(format.readProjection(json)).to.be(getProjection('EPSG:4326'));
|
|
});
|
|
});
|
|
|
|
describe('#writeFeatures', function () {
|
|
it('encodes feature collection', function () {
|
|
const str = JSON.stringify(data);
|
|
const array = format.readFeatures(str);
|
|
const geojson = format.writeFeaturesObject(array);
|
|
const result = format.readFeatures(geojson);
|
|
expect(array.length).to.equal(result.length);
|
|
let got, exp, gotProp, expProp;
|
|
for (let i = 0, ii = array.length; i < ii; ++i) {
|
|
got = array[i];
|
|
exp = result[i];
|
|
expect(got.getGeometry().getCoordinates()).to.eql(
|
|
exp.getGeometry().getCoordinates()
|
|
);
|
|
gotProp = got.getProperties();
|
|
delete gotProp.geometry;
|
|
expProp = exp.getProperties();
|
|
delete expProp.geometry;
|
|
expect(gotProp).to.eql(expProp);
|
|
}
|
|
});
|
|
|
|
it('transforms and encodes feature collection', function () {
|
|
const str = JSON.stringify(data);
|
|
const array = format.readFeatures(str);
|
|
const geojson = format.writeFeatures(array, {
|
|
featureProjection: 'EPSG:3857',
|
|
});
|
|
const result = format.readFeatures(geojson);
|
|
let got, exp;
|
|
for (let i = 0, ii = array.length; i < ii; ++i) {
|
|
got = array[i];
|
|
exp = result[i];
|
|
expect(
|
|
got.getGeometry().transform('EPSG:3857', 'EPSG:4326').getCoordinates()
|
|
).to.eql(exp.getGeometry().getCoordinates());
|
|
}
|
|
});
|
|
|
|
it('writes out a feature with a different geometryName correctly', function () {
|
|
const feature = new Feature({'foo': 'bar'});
|
|
feature.setGeometryName('mygeom');
|
|
feature.setGeometry(new Point([5, 10]));
|
|
const geojson = format.writeFeaturesObject([feature]);
|
|
expect(geojson.features[0].properties.mygeom).to.eql(undefined);
|
|
});
|
|
|
|
it('writes out a feature without properties correctly', function () {
|
|
const feature = new Feature(new Point([5, 10]));
|
|
const geojson = format.writeFeatureObject(feature);
|
|
expect(geojson.properties).to.eql(null);
|
|
expect(geojson.geometry).to.eql({type: 'Point', coordinates: [5, 10]});
|
|
});
|
|
|
|
it('writes out a feature with only non-geometry properties correctly', function () {
|
|
const feature = new Feature({foo: 'bar'});
|
|
const geojson = format.writeFeatureObject(feature);
|
|
expect(geojson.geometry).to.eql(null);
|
|
expect(geojson.properties).to.eql({foo: 'bar'});
|
|
});
|
|
|
|
it('writes out a feature with deleted properties correctly', function () {
|
|
const feature = new Feature({foo: 'bar'});
|
|
feature.unset('foo');
|
|
const geojson = format.writeFeatureObject(feature);
|
|
expect(geojson.geometry).to.eql(null);
|
|
expect(geojson.properties).to.eql(null);
|
|
});
|
|
|
|
it('writes out a feature without geometry correctly', function () {
|
|
const feature = new Feature();
|
|
const geojson = format.writeFeatureObject(feature);
|
|
expect(geojson.geometry).to.eql(null);
|
|
});
|
|
|
|
it('writes out a feature with id equal to 0 correctly', function () {
|
|
const feature = new Feature();
|
|
feature.setId(0);
|
|
const geojson = format.writeFeatureObject(feature);
|
|
expect(geojson.id).to.eql(0);
|
|
});
|
|
});
|
|
|
|
describe('#writeGeometry', function () {
|
|
it('encodes point', function () {
|
|
const point = new Point([10, 20]);
|
|
const geojson = format.writeGeometry(point);
|
|
expect(point.getCoordinates()).to.eql(
|
|
format.readGeometry(geojson).getCoordinates()
|
|
);
|
|
});
|
|
|
|
it('accepts featureProjection', function () {
|
|
const point = new Point(fromLonLat([10, 20]));
|
|
const geojson = format.writeGeometry(point, {
|
|
featureProjection: 'EPSG:3857',
|
|
});
|
|
const obj = JSON.parse(geojson);
|
|
expect(obj.coordinates).to.eql(toLonLat(point.getCoordinates()));
|
|
});
|
|
|
|
it('respects featureProjection passed to constructor', function () {
|
|
const format = new GeoJSON({featureProjection: 'EPSG:3857'});
|
|
const point = new Point(fromLonLat([10, 20]));
|
|
const geojson = format.writeGeometry(point);
|
|
const obj = JSON.parse(geojson);
|
|
expect(obj.coordinates).to.eql(toLonLat(point.getCoordinates()));
|
|
});
|
|
|
|
it('encodes linestring', function () {
|
|
const linestring = new LineString([
|
|
[10, 20],
|
|
[30, 40],
|
|
]);
|
|
const geojson = format.writeGeometry(linestring);
|
|
expect(linestring.getCoordinates()).to.eql(
|
|
format.readGeometry(geojson).getCoordinates()
|
|
);
|
|
});
|
|
|
|
it('encodes polygon', function () {
|
|
const outer = [
|
|
[0, 0],
|
|
[10, 0],
|
|
[10, 10],
|
|
[0, 10],
|
|
[0, 0],
|
|
];
|
|
const inner1 = [
|
|
[1, 1],
|
|
[2, 1],
|
|
[2, 2],
|
|
[1, 2],
|
|
[1, 1],
|
|
];
|
|
const inner2 = [
|
|
[8, 8],
|
|
[9, 8],
|
|
[9, 9],
|
|
[8, 9],
|
|
[8, 8],
|
|
];
|
|
const polygon = new Polygon([outer, inner1, inner2]);
|
|
const geojson = format.writeGeometry(polygon);
|
|
expect(polygon.getCoordinates()).to.eql(
|
|
format.readGeometry(geojson).getCoordinates()
|
|
);
|
|
});
|
|
|
|
it('maintains coordinate order by default', function () {
|
|
const cw = [
|
|
[-180, -90],
|
|
[-180, 90],
|
|
[180, 90],
|
|
[180, -90],
|
|
[-180, -90],
|
|
];
|
|
const ccw = [
|
|
[-180, -90],
|
|
[180, -90],
|
|
[180, 90],
|
|
[-180, 90],
|
|
[-180, -90],
|
|
];
|
|
|
|
const right = new Polygon([ccw, cw]);
|
|
const rightMulti = new MultiPolygon([[ccw, cw]]);
|
|
const left = new Polygon([cw, ccw]);
|
|
const leftMulti = new MultiPolygon([[cw, ccw]]);
|
|
|
|
const rightObj = {
|
|
type: 'Polygon',
|
|
coordinates: [ccw, cw],
|
|
};
|
|
|
|
const rightMultiObj = {
|
|
type: 'MultiPolygon',
|
|
coordinates: [[ccw, cw]],
|
|
};
|
|
|
|
const leftObj = {
|
|
type: 'Polygon',
|
|
coordinates: [cw, ccw],
|
|
};
|
|
|
|
const leftMultiObj = {
|
|
type: 'MultiPolygon',
|
|
coordinates: [[cw, ccw]],
|
|
};
|
|
|
|
expect(JSON.parse(format.writeGeometry(right))).to.eql(rightObj);
|
|
expect(JSON.parse(format.writeGeometry(rightMulti))).to.eql(
|
|
rightMultiObj
|
|
);
|
|
expect(JSON.parse(format.writeGeometry(left))).to.eql(leftObj);
|
|
expect(JSON.parse(format.writeGeometry(leftMulti))).to.eql(leftMultiObj);
|
|
});
|
|
|
|
it('allows serializing following the right-hand rule', function () {
|
|
const cw = [
|
|
[-180, -90],
|
|
[-180, 90],
|
|
[180, 90],
|
|
[180, -90],
|
|
[-180, -90],
|
|
];
|
|
const ccw = [
|
|
[-180, -90],
|
|
[180, -90],
|
|
[180, 90],
|
|
[-180, 90],
|
|
[-180, -90],
|
|
];
|
|
const right = new Polygon([ccw, cw]);
|
|
const rightMulti = new MultiPolygon([[ccw, cw]]);
|
|
const left = new Polygon([cw, ccw]);
|
|
const leftMulti = new MultiPolygon([[cw, ccw]]);
|
|
|
|
const rightObj = {
|
|
type: 'Polygon',
|
|
coordinates: [ccw, cw],
|
|
};
|
|
|
|
const rightMultiObj = {
|
|
type: 'MultiPolygon',
|
|
coordinates: [[ccw, cw]],
|
|
};
|
|
|
|
let json = format.writeGeometry(right, {rightHanded: true});
|
|
expect(JSON.parse(json)).to.eql(rightObj);
|
|
json = format.writeGeometry(rightMulti, {rightHanded: true});
|
|
expect(JSON.parse(json)).to.eql(rightMultiObj);
|
|
|
|
json = format.writeGeometry(left, {rightHanded: true});
|
|
expect(JSON.parse(json)).to.eql(rightObj);
|
|
json = format.writeGeometry(leftMulti, {rightHanded: true});
|
|
expect(JSON.parse(json)).to.eql(rightMultiObj);
|
|
});
|
|
|
|
it('allows serializing following the left-hand rule', function () {
|
|
const cw = [
|
|
[-180, -90],
|
|
[-180, 90],
|
|
[180, 90],
|
|
[180, -90],
|
|
[-180, -90],
|
|
];
|
|
const ccw = [
|
|
[-180, -90],
|
|
[180, -90],
|
|
[180, 90],
|
|
[-180, 90],
|
|
[-180, -90],
|
|
];
|
|
const right = new Polygon([ccw, cw]);
|
|
const rightMulti = new MultiPolygon([[ccw, cw]]);
|
|
const left = new Polygon([cw, ccw]);
|
|
const leftMulti = new MultiPolygon([[cw, ccw]]);
|
|
|
|
const leftObj = {
|
|
type: 'Polygon',
|
|
coordinates: [cw, ccw],
|
|
};
|
|
|
|
const leftMultiObj = {
|
|
type: 'MultiPolygon',
|
|
coordinates: [[cw, ccw]],
|
|
};
|
|
|
|
let json = format.writeGeometry(right, {rightHanded: false});
|
|
expect(JSON.parse(json)).to.eql(leftObj);
|
|
json = format.writeGeometry(rightMulti, {rightHanded: false});
|
|
expect(JSON.parse(json)).to.eql(leftMultiObj);
|
|
|
|
json = format.writeGeometry(left, {rightHanded: false});
|
|
expect(JSON.parse(json)).to.eql(leftObj);
|
|
json = format.writeGeometry(leftMulti, {rightHanded: false});
|
|
expect(JSON.parse(json)).to.eql(leftMultiObj);
|
|
});
|
|
|
|
it('encodes geometry collection', function () {
|
|
const collection = new GeometryCollection([
|
|
new Point([10, 20]),
|
|
new LineString([
|
|
[30, 40],
|
|
[50, 60],
|
|
]),
|
|
]);
|
|
const geojson = format.writeGeometry(collection);
|
|
const got = format.readGeometry(geojson);
|
|
expect(got).to.be.an(GeometryCollection);
|
|
const gotGeometries = got.getGeometries();
|
|
const geometries = collection.getGeometries();
|
|
expect(geometries.length).to.equal(gotGeometries.length);
|
|
for (let i = 0, ii = geometries.length; i < ii; ++i) {
|
|
expect(geometries[i].getCoordinates()).to.eql(
|
|
gotGeometries[i].getCoordinates()
|
|
);
|
|
}
|
|
});
|
|
|
|
it('encodes a circle as an empty geometry collection', function () {
|
|
const circle = new Circle([0, 0], 1);
|
|
const geojson = format.writeGeometryObject(circle);
|
|
expect(geojson).to.eql({
|
|
'type': 'GeometryCollection',
|
|
'geometries': [],
|
|
});
|
|
});
|
|
|
|
it('transforms and encodes a point', function () {
|
|
const point = new Point([2, 3]);
|
|
const geojson = format.writeGeometry(point, {
|
|
featureProjection: 'EPSG:3857',
|
|
});
|
|
const newPoint = format.readGeometry(geojson, {
|
|
featureProjection: 'EPSG:3857',
|
|
});
|
|
expect(point.getCoordinates()[0]).to.roughlyEqual(
|
|
newPoint.getCoordinates()[0],
|
|
1e-8
|
|
);
|
|
expect(point.getCoordinates()[1]).to.roughlyEqual(
|
|
newPoint.getCoordinates()[1],
|
|
1e-8
|
|
);
|
|
});
|
|
|
|
it('transforms and encodes geometry collection', function () {
|
|
const collection = new GeometryCollection([
|
|
new Point([2, 3]),
|
|
new LineString([
|
|
[3, 2],
|
|
[2, 1],
|
|
]),
|
|
]);
|
|
const geojson = format.writeGeometry(collection, {
|
|
featureProjection: 'EPSG:3857',
|
|
});
|
|
const got = format.readGeometry(geojson, {
|
|
featureProjection: 'EPSG:3857',
|
|
});
|
|
const gotGeometries = got.getGeometries();
|
|
const geometries = collection.getGeometries();
|
|
expect(geometries[0].getCoordinates()[0]).to.roughlyEqual(
|
|
gotGeometries[0].getCoordinates()[0],
|
|
1e-8
|
|
);
|
|
expect(geometries[0].getCoordinates()[1]).to.roughlyEqual(
|
|
gotGeometries[0].getCoordinates()[1],
|
|
1e-8
|
|
);
|
|
expect(geometries[1].getCoordinates()[0][0]).to.roughlyEqual(
|
|
gotGeometries[1].getCoordinates()[0][0],
|
|
1e-8
|
|
);
|
|
expect(geometries[1].getCoordinates()[0][1]).to.roughlyEqual(
|
|
gotGeometries[1].getCoordinates()[0][1],
|
|
1e-8
|
|
);
|
|
});
|
|
|
|
it('truncates transformed point with decimals option', function () {
|
|
const point = new Point([2, 3]).transform('EPSG:4326', 'EPSG:3857');
|
|
const geojson = format.writeGeometry(point, {
|
|
featureProjection: 'EPSG:3857',
|
|
decimals: 2,
|
|
});
|
|
expect(format.readGeometry(geojson).getCoordinates()).to.eql([2, 3]);
|
|
});
|
|
|
|
it('truncates a linestring with decimals option', function () {
|
|
const linestring = new LineString([
|
|
[42.123456789, 38.987654321],
|
|
[43, 39],
|
|
]);
|
|
const geojson = format.writeGeometry(linestring, {
|
|
decimals: 6,
|
|
});
|
|
expect(format.readGeometry(geojson).getCoordinates()).to.eql([
|
|
[42.123457, 38.987654],
|
|
[43, 39],
|
|
]);
|
|
expect(linestring.getCoordinates()).to.eql([
|
|
[42.123456789, 38.987654321],
|
|
[43, 39],
|
|
]);
|
|
});
|
|
|
|
it('rounds a linestring with decimals option = 0', function () {
|
|
const linestring = new LineString([
|
|
[42.123456789, 38.987654321],
|
|
[43, 39],
|
|
]);
|
|
const geojson = format.writeGeometry(linestring, {
|
|
decimals: 0,
|
|
});
|
|
expect(format.readGeometry(geojson).getCoordinates()).to.eql([
|
|
[42, 39],
|
|
[43, 39],
|
|
]);
|
|
expect(linestring.getCoordinates()).to.eql([
|
|
[42.123456789, 38.987654321],
|
|
[43, 39],
|
|
]);
|
|
});
|
|
});
|
|
});
|