multipolygon.js 6.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226
  1. module.exports = MultiPolygon;
  2. var util = require('util');
  3. var Types = require('./types');
  4. var Geometry = require('./geometry');
  5. var Point = require('./point');
  6. var Polygon = require('./polygon');
  7. var BinaryWriter = require('./binarywriter');
  8. function MultiPolygon(polygons, srid) {
  9. Geometry.call(this);
  10. this.polygons = polygons || [];
  11. this.srid = srid;
  12. if (this.polygons.length > 0) {
  13. this.hasZ = this.polygons[0].hasZ;
  14. this.hasM = this.polygons[0].hasM;
  15. }
  16. }
  17. util.inherits(MultiPolygon, Geometry);
  18. MultiPolygon.Z = function (polygons, srid) {
  19. var multiPolygon = new MultiPolygon(polygons, srid);
  20. multiPolygon.hasZ = true;
  21. return multiPolygon;
  22. };
  23. MultiPolygon.M = function (polygons, srid) {
  24. var multiPolygon = new MultiPolygon(polygons, srid);
  25. multiPolygon.hasM = true;
  26. return multiPolygon;
  27. };
  28. MultiPolygon.ZM = function (polygons, srid) {
  29. var multiPolygon = new MultiPolygon(polygons, srid);
  30. multiPolygon.hasZ = true;
  31. multiPolygon.hasM = true;
  32. return multiPolygon;
  33. };
  34. MultiPolygon._parseWkt = function (value, options) {
  35. var multiPolygon = new MultiPolygon();
  36. multiPolygon.srid = options.srid;
  37. multiPolygon.hasZ = options.hasZ;
  38. multiPolygon.hasM = options.hasM;
  39. if (value.isMatch(['EMPTY']))
  40. return multiPolygon;
  41. value.expectGroupStart();
  42. do {
  43. value.expectGroupStart();
  44. var exteriorRing = [];
  45. var interiorRings = [];
  46. value.expectGroupStart();
  47. exteriorRing.push.apply(exteriorRing, value.matchCoordinates(options));
  48. value.expectGroupEnd();
  49. while (value.isMatch([','])) {
  50. value.expectGroupStart();
  51. interiorRings.push(value.matchCoordinates(options));
  52. value.expectGroupEnd();
  53. }
  54. multiPolygon.polygons.push(new Polygon(exteriorRing, interiorRings));
  55. value.expectGroupEnd();
  56. } while (value.isMatch([',']));
  57. value.expectGroupEnd();
  58. return multiPolygon;
  59. };
  60. MultiPolygon._parseWkb = function (value, options) {
  61. var multiPolygon = new MultiPolygon();
  62. multiPolygon.srid = options.srid;
  63. multiPolygon.hasZ = options.hasZ;
  64. multiPolygon.hasM = options.hasM;
  65. var polygonCount = value.readUInt32();
  66. for (var i = 0; i < polygonCount; i++)
  67. multiPolygon.polygons.push(Geometry.parse(value, options));
  68. return multiPolygon;
  69. };
  70. MultiPolygon._parseTwkb = function (value, options) {
  71. var multiPolygon = new MultiPolygon();
  72. multiPolygon.hasZ = options.hasZ;
  73. multiPolygon.hasM = options.hasM;
  74. if (options.isEmpty)
  75. return multiPolygon;
  76. var previousPoint = new Point(0, 0, options.hasZ ? 0 : undefined, options.hasM ? 0 : undefined);
  77. var polygonCount = value.readVarInt();
  78. for (var i = 0; i < polygonCount; i++) {
  79. var polygon = new Polygon();
  80. polygon.hasZ = options.hasZ;
  81. polygon.hasM = options.hasM;
  82. var ringCount = value.readVarInt();
  83. var exteriorRingCount = value.readVarInt();
  84. for (var j = 0; j < exteriorRingCount; j++)
  85. polygon.exteriorRing.push(Point._readTwkbPoint(value, options, previousPoint));
  86. for (j = 1; j < ringCount; j++) {
  87. var interiorRing = [];
  88. var interiorRingCount = value.readVarInt();
  89. for (var k = 0; k < interiorRingCount; k++)
  90. interiorRing.push(Point._readTwkbPoint(value, options, previousPoint));
  91. polygon.interiorRings.push(interiorRing);
  92. }
  93. multiPolygon.polygons.push(polygon);
  94. }
  95. return multiPolygon;
  96. };
  97. MultiPolygon._parseGeoJSON = function (value) {
  98. var multiPolygon = new MultiPolygon();
  99. if (value.coordinates.length > 0 && value.coordinates[0].length > 0 && value.coordinates[0][0].length > 0)
  100. multiPolygon.hasZ = value.coordinates[0][0][0].length > 2;
  101. for (var i = 0; i < value.coordinates.length; i++)
  102. multiPolygon.polygons.push(Polygon._parseGeoJSON({ coordinates: value.coordinates[i] }));
  103. return multiPolygon;
  104. };
  105. MultiPolygon.prototype.toWkt = function () {
  106. if (this.polygons.length === 0)
  107. return this._getWktType(Types.wkt.MultiPolygon, true);
  108. var wkt = this._getWktType(Types.wkt.MultiPolygon, false) + '(';
  109. for (var i = 0; i < this.polygons.length; i++)
  110. wkt += this.polygons[i]._toInnerWkt() + ',';
  111. wkt = wkt.slice(0, -1);
  112. wkt += ')';
  113. return wkt;
  114. };
  115. MultiPolygon.prototype.toWkb = function () {
  116. var wkb = new BinaryWriter(this._getWkbSize());
  117. wkb.writeInt8(1);
  118. this._writeWkbType(wkb, Types.wkb.MultiPolygon);
  119. wkb.writeUInt32LE(this.polygons.length);
  120. for (var i = 0; i < this.polygons.length; i++)
  121. wkb.writeBuffer(this.polygons[i].toWkb({ srid: this.srid }));
  122. return wkb.buffer;
  123. };
  124. MultiPolygon.prototype.toTwkb = function () {
  125. var twkb = new BinaryWriter(0, true);
  126. var precision = Geometry.getTwkbPrecision(5, 0, 0);
  127. var isEmpty = this.polygons.length === 0;
  128. this._writeTwkbHeader(twkb, Types.wkb.MultiPolygon, precision, isEmpty);
  129. if (this.polygons.length > 0) {
  130. twkb.writeVarInt(this.polygons.length);
  131. var previousPoint = new Point(0, 0, 0, 0);
  132. for (var i = 0; i < this.polygons.length; i++) {
  133. twkb.writeVarInt(1 + this.polygons[i].interiorRings.length);
  134. twkb.writeVarInt(this.polygons[i].exteriorRing.length);
  135. for (var j = 0; j < this.polygons[i].exteriorRing.length; j++)
  136. this.polygons[i].exteriorRing[j]._writeTwkbPoint(twkb, precision, previousPoint);
  137. for (j = 0; j < this.polygons[i].interiorRings.length; j++) {
  138. twkb.writeVarInt(this.polygons[i].interiorRings[j].length);
  139. for (var k = 0; k < this.polygons[i].interiorRings[j].length; k++)
  140. this.polygons[i].interiorRings[j][k]._writeTwkbPoint(twkb, precision, previousPoint);
  141. }
  142. }
  143. }
  144. return twkb.buffer;
  145. };
  146. MultiPolygon.prototype._getWkbSize = function () {
  147. var size = 1 + 4 + 4;
  148. for (var i = 0; i < this.polygons.length; i++)
  149. size += this.polygons[i]._getWkbSize();
  150. return size;
  151. };
  152. MultiPolygon.prototype.toGeoJSON = function (options) {
  153. var geoJSON = Geometry.prototype.toGeoJSON.call(this, options);
  154. geoJSON.type = Types.geoJSON.MultiPolygon;
  155. geoJSON.coordinates = [];
  156. for (var i = 0; i < this.polygons.length; i++)
  157. geoJSON.coordinates.push(this.polygons[i].toGeoJSON().coordinates);
  158. return geoJSON;
  159. };