Source: OverpassNode.js

  1. /* global L:false */
  2. const OverpassObject = require('./OverpassObject')
  3. const BoundingBox = require('boundingbox')
  4. const OverpassFrontend = require('./defines')
  5. const turf = require('./turf')
  6. /**
  7. * A node
  8. * @extends OverpassObject
  9. * @property {string} id ID of this object, starting with 'n'.
  10. * @property {number} osm_id Numeric id.
  11. * @property {string} type Type: 'node'
  12. * @property {object} tags OpenStreetMap tags.
  13. * @property {object} meta OpenStreetMap meta information.
  14. * @property {Point} geometry of the object
  15. * @property {object} data Data as loaded from Overpass API.
  16. * @property {bit_array} properties Which information about this object is known?
  17. * @property {object[]} memberOf List of ways and relations where this object is member of.
  18. * @property {string} memberOf.id ID of the way or relation where this way is member of.
  19. * @property {string} memberOf.role Role of this object in the relation.
  20. * @property {number} memberOf.sequence This object is the nth member in the way resp. relation.
  21. * @property {BoundingBox} bounds Bounding box of this object.
  22. * @property {Point} center Centroid of the bounding box.
  23. */
  24. class OverpassNode extends OverpassObject {
  25. GeoJSON () {
  26. const result = {
  27. type: 'Feature',
  28. id: this.type + '/' + this.osm_id,
  29. properties: this.GeoJSONProperties()
  30. }
  31. if (this.geometry) {
  32. result.geometry = {
  33. type: 'Point',
  34. coordinates: [this.geometry.lon, this.geometry.lat]
  35. }
  36. }
  37. return result
  38. }
  39. exportOSMXML (options, document, callback) {
  40. super.exportOSMXML(options, document,
  41. (err, result) => {
  42. if (err) {
  43. return callback(err)
  44. }
  45. if (!result) { // already included
  46. return callback(null)
  47. }
  48. result.setAttribute('lat', this.geometry.lat)
  49. result.setAttribute('lon', this.geometry.lon)
  50. callback(null, result)
  51. }
  52. )
  53. }
  54. exportOSMJSON (conf, elements, callback) {
  55. super.exportOSMJSON(conf, elements,
  56. (err, result) => {
  57. if (err) {
  58. return callback(err)
  59. }
  60. if (!result) { // already included
  61. return callback(null)
  62. }
  63. result.lat = this.geometry.lat
  64. result.lon = this.geometry.lon
  65. callback(null, result)
  66. }
  67. )
  68. }
  69. updateData (data, options) {
  70. super.updateData(data, options)
  71. if (data.lat) {
  72. this.geometry = {
  73. lat: data.lat,
  74. lon: data.lon
  75. }
  76. this.bounds = new BoundingBox(data)
  77. this.center = this.bounds.getCenter()
  78. this.properties = this.properties | OverpassFrontend.GEOM | OverpassFrontend.BBOX | OverpassFrontend.CENTER
  79. }
  80. this.properties |= OverpassFrontend.MEMBERS // node does not have members, so it always known all of them
  81. }
  82. /**
  83. * return a leaflet feature for this object
  84. * @param {object} [options] options Options will be passed to the leaflet function
  85. * @param {string} [options.nodeFeature='CircleMarker'] Which type of object should be returned: 'Marker' (L.marker), 'Circle' (L.circle) or 'CircleMarker' (L.circleMarker).
  86. * @param {number[]} [options.shiftWorld=[0, 0]] Shift western (negative) longitudes by shiftWorld[0], eastern (positive) longitudes by shiftWorld[1] (e.g. by 360, 0 to show objects around lon=180)
  87. * @return {L.layer}
  88. */
  89. leafletFeature (options = {}) {
  90. if (!this.geometry) {
  91. return null
  92. }
  93. if (!('shiftWorld' in options)) {
  94. options.shiftWorld = [0, 0]
  95. }
  96. const geom = { lat: this.geometry.lat, lon: this.geometry.lon + options.shiftWorld[this.geometry.lon < 0 ? 0 : 1] }
  97. switch ('nodeFeature' in options ? options.nodeFeature : null) {
  98. case 'Marker':
  99. return L.marker(geom, options)
  100. case 'Circle':
  101. return L.circle(geom, options.radius, options)
  102. case 'CircleMarker':
  103. default:
  104. return L.circleMarker(geom, options)
  105. }
  106. }
  107. intersects (bbox) {
  108. if (!this.bounds) {
  109. return 1
  110. }
  111. if (!bbox.intersects) { // GeoJSON detected
  112. const r = turf.booleanIntersects(this.GeoJSON(), bbox)
  113. return r ? 2 : 0
  114. }
  115. return bbox.intersects(this.bounds) ? 2 : 0
  116. }
  117. }
  118. module.exports = OverpassNode