module.exports = WktParser; var Types = require('./types'); var Point = require('./point'); function WktParser(value) { this.value = value; this.position = 0; } WktParser.prototype.match = function (tokens) { this.skipWhitespaces(); for (var i = 0; i < tokens.length; i++) { if (this.value.substring(this.position).indexOf(tokens[i]) === 0) { this.position += tokens[i].length; return tokens[i]; } } return null; }; WktParser.prototype.matchRegex = function (tokens) { this.skipWhitespaces(); for (var i = 0; i < tokens.length; i++) { var match = this.value.substring(this.position).match(tokens[i]); if (match) { this.position += match[0].length; return match; } } return null; }; WktParser.prototype.isMatch = function (tokens) { this.skipWhitespaces(); for (var i = 0; i < tokens.length; i++) { if (this.value.substring(this.position).indexOf(tokens[i]) === 0) { this.position += tokens[i].length; return true; } } return false; }; WktParser.prototype.matchType = function () { var geometryType = this.match([Types.wkt.Point, Types.wkt.LineString, Types.wkt.Polygon, Types.wkt.MultiPoint, Types.wkt.MultiLineString, Types.wkt.MultiPolygon, Types.wkt.GeometryCollection]); if (!geometryType) throw new Error('Expected geometry type'); return geometryType; }; WktParser.prototype.matchDimension = function () { var dimension = this.match(['ZM', 'Z', 'M']); switch (dimension) { case 'ZM': return { hasZ: true, hasM: true }; case 'Z': return { hasZ: true, hasM: false }; case 'M': return { hasZ: false, hasM: true }; default: return { hasZ: false, hasM: false }; } }; WktParser.prototype.expectGroupStart = function () { if (!this.isMatch(['('])) throw new Error('Expected group start'); }; WktParser.prototype.expectGroupEnd = function () { if (!this.isMatch([')'])) throw new Error('Expected group end'); }; WktParser.prototype.matchCoordinate = function (options) { var match; if (options.hasZ && options.hasM) match = this.matchRegex([/^(\S*)\s+(\S*)\s+(\S*)\s+([^\s,)]*)/]); else if (options.hasZ || options.hasM) match = this.matchRegex([/^(\S*)\s+(\S*)\s+([^\s,)]*)/]); else match = this.matchRegex([/^(\S*)\s+([^\s,)]*)/]); if (!match) throw new Error('Expected coordinates'); if (options.hasZ && options.hasM) return new Point(parseFloat(match[1]), parseFloat(match[2]), parseFloat(match[3]), parseFloat(match[4])); else if (options.hasZ) return new Point(parseFloat(match[1]), parseFloat(match[2]), parseFloat(match[3])); else if (options.hasM) return new Point(parseFloat(match[1]), parseFloat(match[2]), undefined, parseFloat(match[3])); else return new Point(parseFloat(match[1]), parseFloat(match[2])); }; WktParser.prototype.matchCoordinates = function (options) { var coordinates = []; do { var startsWithBracket = this.isMatch(['(']); coordinates.push(this.matchCoordinate(options)); if (startsWithBracket) this.expectGroupEnd(); } while (this.isMatch([','])); return coordinates; }; WktParser.prototype.skipWhitespaces = function () { while (this.position < this.value.length && this.value[this.position] === ' ') this.position++; };