UNPKG

well-known-parser

Version:

A WKT/WKB/EWKT/EWKB/TWKB/GeoJSON parser and serializer

134 lines (104 loc) 3.71 kB
import type { BinaryReader } from '../binaryreader'; import type { WktParser } from '../wktparser'; import type { GeometryOptions } from '../types'; import { Polygon } from '../polygon'; import { Point } from '../point'; import { parsePointGeoJSON, parsePointWkb, parseRelativePointTwkb } from './point'; import type { Polygon as GeoJSONPolygon } from 'geojson'; export function parsePolygonWkt(value: WktParser, options: GeometryOptions): Polygon { const polygon = new Polygon(); polygon.srid = options.srid; polygon.hasZ = options.hasZ ?? false; polygon.hasM = options.hasM ?? false; if (value.isMatch(['EMPTY'])) { return polygon; } value.expectGroupStart(); value.expectGroupStart(); const exteriorCoords = value.matchCoordinates(options); for (const coord of exteriorCoords) { polygon.exteriorRing.push(coord); } value.expectGroupEnd(); while (value.isMatch([','])) { value.expectGroupStart(); const interiorCoords = value.matchCoordinates(options); const ring = []; for (const coord of interiorCoords) { ring.push(coord); } polygon.interiorRings.push(ring); value.expectGroupEnd(); } value.expectGroupEnd(); return polygon; } export function parsePolygonWkb(value: BinaryReader, options: GeometryOptions): Polygon { const polygon = new Polygon(); polygon.srid = options.srid; polygon.hasZ = options.hasZ ?? false; polygon.hasM = options.hasM ?? false; const ringCount = value.readUInt32(); const childOptions: GeometryOptions = { ...options, srid: undefined, }; if (ringCount > 0) { const exteriorRingCount = value.readUInt32(); for (let i = 0; i < exteriorRingCount; i++) { polygon.exteriorRing.push(parsePointWkb(value, childOptions)); } for (let i = 1; i < ringCount; i++) { const interiorRing: Point[] = []; const interiorRingCount = value.readUInt32(); for (let j = 0; j < interiorRingCount; j++) { interiorRing.push(parsePointWkb(value, childOptions)); } polygon.interiorRings.push(interiorRing); } } return polygon; } export function parsePolygonTwkb(value: BinaryReader, options: GeometryOptions): Polygon { const polygon = new Polygon(); polygon.hasZ = options.hasZ ?? false; polygon.hasM = options.hasM ?? false; if (options.isEmpty) { return polygon; } const previousPoint = new Point(0, 0, options.hasZ ? 0 : undefined, options.hasM ? 0 : undefined); const ringCount = value.readVarInt(); const exteriorRingCount = value.readVarInt(); for (let i = 0; i < exteriorRingCount; i++) { polygon.exteriorRing.push(parseRelativePointTwkb(value, options, previousPoint)); } for (let i = 1; i < ringCount; i++) { const interiorRing: Point[] = []; const interiorRingCount = value.readVarInt(); for (let j = 0; j < interiorRingCount; j++) { interiorRing.push(parseRelativePointTwkb(value, options, previousPoint)); } polygon.interiorRings.push(interiorRing); } return polygon; } export function parsePolygonGeoJSON(value: Pick<GeoJSONPolygon, 'coordinates'>): Polygon { const polygon = new Polygon(); if (value.coordinates.length > 0 && value.coordinates[0].length > 0) { polygon.hasZ = value.coordinates[0][0].length > 2; } for (let i = 0; i < value.coordinates.length; i++) { if (i > 0) { polygon.interiorRings.push([]); } for (let j = 0; j < value.coordinates[i].length; j++) { const pointData = parsePointGeoJSON(value.coordinates[i][j]); if (i === 0) { polygon.exteriorRing.push(pointData); } else { polygon.interiorRings[i - 1].push(pointData); } } } return polygon; }