UNPKG

osm2geojson-lite

Version:

a lightweight yet faster osm (either in xml or in json formats) to geojson convertor - 4x faster than xmldom + osmtogeojson in most situations - implemented in pure JavaScript without any 3rd party dependency

1 lines 15.3 kB
!function(e){"object"==typeof exports&&"undefined"!=typeof module?module.exports=e():"function"==typeof define&&define.amd?define([],e):("undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof self?self:this).osm2geojson=e()}(function(){return function s(o,i,n){function a(t,e){if(!i[t]){if(!o[t]){var r="function"==typeof require&&require;if(!e&&r)return r(t,!0);if(l)return l(t,!0);throw(e=new Error("Cannot find module '"+t+"'")).code="MODULE_NOT_FOUND",e}r=i[t]={exports:{}},o[t][0].call(r.exports,function(e){return a(o[t][1][e]||e)},r,r.exports,s,o,i,n)}return i[t].exports}for(var l="function"==typeof require&&require,e=0;e<n.length;e++)a(n[e]);return a}({1:[function(e,t,r){let v=e("./utils"),b=e("./xmlparser"),w=e("./node"),x=e("./way"),L=e("./relation"),T=e("./ref-elements");t.exports=function(e,t){var{completeFeature:r,renderTagged:s,excludeWay:o}=(t=t)?(a=void 0===t.excludeWay||t.excludeWay,{completeFeature:!!t.completeFeature,renderTagged:!!t.renderTagged,excludeWay:a}):{completeFeature:!1,renderTagged:!1,excludeWay:!0};let i=(t=e).elements?"json":0<=t.indexOf("<osm")?"xml":t.trim().startsWith("{")?"json-raw":"invalid";var l,n,a=new T.RefElements;let d=[];if("json-raw"===i&&(e=JSON.parse(e),i=e.elements?"json":"invalid"),"json"===i){var u,h=a;for(u of e.elements)switch(u.type){case"node":var f=new w.Node(u.id,h);u.tags&&f.addTags(u.tags),f.addProps((0,v.purgeProps)(u,["id","type","tags","lat","lon"])),f.setLatLng(u);break;case"way":var c=new x.Way(u.id,h);if(u.tags&&c.addTags(u.tags),c.addProps((0,v.purgeProps)(u,["id","type","tags","nodes","geometry"])),u.geometry)c.setLatLngArray(u.geometry);else if(u.nodes)for(var p of u.nodes)c.addNodeRef(p);break;case"relation":var g=new L.Relation(u.id,h);if(u.bounds&&g.setBounds([parseFloat(u.bounds.minlon),parseFloat(u.bounds.minlat),parseFloat(u.bounds.maxlon),parseFloat(u.bounds.maxlat)]),u.tags&&g.addTags(u.tags),g.addProps((0,v.purgeProps)(u,["id","type","tags","bounds","members"])),u.members)for(var y of u.members)g.addMember(y)}}else"xml"===i&&(t=e,l=a,(e=new b.XmlParser({progressive:!0})).on("</osm.node>",e=>{var t,r,s=new w.Node(e.id,l);for([t,r]of Object.entries(e))!t.startsWith("$")&&["id","lon","lat"].indexOf(t)<0&&s.addProp(t,r);if(s.setLatLng(e),e.$innerNodes)for(var o of e.$innerNodes)"tag"===o.$tag&&s.addTag(o.k,o.v)}),e.on("</osm.way>",e=>{var t,r,s=new x.Way(e.id,l);for([t,r]of Object.entries(e))!t.startsWith("$")&&["id"].indexOf(t)<0&&s.addProp(t,r);if(e.$innerNodes)for(var o of e.$innerNodes)"nd"===o.$tag?o.lon&&o.lat?s.addLatLng(o):o.ref&&s.addNodeRef(o.ref):"tag"===o.$tag&&s.addTag(o.k,o.v)}),e.on("<osm.relation>",e=>new L.Relation(e.id,l)),e.on("</osm.relation.member>",(e,t)=>{var t=l.get("relation/"+(null==t?void 0:t.id)),r={type:e.type,role:e.role||"",ref:e.ref};if(e.lat&&e.lon){r.lat=e.lat,r.lon=e.lon,r.tags={};for(var[s,o]of Object.entries(e))!s.startsWith("$")&&["type","lat","lon"].indexOf(s)<0&&(r[s]=o)}if(e.$innerNodes){var i,n=[],a=[];for(i of e.$innerNodes)i.lat&&i.lon?n.push(i):i.ref&&a.push(i.ref);0<n.length?r.geometry=n:0<a.length&&(r.nodes=a)}t.addMember(r)}),e.on("</osm.relation.bounds>",(e,t)=>{l.get("relation/"+(null==t?void 0:t.id)).setBounds([parseFloat(e.minlon),parseFloat(e.minlat),parseFloat(e.maxlon),parseFloat(e.maxlat)])}),e.on("</osm.relation.tag>",(e,t)=>{l.get("relation/"+(null==t?void 0:t.id)).addTag(e.k,e.v)}),e.parse(t));a.bindAll();for(n of a.values())if(!(0<n.refCount)||n.hasTag&&s&&!(n instanceof x.Way&&o)){var m=n.toFeatureArray();if(n instanceof L.Relation&&!r&&0<m.length)return m[0].geometry;d=d.concat(m)}return{type:"FeatureCollection",features:d}}},{"./node":3,"./ref-elements":6,"./relation":7,"./utils":8,"./way":10,"./xmlparser":11}],2:[function(e,t,r){Object.defineProperty(r,"__esModule",{value:!0}),r.LateBinder=void 0;r.LateBinder=class{constructor(e,t,r,s){this.container=e,this.valueFunc=t,this.ctx=r,this.args=s}bind(){var e=this.valueFunc.apply(this.ctx,this.args),t=this.container.indexOf(this);t<0||(t=[t,1],e&&t.push(e),Array.prototype.splice.apply(this.container,t))}}},{}],3:[function(e,t,r){Object.defineProperty(r,"__esModule",{value:!0}),r.Node=void 0;var s=e("./osm-object");let o=e("./utils");class i extends s.OsmObject{constructor(e,t){super("node",e,t)}setLatLng(e){this.latLng=e}toFeatureArray(){return this.latLng?[{type:"Feature",id:this.getCompositeId(),properties:this.getProps(),geometry:{type:"Point",coordinates:(0,o.strArrayToFloat)([this.latLng.lon,this.latLng.lat])}}]:[]}getLatLng(){return this.latLng}}r.Node=i},{"./osm-object":4,"./utils":8}],4:[function(e,t,r){Object.defineProperty(r,"__esModule",{value:!0}),r.OsmObject=void 0;r.OsmObject=class{constructor(e,t,r){this.type=e,this.id=t,this.refElems=r,this.tags={},this.props={id:this.getCompositeId()},this.refCount=0,this.hasTag=!1,r&&r.add(this.getCompositeId(),this)}addTags(e){this.tags=Object.assign(this.tags,e),this.hasTag=!0}addTag(e,t){this.tags[e]=t,this.hasTag=!0}addProp(e,t){this.props[e]=t}addProps(e){this.props=Object.assign(this.props,e)}getCompositeId(){return this.type+"/"+this.id}getProps(){return Object.assign(this.props,this.tags)}}},{}],5:[function(e,t,r){t.exports={building:{},highway:{whitelist:["services","rest_area","escape","elevator"]},natural:{blacklist:["coastline","cliff","ridge","arete","tree_row"]},landuse:{},waterway:{whitelist:["riverbank","dock","boatyard","dam"]},amenity:{},leisure:{},barrier:{whitelist:["city_wall","ditch","hedge","retaining_wall","wall","spikes"]},railway:{whitelist:["station","turntable","roundhouse","platform"]},area:{},boundary:{},man_made:{blacklist:["cutline","embankment","pipeline"]},power:{whitelist:["plant","substation","generator","transformer"]},place:{},shop:{},aeroway:{blacklist:["taxiway"]},tourism:{},historic:{},public_transport:{},office:{},"building:part":{},military:{},ruins:{},"area:highway":{},craft:{},golf:{},indoor:{}}},{}],6:[function(e,t,r){Object.defineProperty(r,"__esModule",{value:!0}),r.RefElements=void 0;class s extends Map{constructor(){super(),this.binders=[]}add(e,t){this.set(e,t)}addBinder(e){this.binders.push(e)}bindAll(){this.binders.forEach(e=>e.bind())}}r.RefElements=s},{}],7:[function(e,t,r){Object.defineProperty(r,"__esModule",{value:!0}),r.Relation=void 0;var s=e("./osm-object");let a=e("./way"),l=e("./node"),g=e("./way-collection"),d=e("./late-binder"),n=e("./utils");class o extends s.OsmObject{constructor(e,t){super("relation",e,t),this.relations=[],this.nodes=[],this.bounds=void 0,this.ways=[],this.roles=[]}setBounds(e){this.bounds=e}addMember(e){switch(e.type){case"relation":var t=new d.LateBinder(this.relations,e=>{e=this.refElems.get("relation/"+e);if(e)return e.refCount++,e},this,[e.ref]);this.relations.push(t),this.refElems.addBinder(t);break;case"way":if(e.role||(e.role=""),e.geometry){t=new a.Way(e.ref,this.refElems);t.setLatLngArray(e.geometry),t.refCount++,this.ways.push(t),this.roles.push(e.role)}else if(e.nodes){var r,s=new a.Way(e.ref,this.refElems);for(r of e.nodes)s.addNodeRef(r);s.refCount++,this.ways.push(s),this.roles.push(e.role)}else{t=new d.LateBinder(this.ways,e=>{e=this.refElems.get("way/"+e);if(e)return e.refCount++,e},this,[e.ref]);this.ways.push(t),this.roles.push(e.role),this.refElems.addBinder(t)}break;case"node":var o=null;if(e.lat&&e.lon){(o=new l.Node(e.ref,this.refElems)).setLatLng({lon:e.lon,lat:e.lat}),e.tags&&o.addTags(e.tags);for(var[i,n]of Object.entries(e))["id","type","lat","lon"].indexOf(i)<0&&o.addProp(i,n);o.refCount++,this.nodes.push(o)}else{t=new d.LateBinder(this.nodes,e=>{e=this.refElems.get("node/"+e);if(e)return e.refCount++,e},this,[e.ref]);this.nodes.push(t),this.refElems.addBinder(t)}}}constructStringGeometry(e){e=e?e.mergeWays():[];return 0===e.length?null:{type:"MultiLineString",coordinates:e}}constructPolygonGeometry(e,t){var r=e?e.toRings("counterclockwise"):[],s=t?t.toRings("clockwise"):[];if(0<r.length){var o=[];let e;for(e of r)o.push([e]);for(e=s.shift();e;){for(var i in r)if((0,n.pointInsidePolygon)((0,n.first)(e),r[i])){o[i].push(e);break}e=s.shift()}return 1===o.length?{type:"Polygon",coordinates:o[0]}:{type:"MultiPolygon",coordinates:o}}return null}toFeatureArray(){var t,e=[],r=[];let s=[];for(t of this.relations)if(t)for(let e=0;e<t.ways.length;e++){var o=t.ways[e];this.ways.push(o),this.roles.push(t.roles[e])}var i,n={type:"Feature",id:this.getCompositeId(),bbox:this.bounds,properties:this.getProps(),geometry:null};if(this.bounds||delete n.bbox,this.roles.some(e=>"outer"===e)){var a=new g.WayCollection,l=new g.WayCollection;for(let e=0;e<this.ways.length;e++){var d=this.ways[e],u=this.roles[e];"outer"===u?a.addWay(d):"inner"===u&&l.addWay(d)}var h=Object.assign({},n),f=this.constructPolygonGeometry(a,l);f&&(h.geometry=f,e.push(h))}else{var c,p=new g.WayCollection;for(c of this.ways)p.addWay(c);f=this.constructStringGeometry(p);f&&((h=Object.assign({},n)).geometry=f,r.push(h))}for(i of this.nodes)s=s.concat(i.toFeatureArray());return[...e,...r,...s]}}r.Relation=o},{"./late-binder":2,"./node":3,"./osm-object":4,"./utils":8,"./way":10,"./way-collection":9}],8:[function(e,t,r){function s(e){return e[0]}function o(e){return e[e.length-1]}function i(e){return e.join(",")}function n(e){return e.map(parseFloat)}Object.defineProperty(r,"__esModule",{value:!0}),r.purgeProps=function(e,t){if(e){var r=Object.assign({},e);if(t)for(var s of t)delete r[s];return r}return{}},r.first=s,r.last=o,r.coordsToKey=i,r.addToMap=function(e,t,r){var s=e[t];s?s.push(r):e[t]=[r]},r.removeFromMap=function(e,t,r){let s=e[t],o=-1;s&&(o=s.indexOf(r));0<=o&&s.splice(o,1)},r.getFirstFromMap=function(e,t){e=e[t];if(e&&0<e.length)return e[0];return null},r.isRing=function(e){return 3<e.length&&i(e[0])===i(o(e))},r.ringDirection=function(s,o,e){o=o||0,e=e||1;var t=s.reduce((e,t,r)=>s[e][o||0]>t[o||0]?e:r,0),r=t<=0?s.length-2:t-1,i=t>=s.length-1?1:t+1,n=s[r][o],a=s[t][o],l=s[i][o],r=s[r][e],t=s[t][e],i=s[i][e],e=(a-n)*(i-r)-(l-n)*(t-r);return e<0?"clockwise":"counterclockwise"},r.pointInsidePolygon=function(r,s,o,i){o=o||0,i=i||1;let n=!1;for(let e=0,t=s.length-1;e<s.length;t=e++)(s[e][o]<=r[o]&&r[o]<s[t][o]||s[t][o]<=r[o]&&r[o]<s[e][o])&&r[i]<(s[t][i]-s[e][i])*(r[o]-s[e][o])/(s[t][o]-s[e][o])+s[e][i]&&(n=!n);return n},r.strArrayArrayToFloat=function(e){return e.map(n)},r.strArrayToFloat=n},{}],9:[function(e,t,r){Object.defineProperty(r,"__esModule",{value:!0}),r.WayCollection=void 0;let i=e("./utils");class s extends Array{constructor(){super(),this.firstMap={},this.lastMap={}}addWay(e){e=e.toCoordsArray();0<e.length&&(this.push(e),(0,i.addToMap)(this.firstMap,(0,i.coordsToKey)((0,i.first)(e)),e),(0,i.addToMap)(this.lastMap,(0,i.coordsToKey)((0,i.last)(e)),e))}mergeWays(){var r=[];let s=this.shift();for(;s;){(0,i.removeFromMap)(this.firstMap,(0,i.coordsToKey)((0,i.first)(s)),s),(0,i.removeFromMap)(this.lastMap,(0,i.coordsToKey)((0,i.last)(s)),s);let e=s,t;do{var o=this.getNextWay(e),o=(t=o.next,o.mergeType);if(t)switch(this.splice(this.indexOf(t),1),(0,i.removeFromMap)(this.firstMap,(0,i.coordsToKey)((0,i.first)(t)),t),(0,i.removeFromMap)(this.lastMap,(0,i.coordsToKey)((0,i.last)(t)),t),o){case 0:e=e.concat(t.slice(1));break;case 1:t.reverse(),e=e.concat(t.slice(1));break;case 2:e.reverse(),e=e.concat(t.slice(1));break;case 3:e=t.concat(e.slice(1))}}while(t);r.push((0,i.strArrayArrayToFloat)(e)),s=this.shift()}return r}getNextWay(e){var t=(0,i.coordsToKey)((0,i.last)(e)),e=(0,i.coordsToKey)((0,i.first)(e)),r=0<this.length?this[0]:null;if(r){var s=(0,i.coordsToKey)((0,i.first)(r)),o=(0,i.coordsToKey)((0,i.last)(r));if(t===s)return{next:r,mergeType:0};if(t===o)return{next:r,mergeType:1};if(e===s)return{next:r,mergeType:2};if(e===o)return{next:r,mergeType:3}}return(r=(0,i.getFirstFromMap)(this.firstMap,t))?{next:r,mergeType:0}:{next:(0,i.getFirstFromMap)(this.lastMap,t),mergeType:1}}toRings(e){var t=this.mergeWays(),r=[];let s=t.shift();for(;s;)(0,i.isRing)(s)&&((0,i.ringDirection)(s)!==e&&s.reverse(),r.push(s)),s=t.shift();return r}}r.WayCollection=s},{"./utils":8}],10:[function(e,t,r){var s=this&&this.__importDefault||function(e){return e&&e.__esModule?e:{default:e}},o=(Object.defineProperty(r,"__esModule",{value:!0}),r.Way=void 0,e("./osm-object"));let i=e("./late-binder"),n=e("./utils"),a=s(e("./polytags.json"));class l extends o.OsmObject{constructor(e,t){super("way",e,t),this.latLngArray=[],this.isPolygon=!1}addLatLng(e){this.latLngArray.push(e)}setLatLngArray(e){this.latLngArray=e}addNodeRef(e){e=new i.LateBinder(this.latLngArray,e=>{e=this.refElems.get("node/"+e);if(e)return e.refCount++,e.getLatLng()},this,[e]);this.latLngArray.push(e),this.refElems.addBinder(e)}addTags(e){super.addTags(e);for(var[t,r]of Object.entries(e))this.analyzeTag(t,r)}addTag(e,t){super.addTag(e,t),this.analyzeTag(e,t)}toCoordsArray(){return this.latLngArray.map(e=>[e.lon,e.lat])}toFeatureArray(){var e,t=this.toCoordsArray();return 1<t.length?(t=(0,n.strArrayArrayToFloat)(t),e={type:"Feature",id:this.getCompositeId(),properties:this.getProps(),geometry:{type:"LineString",coordinates:t}},this.isPolygon&&(0,n.isRing)(t)&&("counterclockwise"!==(0,n.ringDirection)(t)&&t.reverse(),e.geometry={type:"Polygon",coordinates:[t]}),[e]):[]}analyzeTag(e,t){e=a.default[e];e&&(this.isPolygon=!0,e.whitelist?this.isPolygon=0<=e.whitelist.indexOf(t):e.blacklist&&(this.isPolygon=!(0<=e.blacklist.indexOf(t))))}}r.Way=l},{"./late-binder":2,"./osm-object":4,"./polytags.json":5,"./utils":8}],11:[function(e,t,r){function o(e){return null!==e.match(/^(.+?)\[(.+?)\]>$/g)}function i(e){var t=/^(.+?)\[(.+?)\]>$/g.exec(e);return t?{evt:t[1]+">",exp:t[2]}:{evt:e}}Object.defineProperty(r,"__esModule",{value:!0}),r.XmlParser=void 0;class s{constructor(e){this.queryParent=!1,this.progressive=!1,this.parentMap=new WeakMap,e&&(this.queryParent=!!e.queryParent,this.progressive=e.progressive,this.queryParent)&&(this.parentMap=new WeakMap),this.evtListeners={}}parse(s,o,i){i=i?i+".":"";var n=/<([^ >\/]+)(.*?)>/gm,a=[];let l=n.exec(s);for(;l;){var d=l[1],u={$tag:d},h=i+d,f=l[2].trim();let e=!1;(f.endsWith("/")||d.startsWith("?")||d.startsWith("!"))&&(e=!0);var c,p=/([^ ]+?)="(.+?)"/g,g=/([^ ]+?)='(.+?)'/g;let t=p.exec(f),r=!1;for(;t;)r=!0,u[t[1]]=t[2],t=p.exec(f);if(!r)for(t=g.exec(f);t;)r=!0,u[t[1]]=t[2],t=g.exec(f);r||""===f||(u.text=f),this.progressive&&this.emit(`<${h}>`,u,o),e||((d=new RegExp(`([^]+?)</${d}>`,"g")).lastIndex=n.lastIndex,(c=d.exec(s))&&c[1]&&(n.lastIndex=d.lastIndex,0<(d=this.parse(c[1],u,h)).length?u.$innerNodes=d:u.$innerText=c[1])),this.queryParent&&o&&this.parentMap.set(u,o),this.progressive&&this.emit(`</${h}>`,u,o),a.push(u),l=n.exec(s)}return a}getParent(e){return this.queryParent?this.parentMap.get(e):null}addListener(e,t){var r,s;o(e)&&((r=i(e)).exp&&(t.condition=(s="return "+(s=r.exp).replace(/(\$.+?)(?=[=!.])/g,"node.$&")+";",new Function("node",s))),e=r.evt),this.$addListener(e,t)}removeListener(e,t){o(e)&&(e=i(e).evt),this.$removeListener(e,t)}on(e,t){this.addListener(e,t)}off(e,t){this.removeListener(e,t)}$addListener(e,t){var r=this.evtListeners[e];r?r.push(t):this.evtListeners[e]=[t]}$removeListener(e,t){e=this.evtListeners[e];let r=-1;0<=(r=e?e.indexOf(t):r)&&e.splice(r,1)}emit(e,...t){e=this.evtListeners[e];if(e)for(var r of e)(!r.condition||!0===r.condition.apply(null,t))&&r.apply(null,t)}}r.XmlParser=s},{}]},{},[1])(1)});