UNPKG

wkx

Version:

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

1,618 lines (1,217 loc) 145 kB
require=(function(){function r(e,n,t){function o(i,f){if(!n[i]){if(!e[i]){var c="function"==typeof require&&require;if(!f&&c)return c(i,!0);if(u)return u(i,!0);var a=new Error("Cannot find module '"+i+"'");throw a.code="MODULE_NOT_FOUND",a}var p=n[i]={exports:{}};e[i][0].call(p.exports,function(r){var n=e[i][1][r];return o(n||r)},p,p.exports,r,e,n,t)}return n[i].exports}for(var u="function"==typeof require&&require,i=0;i<t.length;i++)o(t[i]);return o}return r})()({1:[function(require,module,exports){ (function (Buffer){ module.exports = BinaryReader; function BinaryReader(buffer, isBigEndian) { this.buffer = buffer; this.position = 0; this.isBigEndian = isBigEndian || false; } function _read(readLE, readBE, size) { return function () { var value; if (this.isBigEndian) value = readBE.call(this.buffer, this.position); else value = readLE.call(this.buffer, this.position); this.position += size; return value; }; } BinaryReader.prototype.readUInt8 = _read(Buffer.prototype.readUInt8, Buffer.prototype.readUInt8, 1); BinaryReader.prototype.readUInt16 = _read(Buffer.prototype.readUInt16LE, Buffer.prototype.readUInt16BE, 2); BinaryReader.prototype.readUInt32 = _read(Buffer.prototype.readUInt32LE, Buffer.prototype.readUInt32BE, 4); BinaryReader.prototype.readInt8 = _read(Buffer.prototype.readInt8, Buffer.prototype.readInt8, 1); BinaryReader.prototype.readInt16 = _read(Buffer.prototype.readInt16LE, Buffer.prototype.readInt16BE, 2); BinaryReader.prototype.readInt32 = _read(Buffer.prototype.readInt32LE, Buffer.prototype.readInt32BE, 4); BinaryReader.prototype.readFloat = _read(Buffer.prototype.readFloatLE, Buffer.prototype.readFloatBE, 4); BinaryReader.prototype.readDouble = _read(Buffer.prototype.readDoubleLE, Buffer.prototype.readDoubleBE, 8); BinaryReader.prototype.readVarInt = function () { var nextByte, result = 0, bytesRead = 0; do { nextByte = this.buffer[this.position + bytesRead]; result += (nextByte & 0x7F) << (7 * bytesRead); bytesRead++; } while (nextByte >= 0x80); this.position += bytesRead; return result; }; }).call(this,require("buffer").Buffer) },{"buffer":"buffer"}],2:[function(require,module,exports){ (function (Buffer){ module.exports = BinaryWriter; function BinaryWriter(size, allowResize) { this.buffer = new Buffer(size); this.position = 0; this.allowResize = allowResize; } function _write(write, size) { return function (value, noAssert) { this.ensureSize(size); write.call(this.buffer, value, this.position, noAssert); this.position += size; }; } BinaryWriter.prototype.writeUInt8 = _write(Buffer.prototype.writeUInt8, 1); BinaryWriter.prototype.writeUInt16LE = _write(Buffer.prototype.writeUInt16LE, 2); BinaryWriter.prototype.writeUInt16BE = _write(Buffer.prototype.writeUInt16BE, 2); BinaryWriter.prototype.writeUInt32LE = _write(Buffer.prototype.writeUInt32LE, 4); BinaryWriter.prototype.writeUInt32BE = _write(Buffer.prototype.writeUInt32BE, 4); BinaryWriter.prototype.writeInt8 = _write(Buffer.prototype.writeInt8, 1); BinaryWriter.prototype.writeInt16LE = _write(Buffer.prototype.writeInt16LE, 2); BinaryWriter.prototype.writeInt16BE = _write(Buffer.prototype.writeInt16BE, 2); BinaryWriter.prototype.writeInt32LE = _write(Buffer.prototype.writeInt32LE, 4); BinaryWriter.prototype.writeInt32BE = _write(Buffer.prototype.writeInt32BE, 4); BinaryWriter.prototype.writeFloatLE = _write(Buffer.prototype.writeFloatLE, 4); BinaryWriter.prototype.writeFloatBE = _write(Buffer.prototype.writeFloatBE, 4); BinaryWriter.prototype.writeDoubleLE = _write(Buffer.prototype.writeDoubleLE, 8); BinaryWriter.prototype.writeDoubleBE = _write(Buffer.prototype.writeDoubleBE, 8); BinaryWriter.prototype.writeBuffer = function (buffer) { this.ensureSize(buffer.length); buffer.copy(this.buffer, this.position, 0, buffer.length); this.position += buffer.length; }; BinaryWriter.prototype.writeVarInt = function (value) { var length = 1; while ((value & 0xFFFFFF80) !== 0) { this.writeUInt8((value & 0x7F) | 0x80); value >>>= 7; length++; } this.writeUInt8(value & 0x7F); return length; }; BinaryWriter.prototype.ensureSize = function (size) { if (this.buffer.length < this.position + size) { if (this.allowResize) { var tempBuffer = new Buffer(this.position + size); this.buffer.copy(tempBuffer, 0, 0, this.buffer.length); this.buffer = tempBuffer; } else { throw new RangeError('index out of range'); } } }; }).call(this,require("buffer").Buffer) },{"buffer":"buffer"}],3:[function(require,module,exports){ (function (Buffer){ module.exports = Geometry; var Types = require('./types'); var Point = require('./point'); var LineString = require('./linestring'); var Polygon = require('./polygon'); var MultiPoint = require('./multipoint'); var MultiLineString = require('./multilinestring'); var MultiPolygon = require('./multipolygon'); var GeometryCollection = require('./geometrycollection'); var BinaryReader = require('./binaryreader'); var BinaryWriter = require('./binarywriter'); var WktParser = require('./wktparser'); var ZigZag = require('./zigzag.js'); function Geometry() { this.srid = undefined; this.hasZ = false; this.hasM = false; } Geometry.parse = function (value, options) { var valueType = typeof value; if (valueType === 'string' || value instanceof WktParser) return Geometry._parseWkt(value); else if (Buffer.isBuffer(value) || value instanceof BinaryReader) return Geometry._parseWkb(value, options); else throw new Error('first argument must be a string or Buffer'); }; Geometry._parseWkt = function (value) { var wktParser, srid; if (value instanceof WktParser) wktParser = value; else wktParser = new WktParser(value); var match = wktParser.matchRegex([/^SRID=(\d+);/]); if (match) srid = parseInt(match[1], 10); var geometryType = wktParser.matchType(); var dimension = wktParser.matchDimension(); var options = { srid: srid, hasZ: dimension.hasZ, hasM: dimension.hasM }; switch (geometryType) { case Types.wkt.Point: return Point._parseWkt(wktParser, options); case Types.wkt.LineString: return LineString._parseWkt(wktParser, options); case Types.wkt.Polygon: return Polygon._parseWkt(wktParser, options); case Types.wkt.MultiPoint: return MultiPoint._parseWkt(wktParser, options); case Types.wkt.MultiLineString: return MultiLineString._parseWkt(wktParser, options); case Types.wkt.MultiPolygon: return MultiPolygon._parseWkt(wktParser, options); case Types.wkt.GeometryCollection: return GeometryCollection._parseWkt(wktParser, options); } }; Geometry._parseWkb = function (value, parentOptions) { var binaryReader, wkbType, geometryType, options = {}; if (value instanceof BinaryReader) binaryReader = value; else binaryReader = new BinaryReader(value); binaryReader.isBigEndian = !binaryReader.readInt8(); wkbType = binaryReader.readUInt32(); options.hasSrid = (wkbType & 0x20000000) === 0x20000000; options.isEwkb = (wkbType & 0x20000000) || (wkbType & 0x40000000) || (wkbType & 0x80000000); if (options.hasSrid) options.srid = binaryReader.readUInt32(); options.hasZ = false; options.hasM = false; if (!options.isEwkb && (!parentOptions || !parentOptions.isEwkb)) { if (wkbType >= 1000 && wkbType < 2000) { options.hasZ = true; geometryType = wkbType - 1000; } else if (wkbType >= 2000 && wkbType < 3000) { options.hasM = true; geometryType = wkbType - 2000; } else if (wkbType >= 3000 && wkbType < 4000) { options.hasZ = true; options.hasM = true; geometryType = wkbType - 3000; } else { geometryType = wkbType; } } else { if (wkbType & 0x80000000) options.hasZ = true; if (wkbType & 0x40000000) options.hasM = true; geometryType = wkbType & 0xF; } switch (geometryType) { case Types.wkb.Point: return Point._parseWkb(binaryReader, options); case Types.wkb.LineString: return LineString._parseWkb(binaryReader, options); case Types.wkb.Polygon: return Polygon._parseWkb(binaryReader, options); case Types.wkb.MultiPoint: return MultiPoint._parseWkb(binaryReader, options); case Types.wkb.MultiLineString: return MultiLineString._parseWkb(binaryReader, options); case Types.wkb.MultiPolygon: return MultiPolygon._parseWkb(binaryReader, options); case Types.wkb.GeometryCollection: return GeometryCollection._parseWkb(binaryReader, options); default: throw new Error('GeometryType ' + geometryType + ' not supported'); } }; Geometry.parseTwkb = function (value) { var binaryReader, options = {}; if (value instanceof BinaryReader) binaryReader = value; else binaryReader = new BinaryReader(value); var type = binaryReader.readUInt8(); var metadataHeader = binaryReader.readUInt8(); var geometryType = type & 0x0F; options.precision = ZigZag.decode(type >> 4); options.precisionFactor = Math.pow(10, options.precision); options.hasBoundingBox = metadataHeader >> 0 & 1; options.hasSizeAttribute = metadataHeader >> 1 & 1; options.hasIdList = metadataHeader >> 2 & 1; options.hasExtendedPrecision = metadataHeader >> 3 & 1; options.isEmpty = metadataHeader >> 4 & 1; if (options.hasExtendedPrecision) { var extendedPrecision = binaryReader.readUInt8(); options.hasZ = (extendedPrecision & 0x01) === 0x01; options.hasM = (extendedPrecision & 0x02) === 0x02; options.zPrecision = ZigZag.decode((extendedPrecision & 0x1C) >> 2); options.zPrecisionFactor = Math.pow(10, options.zPrecision); options.mPrecision = ZigZag.decode((extendedPrecision & 0xE0) >> 5); options.mPrecisionFactor = Math.pow(10, options.mPrecision); } else { options.hasZ = false; options.hasM = false; } if (options.hasSizeAttribute) binaryReader.readVarInt(); if (options.hasBoundingBox) { var dimensions = 2; if (options.hasZ) dimensions++; if (options.hasM) dimensions++; for (var i = 0; i < dimensions; i++) { binaryReader.readVarInt(); binaryReader.readVarInt(); } } switch (geometryType) { case Types.wkb.Point: return Point._parseTwkb(binaryReader, options); case Types.wkb.LineString: return LineString._parseTwkb(binaryReader, options); case Types.wkb.Polygon: return Polygon._parseTwkb(binaryReader, options); case Types.wkb.MultiPoint: return MultiPoint._parseTwkb(binaryReader, options); case Types.wkb.MultiLineString: return MultiLineString._parseTwkb(binaryReader, options); case Types.wkb.MultiPolygon: return MultiPolygon._parseTwkb(binaryReader, options); case Types.wkb.GeometryCollection: return GeometryCollection._parseTwkb(binaryReader, options); default: throw new Error('GeometryType ' + geometryType + ' not supported'); } }; Geometry.parseGeoJSON = function (value) { return Geometry._parseGeoJSON(value); }; Geometry._parseGeoJSON = function (value, isSubGeometry) { var geometry; switch (value.type) { case Types.geoJSON.Point: geometry = Point._parseGeoJSON(value); break; case Types.geoJSON.LineString: geometry = LineString._parseGeoJSON(value); break; case Types.geoJSON.Polygon: geometry = Polygon._parseGeoJSON(value); break; case Types.geoJSON.MultiPoint: geometry = MultiPoint._parseGeoJSON(value); break; case Types.geoJSON.MultiLineString: geometry = MultiLineString._parseGeoJSON(value); break; case Types.geoJSON.MultiPolygon: geometry = MultiPolygon._parseGeoJSON(value); break; case Types.geoJSON.GeometryCollection: geometry = GeometryCollection._parseGeoJSON(value); break; default: throw new Error('GeometryType ' + value.type + ' not supported'); } if (value.crs && value.crs.type && value.crs.type === 'name' && value.crs.properties && value.crs.properties.name) { var crs = value.crs.properties.name; if (crs.indexOf('EPSG:') === 0) geometry.srid = parseInt(crs.substring(5)); else if (crs.indexOf('urn:ogc:def:crs:EPSG::') === 0) geometry.srid = parseInt(crs.substring(22)); else throw new Error('Unsupported crs: ' + crs); } else if (!isSubGeometry) { geometry.srid = 4326; } return geometry; }; Geometry.prototype.toEwkt = function () { return 'SRID=' + this.srid + ';' + this.toWkt(); }; Geometry.prototype.toEwkb = function () { var ewkb = new BinaryWriter(this._getWkbSize() + 4); var wkb = this.toWkb(); ewkb.writeInt8(1); ewkb.writeUInt32LE((wkb.slice(1, 5).readUInt32LE(0) | 0x20000000) >>> 0, true); ewkb.writeUInt32LE(this.srid); ewkb.writeBuffer(wkb.slice(5)); return ewkb.buffer; }; Geometry.prototype._getWktType = function (wktType, isEmpty) { var wkt = wktType; if (this.hasZ && this.hasM) wkt += ' ZM '; else if (this.hasZ) wkt += ' Z '; else if (this.hasM) wkt += ' M '; if (isEmpty && !this.hasZ && !this.hasM) wkt += ' '; if (isEmpty) wkt += 'EMPTY'; return wkt; }; Geometry.prototype._getWktCoordinate = function (point) { var coordinates = point.x + ' ' + point.y; if (this.hasZ) coordinates += ' ' + point.z; if (this.hasM) coordinates += ' ' + point.m; return coordinates; }; Geometry.prototype._writeWkbType = function (wkb, geometryType, parentOptions) { var dimensionType = 0; if (typeof this.srid === 'undefined' && (!parentOptions || typeof parentOptions.srid === 'undefined')) { if (this.hasZ && this.hasM) dimensionType += 3000; else if (this.hasZ) dimensionType += 1000; else if (this.hasM) dimensionType += 2000; } else { if (this.hasZ) dimensionType |= 0x80000000; if (this.hasM) dimensionType |= 0x40000000; } wkb.writeUInt32LE((dimensionType + geometryType) >>> 0, true); }; Geometry.getTwkbPrecision = function (xyPrecision, zPrecision, mPrecision) { return { xy: xyPrecision, z: zPrecision, m: mPrecision, xyFactor: Math.pow(10, xyPrecision), zFactor: Math.pow(10, zPrecision), mFactor: Math.pow(10, mPrecision) }; }; Geometry.prototype._writeTwkbHeader = function (twkb, geometryType, precision, isEmpty) { var type = (ZigZag.encode(precision.xy) << 4) + geometryType; var metadataHeader = (this.hasZ || this.hasM) << 3; metadataHeader += isEmpty << 4; twkb.writeUInt8(type); twkb.writeUInt8(metadataHeader); if (this.hasZ || this.hasM) { var extendedPrecision = 0; if (this.hasZ) extendedPrecision |= 0x1; if (this.hasM) extendedPrecision |= 0x2; twkb.writeUInt8(extendedPrecision); } }; Geometry.prototype.toGeoJSON = function (options) { var geoJSON = {}; if (this.srid) { if (options) { if (options.shortCrs) { geoJSON.crs = { type: 'name', properties: { name: 'EPSG:' + this.srid } }; } else if (options.longCrs) { geoJSON.crs = { type: 'name', properties: { name: 'urn:ogc:def:crs:EPSG::' + this.srid } }; } } } return geoJSON; }; }).call(this,{"isBuffer":require("../node_modules/is-buffer/index.js")}) },{"../node_modules/is-buffer/index.js":17,"./binaryreader":1,"./binarywriter":2,"./geometrycollection":4,"./linestring":5,"./multilinestring":6,"./multipoint":7,"./multipolygon":8,"./point":9,"./polygon":10,"./types":11,"./wktparser":12,"./zigzag.js":13}],4:[function(require,module,exports){ module.exports = GeometryCollection; var util = require('util'); var Types = require('./types'); var Geometry = require('./geometry'); var BinaryWriter = require('./binarywriter'); function GeometryCollection(geometries, srid) { Geometry.call(this); this.geometries = geometries || []; this.srid = srid; if (this.geometries.length > 0) { this.hasZ = this.geometries[0].hasZ; this.hasM = this.geometries[0].hasM; } } util.inherits(GeometryCollection, Geometry); GeometryCollection.Z = function (geometries, srid) { var geometryCollection = new GeometryCollection(geometries, srid); geometryCollection.hasZ = true; return geometryCollection; }; GeometryCollection.M = function (geometries, srid) { var geometryCollection = new GeometryCollection(geometries, srid); geometryCollection.hasM = true; return geometryCollection; }; GeometryCollection.ZM = function (geometries, srid) { var geometryCollection = new GeometryCollection(geometries, srid); geometryCollection.hasZ = true; geometryCollection.hasM = true; return geometryCollection; }; GeometryCollection._parseWkt = function (value, options) { var geometryCollection = new GeometryCollection(); geometryCollection.srid = options.srid; geometryCollection.hasZ = options.hasZ; geometryCollection.hasM = options.hasM; if (value.isMatch(['EMPTY'])) return geometryCollection; value.expectGroupStart(); do { geometryCollection.geometries.push(Geometry.parse(value)); } while (value.isMatch([','])); value.expectGroupEnd(); return geometryCollection; }; GeometryCollection._parseWkb = function (value, options) { var geometryCollection = new GeometryCollection(); geometryCollection.srid = options.srid; geometryCollection.hasZ = options.hasZ; geometryCollection.hasM = options.hasM; var geometryCount = value.readUInt32(); for (var i = 0; i < geometryCount; i++) geometryCollection.geometries.push(Geometry.parse(value, options)); return geometryCollection; }; GeometryCollection._parseTwkb = function (value, options) { var geometryCollection = new GeometryCollection(); geometryCollection.hasZ = options.hasZ; geometryCollection.hasM = options.hasM; if (options.isEmpty) return geometryCollection; var geometryCount = value.readVarInt(); for (var i = 0; i < geometryCount; i++) geometryCollection.geometries.push(Geometry.parseTwkb(value)); return geometryCollection; }; GeometryCollection._parseGeoJSON = function (value) { var geometryCollection = new GeometryCollection(); for (var i = 0; i < value.geometries.length; i++) geometryCollection.geometries.push(Geometry._parseGeoJSON(value.geometries[i], true)); if (geometryCollection.geometries.length > 0) geometryCollection.hasZ = geometryCollection.geometries[0].hasZ; return geometryCollection; }; GeometryCollection.prototype.toWkt = function () { if (this.geometries.length === 0) return this._getWktType(Types.wkt.GeometryCollection, true); var wkt = this._getWktType(Types.wkt.GeometryCollection, false) + '('; for (var i = 0; i < this.geometries.length; i++) wkt += this.geometries[i].toWkt() + ','; wkt = wkt.slice(0, -1); wkt += ')'; return wkt; }; GeometryCollection.prototype.toWkb = function () { var wkb = new BinaryWriter(this._getWkbSize()); wkb.writeInt8(1); this._writeWkbType(wkb, Types.wkb.GeometryCollection); wkb.writeUInt32LE(this.geometries.length); for (var i = 0; i < this.geometries.length; i++) wkb.writeBuffer(this.geometries[i].toWkb({ srid: this.srid })); return wkb.buffer; }; GeometryCollection.prototype.toTwkb = function () { var twkb = new BinaryWriter(0, true); var precision = Geometry.getTwkbPrecision(5, 0, 0); var isEmpty = this.geometries.length === 0; this._writeTwkbHeader(twkb, Types.wkb.GeometryCollection, precision, isEmpty); if (this.geometries.length > 0) { twkb.writeVarInt(this.geometries.length); for (var i = 0; i < this.geometries.length; i++) twkb.writeBuffer(this.geometries[i].toTwkb()); } return twkb.buffer; }; GeometryCollection.prototype._getWkbSize = function () { var size = 1 + 4 + 4; for (var i = 0; i < this.geometries.length; i++) size += this.geometries[i]._getWkbSize(); return size; }; GeometryCollection.prototype.toGeoJSON = function (options) { var geoJSON = Geometry.prototype.toGeoJSON.call(this, options); geoJSON.type = Types.geoJSON.GeometryCollection; geoJSON.geometries = []; for (var i = 0; i < this.geometries.length; i++) geoJSON.geometries.push(this.geometries[i].toGeoJSON()); return geoJSON; }; },{"./binarywriter":2,"./geometry":3,"./types":11,"util":20}],5:[function(require,module,exports){ module.exports = LineString; var util = require('util'); var Geometry = require('./geometry'); var Types = require('./types'); var Point = require('./point'); var BinaryWriter = require('./binarywriter'); function LineString(points, srid) { Geometry.call(this); this.points = points || []; this.srid = srid; if (this.points.length > 0) { this.hasZ = this.points[0].hasZ; this.hasM = this.points[0].hasM; } } util.inherits(LineString, Geometry); LineString.Z = function (points, srid) { var lineString = new LineString(points, srid); lineString.hasZ = true; return lineString; }; LineString.M = function (points, srid) { var lineString = new LineString(points, srid); lineString.hasM = true; return lineString; }; LineString.ZM = function (points, srid) { var lineString = new LineString(points, srid); lineString.hasZ = true; lineString.hasM = true; return lineString; }; LineString._parseWkt = function (value, options) { var lineString = new LineString(); lineString.srid = options.srid; lineString.hasZ = options.hasZ; lineString.hasM = options.hasM; if (value.isMatch(['EMPTY'])) return lineString; value.expectGroupStart(); lineString.points.push.apply(lineString.points, value.matchCoordinates(options)); value.expectGroupEnd(); return lineString; }; LineString._parseWkb = function (value, options) { var lineString = new LineString(); lineString.srid = options.srid; lineString.hasZ = options.hasZ; lineString.hasM = options.hasM; var pointCount = value.readUInt32(); for (var i = 0; i < pointCount; i++) lineString.points.push(Point._readWkbPoint(value, options)); return lineString; }; LineString._parseTwkb = function (value, options) { var lineString = new LineString(); lineString.hasZ = options.hasZ; lineString.hasM = options.hasM; if (options.isEmpty) return lineString; var previousPoint = new Point(0, 0, options.hasZ ? 0 : undefined, options.hasM ? 0 : undefined); var pointCount = value.readVarInt(); for (var i = 0; i < pointCount; i++) lineString.points.push(Point._readTwkbPoint(value, options, previousPoint)); return lineString; }; LineString._parseGeoJSON = function (value) { var lineString = new LineString(); if (value.coordinates.length > 0) lineString.hasZ = value.coordinates[0].length > 2; for (var i = 0; i < value.coordinates.length; i++) lineString.points.push(Point._readGeoJSONPoint(value.coordinates[i])); return lineString; }; LineString.prototype.toWkt = function () { if (this.points.length === 0) return this._getWktType(Types.wkt.LineString, true); return this._getWktType(Types.wkt.LineString, false) + this._toInnerWkt(); }; LineString.prototype._toInnerWkt = function () { var innerWkt = '('; for (var i = 0; i < this.points.length; i++) innerWkt += this._getWktCoordinate(this.points[i]) + ','; innerWkt = innerWkt.slice(0, -1); innerWkt += ')'; return innerWkt; }; LineString.prototype.toWkb = function (parentOptions) { var wkb = new BinaryWriter(this._getWkbSize()); wkb.writeInt8(1); this._writeWkbType(wkb, Types.wkb.LineString, parentOptions); wkb.writeUInt32LE(this.points.length); for (var i = 0; i < this.points.length; i++) this.points[i]._writeWkbPoint(wkb); return wkb.buffer; }; LineString.prototype.toTwkb = function () { var twkb = new BinaryWriter(0, true); var precision = Geometry.getTwkbPrecision(5, 0, 0); var isEmpty = this.points.length === 0; this._writeTwkbHeader(twkb, Types.wkb.LineString, precision, isEmpty); if (this.points.length > 0) { twkb.writeVarInt(this.points.length); var previousPoint = new Point(0, 0, 0, 0); for (var i = 0; i < this.points.length; i++) this.points[i]._writeTwkbPoint(twkb, precision, previousPoint); } return twkb.buffer; }; LineString.prototype._getWkbSize = function () { var coordinateSize = 16; if (this.hasZ) coordinateSize += 8; if (this.hasM) coordinateSize += 8; return 1 + 4 + 4 + (this.points.length * coordinateSize); }; LineString.prototype.toGeoJSON = function (options) { var geoJSON = Geometry.prototype.toGeoJSON.call(this, options); geoJSON.type = Types.geoJSON.LineString; geoJSON.coordinates = []; for (var i = 0; i < this.points.length; i++) { if (this.hasZ) geoJSON.coordinates.push([this.points[i].x, this.points[i].y, this.points[i].z]); else geoJSON.coordinates.push([this.points[i].x, this.points[i].y]); } return geoJSON; }; },{"./binarywriter":2,"./geometry":3,"./point":9,"./types":11,"util":20}],6:[function(require,module,exports){ module.exports = MultiLineString; var util = require('util'); var Types = require('./types'); var Geometry = require('./geometry'); var Point = require('./point'); var LineString = require('./linestring'); var BinaryWriter = require('./binarywriter'); function MultiLineString(lineStrings, srid) { Geometry.call(this); this.lineStrings = lineStrings || []; this.srid = srid; if (this.lineStrings.length > 0) { this.hasZ = this.lineStrings[0].hasZ; this.hasM = this.lineStrings[0].hasM; } } util.inherits(MultiLineString, Geometry); MultiLineString.Z = function (lineStrings, srid) { var multiLineString = new MultiLineString(lineStrings, srid); multiLineString.hasZ = true; return multiLineString; }; MultiLineString.M = function (lineStrings, srid) { var multiLineString = new MultiLineString(lineStrings, srid); multiLineString.hasM = true; return multiLineString; }; MultiLineString.ZM = function (lineStrings, srid) { var multiLineString = new MultiLineString(lineStrings, srid); multiLineString.hasZ = true; multiLineString.hasM = true; return multiLineString; }; MultiLineString._parseWkt = function (value, options) { var multiLineString = new MultiLineString(); multiLineString.srid = options.srid; multiLineString.hasZ = options.hasZ; multiLineString.hasM = options.hasM; if (value.isMatch(['EMPTY'])) return multiLineString; value.expectGroupStart(); do { value.expectGroupStart(); multiLineString.lineStrings.push(new LineString(value.matchCoordinates(options))); value.expectGroupEnd(); } while (value.isMatch([','])); value.expectGroupEnd(); return multiLineString; }; MultiLineString._parseWkb = function (value, options) { var multiLineString = new MultiLineString(); multiLineString.srid = options.srid; multiLineString.hasZ = options.hasZ; multiLineString.hasM = options.hasM; var lineStringCount = value.readUInt32(); for (var i = 0; i < lineStringCount; i++) multiLineString.lineStrings.push(Geometry.parse(value, options)); return multiLineString; }; MultiLineString._parseTwkb = function (value, options) { var multiLineString = new MultiLineString(); multiLineString.hasZ = options.hasZ; multiLineString.hasM = options.hasM; if (options.isEmpty) return multiLineString; var previousPoint = new Point(0, 0, options.hasZ ? 0 : undefined, options.hasM ? 0 : undefined); var lineStringCount = value.readVarInt(); for (var i = 0; i < lineStringCount; i++) { var lineString = new LineString(); lineString.hasZ = options.hasZ; lineString.hasM = options.hasM; var pointCount = value.readVarInt(); for (var j = 0; j < pointCount; j++) lineString.points.push(Point._readTwkbPoint(value, options, previousPoint)); multiLineString.lineStrings.push(lineString); } return multiLineString; }; MultiLineString._parseGeoJSON = function (value) { var multiLineString = new MultiLineString(); if (value.coordinates.length > 0 && value.coordinates[0].length > 0) multiLineString.hasZ = value.coordinates[0][0].length > 2; for (var i = 0; i < value.coordinates.length; i++) multiLineString.lineStrings.push(LineString._parseGeoJSON({ coordinates: value.coordinates[i] })); return multiLineString; }; MultiLineString.prototype.toWkt = function () { if (this.lineStrings.length === 0) return this._getWktType(Types.wkt.MultiLineString, true); var wkt = this._getWktType(Types.wkt.MultiLineString, false) + '('; for (var i = 0; i < this.lineStrings.length; i++) wkt += this.lineStrings[i]._toInnerWkt() + ','; wkt = wkt.slice(0, -1); wkt += ')'; return wkt; }; MultiLineString.prototype.toWkb = function () { var wkb = new BinaryWriter(this._getWkbSize()); wkb.writeInt8(1); this._writeWkbType(wkb, Types.wkb.MultiLineString); wkb.writeUInt32LE(this.lineStrings.length); for (var i = 0; i < this.lineStrings.length; i++) wkb.writeBuffer(this.lineStrings[i].toWkb({ srid: this.srid })); return wkb.buffer; }; MultiLineString.prototype.toTwkb = function () { var twkb = new BinaryWriter(0, true); var precision = Geometry.getTwkbPrecision(5, 0, 0); var isEmpty = this.lineStrings.length === 0; this._writeTwkbHeader(twkb, Types.wkb.MultiLineString, precision, isEmpty); if (this.lineStrings.length > 0) { twkb.writeVarInt(this.lineStrings.length); var previousPoint = new Point(0, 0, 0, 0); for (var i = 0; i < this.lineStrings.length; i++) { twkb.writeVarInt(this.lineStrings[i].points.length); for (var j = 0; j < this.lineStrings[i].points.length; j++) this.lineStrings[i].points[j]._writeTwkbPoint(twkb, precision, previousPoint); } } return twkb.buffer; }; MultiLineString.prototype._getWkbSize = function () { var size = 1 + 4 + 4; for (var i = 0; i < this.lineStrings.length; i++) size += this.lineStrings[i]._getWkbSize(); return size; }; MultiLineString.prototype.toGeoJSON = function (options) { var geoJSON = Geometry.prototype.toGeoJSON.call(this, options); geoJSON.type = Types.geoJSON.MultiLineString; geoJSON.coordinates = []; for (var i = 0; i < this.lineStrings.length; i++) geoJSON.coordinates.push(this.lineStrings[i].toGeoJSON().coordinates); return geoJSON; }; },{"./binarywriter":2,"./geometry":3,"./linestring":5,"./point":9,"./types":11,"util":20}],7:[function(require,module,exports){ module.exports = MultiPoint; var util = require('util'); var Types = require('./types'); var Geometry = require('./geometry'); var Point = require('./point'); var BinaryWriter = require('./binarywriter'); function MultiPoint(points, srid) { Geometry.call(this); this.points = points || []; this.srid = srid; if (this.points.length > 0) { this.hasZ = this.points[0].hasZ; this.hasM = this.points[0].hasM; } } util.inherits(MultiPoint, Geometry); MultiPoint.Z = function (points, srid) { var multiPoint = new MultiPoint(points, srid); multiPoint.hasZ = true; return multiPoint; }; MultiPoint.M = function (points, srid) { var multiPoint = new MultiPoint(points, srid); multiPoint.hasM = true; return multiPoint; }; MultiPoint.ZM = function (points, srid) { var multiPoint = new MultiPoint(points, srid); multiPoint.hasZ = true; multiPoint.hasM = true; return multiPoint; }; MultiPoint._parseWkt = function (value, options) { var multiPoint = new MultiPoint(); multiPoint.srid = options.srid; multiPoint.hasZ = options.hasZ; multiPoint.hasM = options.hasM; if (value.isMatch(['EMPTY'])) return multiPoint; value.expectGroupStart(); multiPoint.points.push.apply(multiPoint.points, value.matchCoordinates(options)); value.expectGroupEnd(); return multiPoint; }; MultiPoint._parseWkb = function (value, options) { var multiPoint = new MultiPoint(); multiPoint.srid = options.srid; multiPoint.hasZ = options.hasZ; multiPoint.hasM = options.hasM; var pointCount = value.readUInt32(); for (var i = 0; i < pointCount; i++) multiPoint.points.push(Geometry.parse(value, options)); return multiPoint; }; MultiPoint._parseTwkb = function (value, options) { var multiPoint = new MultiPoint(); multiPoint.hasZ = options.hasZ; multiPoint.hasM = options.hasM; if (options.isEmpty) return multiPoint; var previousPoint = new Point(0, 0, options.hasZ ? 0 : undefined, options.hasM ? 0 : undefined); var pointCount = value.readVarInt(); for (var i = 0; i < pointCount; i++) multiPoint.points.push(Point._readTwkbPoint(value, options, previousPoint)); return multiPoint; }; MultiPoint._parseGeoJSON = function (value) { var multiPoint = new MultiPoint(); if (value.coordinates.length > 0) multiPoint.hasZ = value.coordinates[0].length > 2; for (var i = 0; i < value.coordinates.length; i++) multiPoint.points.push(Point._parseGeoJSON({ coordinates: value.coordinates[i] })); return multiPoint; }; MultiPoint.prototype.toWkt = function () { if (this.points.length === 0) return this._getWktType(Types.wkt.MultiPoint, true); var wkt = this._getWktType(Types.wkt.MultiPoint, false) + '('; for (var i = 0; i < this.points.length; i++) wkt += this._getWktCoordinate(this.points[i]) + ','; wkt = wkt.slice(0, -1); wkt += ')'; return wkt; }; MultiPoint.prototype.toWkb = function () { var wkb = new BinaryWriter(this._getWkbSize()); wkb.writeInt8(1); this._writeWkbType(wkb, Types.wkb.MultiPoint); wkb.writeUInt32LE(this.points.length); for (var i = 0; i < this.points.length; i++) wkb.writeBuffer(this.points[i].toWkb({ srid: this.srid })); return wkb.buffer; }; MultiPoint.prototype.toTwkb = function () { var twkb = new BinaryWriter(0, true); var precision = Geometry.getTwkbPrecision(5, 0, 0); var isEmpty = this.points.length === 0; this._writeTwkbHeader(twkb, Types.wkb.MultiPoint, precision, isEmpty); if (this.points.length > 0) { twkb.writeVarInt(this.points.length); var previousPoint = new Point(0, 0, 0, 0); for (var i = 0; i < this.points.length; i++) this.points[i]._writeTwkbPoint(twkb, precision, previousPoint); } return twkb.buffer; }; MultiPoint.prototype._getWkbSize = function () { var coordinateSize = 16; if (this.hasZ) coordinateSize += 8; if (this.hasM) coordinateSize += 8; coordinateSize += 5; return 1 + 4 + 4 + (this.points.length * coordinateSize); }; MultiPoint.prototype.toGeoJSON = function (options) { var geoJSON = Geometry.prototype.toGeoJSON.call(this, options); geoJSON.type = Types.geoJSON.MultiPoint; geoJSON.coordinates = []; for (var i = 0; i < this.points.length; i++) geoJSON.coordinates.push(this.points[i].toGeoJSON().coordinates); return geoJSON; }; },{"./binarywriter":2,"./geometry":3,"./point":9,"./types":11,"util":20}],8:[function(require,module,exports){ module.exports = MultiPolygon; var util = require('util'); var Types = require('./types'); var Geometry = require('./geometry'); var Point = require('./point'); var Polygon = require('./polygon'); var BinaryWriter = require('./binarywriter'); function MultiPolygon(polygons, srid) { Geometry.call(this); this.polygons = polygons || []; this.srid = srid; if (this.polygons.length > 0) { this.hasZ = this.polygons[0].hasZ; this.hasM = this.polygons[0].hasM; } } util.inherits(MultiPolygon, Geometry); MultiPolygon.Z = function (polygons, srid) { var multiPolygon = new MultiPolygon(polygons, srid); multiPolygon.hasZ = true; return multiPolygon; }; MultiPolygon.M = function (polygons, srid) { var multiPolygon = new MultiPolygon(polygons, srid); multiPolygon.hasM = true; return multiPolygon; }; MultiPolygon.ZM = function (polygons, srid) { var multiPolygon = new MultiPolygon(polygons, srid); multiPolygon.hasZ = true; multiPolygon.hasM = true; return multiPolygon; }; MultiPolygon._parseWkt = function (value, options) { var multiPolygon = new MultiPolygon(); multiPolygon.srid = options.srid; multiPolygon.hasZ = options.hasZ; multiPolygon.hasM = options.hasM; if (value.isMatch(['EMPTY'])) return multiPolygon; value.expectGroupStart(); do { value.expectGroupStart(); var exteriorRing = []; var interiorRings = []; value.expectGroupStart(); exteriorRing.push.apply(exteriorRing, value.matchCoordinates(options)); value.expectGroupEnd(); while (value.isMatch([','])) { value.expectGroupStart(); interiorRings.push(value.matchCoordinates(options)); value.expectGroupEnd(); } multiPolygon.polygons.push(new Polygon(exteriorRing, interiorRings)); value.expectGroupEnd(); } while (value.isMatch([','])); value.expectGroupEnd(); return multiPolygon; }; MultiPolygon._parseWkb = function (value, options) { var multiPolygon = new MultiPolygon(); multiPolygon.srid = options.srid; multiPolygon.hasZ = options.hasZ; multiPolygon.hasM = options.hasM; var polygonCount = value.readUInt32(); for (var i = 0; i < polygonCount; i++) multiPolygon.polygons.push(Geometry.parse(value, options)); return multiPolygon; }; MultiPolygon._parseTwkb = function (value, options) { var multiPolygon = new MultiPolygon(); multiPolygon.hasZ = options.hasZ; multiPolygon.hasM = options.hasM; if (options.isEmpty) return multiPolygon; var previousPoint = new Point(0, 0, options.hasZ ? 0 : undefined, options.hasM ? 0 : undefined); var polygonCount = value.readVarInt(); for (var i = 0; i < polygonCount; i++) { var polygon = new Polygon(); polygon.hasZ = options.hasZ; polygon.hasM = options.hasM; var ringCount = value.readVarInt(); var exteriorRingCount = value.readVarInt(); for (var j = 0; j < exteriorRingCount; j++) polygon.exteriorRing.push(Point._readTwkbPoint(value, options, previousPoint)); for (j = 1; j < ringCount; j++) { var interiorRing = []; var interiorRingCount = value.readVarInt(); for (var k = 0; k < interiorRingCount; k++) interiorRing.push(Point._readTwkbPoint(value, options, previousPoint)); polygon.interiorRings.push(interiorRing); } multiPolygon.polygons.push(polygon); } return multiPolygon; }; MultiPolygon._parseGeoJSON = function (value) { var multiPolygon = new MultiPolygon(); if (value.coordinates.length > 0 && value.coordinates[0].length > 0 && value.coordinates[0][0].length > 0) multiPolygon.hasZ = value.coordinates[0][0][0].length > 2; for (var i = 0; i < value.coordinates.length; i++) multiPolygon.polygons.push(Polygon._parseGeoJSON({ coordinates: value.coordinates[i] })); return multiPolygon; }; MultiPolygon.prototype.toWkt = function () { if (this.polygons.length === 0) return this._getWktType(Types.wkt.MultiPolygon, true); var wkt = this._getWktType(Types.wkt.MultiPolygon, false) + '('; for (var i = 0; i < this.polygons.length; i++) wkt += this.polygons[i]._toInnerWkt() + ','; wkt = wkt.slice(0, -1); wkt += ')'; return wkt; }; MultiPolygon.prototype.toWkb = function () { var wkb = new BinaryWriter(this._getWkbSize()); wkb.writeInt8(1); this._writeWkbType(wkb, Types.wkb.MultiPolygon); wkb.writeUInt32LE(this.polygons.length); for (var i = 0; i < this.polygons.length; i++) wkb.writeBuffer(this.polygons[i].toWkb({ srid: this.srid })); return wkb.buffer; }; MultiPolygon.prototype.toTwkb = function () { var twkb = new BinaryWriter(0, true); var precision = Geometry.getTwkbPrecision(5, 0, 0); var isEmpty = this.polygons.length === 0; this._writeTwkbHeader(twkb, Types.wkb.MultiPolygon, precision, isEmpty); if (this.polygons.length > 0) { twkb.writeVarInt(this.polygons.length); var previousPoint = new Point(0, 0, 0, 0); for (var i = 0; i < this.polygons.length; i++) { twkb.writeVarInt(1 + this.polygons[i].interiorRings.length); twkb.writeVarInt(this.polygons[i].exteriorRing.length); for (var j = 0; j < this.polygons[i].exteriorRing.length; j++) this.polygons[i].exteriorRing[j]._writeTwkbPoint(twkb, precision, previousPoint); for (j = 0; j < this.polygons[i].interiorRings.length; j++) { twkb.writeVarInt(this.polygons[i].interiorRings[j].length); for (var k = 0; k < this.polygons[i].interiorRings[j].length; k++) this.polygons[i].interiorRings[j][k]._writeTwkbPoint(twkb, precision, previousPoint); } } } return twkb.buffer; }; MultiPolygon.prototype._getWkbSize = function () { var size = 1 + 4 + 4; for (var i = 0; i < this.polygons.length; i++) size += this.polygons[i]._getWkbSize(); return size; }; MultiPolygon.prototype.toGeoJSON = function (options) { var geoJSON = Geometry.prototype.toGeoJSON.call(this, options); geoJSON.type = Types.geoJSON.MultiPolygon; geoJSON.coordinates = []; for (var i = 0; i < this.polygons.length; i++) geoJSON.coordinates.push(this.polygons[i].toGeoJSON().coordinates); return geoJSON; }; },{"./binarywriter":2,"./geometry":3,"./point":9,"./polygon":10,"./types":11,"util":20}],9:[function(require,module,exports){ module.exports = Point; var util = require('util'); var Geometry = require('./geometry'); var Types = require('./types'); var BinaryWriter = require('./binarywriter'); var ZigZag = require('./zigzag.js'); function Point(x, y, z, m, srid) { Geometry.call(this); this.x = x; this.y = y; this.z = z; this.m = m; this.srid = srid; this.hasZ = typeof this.z !== 'undefined'; this.hasM = typeof this.m !== 'undefined'; } util.inherits(Point, Geometry); Point.Z = function (x, y, z, srid) { var point = new Point(x, y, z, undefined, srid); point.hasZ = true; return point; }; Point.M = function (x, y, m, srid) { var point = new Point(x, y, undefined, m, srid); point.hasM = true; return point; }; Point.ZM = function (x, y, z, m, srid) { var point = new Point(x, y, z, m, srid); point.hasZ = true; point.hasM = true; return point; }; Point._parseWkt = function (value, options) { var point = new Point(); point.srid = options.srid; point.hasZ = options.hasZ; point.hasM = options.hasM; if (value.isMatch(['EMPTY'])) return point; value.expectGroupStart(); var coordinate = value.matchCoordinate(options); point.x = coordinate.x; point.y = coordinate.y; point.z = coordinate.z; point.m = coordinate.m; value.expectGroupEnd(); return point; }; Point._parseWkb = function (value, options) { var point = Point._readWkbPoint(value, options); point.srid = options.srid; return point; }; Point._readWkbPoint = function (value, options) { return new Point(value.readDouble(), value.readDouble(), options.hasZ ? value.readDouble() : undefined, options.hasM ? value.readDouble() : undefined); }; Point._parseTwkb = function (value, options) { var point = new Point(); point.hasZ = options.hasZ; point.hasM = options.hasM; if (options.isEmpty) return point; point.x = ZigZag.decode(value.readVarInt()) / options.precisionFactor; point.y = ZigZag.decode(value.readVarInt()) / options.precisionFactor; point.z = options.hasZ ? ZigZag.decode(value.readVarInt()) / options.zPrecisionFactor : undefined; point.m = options.hasM ? ZigZag.decode(value.readVarInt()) / options.mPrecisionFactor : undefined; return point; }; Point._readTwkbPoint = function (value, options, previousPoint) { previousPoint.x += ZigZag.decode(value.readVarInt()) / options.precisionFactor; previousPoint.y += ZigZag.decode(value.readVarInt()) / options.precisionFactor; if (options.hasZ) previousPoint.z += ZigZag.decode(value.readVarInt()) / options.zPrecisionFactor; if (options.hasM) previousPoint.m += ZigZag.decode(value.readVarInt()) / options.mPrecisionFactor; return new Point(previousPoint.x, previousPoint.y, previousPoint.z, previousPoint.m); }; Point._parseGeoJSON = function (value) { return Point._readGeoJSONPoint(value.coordinates); }; Point._readGeoJSONPoint = function (coordinates) { if (coordinates.length === 0) return new Point(); if (coordinates.length > 2) return new Point(coordinates[0], coordinates[1], coordinates[2]); return new Point(coordinates[0], coordinates[1]); }; Point.prototype.toWkt = function () { if (typeof this.x === 'undefined' && typeof this.y === 'undefined' && typeof this.z === 'undefined' && typeof this.m === 'undefined') return this._getWktType(Types.wkt.Point, true); return this._getWktType(Types.wkt.Point, false) + '(' + this._getWktCoordinate(this) + ')'; }; Point.prototype.toWkb = function (parentOptions) { var wkb = new BinaryWriter(this._getWkbSize()); wkb.writeInt8(1); this._writeWkbType(wkb, Types.wkb.Point, parentOptions); if (typeof this.x === 'undefined' && typeof this.y === 'undefined') { wkb.writeDoubleLE(NaN); wkb.writeDoubleLE(NaN); if (this.hasZ) wkb.writeDoubleLE(NaN); if (this.hasM) wkb.writeDoubleLE(NaN); } else { this._writeWkbPoint(wkb); } return wkb.buffer; }; Point.prototype._writeWkbPoint = function (wkb) { wkb.writeDoubleLE(this.x); wkb.writeDoubleLE(this.y); if (this.hasZ) wkb.writeDoubleLE(this.z); if (this.hasM) wkb.writeDoubleLE(this.m); }; Point.prototype.toTwkb = function () { var twkb = new BinaryWriter(0, true); var precision = Geometry.getTwkbPrecision(5, 0, 0);