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; };