123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288 |
- module.exports = Polygon;
- var util = require('util');
- var Geometry = require('./geometry');
- var Types = require('./types');
- var Point = require('./point');
- var BinaryWriter = require('./binarywriter');
- function Polygon(exteriorRing, interiorRings, srid) {
- Geometry.call(this);
- this.exteriorRing = exteriorRing || [];
- this.interiorRings = interiorRings || [];
- this.srid = srid;
- if (this.exteriorRing.length > 0) {
- this.hasZ = this.exteriorRing[0].hasZ;
- this.hasM = this.exteriorRing[0].hasM;
- }
- }
- util.inherits(Polygon, Geometry);
- Polygon.Z = function (exteriorRing, interiorRings, srid) {
- var polygon = new Polygon(exteriorRing, interiorRings, srid);
- polygon.hasZ = true;
- return polygon;
- };
- Polygon.M = function (exteriorRing, interiorRings, srid) {
- var polygon = new Polygon(exteriorRing, interiorRings, srid);
- polygon.hasM = true;
- return polygon;
- };
- Polygon.ZM = function (exteriorRing, interiorRings, srid) {
- var polygon = new Polygon(exteriorRing, interiorRings, srid);
- polygon.hasZ = true;
- polygon.hasM = true;
- return polygon;
- };
- Polygon._parseWkt = function (value, options) {
- var polygon = new Polygon();
- polygon.srid = options.srid;
- polygon.hasZ = options.hasZ;
- polygon.hasM = options.hasM;
- if (value.isMatch(['EMPTY']))
- return polygon;
- value.expectGroupStart();
- value.expectGroupStart();
- polygon.exteriorRing.push.apply(polygon.exteriorRing, value.matchCoordinates(options));
- value.expectGroupEnd();
- while (value.isMatch([','])) {
- value.expectGroupStart();
- polygon.interiorRings.push(value.matchCoordinates(options));
- value.expectGroupEnd();
- }
- value.expectGroupEnd();
- return polygon;
- };
- Polygon._parseWkb = function (value, options) {
- var polygon = new Polygon();
- polygon.srid = options.srid;
- polygon.hasZ = options.hasZ;
- polygon.hasM = options.hasM;
- var ringCount = value.readUInt32();
- if (ringCount > 0) {
- var exteriorRingCount = value.readUInt32();
- for (var i = 0; i < exteriorRingCount; i++)
- polygon.exteriorRing.push(Point._readWkbPoint(value, options));
- for (i = 1; i < ringCount; i++) {
- var interiorRing = [];
- var interiorRingCount = value.readUInt32();
- for (var j = 0; j < interiorRingCount; j++)
- interiorRing.push(Point._readWkbPoint(value, options));
- polygon.interiorRings.push(interiorRing);
- }
- }
- return polygon;
- };
- Polygon._parseTwkb = function (value, options) {
- var polygon = new Polygon();
- polygon.hasZ = options.hasZ;
- polygon.hasM = options.hasM;
- if (options.isEmpty)
- return polygon;
- var previousPoint = new Point(0, 0, options.hasZ ? 0 : undefined, options.hasM ? 0 : undefined);
- var ringCount = value.readVarInt();
- var exteriorRingCount = value.readVarInt();
- for (var i = 0; i < exteriorRingCount; i++)
- polygon.exteriorRing.push(Point._readTwkbPoint(value, options, previousPoint));
- for (i = 1; i < ringCount; i++) {
- var interiorRing = [];
- var interiorRingCount = value.readVarInt();
- for (var j = 0; j < interiorRingCount; j++)
- interiorRing.push(Point._readTwkbPoint(value, options, previousPoint));
- polygon.interiorRings.push(interiorRing);
- }
- return polygon;
- };
- Polygon._parseGeoJSON = function (value) {
- var polygon = new Polygon();
- if (value.coordinates.length > 0 && value.coordinates[0].length > 0)
- polygon.hasZ = value.coordinates[0][0].length > 2;
- for (var i = 0; i < value.coordinates.length; i++) {
- if (i > 0)
- polygon.interiorRings.push([]);
- for (var j = 0; j < value.coordinates[i].length; j++) {
- if (i === 0)
- polygon.exteriorRing.push(Point._readGeoJSONPoint(value.coordinates[i][j]));
- else
- polygon.interiorRings[i - 1].push(Point._readGeoJSONPoint(value.coordinates[i][j]));
- }
- }
- return polygon;
- };
- Polygon.prototype.toWkt = function () {
- if (this.exteriorRing.length === 0)
- return this._getWktType(Types.wkt.Polygon, true);
- return this._getWktType(Types.wkt.Polygon, false) + this._toInnerWkt();
- };
- Polygon.prototype._toInnerWkt = function () {
- var innerWkt = '((';
- for (var i = 0; i < this.exteriorRing.length; i++)
- innerWkt += this._getWktCoordinate(this.exteriorRing[i]) + ',';
- innerWkt = innerWkt.slice(0, -1);
- innerWkt += ')';
- for (i = 0; i < this.interiorRings.length; i++) {
- innerWkt += ',(';
- for (var j = 0; j < this.interiorRings[i].length; j++) {
- innerWkt += this._getWktCoordinate(this.interiorRings[i][j]) + ',';
- }
- innerWkt = innerWkt.slice(0, -1);
- innerWkt += ')';
- }
- innerWkt += ')';
- return innerWkt;
- };
- Polygon.prototype.toWkb = function (parentOptions) {
- var wkb = new BinaryWriter(this._getWkbSize());
- wkb.writeInt8(1);
- this._writeWkbType(wkb, Types.wkb.Polygon, parentOptions);
- if (this.exteriorRing.length > 0) {
- wkb.writeUInt32LE(1 + this.interiorRings.length);
- wkb.writeUInt32LE(this.exteriorRing.length);
- }
- else {
- wkb.writeUInt32LE(0);
- }
- for (var i = 0; i < this.exteriorRing.length; i++)
- this.exteriorRing[i]._writeWkbPoint(wkb);
- for (i = 0; i < this.interiorRings.length; i++) {
- wkb.writeUInt32LE(this.interiorRings[i].length);
- for (var j = 0; j < this.interiorRings[i].length; j++)
- this.interiorRings[i][j]._writeWkbPoint(wkb);
- }
- return wkb.buffer;
- };
- Polygon.prototype.toTwkb = function () {
- var twkb = new BinaryWriter(0, true);
- var precision = Geometry.getTwkbPrecision(5, 0, 0);
- var isEmpty = this.exteriorRing.length === 0;
- this._writeTwkbHeader(twkb, Types.wkb.Polygon, precision, isEmpty);
- if (this.exteriorRing.length > 0) {
- twkb.writeVarInt(1 + this.interiorRings.length);
- twkb.writeVarInt(this.exteriorRing.length);
- var previousPoint = new Point(0, 0, 0, 0);
- for (var i = 0; i < this.exteriorRing.length; i++)
- this.exteriorRing[i]._writeTwkbPoint(twkb, precision, previousPoint);
- for (i = 0; i < this.interiorRings.length; i++) {
- twkb.writeVarInt(this.interiorRings[i].length);
- for (var j = 0; j < this.interiorRings[i].length; j++)
- this.interiorRings[i][j]._writeTwkbPoint(twkb, precision, previousPoint);
- }
- }
- return twkb.buffer;
- };
- Polygon.prototype._getWkbSize = function () {
- var coordinateSize = 16;
- if (this.hasZ)
- coordinateSize += 8;
- if (this.hasM)
- coordinateSize += 8;
- var size = 1 + 4 + 4;
- if (this.exteriorRing.length > 0)
- size += 4 + (this.exteriorRing.length * coordinateSize);
- for (var i = 0; i < this.interiorRings.length; i++)
- size += 4 + (this.interiorRings[i].length * coordinateSize);
- return size;
- };
- Polygon.prototype.toGeoJSON = function (options) {
- var geoJSON = Geometry.prototype.toGeoJSON.call(this, options);
- geoJSON.type = Types.geoJSON.Polygon;
- geoJSON.coordinates = [];
- if (this.exteriorRing.length > 0) {
- var exteriorRing = [];
- for (var i = 0; i < this.exteriorRing.length; i++) {
- if (this.hasZ)
- exteriorRing.push([this.exteriorRing[i].x, this.exteriorRing[i].y, this.exteriorRing[i].z]);
- else
- exteriorRing.push([this.exteriorRing[i].x, this.exteriorRing[i].y]);
- }
- geoJSON.coordinates.push(exteriorRing);
- }
- for (var j = 0; j < this.interiorRings.length; j++) {
- var interiorRing = [];
- for (var k = 0; k < this.interiorRings[j].length; k++) {
- if (this.hasZ)
- interiorRing.push([this.interiorRings[j][k].x, this.interiorRings[j][k].y, this.interiorRings[j][k].z]);
- else
- interiorRing.push([this.interiorRings[j][k].x, this.interiorRings[j][k].y]);
- }
- geoJSON.coordinates.push(interiorRing);
- }
- return geoJSON;
- };
|