From 0705eb5a9afc8de4c4edf806f5ef57f0eec033f4 Mon Sep 17 00:00:00 2001 From: Vojta Tomas Date: Wed, 10 May 2023 12:02:58 +0200 Subject: [PATCH 1/2] Adding types to records --- .github/workflows/ci.yaml | 2 +- package.json | 2 +- shpts/geometry/base.ts | 2 ++ shpts/geometry/multipatch.ts | 5 +++++ shpts/geometry/multipoint.ts | 4 ++++ shpts/geometry/null.ts | 4 ++++ shpts/geometry/point.ts | 4 ++++ shpts/geometry/polygon.ts | 5 +++++ shpts/geometry/polyline.ts | 6 +++++- 9 files changed, 31 insertions(+), 3 deletions(-) diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml index 42bcbcb..765bb54 100644 --- a/.github/workflows/ci.yaml +++ b/.github/workflows/ci.yaml @@ -12,7 +12,7 @@ jobs: steps: - uses: actions/checkout@v3 - name: 'Setup Node.js' - uses: 'actions/setup-node@v1' + uses: 'actions/setup-node@v3' with: node-version: 18 - name: Install dependencies diff --git a/package.json b/package.json index d16b9c3..fa11541 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "shpts", "private": false, - "version": "1.0.5", + "version": "1.0.6", "type": "module", "repository": { "type": "git", diff --git a/shpts/geometry/base.ts b/shpts/geometry/base.ts index 39de49a..95270f7 100644 --- a/shpts/geometry/base.ts +++ b/shpts/geometry/base.ts @@ -21,6 +21,8 @@ export abstract class BaseRecord { return 4; } + abstract get type(): string; + protected static readBbox(stream: MemoryStream): BoundingBox { const xMin = stream.readDouble(true); const yMin = stream.readDouble(true); diff --git a/shpts/geometry/multipatch.ts b/shpts/geometry/multipatch.ts index c649ec6..40c2c4d 100644 --- a/shpts/geometry/multipatch.ts +++ b/shpts/geometry/multipatch.ts @@ -16,6 +16,11 @@ export class MultiPatchRecord extends BaseRingedRecord { super(coordType); } + get type() { + if (this.coords.length === 1) return 'Polygon'; + return 'MultiPolygon'; + } + static fromPresetReader(reader: ShapeReader, header: GeomHeader) { const hasZ = reader.hasZ; const hasM = reader.hasM; diff --git a/shpts/geometry/multipoint.ts b/shpts/geometry/multipoint.ts index 5af77ad..52e6c1d 100644 --- a/shpts/geometry/multipoint.ts +++ b/shpts/geometry/multipoint.ts @@ -11,6 +11,10 @@ export class MultiPointRecord extends BaseRecord { super(coordType); } + get type() { + return 'MultiPoint'; + } + static fromPresetReader(reader: ShapeReader, header: GeomHeader) { const hasZ = reader.hasZ; const hasM = reader.hasM; diff --git a/shpts/geometry/null.ts b/shpts/geometry/null.ts index c5452e1..c3cfe2b 100644 --- a/shpts/geometry/null.ts +++ b/shpts/geometry/null.ts @@ -7,6 +7,10 @@ export class ShpNullGeom extends BaseRecord { super(CoordType.NULL); } + get type() { + return 'Null'; + } + public toGeoJson(): GeoJsonGeom { throw new Error('Method cannot be implemented.'); } diff --git a/shpts/geometry/point.ts b/shpts/geometry/point.ts index c9fdccb..e0f8437 100644 --- a/shpts/geometry/point.ts +++ b/shpts/geometry/point.ts @@ -10,6 +10,10 @@ export class PointRecord extends BaseRecord { super(coordType); } + get type() { + return 'Point'; + } + static fromPresetReader(reader: ShapeReader, header: GeomHeader) { const hasZ = reader.hasZ; const hasM = reader.hasM; diff --git a/shpts/geometry/polygon.ts b/shpts/geometry/polygon.ts index d1de8ae..1a8f77c 100644 --- a/shpts/geometry/polygon.ts +++ b/shpts/geometry/polygon.ts @@ -16,6 +16,11 @@ export class PolygonRecord extends BaseRingedRecord { super(coordType); } + get type() { + if (this.coords.length === 1) return 'Polygon'; + return 'MultiPolygon'; + } + static fromPresetReader(reader: ShapeReader, header: GeomHeader) { const hasZ = reader.hasZ; const hasM = reader.hasM; diff --git a/shpts/geometry/polyline.ts b/shpts/geometry/polyline.ts index ebffb8c..fa376ef 100644 --- a/shpts/geometry/polyline.ts +++ b/shpts/geometry/polyline.ts @@ -4,13 +4,17 @@ import { BaseRingedRecord } from './base'; import { GeoJsonCoord, GeoJsonLineString, GeoJsonMultiLineString } from '@shpts/types/geojson'; import { GeomUtil } from '@shpts/utils/geometry'; import { GeomHeader } from '@shpts/types/data'; -import { MemoryStream } from '@shpts/utils/stream'; export class PolyLineRecord extends BaseRingedRecord { constructor(public coords: PolyLineCoord, coordType: CoordType) { super(coordType); } + get type() { + if (this.coords.length === 1) return 'LineString'; + return 'MultiLineString'; + } + static fromPresetReader(reader: ShapeReader, header: GeomHeader) { const hasZ = reader.hasZ; const hasM = reader.hasM; From 10ee1563afd02a6af078d158ccc586bb351634ef Mon Sep 17 00:00:00 2001 From: Vojta Tomas Date: Wed, 10 May 2023 12:10:08 +0200 Subject: [PATCH 2/2] Tests for types --- test/multipatch.test.ts | 4 ++++ test/multipoint.test.ts | 9 +++++++++ test/point.test.ts | 9 ++++++++- test/polygon.test.ts | 7 +++++++ test/polyline.test.ts | 9 +++++++++ 5 files changed, 37 insertions(+), 1 deletion(-) diff --git a/test/multipatch.test.ts b/test/multipatch.test.ts index 1115956..cce0136 100644 --- a/test/multipatch.test.ts +++ b/test/multipatch.test.ts @@ -10,6 +10,7 @@ test('Reading MultiPatchRecord with Z', async () => { expect(reader.recordCount).toEqual(1); let geom = expectGeometry(reader, 0, CoordType.XYZM, MultiPatchRecord); + expect(geom.type).toEqual('MultiPolygon'); expect(geom.coords.length).toEqual(12); let polygon = geom.coords[0]; expectRing(polygon[0], [ @@ -116,6 +117,7 @@ test('Reading MultiPatchRecord with Outer/Inner Rings', async () => { expect(reader.recordCount).toEqual(1); let geom = expectGeometry(reader, 0, CoordType.XYZM, MultiPatchRecord); + expect(geom.type).toEqual('Polygon'); expect(geom.coords.length).toBe(1); let polygon = geom.coords[0]; expect(polygon.length).toBe(3); @@ -150,6 +152,7 @@ test('Reading MultiPatchRecord with First Ring and Rings', async () => { expect(reader.recordCount).toEqual(1); let geom = expectGeometry(reader, 0, CoordType.XYZM, MultiPatchRecord); + expect(geom.type).toEqual('Polygon'); expect(geom.coords.length).toBe(1); let polygon = geom.coords[0]; expect(polygon.length).toBe(3); @@ -184,6 +187,7 @@ test('Reading MultiPatchRecord with First Ring and Rings', async () => { expect(reader.recordCount).toEqual(1); let geom = expectGeometry(reader, 0, CoordType.XYZM, MultiPatchRecord); + expect(geom.type).toEqual('MultiPolygon'); expect(geom.coords.length).toBe(3); let polygon = geom.coords[0]; expect(polygon.length).toBe(1); diff --git a/test/multipoint.test.ts b/test/multipoint.test.ts index 19ff231..ad52a2f 100644 --- a/test/multipoint.test.ts +++ b/test/multipoint.test.ts @@ -9,6 +9,7 @@ test('Reading PointRecord', async () => { const reader = await ShapeReader.fromArrayBuffer(shpBuffer, shxBuffer); let geom = expectGeometry(reader, 0, CoordType.XY, MultiPointRecord); + expect(geom.type).toEqual('MultiPoint'); expect(geom.coords.length).toBe(5); expectPointsEqual(geom.coords[0], [36.963112042621276, -129.36489649456098]); expectPointsEqual(geom.coords[1], [37.148521428162326, -118.98197090426271]); @@ -17,6 +18,7 @@ test('Reading PointRecord', async () => { expectPointsEqual(geom.coords[4], [48.273084560624625, -124.35884308495292]); geom = expectGeometry(reader, 1, CoordType.XY, MultiPointRecord); + expect(geom.type).toEqual('MultiPoint'); expect(geom.coords.length).toBe(4); expectPointsEqual(geom.coords[0], [56.060278753348484, -131.96062789213556]); expectPointsEqual(geom.coords[1], [57.72896322321782, -136.41045314512053]); @@ -24,6 +26,7 @@ test('Reading PointRecord', async () => { expectPointsEqual(geom.coords[3], [63.662063560531124, -131.21899034997142]); geom = expectGeometry(reader, 2, CoordType.XY, MultiPointRecord); + expect(geom.type).toEqual('MultiPoint'); expect(geom.coords.length).toBe(3); expectPointsEqual(geom.coords[0], [44.564896849803915, -151.05779460286274]); expectPointsEqual(geom.coords[1], [47.71685640400153, -142.3435534824339]); @@ -37,6 +40,7 @@ test('Reading PointRecord with M', async () => { const reader = await ShapeReader.fromArrayBuffer(shpBuffer, shxBuffer); let geom = expectGeometry(reader, 0, CoordType.XYM, MultiPointRecord); + expect(geom.type).toEqual('MultiPoint'); expect(geom.coords.length).toBe(5); expectPointsEqual(geom.coords[0], [88.87773999411263, -137.89372822944887, 1]); expectPointsEqual(geom.coords[1], [92.95674647601561, -143.08519102459798, 2]); @@ -45,12 +49,14 @@ test('Reading PointRecord with M', async () => { expectPointsEqual(geom.coords[4], [97.59198111454151, -141.41650655472864, 5]); geom = expectGeometry(reader, 1, CoordType.XYM, MultiPointRecord); + expect(geom.type).toEqual('MultiPoint'); expect(geom.coords.length).toBe(3); expectPointsEqual(geom.coords[0], [96.10870603021323, -121.94852107291939, 44]); expectPointsEqual(geom.coords[1], [98.33361865670565, -127.32539325360949, 55]); expectPointsEqual(geom.coords[2], [101.11475943982134, -122.69015861508353, 66]); geom = expectGeometry(reader, 2, CoordType.XYM, MultiPointRecord); + expect(geom.type).toEqual('MultiPoint'); expect(geom.coords.length).toBe(4); expectPointsEqual(geom.coords[0], [104.45212837956001, -133.2584935909228, 5]); expectPointsEqual(geom.coords[1], [106.86245039159343, -136.96668130174362, 55]); @@ -65,6 +71,7 @@ test('Reading PointRecord with Z', async () => { const reader = await ShapeReader.fromArrayBuffer(shpBuffer, shxBuffer); let geom = expectGeometry(reader, 0, CoordType.XYZM, MultiPointRecord); + expect(geom.type).toEqual('MultiPoint'); expect(geom.coords.length).toBe(6); expectPointsEqual(geom.coords[0], [106.12081284942929, -160.14285449437375, 0, NaN]); expectPointsEqual(geom.coords[1], [106.86245039159343, -155.32221047030666, 0, NaN]); @@ -74,10 +81,12 @@ test('Reading PointRecord with Z', async () => { expectPointsEqual(geom.coords[5], [114.09341642769414, -160.3282638799148, 0, NaN]); geom = expectGeometry(reader, 1, CoordType.XYZM, MultiPointRecord); + expect(geom.type).toEqual('MultiPoint'); expect(geom.coords.length).toBe(1); expectPointsEqual(geom.coords[0], [110.01440994579121, -149.57451951853437, -10, -10]); geom = expectGeometry(reader, 2, CoordType.XYZM, MultiPointRecord); + expect(geom.type).toEqual('MultiPoint'); expect(geom.coords.length).toBe(3); expectPointsEqual(geom.coords[0], [89.06314937965368, -154.02434477151942, 22, -10]); expectPointsEqual(geom.coords[1], [91.8442901627692, -161.81153896424308, 33, -20]); diff --git a/test/point.test.ts b/test/point.test.ts index 8a5ec9c..cc414d8 100644 --- a/test/point.test.ts +++ b/test/point.test.ts @@ -1,4 +1,4 @@ -import { test } from 'vitest'; +import { expect, test } from 'vitest'; import { expectGeometry, expectPointsEqual, openFileAsArray } from './utils'; import { ShapeReader, PointRecord, CoordType } from '@shpts/shpts'; @@ -9,6 +9,7 @@ test('Reading PointRecord', async () => { const reader = await ShapeReader.fromArrayBuffer(shpBuffer, shxBuffer); let geom = expectGeometry(reader, 0, CoordType.XY, PointRecord); + expect(geom.type).toEqual('Point'); expectPointsEqual(geom.coords, [-155, -154]); geom = expectGeometry(reader, 4, CoordType.XY, PointRecord); expectPointsEqual(geom.coords, [-147.43741476950902, -157.28937716011498]); @@ -21,10 +22,13 @@ test('Reading PointRecord with M ', async () => { const reader = await ShapeReader.fromArrayBuffer(shpBuffer, shxBuffer); let geom = expectGeometry(reader, 0, CoordType.XYM, PointRecord); + expect(geom.type).toEqual('Point'); expectPointsEqual((geom as PointRecord).coords, [-178, -160, 1]); geom = expectGeometry(reader, 1, CoordType.XYM, PointRecord); + expect(geom.type).toEqual('Point'); expectPointsEqual((geom as PointRecord).coords, [-177, -165, 1000]); geom = expectGeometry(reader, 2, CoordType.XYM, PointRecord); + expect(geom.type).toEqual('Point'); expectPointsEqual((geom as PointRecord).coords, [-171, -165, NaN]); }); @@ -35,9 +39,12 @@ test('Reading PointRecord with Z', async () => { const reader = await ShapeReader.fromArrayBuffer(shpBuffer, shxBuffer); let geom = expectGeometry(reader, 0, CoordType.XYZM, PointRecord); + expect(geom.type).toEqual('Point'); expectPointsEqual((geom as PointRecord).coords, [-153, -178, 1, 2]); geom = expectGeometry(reader, 1, CoordType.XYZM, PointRecord); + expect(geom.type).toEqual('Point'); expectPointsEqual((geom as PointRecord).coords, [-158, -175, 2, 3]); geom = expectGeometry(reader, 5, CoordType.XYZM, PointRecord); + expect(geom.type).toEqual('Point'); expectPointsEqual((geom as PointRecord).coords, [-159, -186, 99.999, NaN]); }); diff --git a/test/polygon.test.ts b/test/polygon.test.ts index b29715a..78eca65 100644 --- a/test/polygon.test.ts +++ b/test/polygon.test.ts @@ -9,6 +9,7 @@ test('Reading PolygonRecord', async () => { const reader = await ShapeReader.fromArrayBuffer(shpBuffer, shxBuffer); let geom = expectGeometry(reader, 0, CoordType.XY, PolygonRecord); + expect(geom.type).toEqual('Polygon'); expect(geom.coords.length).toBe(1); let polygon = geom.coords[0]; expect(polygon.length).toBe(3); @@ -38,6 +39,7 @@ test('Reading PolygonRecord', async () => { ]); geom = expectGeometry(reader, 1, CoordType.XY, PolygonRecord); + expect(geom.type).toEqual('Polygon'); expect(geom.coords.length).toBe(1); polygon = geom.coords[0]; expect(polygon.length).toBe(1); @@ -50,6 +52,7 @@ test('Reading PolygonRecord', async () => { ]); geom = expectGeometry(reader, 2, CoordType.XY, PolygonRecord); + expect(geom.type).toEqual('MultiPolygon'); expect(geom.coords.length).toBe(3); polygon = geom.coords[0]; expect(polygon.length).toBe(3); @@ -111,6 +114,7 @@ test('Reading PolygonRecord with M', async () => { expect(reader.recordCount).toBe(2); let geom = expectGeometry(reader, 0, CoordType.XYM, PolygonRecord); + expect(geom.type).toEqual('Polygon'); expect(geom.coords.length).toBe(1); let polygon = geom.coords[0]; expect(polygon.length).toBe(1); @@ -122,6 +126,7 @@ test('Reading PolygonRecord with M', async () => { ]); geom = expectGeometry(reader, 1, CoordType.XYM, PolygonRecord); + expect(geom.type).toEqual('MultiPolygon'); expect(geom.coords.length).toBe(3); polygon = geom.coords[0]; @@ -184,6 +189,7 @@ test('Reading PolygonRecord with Z', async () => { expect(reader.recordCount).toBe(2); let geom = expectGeometry(reader, 0, CoordType.XYZM, PolygonRecord); + expect(geom.type).toEqual('Polygon'); expect(geom.coords.length).toBe(1); let polygon = geom.coords[0]; @@ -197,6 +203,7 @@ test('Reading PolygonRecord with Z', async () => { ]); geom = expectGeometry(reader, 1, CoordType.XYZM, PolygonRecord); + expect(geom.type).toEqual('MultiPolygon'); expect(geom.coords.length).toBe(3); //testing only the first polygon bellow polygon = geom.coords[0]; diff --git a/test/polyline.test.ts b/test/polyline.test.ts index fedb4eb..8704e19 100644 --- a/test/polyline.test.ts +++ b/test/polyline.test.ts @@ -9,6 +9,7 @@ test('Reading PolyLineRecord', async () => { const reader = await ShapeReader.fromArrayBuffer(shpBuffer, shxBuffer); let geom = expectGeometry(reader, 0, CoordType.XY, PolyLineRecord); + expect(geom.type).toEqual('LineString'); expect(geom.coords.length).toBe(1); let segment = geom.coords[0]; expect(segment.length).toBe(3); @@ -17,9 +18,11 @@ test('Reading PolyLineRecord', async () => { expectPointsEqual(segment[2], [-146.82619944462766, -153.40391265875377]); geom = expectGeometry(reader, 1, CoordType.XY, PolyLineRecord); + expect(geom.type).toEqual('LineString'); expect(geom.coords.length).toBe(1); geom = expectGeometry(reader, 2, CoordType.XY, PolyLineRecord); + expect(geom.type).toEqual('MultiLineString'); expect(geom.coords.length).toBe(3); segment = geom.coords[0]; expect(segment.length).toBe(4); @@ -46,6 +49,7 @@ test('Reading PolyLineRecord with M', async () => { const reader = await ShapeReader.fromArrayBuffer(shpBuffer, shxBuffer); let geom = expectGeometry(reader, 0, CoordType.XYM, PolyLineRecord); + expect(geom.type).toEqual('LineString'); expect(geom.coords.length).toBe(1); let segment = geom.coords[0]; expect(segment.length).toBe(3); @@ -54,6 +58,7 @@ test('Reading PolyLineRecord with M', async () => { expectPointsEqual(segment[2], [64.17836737175264, -110.86618752096422, 30]); geom = expectGeometry(reader, 1, CoordType.XYM, PolyLineRecord); + expect(geom.type).toEqual('LineString'); expect(geom.coords.length).toBe(1); segment = geom.coords[0]; expect(segment.length).toBe(5); @@ -64,6 +69,7 @@ test('Reading PolyLineRecord with M', async () => { expectPointsEqual(segment[4], [75.77823977517522, -100.75347824618558, 5]); geom = expectGeometry(reader, 2, CoordType.XYM, PolyLineRecord); + expect(geom.type).toEqual('MultiLineString'); expect(geom.coords.length).toBe(3); segment = geom.coords[0]; expect(segment.length).toBe(3); @@ -89,6 +95,7 @@ test('Reading PolyLineRecord with Z', async () => { const reader = await ShapeReader.fromArrayBuffer(shpBuffer, shxBuffer); let geom = expectGeometry(reader, 0, CoordType.XYZM, PolyLineRecord); + expect(geom.type).toEqual('LineString'); expect(geom.coords.length).toBe(1); let segment = geom.coords[0]; expectPointsEqual(segment[0], [-115.47093856843338, -100.45604562045679, 100, 5000]); @@ -98,6 +105,7 @@ test('Reading PolyLineRecord with Z', async () => { expectPointsEqual(segment[4], [-29.215477107085803, -93.91252785442344, 104, 9000]); geom = expectGeometry(reader, 1, CoordType.XYZM, PolyLineRecord); + expect(geom.type).toEqual('LineString'); expect(geom.coords.length).toBe(1); segment = geom.coords[0]; expectPointsEqual(segment[0], [-112.79404493687429, -114.43537902970968, 1000, NaN]); @@ -107,6 +115,7 @@ test('Reading PolyLineRecord with Z', async () => { expectPointsEqual(segment[4], [-23.861689843967667, -106.4046981350325, 1004, NaN]); geom = expectGeometry(reader, 2, CoordType.XYZM, PolyLineRecord); + expect(geom.type).toEqual('MultiLineString'); expect(geom.coords.length).toBe(3); segment = geom.coords[0]; expectPointsEqual(segment[0], [-111.60670519384564, -126.90578866647462, 11, 1]);