flatgeobuf
Version:
A performant binary encoding for geographic data
8 lines • 7.81 kB
JavaScript
import{readFileSync as e}from"node:fs";import t from"jsts/org/locationtech/jts/geom/GeometryFactory.js";import a from"jsts/org/locationtech/jts/io/GeoJSONWriter.js";import o from"jsts/org/locationtech/jts/io/WKTReader.js";import{describe as r,expect as i,it as s}from"vitest";import{deserialize as n,serialize as l}from"./geojson.js";import{arrayToStream as u,takeAsync as p}from"./streams/utils.js";function y(e,t){return f([e],t)}function f(e,r){let i=new o(new t),s=new a,n=e.map(e=>s.write(i.read(e))).map((e,t)=>({type:"Feature",id:t,geometry:e,properties:{}}));if(r)for(let e of n)e.properties=r;return{type:"FeatureCollection",features:n}}r("geojson module",()=>{r("Geometry roundtrips",()=>{s("Point",async()=>{let e=y("POINT(1.2 -2.1)"),t=l(e);i(await p(n(t))).to.deep.equal(e.features)}),s("Point 3D",async()=>{let e=y("POINT Z(1.2 -2.1 10)"),t=l(e);i(await p(n(t))).to.deep.equal(e.features)}),s("Point via stream",async()=>{let e=y("POINT(1.2 -2.1)"),t=u(l(e));i(await p(n(t))).to.deep.equal(e.features)}),s("Points",async()=>{let e=f(["POINT(1.2 -2.1)","POINT(2.4 -4.8)"]);i(await p(n(l(e)))).to.deep.equal(e.features)}),s("MultiPoint",async()=>{let e=y("MULTIPOINT(10 40, 40 30, 20 20, 30 10)");i(await p(n(l(e)))).to.deep.equal(e.features)}),s("LineString",async()=>{let e=y("LINESTRING(1.2 -2.1, 2.4 -4.8)");i(await p(n(l(e)))).to.deep.equal(e.features)}),s("LineString 3D",async()=>{let e=y("LINESTRING Z(1.2 -2.1 1.1, 2.4 -4.8 1.2)");i(await p(n(l(e)))).to.deep.equal(e.features)}),s("MultiLineString",async()=>{let e=y(`MULTILINESTRING((10 10, 20 20, 10 40),
(40 40, 30 30, 40 20, 30 10), (50 50, 60 60, 50 90))`);i(await p(n(l(e)))).to.deep.equal(e.features)}),s("MultiLineStringSinglePart",async()=>{let e=y("MULTILINESTRING((1.2 -2.1, 2.4 -4.8))");i(await p(n(l(e)))).to.deep.equal(e.features)}),s("Polygon",async()=>{let e=y("POLYGON ((30 10, 40 40, 20 40, 10 20, 30 10))");i(await p(n(l(e)))).to.deep.equal(e.features)}),s("Polygon via stream",async()=>{let e=y("POLYGON ((30 10, 40 40, 20 40, 10 20, 30 10))"),t=u(l(e));i(await p(n(t))).to.deep.equal(e.features)}),s("PolygonWithHole",async()=>{let e=y(`POLYGON ((35 10, 45 45, 15 40, 10 20, 35 10),
(20 30, 35 35, 30 20, 20 30))`);i(await p(n(l(e)))).to.deep.equal(e.features)}),s("PolygonWithHole 3D",async()=>{let e=y(`POLYGON Z((35 10 3, 45 45 4, 15 40 5, 10 20 6, 35 10 7),
(20 30 3, 35 35 4, 30 20 5, 20 30 6))`);i(await p(n(l(e)))).to.deep.equal(e.features)}),s("MultiPolygon",async()=>{let e=y(`MULTIPOLYGON (((30 20, 45 40, 10 40, 30 20)),
((15 5, 40 10, 10 20, 5 10, 15 5)))`);i(await p(n(l(e)))).to.deep.equal(e.features)}),s("MultiPolygonWithHole",async()=>{let e=y(`MULTIPOLYGON (((40 40, 20 45, 45 30, 40 40)),
((20 35, 10 30, 10 10, 30 5, 45 20, 20 35), (30 20, 20 15, 20 25, 30 20)))`);i(await p(n(l(e)))).to.deep.equal(e.features)}),s("MultiPolygonSinglePart",async()=>{let e=y("MULTIPOLYGON (((30 20, 45 40, 10 40, 30 20)))");i(await p(n(l(e)))).to.deep.equal(e.features)}),s("MultiPolygonSinglePartWithHole",async()=>{let e=y(`MULTIPOLYGON (((35 10, 45 45, 15 40, 10 20, 35 10),
(20 30, 35 35, 30 20, 20 30))))`);i(await p(n(l(e)))).to.deep.equal(e.features)}),s("GeometryCollection",async()=>{let e=y("GEOMETRYCOLLECTION(POINT(4 6),LINESTRING(4 6,7 10))");i(await p(n(l(e)))).to.deep.equal(e.features)}),s("GeometryCollection 3D",async()=>{let e=y("GEOMETRYCOLLECTION Z(POINT Z(4 6 3),LINESTRING Z(4 6 4,7 10 5))");i(await p(n(l(e)))).to.deep.equal(e.features)}),s("Bahamas",async()=>{let e={type:"FeatureCollection",features:[{type:"Feature",id:0,properties:{name:"The Bahamas"},geometry:{type:"MultiPolygon",coordinates:[[[[-77.53466,23.75975],[-77.78,23.71],[-78.03405,24.28615],[-78.40848,24.57564],[-78.19087,25.2103],[-77.89,25.17],[-77.54,24.34],[-77.53466,23.75975]]],[[[-77.82,26.58],[-78.91,26.42],[-78.98,26.79],[-78.51,26.87],[-77.85,26.84],[-77.82,26.58]]],[[[-77,26.59],[-77.17255,25.87918],[-77.35641,26.00735],[-77.34,26.53],[-77.78802,26.92516],[-77.79,27.04],[-77,26.59]]]]}}]};i(await p(n(l(e)))).to.deep.equal(e.features)}),s("Heterogeneous geometries",async()=>{let e=f(["POINT(1.2 -2.1)","LINESTRING(1.2 -2.1, 2.4 -4.8)","MULTIPOLYGON (((30 20, 45 40, 10 40, 30 20)))"]);i(await p(n(l(e)))).to.deep.equal(e.features)}),s("Long feature properties",async()=>{let e={type:"FeatureCollection",features:[{type:"Feature",id:0,properties:{veryLong1:Array(10240).fill("X").join(""),veryLong2:Array(10240).fill("Y").join(""),veryLong3:Array(10240).fill("Z").join("")},geometry:{type:"Point",coordinates:[-77.53466,23.75975]}}]};i(await p(n(l(e)))).to.deep.equal(e.features)})}),r("Attribute roundtrips",()=>{s("Number",async()=>{let e=y("POINT(1 1)",{test:1});i(await p(n(l(e)))).to.deep.equal(e.features)}),s("Number with decimals",async()=>{let e=y("POINT(1 1)",{test:1.1});i(await p(n(l(e)))).to.deep.equal(e.features)}),s("NumberTwoAttribs",async()=>{let e=y("POINT(1 1)",{test1:1,test2:1});i(await p(n(l(e)))).to.deep.equal(e.features)}),s("NumberWithDecimal",async()=>{let e=y("POINT(1 1)",{test:1.1});i(await p(n(l(e)))).to.deep.equal(e.features)}),s("Boolean",async()=>{let e=y("POINT(1 1)",{test:!0});i(await p(n(l(e)))).to.deep.equal(e.features)}),s("String",async()=>{let e=y("POINT(1 1)",{test:"test"});i(await p(n(l(e)))).to.deep.equal(e.features)}),s("Mixed",async()=>{let e=y("POINT(1 1)",{test1:1,test2:1.1,test3:"test",test4:!0});i(await p(n(l(e)))).to.deep.equal(e.features)}),s("Json Value",async()=>{let e=y("POINT(1 1)",{test:{hello:"world"}});i(await p(n(l(e)))).to.deep.equal(e.features)}),s("Binary",async()=>{let e=y("POINT(1 1)",{test:new Uint8Array([116,101,115,116])});i(await p(n(l(e)))).to.deep.equal(e.features)})}),r("Prepared buffers tests",()=>{s("Should parse countries fgb produced from GDAL byte array",async()=>{let t,a=new Uint8Array(e("./test/data/countries.fgb")),o=await p(n(a,void 0,e=>t=e));for(let e of(i(t?.crs?.code).to.eq(4326),i(o.length).to.eq(179),o))i(e.geometry.coordinates[0].length).to.be.greaterThan(0)}),s("Should parse countries fgb produced from GDAL stream filter",async()=>{let e=await p(n("https://flatgeobuf.septima.dk/countries.fgb",{minX:12,minY:56,maxX:12,maxY:56},void 0,!1));for(let t of(i(e.length).to.eq(3),e))i(t.geometry.coordinates[0].length).to.be.greaterThan(0)}),s("Should parse countries fgb produced from GDAL stream no filter",async()=>{let t=u(new Uint8Array(e("./test/data/countries.fgb")).buffer),a=await p(n(t));for(let e of(i(a.length).to.eq(179),a))i(e.geometry.coordinates[0].length).to.be.greaterThan(0)}),s("Should parse UScounties fgb produced from GDAL",async()=>{let t=new Uint8Array(e("./test/data/UScounties.fgb")),a=await p(n(t));for(let e of(i(a.length).to.eq(3221),a))i(e.geometry.coordinates[0].length).to.be.greaterThan(0)}),s("Should parse heterogeneous fgb produced from Rust impl",async()=>{let t=new Uint8Array(e("./test/data/heterogeneous.fgb")),a=await p(n(t)),o=[{type:"Feature",id:0,properties:{},geometry:{type:"Point",coordinates:[1.2,-2.1]}},{type:"Feature",id:1,properties:{},geometry:{type:"LineString",coordinates:[[1.2,-2.1],[2.4,-4.8]]}},{type:"Feature",id:2,properties:{},geometry:{type:"MultiPolygon",coordinates:[[[[30,20],[45,40],[10,40],[30,20]]]]}}];i(a).to.deep.equal(o)})}),r("Spatial filter",()=>{s("Should filter by rect when using byte array",async()=>{let t=new Uint8Array(e("./test/data/UScounties.fgb")),a=await p(n(t,{minX:-106.88,minY:36.75,maxX:-101.11,maxY:41.24}));i(a.length).toBe(86),i(a.slice(0,4).map(e=>`${e.properties?.NAME}, ${e.properties?.STATE}`)).toEqual(["Texas, OK","Cimarron, OK","Taos, NM","Colfax, NM"])}),s("Should filter overlapping multipoly as expected",async()=>{let t=new Uint8Array(e("./test/data/mp_overlapping.fgb"));i((await p(n(t,{minX:14.9,minY:55.1,maxX:14.9,maxY:55.1}))).length).toBe(2)})})});
//# sourceMappingURL=geojson.spec.js.map