227 lines
4.7 KiB
JavaScript
227 lines
4.7 KiB
JavaScript
var numberRegexp = /[-+]?([0-9]*\.[0-9]+|[0-9]+)([eE][-+]?[0-9]+)?/;
|
|
// Matches sequences like '100 100' or '100 100 100'.
|
|
var tuples = new RegExp('^' + numberRegexp.source + '(\\s' + numberRegexp.source + '){1,}');
|
|
/*
|
|
* Parse WKT and return GeoJSON.
|
|
*
|
|
* @param {string} _ A WKT geometry
|
|
* @return {?Object} A GeoJSON geometry object
|
|
*/
|
|
const parse = function(input) {
|
|
if (!input) {
|
|
return {
|
|
"coordinates": [],
|
|
"type": "LineString"
|
|
}
|
|
}
|
|
var parts = input.split(';');
|
|
var _ = parts.pop();
|
|
var srid = (parts.shift() || '').split('=').pop();
|
|
|
|
var i = 0;
|
|
|
|
function $(re) {
|
|
var match = _.substring(i).match(re);
|
|
if (!match) return null;
|
|
else {
|
|
i += match[0].length;
|
|
return match[0];
|
|
}
|
|
}
|
|
|
|
function crs(obj) {
|
|
if (obj && srid.match(/\d+/)) {
|
|
obj.crs = {
|
|
type: 'name',
|
|
properties: {
|
|
name: 'urn:ogc:def:crs:EPSG::' + srid
|
|
}
|
|
};
|
|
}
|
|
|
|
return obj;
|
|
}
|
|
|
|
function white() { $(/^\s*/); }
|
|
|
|
function multicoords() {
|
|
white();
|
|
var depth = 0;
|
|
var rings = [];
|
|
var stack = [rings];
|
|
var pointer = rings;
|
|
var elem;
|
|
|
|
while (elem =
|
|
$(/^(\()/) ||
|
|
$(/^(\))/) ||
|
|
$(/^(,)/) ||
|
|
$(tuples)) {
|
|
if (elem === '(') {
|
|
stack.push(pointer);
|
|
pointer = [];
|
|
stack[stack.length - 1].push(pointer);
|
|
depth++;
|
|
} else if (elem === ')') {
|
|
// For the case: Polygon(), ...
|
|
if (pointer.length === 0) return null;
|
|
|
|
pointer = stack.pop();
|
|
// the stack was empty, input was malformed
|
|
if (!pointer) return null;
|
|
depth--;
|
|
if (depth === 0) break;
|
|
} else if (elem === ',') {
|
|
pointer = [];
|
|
stack[stack.length - 1].push(pointer);
|
|
} else if (!elem.split(/\s/g).some(isNaN)) {
|
|
Array.prototype.push.apply(pointer, elem.split(/\s/g).map(parseFloat));
|
|
} else {
|
|
return null;
|
|
}
|
|
white();
|
|
}
|
|
|
|
if (depth !== 0) return null;
|
|
|
|
return rings;
|
|
}
|
|
|
|
function coords() {
|
|
var list = [];
|
|
var item;
|
|
var pt;
|
|
while (pt =
|
|
$(tuples) ||
|
|
$(/^(,)/)) {
|
|
if (pt === ',') {
|
|
list.push(item);
|
|
item = [];
|
|
} else if (!pt.split(/\s/g).some(isNaN)) {
|
|
if (!item) item = [];
|
|
Array.prototype.push.apply(item, pt.split(/\s/g).map(parseFloat));
|
|
}
|
|
white();
|
|
}
|
|
|
|
if (item) list.push(item);
|
|
else return null;
|
|
|
|
return list.length ? list : null;
|
|
}
|
|
|
|
function point() {
|
|
if (!$(/^(point(\sz)?)/i)) return null;
|
|
white();
|
|
if (!$(/^(\()/)) return null;
|
|
var c = coords();
|
|
if (!c) return null;
|
|
white();
|
|
if (!$(/^(\))/)) return null;
|
|
return {
|
|
type: 'Point',
|
|
coordinates: c[0]
|
|
};
|
|
}
|
|
|
|
function multipoint() {
|
|
if (!$(/^(multipoint)/i)) return null;
|
|
white();
|
|
var newCoordsFormat = _
|
|
.substring(_.indexOf('(') + 1, _.length - 1)
|
|
.replace(/\(/g, '')
|
|
.replace(/\)/g, '');
|
|
_ = 'MULTIPOINT (' + newCoordsFormat + ')';
|
|
var c = multicoords();
|
|
if (!c) return null;
|
|
white();
|
|
return {
|
|
type: 'MultiPoint',
|
|
coordinates: c
|
|
};
|
|
}
|
|
|
|
function multilinestring() {
|
|
if (!$(/^(multilinestring)/i)) return null;
|
|
white();
|
|
var c = multicoords();
|
|
if (!c) return null;
|
|
white();
|
|
return {
|
|
type: 'MultiLineString',
|
|
coordinates: c
|
|
};
|
|
}
|
|
|
|
function linestring() {
|
|
if (!$(/^(linestring(\sz)?)/i)) return null;
|
|
white();
|
|
if (!$(/^(\()/)) return null;
|
|
var c = coords();
|
|
if (!c) return null;
|
|
if (!$(/^(\))/)) return null;
|
|
return {
|
|
type: 'LineString',
|
|
coordinates: c
|
|
};
|
|
}
|
|
|
|
function polygon() {
|
|
if (!$(/^(polygon(\sz)?)/i)) return null;
|
|
white();
|
|
var c = multicoords();
|
|
if (!c) return null;
|
|
return {
|
|
type: 'Polygon',
|
|
coordinates: c
|
|
};
|
|
}
|
|
|
|
function multipolygon() {
|
|
if (!$(/^(multipolygon)/i)) return null;
|
|
white();
|
|
var c = multicoords();
|
|
if (!c) return null;
|
|
return {
|
|
type: 'MultiPolygon',
|
|
coordinates: c
|
|
};
|
|
}
|
|
|
|
function geometrycollection() {
|
|
var geometries = [];
|
|
var geometry;
|
|
|
|
if (!$(/^(geometrycollection)/i)) return null;
|
|
white();
|
|
|
|
if (!$(/^(\()/)) return null;
|
|
while (geometry = root()) {
|
|
geometries.push(geometry);
|
|
white();
|
|
$(/^(,)/);
|
|
white();
|
|
}
|
|
if (!$(/^(\))/)) return null;
|
|
|
|
return {
|
|
type: 'GeometryCollection',
|
|
geometries: geometries
|
|
};
|
|
}
|
|
|
|
function root() {
|
|
return point() ||
|
|
linestring() ||
|
|
polygon() ||
|
|
multipoint() ||
|
|
multilinestring() ||
|
|
multipolygon() ||
|
|
geometrycollection();
|
|
}
|
|
|
|
return crs(root());
|
|
}
|
|
module.exports = {
|
|
parse: parse
|
|
} |