123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484 |
- 'use strict';
- var NEUTRAL = 1;
- var KEYWORD = 2;
- var NUMBER = 3;
- var QUOTED = 4;
- var AFTERQUOTE = 5;
- var ENDED = -1;
- var whitespace = /\s/;
- var latin = /[A-Za-z]/;
- var keyword = /[A-Za-z84_]/;
- var endThings = /[,\]]/;
- var digets = /[\d\.E\-\+]/;
- // const ignoredChar = /[\s_\-\/\(\)]/g;
- function Parser(text) {
- if (typeof text !== 'string') {
- throw new Error('not a string');
- }
- this.text = text.trim();
- this.level = 0;
- this.place = 0;
- this.root = null;
- this.stack = [];
- this.currentObject = null;
- this.state = NEUTRAL;
- }
- Parser.prototype.readCharicter = function() {
- var char = this.text[this.place++];
- if (this.state !== QUOTED) {
- while (whitespace.test(char)) {
- if (this.place >= this.text.length) {
- return;
- }
- char = this.text[this.place++];
- }
- }
- switch (this.state) {
- case NEUTRAL:
- return this.neutral(char);
- case KEYWORD:
- return this.keyword(char)
- case QUOTED:
- return this.quoted(char);
- case AFTERQUOTE:
- return this.afterquote(char);
- case NUMBER:
- return this.number(char);
- case ENDED:
- return;
- }
- };
- Parser.prototype.afterquote = function(char) {
- if (char === '"') {
- this.word += '"';
- this.state = QUOTED;
- return;
- }
- if (endThings.test(char)) {
- this.word = this.word.trim();
- this.afterItem(char);
- return;
- }
- throw new Error('havn\'t handled "' +char + '" in afterquote yet, index ' + this.place);
- };
- Parser.prototype.afterItem = function(char) {
- if (char === ',') {
- if (this.word !== null) {
- this.currentObject.push(this.word);
- }
- this.word = null;
- this.state = NEUTRAL;
- return;
- }
- if (char === ']') {
- this.level--;
- if (this.word !== null) {
- this.currentObject.push(this.word);
- this.word = null;
- }
- this.state = NEUTRAL;
- this.currentObject = this.stack.pop();
- if (!this.currentObject) {
- this.state = ENDED;
- }
- return;
- }
- };
- Parser.prototype.number = function(char) {
- if (digets.test(char)) {
- this.word += char;
- return;
- }
- if (endThings.test(char)) {
- this.word = parseFloat(this.word);
- this.afterItem(char);
- return;
- }
- throw new Error('havn\'t handled "' +char + '" in number yet, index ' + this.place);
- };
- Parser.prototype.quoted = function(char) {
- if (char === '"') {
- this.state = AFTERQUOTE;
- return;
- }
- this.word += char;
- return;
- };
- Parser.prototype.keyword = function(char) {
- if (keyword.test(char)) {
- this.word += char;
- return;
- }
- if (char === '[') {
- var newObjects = [];
- newObjects.push(this.word);
- this.level++;
- if (this.root === null) {
- this.root = newObjects;
- } else {
- this.currentObject.push(newObjects);
- }
- this.stack.push(this.currentObject);
- this.currentObject = newObjects;
- this.state = NEUTRAL;
- return;
- }
- if (endThings.test(char)) {
- this.afterItem(char);
- return;
- }
- throw new Error('havn\'t handled "' +char + '" in keyword yet, index ' + this.place);
- };
- Parser.prototype.neutral = function(char) {
- if (latin.test(char)) {
- this.word = char;
- this.state = KEYWORD;
- return;
- }
- if (char === '"') {
- this.word = '';
- this.state = QUOTED;
- return;
- }
- if (digets.test(char)) {
- this.word = char;
- this.state = NUMBER;
- return;
- }
- if (endThings.test(char)) {
- this.afterItem(char);
- return;
- }
- throw new Error('havn\'t handled "' +char + '" in neutral yet, index ' + this.place);
- };
- Parser.prototype.output = function() {
- while (this.place < this.text.length) {
- this.readCharicter();
- }
- if (this.state === ENDED) {
- return this.root;
- }
- throw new Error('unable to parse string "' +this.text + '". State is ' + this.state);
- };
- function parseString(txt) {
- var parser = new Parser(txt);
- return parser.output();
- }
- function mapit(obj, key, value) {
- if (Array.isArray(key)) {
- value.unshift(key);
- key = null;
- }
- var thing = key ? {} : obj;
- var out = value.reduce(function(newObj, item) {
- sExpr(item, newObj);
- return newObj
- }, thing);
- if (key) {
- obj[key] = out;
- }
- }
- function sExpr(v, obj) {
- if (!Array.isArray(v)) {
- obj[v] = true;
- return;
- }
- var key = v.shift();
- if (key === 'PARAMETER') {
- key = v.shift();
- }
- if (v.length === 1) {
- if (Array.isArray(v[0])) {
- obj[key] = {};
- sExpr(v[0], obj[key]);
- return;
- }
- obj[key] = v[0];
- return;
- }
- if (!v.length) {
- obj[key] = true;
- return;
- }
- if (key === 'TOWGS84') {
- obj[key] = v;
- return;
- }
- if (key === 'AXIS') {
- if (!(key in obj)) {
- obj[key] = [];
- }
- obj[key].push(v);
- return;
- }
- if (!Array.isArray(key)) {
- obj[key] = {};
- }
- var i;
- switch (key) {
- case 'UNIT':
- case 'PRIMEM':
- case 'VERT_DATUM':
- obj[key] = {
- name: v[0].toLowerCase(),
- convert: v[1]
- };
- if (v.length === 3) {
- sExpr(v[2], obj[key]);
- }
- return;
- case 'SPHEROID':
- case 'ELLIPSOID':
- obj[key] = {
- name: v[0],
- a: v[1],
- rf: v[2]
- };
- if (v.length === 4) {
- sExpr(v[3], obj[key]);
- }
- return;
- case 'PROJECTEDCRS':
- case 'PROJCRS':
- case 'GEOGCS':
- case 'GEOCCS':
- case 'PROJCS':
- case 'LOCAL_CS':
- case 'GEODCRS':
- case 'GEODETICCRS':
- case 'GEODETICDATUM':
- case 'EDATUM':
- case 'ENGINEERINGDATUM':
- case 'VERT_CS':
- case 'VERTCRS':
- case 'VERTICALCRS':
- case 'COMPD_CS':
- case 'COMPOUNDCRS':
- case 'ENGINEERINGCRS':
- case 'ENGCRS':
- case 'FITTED_CS':
- case 'LOCAL_DATUM':
- case 'DATUM':
- v[0] = ['name', v[0]];
- mapit(obj, key, v);
- return;
- default:
- i = -1;
- while (++i < v.length) {
- if (!Array.isArray(v[i])) {
- return sExpr(v, obj[key]);
- }
- }
- return mapit(obj, key, v);
- }
- }
- var D2R = 0.01745329251994329577;
- function rename(obj, params) {
- var outName = params[0];
- var inName = params[1];
- if (!(outName in obj) && (inName in obj)) {
- obj[outName] = obj[inName];
- if (params.length === 3) {
- obj[outName] = params[2](obj[outName]);
- }
- }
- }
- function d2r(input) {
- return input * D2R;
- }
- function cleanWKT(wkt) {
- if (wkt.type === 'GEOGCS') {
- wkt.projName = 'longlat';
- } else if (wkt.type === 'LOCAL_CS') {
- wkt.projName = 'identity';
- wkt.local = true;
- } else {
- if (typeof wkt.PROJECTION === 'object') {
- wkt.projName = Object.keys(wkt.PROJECTION)[0];
- } else {
- wkt.projName = wkt.PROJECTION;
- }
- }
- if (wkt.AXIS) {
- var axisOrder = '';
- for (var i = 0, ii = wkt.AXIS.length; i < ii; ++i) {
- var axis = [wkt.AXIS[i][0].toLowerCase(), wkt.AXIS[i][1].toLowerCase()];
- if (axis[0].indexOf('north') !== -1 || ((axis[0] === 'y' || axis[0] === 'lat') && axis[1] === 'north')) {
- axisOrder += 'n';
- } else if (axis[0].indexOf('south') !== -1 || ((axis[0] === 'y' || axis[0] === 'lat') && axis[1] === 'south')) {
- axisOrder += 's';
- } else if (axis[0].indexOf('east') !== -1 || ((axis[0] === 'x' || axis[0] === 'lon') && axis[1] === 'east')) {
- axisOrder += 'e';
- } else if (axis[0].indexOf('west') !== -1 || ((axis[0] === 'x' || axis[0] === 'lon') && axis[1] === 'west')) {
- axisOrder += 'w';
- }
- }
- if (axisOrder.length === 2) {
- axisOrder += 'u';
- }
- if (axisOrder.length === 3) {
- wkt.axis = axisOrder;
- }
- }
- if (wkt.UNIT) {
- wkt.units = wkt.UNIT.name.toLowerCase();
- if (wkt.units === 'metre') {
- wkt.units = 'meter';
- }
- if (wkt.UNIT.convert) {
- if (wkt.type === 'GEOGCS') {
- if (wkt.DATUM && wkt.DATUM.SPHEROID) {
- wkt.to_meter = wkt.UNIT.convert*wkt.DATUM.SPHEROID.a;
- }
- } else {
- wkt.to_meter = wkt.UNIT.convert;
- }
- }
- }
- var geogcs = wkt.GEOGCS;
- if (wkt.type === 'GEOGCS') {
- geogcs = wkt;
- }
- if (geogcs) {
- //if(wkt.GEOGCS.PRIMEM&&wkt.GEOGCS.PRIMEM.convert){
- // wkt.from_greenwich=wkt.GEOGCS.PRIMEM.convert*D2R;
- //}
- if (geogcs.DATUM) {
- wkt.datumCode = geogcs.DATUM.name.toLowerCase();
- } else {
- wkt.datumCode = geogcs.name.toLowerCase();
- }
- if (wkt.datumCode.slice(0, 2) === 'd_') {
- wkt.datumCode = wkt.datumCode.slice(2);
- }
- if (wkt.datumCode === 'new_zealand_geodetic_datum_1949' || wkt.datumCode === 'new_zealand_1949') {
- wkt.datumCode = 'nzgd49';
- }
- if (wkt.datumCode === 'wgs_1984' || wkt.datumCode === 'world_geodetic_system_1984') {
- if (wkt.PROJECTION === 'Mercator_Auxiliary_Sphere') {
- wkt.sphere = true;
- }
- wkt.datumCode = 'wgs84';
- }
- if (wkt.datumCode.slice(-6) === '_ferro') {
- wkt.datumCode = wkt.datumCode.slice(0, - 6);
- }
- if (wkt.datumCode.slice(-8) === '_jakarta') {
- wkt.datumCode = wkt.datumCode.slice(0, - 8);
- }
- if (~wkt.datumCode.indexOf('belge')) {
- wkt.datumCode = 'rnb72';
- }
- if (geogcs.DATUM && geogcs.DATUM.SPHEROID) {
- wkt.ellps = geogcs.DATUM.SPHEROID.name.replace('_19', '').replace(/[Cc]larke\_18/, 'clrk');
- if (wkt.ellps.toLowerCase().slice(0, 13) === 'international') {
- wkt.ellps = 'intl';
- }
- wkt.a = geogcs.DATUM.SPHEROID.a;
- wkt.rf = parseFloat(geogcs.DATUM.SPHEROID.rf, 10);
- }
- if (geogcs.DATUM && geogcs.DATUM.TOWGS84) {
- wkt.datum_params = geogcs.DATUM.TOWGS84;
- }
- if (~wkt.datumCode.indexOf('osgb_1936')) {
- wkt.datumCode = 'osgb36';
- }
- if (~wkt.datumCode.indexOf('osni_1952')) {
- wkt.datumCode = 'osni52';
- }
- if (~wkt.datumCode.indexOf('tm65')
- || ~wkt.datumCode.indexOf('geodetic_datum_of_1965')) {
- wkt.datumCode = 'ire65';
- }
- if (wkt.datumCode === 'ch1903+') {
- wkt.datumCode = 'ch1903';
- }
- if (~wkt.datumCode.indexOf('israel')) {
- wkt.datumCode = 'isr93';
- }
- }
- if (wkt.b && !isFinite(wkt.b)) {
- wkt.b = wkt.a;
- }
- function toMeter(input) {
- var ratio = wkt.to_meter || 1;
- return input * ratio;
- }
- var renamer = function(a) {
- return rename(wkt, a);
- };
- var list = [
- ['standard_parallel_1', 'Standard_Parallel_1'],
- ['standard_parallel_1', 'Latitude of 1st standard parallel'],
- ['standard_parallel_2', 'Standard_Parallel_2'],
- ['standard_parallel_2', 'Latitude of 2nd standard parallel'],
- ['false_easting', 'False_Easting'],
- ['false_easting', 'False easting'],
- ['false-easting', 'Easting at false origin'],
- ['false_northing', 'False_Northing'],
- ['false_northing', 'False northing'],
- ['false_northing', 'Northing at false origin'],
- ['central_meridian', 'Central_Meridian'],
- ['central_meridian', 'Longitude of natural origin'],
- ['central_meridian', 'Longitude of false origin'],
- ['latitude_of_origin', 'Latitude_Of_Origin'],
- ['latitude_of_origin', 'Central_Parallel'],
- ['latitude_of_origin', 'Latitude of natural origin'],
- ['latitude_of_origin', 'Latitude of false origin'],
- ['scale_factor', 'Scale_Factor'],
- ['k0', 'scale_factor'],
- ['latitude_of_center', 'Latitude_Of_Center'],
- ['latitude_of_center', 'Latitude_of_center'],
- ['lat0', 'latitude_of_center', d2r],
- ['longitude_of_center', 'Longitude_Of_Center'],
- ['longitude_of_center', 'Longitude_of_center'],
- ['longc', 'longitude_of_center', d2r],
- ['x0', 'false_easting', toMeter],
- ['y0', 'false_northing', toMeter],
- ['long0', 'central_meridian', d2r],
- ['lat0', 'latitude_of_origin', d2r],
- ['lat0', 'standard_parallel_1', d2r],
- ['lat1', 'standard_parallel_1', d2r],
- ['lat2', 'standard_parallel_2', d2r],
- ['azimuth', 'Azimuth'],
- ['alpha', 'azimuth', d2r],
- ['srsCode', 'name']
- ];
- list.forEach(renamer);
- if (!wkt.long0 && wkt.longc && (wkt.projName === 'Albers_Conic_Equal_Area' || wkt.projName === 'Lambert_Azimuthal_Equal_Area')) {
- wkt.long0 = wkt.longc;
- }
- if (!wkt.lat_ts && wkt.lat1 && (wkt.projName === 'Stereographic_South_Pole' || wkt.projName === 'Polar Stereographic (variant B)')) {
- wkt.lat0 = d2r(wkt.lat1 > 0 ? 90 : -90);
- wkt.lat_ts = wkt.lat1;
- } else if (!wkt.lat_ts && wkt.lat0 && wkt.projName === 'Polar_Stereographic') {
- wkt.lat_ts = wkt.lat0;
- wkt.lat0 = d2r(wkt.lat0 > 0 ? 90 : -90);
- }
- }
- var index = function(wkt) {
- var lisp = parseString(wkt);
- var type = lisp.shift();
- var name = lisp.shift();
- lisp.unshift(['name', name]);
- lisp.unshift(['type', type]);
- var obj = {};
- sExpr(lisp, obj);
- cleanWKT(obj);
- return obj;
- };
- module.exports = index;
|