wktparser.js 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124
  1. module.exports = WktParser;
  2. var Types = require('./types');
  3. var Point = require('./point');
  4. function WktParser(value) {
  5. this.value = value;
  6. this.position = 0;
  7. }
  8. WktParser.prototype.match = function (tokens) {
  9. this.skipWhitespaces();
  10. for (var i = 0; i < tokens.length; i++) {
  11. if (this.value.substring(this.position).indexOf(tokens[i]) === 0) {
  12. this.position += tokens[i].length;
  13. return tokens[i];
  14. }
  15. }
  16. return null;
  17. };
  18. WktParser.prototype.matchRegex = function (tokens) {
  19. this.skipWhitespaces();
  20. for (var i = 0; i < tokens.length; i++) {
  21. var match = this.value.substring(this.position).match(tokens[i]);
  22. if (match) {
  23. this.position += match[0].length;
  24. return match;
  25. }
  26. }
  27. return null;
  28. };
  29. WktParser.prototype.isMatch = function (tokens) {
  30. this.skipWhitespaces();
  31. for (var i = 0; i < tokens.length; i++) {
  32. if (this.value.substring(this.position).indexOf(tokens[i]) === 0) {
  33. this.position += tokens[i].length;
  34. return true;
  35. }
  36. }
  37. return false;
  38. };
  39. WktParser.prototype.matchType = function () {
  40. var geometryType = this.match([Types.wkt.Point, Types.wkt.LineString, Types.wkt.Polygon, Types.wkt.MultiPoint,
  41. Types.wkt.MultiLineString, Types.wkt.MultiPolygon, Types.wkt.GeometryCollection]);
  42. if (!geometryType)
  43. throw new Error('Expected geometry type');
  44. return geometryType;
  45. };
  46. WktParser.prototype.matchDimension = function () {
  47. var dimension = this.match(['ZM', 'Z', 'M']);
  48. switch (dimension) {
  49. case 'ZM': return { hasZ: true, hasM: true };
  50. case 'Z': return { hasZ: true, hasM: false };
  51. case 'M': return { hasZ: false, hasM: true };
  52. default: return { hasZ: false, hasM: false };
  53. }
  54. };
  55. WktParser.prototype.expectGroupStart = function () {
  56. if (!this.isMatch(['(']))
  57. throw new Error('Expected group start');
  58. };
  59. WktParser.prototype.expectGroupEnd = function () {
  60. if (!this.isMatch([')']))
  61. throw new Error('Expected group end');
  62. };
  63. WktParser.prototype.matchCoordinate = function (options) {
  64. var match;
  65. if (options.hasZ && options.hasM)
  66. match = this.matchRegex([/^(\S*)\s+(\S*)\s+(\S*)\s+([^\s,)]*)/]);
  67. else if (options.hasZ || options.hasM)
  68. match = this.matchRegex([/^(\S*)\s+(\S*)\s+([^\s,)]*)/]);
  69. else
  70. match = this.matchRegex([/^(\S*)\s+([^\s,)]*)/]);
  71. if (!match)
  72. throw new Error('Expected coordinates');
  73. if (options.hasZ && options.hasM)
  74. return new Point(parseFloat(match[1]), parseFloat(match[2]), parseFloat(match[3]), parseFloat(match[4]));
  75. else if (options.hasZ)
  76. return new Point(parseFloat(match[1]), parseFloat(match[2]), parseFloat(match[3]));
  77. else if (options.hasM)
  78. return new Point(parseFloat(match[1]), parseFloat(match[2]), undefined, parseFloat(match[3]));
  79. else
  80. return new Point(parseFloat(match[1]), parseFloat(match[2]));
  81. };
  82. WktParser.prototype.matchCoordinates = function (options) {
  83. var coordinates = [];
  84. do {
  85. var startsWithBracket = this.isMatch(['(']);
  86. coordinates.push(this.matchCoordinate(options));
  87. if (startsWithBracket)
  88. this.expectGroupEnd();
  89. } while (this.isMatch([',']));
  90. return coordinates;
  91. };
  92. WktParser.prototype.skipWhitespaces = function () {
  93. while (this.position < this.value.length && this.value[this.position] === ' ')
  94. this.position++;
  95. };