leaflet-shadow-simulator 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md ADDED
@@ -0,0 +1,188 @@
1
+ # leaflet-shadow-simulator
2
+
3
+ Terrain, building and object shadow simulator for Leaflet. Display sunlight and shadow on a map for any date and time of year.
4
+
5
+ ![Leaflet Shadow Simulator demo](/demo.gif)
6
+
7
+ [Live Demo](https://ted-piotrowski.github.io/leaflet-shadow-simulator/examples/map.html)
8
+
9
+ ## Download
10
+
11
+ [unpkg CDN](https://unpkg.com/leaflet-shadow-simulator/dist/leaflet-shadow-simulator.umd.min.js)
12
+
13
+ ## Installation
14
+
15
+ In a browser:
16
+
17
+ `<script src="https://unpkg.com/leaflet-shadow-simulator/dist/leaflet-shadow-simulator.umd.min.js"></script>`
18
+
19
+ Using npm:
20
+
21
+ `npm i leaflet-shadow-simulator --save`
22
+
23
+ ## Usage
24
+
25
+ In a browser:
26
+
27
+ ```html
28
+ <link rel="stylesheet" href="https://unpkg.com/leaflet@1.7.1/dist/leaflet.css" />
29
+ <script src="https://unpkg.com/leaflet@1.7.1/dist/leaflet.js"></script>
30
+ <script src="https://unpkg.com/leaflet-shadow-simulator/dist/leaflet-shadow-simulator.umd.min.js"></script>
31
+ <script>
32
+ var map = L.map("mapid");
33
+
34
+ const shadeMap = L.shadeMap({
35
+ date: new Date(), // display shadows for current date
36
+ color: '#01112f', // shade color
37
+ opacity: 0.7, // opacity of shade color
38
+ apiKey: "XXXXXX", // obtain from https://shademap.app/about/
39
+ terrainSource: {
40
+ tileSize: 256, // DEM tile size
41
+ maxZoom: 15, // Maximum zoom of DEM tile set
42
+ getSourceUrl: ({ x, y, z }) => {
43
+ // return DEM tile url for given x,y,z coordinates
44
+ return `https://s3.amazonaws.com/elevation-tiles-prod/terrarium/${z}/${x}/${y}.png`
45
+ },
46
+ getElevation: ({ r, g, b, a }) => {
47
+ // return elevation in meters for a given DEM tile pixel
48
+ return (r * 256 + g + b / 256) - 32768
49
+ }
50
+ },
51
+ }).addTo(map);
52
+
53
+ // advance shade by 1 hour
54
+ shadeMap.setDate(new Date(Date.now() + 1000 * 60 * 60));
55
+
56
+ // sometime later...
57
+ // ...remove layer
58
+ shadeMap.remove();
59
+ </script>
60
+ ```
61
+
62
+ Using Node.js:
63
+
64
+ ```javascript
65
+ import * as L from 'leaflet'
66
+ import ShadeMap from 'leaflet-shadow-simulator';
67
+
68
+ const map = L.map("mapid");
69
+
70
+ const shadeMap = ShadeMap({
71
+ date: new Date(), // display shadows for current date
72
+ color: '#01112f', // shade color
73
+ opacity: 0.7, // opacity of shade color
74
+ apiKey: "XXXXXX", // obtain from https://shademap.app/about/
75
+ terrainSource: {
76
+ tileSize: 256, // DEM tile size
77
+ maxZoom: 15, // Maximum zoom of DEM tile set
78
+ getSourceUrl: ({ x, y, z }) => {
79
+ // return DEM tile url for given x,y,z coordinates
80
+ return `https://s3.amazonaws.com/elevation-tiles-prod/terrarium/${z}/${x}/${y}.png`
81
+ },
82
+ getElevation: ({ r, g, b, a }) => {
83
+ // return elevation in meters for a given DEM tile pixel
84
+ return (r * 256 + g + b / 256) - 32768
85
+ }
86
+ },
87
+ }).addTo(map);
88
+
89
+ // advance shade by 1 hour
90
+ shadeMap.setDate(new Date(Date.now() + 1000 * 60 * 60));
91
+
92
+ // sometime later
93
+ // ...remove layer
94
+ shadeMap.remove();
95
+ ```
96
+
97
+ ### Constructor options
98
+
99
+ Property name | Type | Default value | Comment
100
+ :--- | :--- | :--- | :---
101
+ `apiKey` | `String` | `''` | See [https://shademap.app/about/](https://shademap.app/about/)
102
+ `date` | `Date` | `new Date()` | Sun's position in the sky is based on this date
103
+ `color` | `String` | `#000` | 3 or 6 digit hexadecimal number
104
+ `opacity` | `Number` | `0.3`
105
+ `terrainSource` | `Object` | See [terrainSource](#terrainsource) | Specify DEM or DSM tiles containing terrain elevation data
106
+ `getFeatures` | `Function` | See [getFeatures](#getfeatures) | Returns GeoJSON of objects, such as buildings, to display on the map
107
+
108
+ #### terrainSource
109
+
110
+ An object describing a DEM tile set to use for terrain shadows
111
+
112
+ Property name | Type | Default value | Comment
113
+ :--- | :--- | :--- | :---
114
+ `maxZoom` | `Number` | `15` | Max zoom for custom DEM tile source
115
+ `tileSize` | `Number` | `256` | Tile size for custom DEM tile source
116
+ `sourceUrl` | `Function` | `Returns tile encoding 0m elevation for all locations` | Returns url of DEM tile for given `(x, y, z)` coordinate
117
+ `getElevation` | `Function` | `return (r * 256 + g + b / 256) - 32768` | Returns elevation in meters for each (r,g,b,a) pixel of DEM tile
118
+
119
+ ##### Open Data on AWS for terrainSource
120
+
121
+ A global dataset providing bare-earth terrain heights, tiled for easy usage and provided on S3 - [More info](https://registry.opendata.aws/terrain-tiles/)
122
+
123
+ ```javascript
124
+ {
125
+ tileSize: 256,
126
+ maxZoom: 15,
127
+ getSourceUrl: ({x, y, z}) => {
128
+ return `https://s3.amazonaws.com/elevation-tiles-prod/terrarium/${z}/${x}/${y}.png`;
129
+ },
130
+ getElevation: ({r, g, b, a}) => {
131
+ return (r * 256 + g + b / 256) - 32768;
132
+ }
133
+ }
134
+ ```
135
+
136
+ ##### Mapbox Terrain DEM V1 for terrainSource
137
+
138
+ Mapbox Terrain-DEM v1 is a Mapbox-provided raster tileset is a global elevation layer. This tileset contains raw height values in meters in the Red, Green, and Blue channels of PNG tiles that can be decoded to raw heights in meters - [More info](https://docs.mapbox.com/data/tilesets/reference/mapbox-terrain-dem-v1/)
139
+
140
+ ```javascript
141
+ {
142
+ tileSize: 256,
143
+ maxZoom: 15,
144
+ getSourceUrl: ({x, y, z}) => {
145
+ return `https://${subdomain}.tiles.mapbox.com/raster/v1/mapbox.mapbox-terrain-dem-v1/${z}/${x}/${y}.webp?sku=101wuwGrczDtH&access_token=${MAPBOX_API_KEY}`;
146
+ },
147
+ getElevation: ({r, g, b, a}) => {
148
+ return -10000 + ((r * 256 * 256 + g * 256 + b) * .1);
149
+ }
150
+ }
151
+ ```
152
+
153
+ #### getFeatures
154
+
155
+ Takes `map` as an argument and returns a GeoJSON collection of features whose shadows will be displayed on the map. Currently only supports `Polygon` and `MultiPolygon`.
156
+
157
+ ##### Adds a 1000 meter tall structure near Alexandria, Egypt
158
+
159
+ ```javascript
160
+ getFeatures: (map) => {
161
+ return [{
162
+ "type": "Feature",
163
+ "geometry": {
164
+ "type": "Polygon",
165
+ "coordinates": [
166
+ [29.8148007, 31.2240349],
167
+ [29.8248007, 31.2240349],
168
+ [29.8248007, 31.2140349],
169
+ [29.8148007, 31.2140349],
170
+ ]
171
+ },
172
+ "properties": {
173
+ "height": 1000,
174
+ "render_height": 1000,
175
+ "name": "Alexandria column"
176
+ }
177
+ },
178
+ },
179
+ ```
180
+
181
+ ### Available functions
182
+
183
+ `setDate(date: Date)` - update shade layer to reflect new date
184
+
185
+ `setColor(color: String)` - change shade color
186
+
187
+ `setOpacity(opacity: Number)` - change shade opacity
188
+
package/demo.gif ADDED
Binary file
@@ -0,0 +1,8 @@
1
+ /**
2
+ * Copyright Ted Piotrowski 2022
3
+ * Package: leaflet-shadow-simulator
4
+ * Version: 0.13.3
5
+ * For licensing visit: https://shademap.app/about/
6
+ */
7
+
8
+ !function(t,e){"object"==typeof exports&&"undefined"!=typeof module?e(exports,require("leaflet"),require("suncalc")):"function"==typeof define&&define.amd?define(["exports","leaflet","suncalc"],e):e((t="undefined"!=typeof globalThis?globalThis:t||self).ShadeMap={},t.L,t.suncalc)}(this,(function(t,e,r){"use strict";function n(t){return t&&"object"==typeof t&&"default"in t?t:{default:t}}var o=n(r),i=function(t,e){return(i=Object.setPrototypeOf||{__proto__:[]}instanceof Array&&function(t,e){t.__proto__=e}||function(t,e){for(var r in e)Object.prototype.hasOwnProperty.call(e,r)&&(t[r]=e[r])})(t,e)};function a(t,e){if("function"!=typeof e&&null!==e)throw new TypeError("Class extends value "+String(e)+" is not a constructor or null");function r(){this.constructor=t}i(t,e),t.prototype=null===e?Object.create(e):(r.prototype=e.prototype,new r)}var s=function(){return(s=Object.assign||function(t){for(var e,r=1,n=arguments.length;r<n;r++)for(var o in e=arguments[r])Object.prototype.hasOwnProperty.call(e,o)&&(t[o]=e[o]);return t}).apply(this,arguments)};function u(t,e,r,n){return new(r||(r=Promise))((function(o,i){function a(t){try{u(n.next(t))}catch(t){i(t)}}function s(t){try{u(n.throw(t))}catch(t){i(t)}}function u(t){var e;t.done?o(t.value):(e=t.value,e instanceof r?e:new r((function(t){t(e)}))).then(a,s)}u((n=n.apply(t,e||[])).next())}))}function l(t,e){var r,n,o,i,a={label:0,sent:function(){if(1&o[0])throw o[1];return o[1]},trys:[],ops:[]};return i={next:s(0),throw:s(1),return:s(2)},"function"==typeof Symbol&&(i[Symbol.iterator]=function(){return this}),i;function s(i){return function(s){return function(i){if(r)throw new TypeError("Generator is already executing.");for(;a;)try{if(r=1,n&&(o=2&i[0]?n.return:i[0]?n.throw||((o=n.return)&&o.call(n),0):n.next)&&!(o=o.call(n,i[1])).done)return o;switch(n=0,o&&(i=[2&i[0],o.value]),i[0]){case 0:case 1:o=i;break;case 4:return a.label++,{value:i[1],done:!1};case 5:a.label++,n=i[1],i=[0];continue;case 7:i=a.ops.pop(),a.trys.pop();continue;default:if(!(o=a.trys,(o=o.length>0&&o[o.length-1])||6!==i[0]&&2!==i[0])){a=0;continue}if(3===i[0]&&(!o||i[1]>o[0]&&i[1]<o[3])){a.label=i[1];break}if(6===i[0]&&a.label<o[1]){a.label=o[1],o=i;break}if(o&&a.label<o[2]){a.label=o[2],a.ops.push(i);break}o[2]&&a.ops.pop(),a.trys.pop();continue}i=e.call(t,a)}catch(t){i=[6,t],n=0}finally{r=o=0}if(5&i[0])throw i[1];return{value:i[0]?i[1]:void 0,done:!0}}([i,s])}}}function f(t,e,r){if(r||2===arguments.length)for(var n,o=0,i=e.length;o<i;o++)!n&&o in e||(n||(n=Array.prototype.slice.call(e,0,o)),n[o]=e[o]);return t.concat(n||Array.prototype.slice.call(e))}var c=function(t){function r(e,r,n){void 0===n&&(n={});var o=t.call(this,"",r,n)||this;return o._url=e,o}return a(r,t),r.prototype._initImage=function(){var t="CANVAS"===this._url.tagName,r=this._image=t?this._url:e.DomUtil.create("canvas");return e.DomUtil.addClass(r,"leaflet-image-layer"),this._zoomAnimated&&e.DomUtil.addClass(r,"leaflet-zoom-animated"),this.options.className&&e.DomUtil.addClass(r,this.options.className),r.onselectstart=e.Util.falseFn,r.onmousemove=e.Util.falseFn,this},r}(e.ImageOverlay);function h(t,e,r){var n=e[1],o=e[0],i=n-o;return t===n&&r?t:((t-o)%i+i)%i+o}function p(t,e){var r=Math.pow(10,void 0===e?6:e);return Math.round(t*r)/r}var d=Array.isArray||function(t){return"[object Array]"===Object.prototype.toString.call(t)};function m(t,e,r){this.x=r?Math.round(t):t,this.y=r?Math.round(e):e}var _=Math.trunc||function(t){return t>0?Math.floor(t):Math.ceil(t)};function x(t,e,r){return t instanceof m?t:d(t)?new m(t[0],t[1]):null==t?t:"object"==typeof t&&"x"in t&&"y"in t?new m(t.x,t.y):new m(t,e,r)}function g(t,e){if(t)for(var r=e?[t,e]:t,n=0,o=r.length;n<o;n++)this.extend(r[n])}function v(t,e){return!t||t instanceof g?t:new g(t,e)}function y(t,e){if(t)for(var r=e?[t,e]:t,n=0,o=r.length;n<o;n++)this.extend(r[n])}function E(t,e){return t instanceof y?t:new y(t,e)}m.prototype={clone:function(){return new m(this.x,this.y)},add:function(t){return this.clone()._add(x(t))},_add:function(t){return this.x+=t.x,this.y+=t.y,this},subtract:function(t){return this.clone()._subtract(x(t))},_subtract:function(t){return this.x-=t.x,this.y-=t.y,this},divideBy:function(t){return this.clone()._divideBy(t)},_divideBy:function(t){return this.x/=t,this.y/=t,this},multiplyBy:function(t){return this.clone()._multiplyBy(t)},_multiplyBy:function(t){return this.x*=t,this.y*=t,this},scaleBy:function(t){return new m(this.x*t.x,this.y*t.y)},unscaleBy:function(t){return new m(this.x/t.x,this.y/t.y)},round:function(){return this.clone()._round()},_round:function(){return this.x=Math.round(this.x),this.y=Math.round(this.y),this},floor:function(){return this.clone()._floor()},_floor:function(){return this.x=Math.floor(this.x),this.y=Math.floor(this.y),this},ceil:function(){return this.clone()._ceil()},_ceil:function(){return this.x=Math.ceil(this.x),this.y=Math.ceil(this.y),this},trunc:function(){return this.clone()._trunc()},_trunc:function(){return this.x=_(this.x),this.y=_(this.y),this},distanceTo:function(t){var e=(t=x(t)).x-this.x,r=t.y-this.y;return Math.sqrt(e*e+r*r)},equals:function(t){return(t=x(t)).x===this.x&&t.y===this.y},contains:function(t){return t=x(t),Math.abs(t.x)<=Math.abs(this.x)&&Math.abs(t.y)<=Math.abs(this.y)},toString:function(){return"Point("+p(this.x)+", "+p(this.y)+")"}},g.prototype={extend:function(t){return t=x(t),this.min||this.max?(this.min.x=Math.min(t.x,this.min.x),this.max.x=Math.max(t.x,this.max.x),this.min.y=Math.min(t.y,this.min.y),this.max.y=Math.max(t.y,this.max.y)):(this.min=t.clone(),this.max=t.clone()),this},getCenter:function(t){return new m((this.min.x+this.max.x)/2,(this.min.y+this.max.y)/2,t)},getBottomLeft:function(){return new m(this.min.x,this.max.y)},getTopRight:function(){return new m(this.max.x,this.min.y)},getTopLeft:function(){return this.min},getBottomRight:function(){return this.max},getSize:function(){return this.max.subtract(this.min)},contains:function(t){var e,r;return(t="number"==typeof t[0]||t instanceof m?x(t):v(t))instanceof g?(e=t.min,r=t.max):e=r=t,e.x>=this.min.x&&r.x<=this.max.x&&e.y>=this.min.y&&r.y<=this.max.y},intersects:function(t){t=v(t);var e=this.min,r=this.max,n=t.min,o=t.max,i=o.x>=e.x&&n.x<=r.x,a=o.y>=e.y&&n.y<=r.y;return i&&a},overlaps:function(t){t=v(t);var e=this.min,r=this.max,n=t.min,o=t.max,i=o.x>e.x&&n.x<r.x,a=o.y>e.y&&n.y<r.y;return i&&a},isValid:function(){return!(!this.min||!this.max)}},y.prototype={extend:function(t){var e,r,n=this._southWest,o=this._northEast;if(t instanceof w)e=t,r=t;else{if(!(t instanceof y))return t?this.extend(M(t)||E(t)):this;if(e=t._southWest,r=t._northEast,!e||!r)return this}return n||o?(n.lat=Math.min(e.lat,n.lat),n.lng=Math.min(e.lng,n.lng),o.lat=Math.max(r.lat,o.lat),o.lng=Math.max(r.lng,o.lng)):(this._southWest=new w(e.lat,e.lng),this._northEast=new w(r.lat,r.lng)),this},pad:function(t){var e=this._southWest,r=this._northEast,n=Math.abs(e.lat-r.lat)*t,o=Math.abs(e.lng-r.lng)*t;return new y(new w(e.lat-n,e.lng-o),new w(r.lat+n,r.lng+o))},getCenter:function(){return new w((this._southWest.lat+this._northEast.lat)/2,(this._southWest.lng+this._northEast.lng)/2)},getSouthWest:function(){return this._southWest},getNorthEast:function(){return this._northEast},getNorthWest:function(){return new w(this.getNorth(),this.getWest())},getSouthEast:function(){return new w(this.getSouth(),this.getEast())},getWest:function(){return this._southWest.lng},getSouth:function(){return this._southWest.lat},getEast:function(){return this._northEast.lng},getNorth:function(){return this._northEast.lat},contains:function(t){t="number"==typeof t[0]||t instanceof w||"lat"in t?M(t):E(t);var e,r,n=this._southWest,o=this._northEast;return t instanceof y?(e=t.getSouthWest(),r=t.getNorthEast()):e=r=t,e.lat>=n.lat&&r.lat<=o.lat&&e.lng>=n.lng&&r.lng<=o.lng},intersects:function(t){t=E(t);var e=this._southWest,r=this._northEast,n=t.getSouthWest(),o=t.getNorthEast(),i=o.lat>=e.lat&&n.lat<=r.lat,a=o.lng>=e.lng&&n.lng<=r.lng;return i&&a},overlaps:function(t){t=E(t);var e=this._southWest,r=this._northEast,n=t.getSouthWest(),o=t.getNorthEast(),i=o.lat>e.lat&&n.lat<r.lat,a=o.lng>e.lng&&n.lng<r.lng;return i&&a},toBBoxString:function(){return[this.getWest(),this.getSouth(),this.getEast(),this.getNorth()].join(",")},equals:function(t,e){return!!t&&(t=E(t),this._southWest.equals(t.getSouthWest(),e)&&this._northEast.equals(t.getNorthEast(),e))},isValid:function(){return!(!this._southWest||!this._northEast)}};var T=function(t){var e,r,n,o;for(r=1,n=arguments.length;r<n;r++)for(e in o=arguments[r])t[e]=o[e];return t}({},{latLngToPoint:function(t,e){var r=this.projection.project(t),n=this.scale(e);return this.transformation._transform(r,n)},pointToLatLng:function(t,e){var r=this.scale(e),n=this.transformation.untransform(t,r);return this.projection.unproject(n)},project:function(t){return this.projection.project(t)},unproject:function(t){return this.projection.unproject(t)},scale:function(t){return 256*Math.pow(2,t)},zoom:function(t){return Math.log(t/256)/Math.LN2},getProjectedBounds:function(t){if(this.infinite)return null;var e=this.projection.bounds,r=this.scale(t);return new g(this.transformation.transform(e.min,r),this.transformation.transform(e.max,r))},infinite:!1,wrapLatLng:function(t){var e=this.wrapLng?h(t.lng,this.wrapLng,!0):t.lng;return new w(this.wrapLat?h(t.lat,this.wrapLat,!0):t.lat,e,t.alt)},wrapLatLngBounds:function(t){var e=t.getCenter(),r=this.wrapLatLng(e),n=e.lat-r.lat,o=e.lng-r.lng;if(0===n&&0===o)return t;var i=t.getSouthWest(),a=t.getNorthEast();return new y(new w(i.lat-n,i.lng-o),new w(a.lat-n,a.lng-o))}},{wrapLng:[-180,180],R:6371e3,distance:function(t,e){var r=Math.PI/180,n=t.lat*r,o=e.lat*r,i=Math.sin((e.lat-t.lat)*r/2),a=Math.sin((e.lng-t.lng)*r/2),s=i*i+Math.cos(n)*Math.cos(o)*a*a,u=2*Math.atan2(Math.sqrt(s),Math.sqrt(1-s));return this.R*u}});function w(t,e,r){if(isNaN(t)||isNaN(e))throw new Error("Invalid LatLng object: ("+t+", "+e+")");this.lat=+t,this.lng=+e,void 0!==r&&(this.alt=+r)}function M(t,e,r){return t instanceof w?t:d(t)&&"object"!=typeof t[0]?3===t.length?new w(t[0],t[1],t[2]):2===t.length?new w(t[0],t[1]):null:null==t?t:"object"==typeof t&&"lat"in t?new w(t.lat,"lng"in t?t.lng:t.lon,t.alt):void 0===e?null:new w(t,e,r)}w.prototype={equals:function(t,e){return!!t&&(t=M(t),Math.max(Math.abs(this.lat-t.lat),Math.abs(this.lng-t.lng))<=(void 0===e?1e-9:e))},toString:function(t){return"LatLng("+p(this.lat,t)+", "+p(this.lng,t)+")"},distanceTo:function(t){return T.distance(this,M(t))},wrap:function(){return T.wrapLatLng(this)},toBounds:function(t){var e=180*t/40075017,r=e/Math.cos(Math.PI/180*this.lat);return E([this.lat-e,this.lng-r],[this.lat+e,this.lng+r])},clone:function(){return new w(this.lat,this.lng,this.alt)}};var b,R=8848,L=256,A=function(t){var e=function(t,e,r){var n=t.createShader(t.VERTEX_SHADER);if(null===n)return null;t.shaderSource(n,e),t.compileShader(n);var o=t.createShader(t.FRAGMENT_SHADER);if(null===o)return null;t.shaderSource(o,r),t.compileShader(o);var i=t.createProgram();if(null===i)return null;t.attachShader(i,n),t.attachShader(i,o),t.linkProgram(i),t.getProgramParameter(i,t.LINK_STATUS)||console.log(t.getProgramInfoLog(i));return i}(t,"\nuniform vec3 xyz;\nuniform vec2 dimensions;\nattribute vec2 a_position;\nfloat PI = 3.141592653589793;\nvarying vec2 vCoord;\n\n\tvoid main() {\n\t\tif (abs(a_position) == vec2(1,1)) {\n\t\t\tgl_Position = vec4(a_position, 0, 1);\n\t\t\tvCoord = a_position * 0.5 + 0.5;\n\t\t\treturn;\n\t\t}\n\t\tfloat x = ((a_position.x + 180.0) / 360.0 * pow(2.0, xyz.z)) * 256.0 - xyz.x;\n\t\tfloat y = (1.0 - (log(a_position.y) / PI)) / 2.0 * pow(2.0, xyz.z) * 256.0 - xyz.y;\n\t\tvec2 transformed = vec2(x, y);\n\t\tvec2 normalized = transformed / dimensions;\n\t\tvec2 final = normalized * 2.0 - 1.0;\n\t\tgl_Position = vec4(final, 0, 1);\n\t}\n","\n#ifdef GL_FRAGMENT_PRECISION_HIGH\n precision highp float;\n#else\n precision mediump float;\n#endif\n\nuniform vec4 color;\nuniform sampler2D height_map;\nvarying vec2 vCoord;\n\nvoid main() {\n\tif (color == vec4(0,0,0,0)) {\n\t \tvec4 textureColor = texture2D(height_map, vec2(vCoord.x, vCoord.y));\n\t \tgl_FragColor = vec4(textureColor.b, textureColor.a, 0, 1.0);\n\t\treturn;\n\t} \n\tgl_FragColor = color;\n}\n"),r=t.getAttribLocation(e,"a_position"),n=t.getUniformLocation(e,"xyz"),o=t.getUniformLocation(e,"dimensions"),i=t.getUniformLocation(e,"height_map"),a=t.getUniformLocation(e,"color"),s=t.createBuffer(),u=t.createBuffer(),l=t.createTexture();b={program:e,positionAttributeLocation:r,xyzUniformLocation:n,dimensionsUniformLocation:o,heightMapUniformLocation:i,colorUniformLocation:a,positionBuffer:s,indexBuffer:u,targetTexture:l}};var S=function(){function t(){this.events={}}return t.prototype.on=function(t,e){var r=this;return"object"!=typeof this.events[t]&&(this.events[t]=[]),this.events[t].push(e),function(){return r.removeListener(t,e)}},t.prototype.removeListener=function(t,e){if("object"==typeof this.events[t]){var r=this.events[t].indexOf(e);r>-1&&this.events[t].splice(r,1)}},t.prototype.removeAllListeners=function(){var t=this;Object.keys(this.events).forEach((function(e){return t.events[e].splice(0,t.events[e].length)}))},t.prototype.emit=function(t){for(var e=this,r=[],n=1;n<arguments.length;n++)r[n-1]=arguments[n];"object"==typeof this.events[t]&&f([],this.events[t]).forEach((function(t){return t.apply(e,r)}))},t.prototype.once=function(t,e){var r=this,n=this.on(t,(function(){for(var t=[],o=0;o<arguments.length;o++)t[o]=arguments[o];n(),e.apply(r,t)}));return n},t}();function U(t,e,r){r=r||2;var n,o,i,a,s,u,l,f=e&&e.length,c=f?e[0]*r:t.length,h=P(t,0,c,r,!0),p=[];if(!h||h.next===h.prev)return p;if(f&&(h=function(t,e,r,n){var o,i,a,s=[];for(o=0,i=e.length;o<i;o++)(a=P(t,e[o]*n,o<i-1?e[o+1]*n:t.length,n,!1))===a.next&&(a.steiner=!0),s.push(W(a));for(s.sort(N),o=0;o<s.length;o++)r=I(r=H(s[o],r),r.next);return r}(t,e,h,r)),t.length>80*r){n=i=t[0],o=a=t[1];for(var d=r;d<c;d+=r)(s=t[d])<n&&(n=s),(u=t[d+1])<o&&(o=u),s>i&&(i=s),u>a&&(a=u);l=0!==(l=Math.max(i-n,a-o))?1/l:0}return D(h,p,r,n,o,l),p}function P(t,e,r,n,o){var i,a;if(o===et(t,e,r,n)>0)for(i=e;i<r;i+=n)a=J(i,t[i],t[i+1],a);else for(i=r-n;i>=e;i-=n)a=J(i,t[i],t[i+1],a);return a&&q(a,a.next)&&($(a),a=a.next),a}function I(t,e){if(!t)return t;e||(e=t);var r,n=t;do{if(r=!1,n.steiner||!q(n,n.next)&&0!==G(n.prev,n,n.next))n=n.next;else{if($(n),(n=e=n.prev)===n.next)break;r=!0}}while(r||n!==e);return e}function D(t,e,r,n,o,i,a){if(t){!a&&i&&function(t,e,r,n){var o=t;do{null===o.z&&(o.z=X(o.x,o.y,e,r,n)),o.prevZ=o.prev,o.nextZ=o.next,o=o.next}while(o!==t);o.prevZ.nextZ=null,o.prevZ=null,function(t){var e,r,n,o,i,a,s,u,l=1;do{for(r=t,t=null,i=null,a=0;r;){for(a++,n=r,s=0,e=0;e<l&&(s++,n=n.nextZ);e++);for(u=l;s>0||u>0&&n;)0!==s&&(0===u||!n||r.z<=n.z)?(o=r,r=r.nextZ,s--):(o=n,n=n.nextZ,u--),i?i.nextZ=o:t=o,o.prevZ=i,i=o;r=n}i.nextZ=null,l*=2}while(a>1)}(o)}(t,n,o,i);for(var s,u,l=t;t.prev!==t.next;)if(s=t.prev,u=t.next,i?F(t,n,o,i):C(t))e.push(s.i/r),e.push(t.i/r),e.push(u.i/r),$(t),t=u.next,l=u.next;else if((t=u)===l){a?1===a?D(t=z(I(t),e,r),e,r,n,o,i,2):2===a&&B(t,e,r,n,o,i):D(I(t),e,r,n,o,i,1);break}}}function C(t){var e=t.prev,r=t,n=t.next;if(G(e,r,n)>=0)return!1;for(var o=t.next.next;o!==t.prev;){if(Z(e.x,e.y,r.x,r.y,n.x,n.y,o.x,o.y)&&G(o.prev,o,o.next)>=0)return!1;o=o.next}return!0}function F(t,e,r,n){var o=t.prev,i=t,a=t.next;if(G(o,i,a)>=0)return!1;for(var s=o.x<i.x?o.x<a.x?o.x:a.x:i.x<a.x?i.x:a.x,u=o.y<i.y?o.y<a.y?o.y:a.y:i.y<a.y?i.y:a.y,l=o.x>i.x?o.x>a.x?o.x:a.x:i.x>a.x?i.x:a.x,f=o.y>i.y?o.y>a.y?o.y:a.y:i.y>a.y?i.y:a.y,c=X(s,u,e,r,n),h=X(l,f,e,r,n),p=t.prevZ,d=t.nextZ;p&&p.z>=c&&d&&d.z<=h;){if(p!==t.prev&&p!==t.next&&Z(o.x,o.y,i.x,i.y,a.x,a.y,p.x,p.y)&&G(p.prev,p,p.next)>=0)return!1;if(p=p.prevZ,d!==t.prev&&d!==t.next&&Z(o.x,o.y,i.x,i.y,a.x,a.y,d.x,d.y)&&G(d.prev,d,d.next)>=0)return!1;d=d.nextZ}for(;p&&p.z>=c;){if(p!==t.prev&&p!==t.next&&Z(o.x,o.y,i.x,i.y,a.x,a.y,p.x,p.y)&&G(p.prev,p,p.next)>=0)return!1;p=p.prevZ}for(;d&&d.z<=h;){if(d!==t.prev&&d!==t.next&&Z(o.x,o.y,i.x,i.y,a.x,a.y,d.x,d.y)&&G(d.prev,d,d.next)>=0)return!1;d=d.nextZ}return!0}function z(t,e,r){var n=t;do{var o=n.prev,i=n.next.next;!q(o,i)&&k(o,n,n.next,i)&&V(o,i)&&V(i,o)&&(e.push(o.i/r),e.push(n.i/r),e.push(i.i/r),$(n),$(n.next),n=t=i),n=n.next}while(n!==t);return I(n)}function B(t,e,r,n,o,i){var a=t;do{for(var s=a.next.next;s!==a.prev;){if(a.i!==s.i&&j(a,s)){var u=Q(a,s);return a=I(a,a.next),u=I(u,u.next),D(a,e,r,n,o,i),void D(u,e,r,n,o,i)}s=s.next}a=a.next}while(a!==t)}function N(t,e){return t.x-e.x}function H(t,e){var r=function(t,e){var r,n=e,o=t.x,i=t.y,a=-1/0;do{if(i<=n.y&&i>=n.next.y&&n.next.y!==n.y){var s=n.x+(i-n.y)*(n.next.x-n.x)/(n.next.y-n.y);if(s<=o&&s>a){if(a=s,s===o){if(i===n.y)return n;if(i===n.next.y)return n.next}r=n.x<n.next.x?n:n.next}}n=n.next}while(n!==e);if(!r)return null;if(o===a)return r;var u,l=r,f=r.x,c=r.y,h=1/0;n=r;do{o>=n.x&&n.x>=f&&o!==n.x&&Z(i<c?o:a,i,f,c,i<c?a:o,i,n.x,n.y)&&(u=Math.abs(i-n.y)/(o-n.x),V(n,t)&&(u<h||u===h&&(n.x>r.x||n.x===r.x&&O(r,n)))&&(r=n,h=u)),n=n.next}while(n!==l);return r}(t,e);if(!r)return e;var n=Q(r,t),o=I(r,r.next);return I(n,n.next),e===r?o:e}function O(t,e){return G(t.prev,t,e.prev)<0&&G(e.next,t,t.next)<0}function X(t,e,r,n,o){return(t=1431655765&((t=858993459&((t=252645135&((t=16711935&((t=32767*(t-r)*o)|t<<8))|t<<4))|t<<2))|t<<1))|(e=1431655765&((e=858993459&((e=252645135&((e=16711935&((e=32767*(e-n)*o)|e<<8))|e<<4))|e<<2))|e<<1))<<1}function W(t){var e=t,r=t;do{(e.x<r.x||e.x===r.x&&e.y<r.y)&&(r=e),e=e.next}while(e!==t);return r}function Z(t,e,r,n,o,i,a,s){return(o-a)*(e-s)-(t-a)*(i-s)>=0&&(t-a)*(n-s)-(r-a)*(e-s)>=0&&(r-a)*(i-s)-(o-a)*(n-s)>=0}function j(t,e){return t.next.i!==e.i&&t.prev.i!==e.i&&!function(t,e){var r=t;do{if(r.i!==t.i&&r.next.i!==t.i&&r.i!==e.i&&r.next.i!==e.i&&k(r,r.next,t,e))return!0;r=r.next}while(r!==t);return!1}(t,e)&&(V(t,e)&&V(e,t)&&function(t,e){var r=t,n=!1,o=(t.x+e.x)/2,i=(t.y+e.y)/2;do{r.y>i!=r.next.y>i&&r.next.y!==r.y&&o<(r.next.x-r.x)*(i-r.y)/(r.next.y-r.y)+r.x&&(n=!n),r=r.next}while(r!==t);return n}(t,e)&&(G(t.prev,t,e.prev)||G(t,e.prev,e))||q(t,e)&&G(t.prev,t,t.next)>0&&G(e.prev,e,e.next)>0)}function G(t,e,r){return(e.y-t.y)*(r.x-e.x)-(e.x-t.x)*(r.y-e.y)}function q(t,e){return t.x===e.x&&t.y===e.y}function k(t,e,r,n){var o=Y(G(t,e,r)),i=Y(G(t,e,n)),a=Y(G(r,n,t)),s=Y(G(r,n,e));return o!==i&&a!==s||(!(0!==o||!K(t,r,e))||(!(0!==i||!K(t,n,e))||(!(0!==a||!K(r,t,n))||!(0!==s||!K(r,e,n)))))}function K(t,e,r){return e.x<=Math.max(t.x,r.x)&&e.x>=Math.min(t.x,r.x)&&e.y<=Math.max(t.y,r.y)&&e.y>=Math.min(t.y,r.y)}function Y(t){return t>0?1:t<0?-1:0}function V(t,e){return G(t.prev,t,t.next)<0?G(t,e,t.next)>=0&&G(t,t.prev,e)>=0:G(t,e,t.prev)<0||G(t,t.next,e)<0}function Q(t,e){var r=new tt(t.i,t.x,t.y),n=new tt(e.i,e.x,e.y),o=t.next,i=e.prev;return t.next=e,e.prev=t,r.next=o,o.prev=r,n.next=r,r.prev=n,i.next=n,n.prev=i,n}function J(t,e,r,n){var o=new tt(t,e,r);return n?(o.next=n.next,o.prev=n,n.next.prev=o,n.next=o):(o.prev=o,o.next=o),o}function $(t){t.next.prev=t.prev,t.prev.next=t.next,t.prevZ&&(t.prevZ.nextZ=t.nextZ),t.nextZ&&(t.nextZ.prevZ=t.prevZ)}function tt(t,e,r){this.i=t,this.x=e,this.y=r,this.prev=null,this.next=null,this.z=null,this.prevZ=null,this.nextZ=null,this.steiner=!1}function et(t,e,r,n){for(var o=0,i=e,a=r-n;i<r;i+=n)o+=(t[a]-t[i])*(t[i+1]+t[a+1]),a=i;return o}function rt(t,e){return t.filter((function(t){return"MultiPolygon"===t.geometry.type})).forEach((function(e){var r=e.geometry;if(e.properties,e.type,"MultiPolygon"===r.type)for(var n=0;n<r.coordinates.length;n++)t.push(s(s({},e),{geometry:s(s({},r),{type:"Polygon",coordinates:r.coordinates[n]})}))})),t.filter((function(t){return"Polygon"===t.geometry.type})).map((function(t){var e=t.geometry,r=t.properties,n=e.coordinates.flat().flat(),o=new Float32Array(n.map((function(t,e){if(e%2==1){var r=t*Math.PI/180;return Math.tan(r)+1/Math.cos(r)}return t}))),i=U(o);return{aPosition:o,cuts:i.length>256?new Uint16Array(i):new Uint8Array(i),buildingHeight:function(t){var e=t,r=e.height,n=void 0===r?0:r,o=e.levels,i=void 0===o?0:o,a=e.render_height,s=void 0===a?0:a;if(i)return 3.04*i;return Math.max(n,s)}(r),startPos:[n[0],n[1]]}}))}U.deviation=function(t,e,r,n){var o=e&&e.length,i=o?e[0]*r:t.length,a=Math.abs(et(t,0,i,r));if(o)for(var s=0,u=e.length;s<u;s++){var l=e[s]*r,f=s<u-1?e[s+1]*r:t.length;a-=Math.abs(et(t,l,f,r))}var c=0;for(s=0;s<n.length;s+=3){var h=n[s]*r,p=n[s+1]*r,d=n[s+2]*r;c+=Math.abs((t[h]-t[d])*(t[p+1]-t[h+1])-(t[h]-t[p])*(t[d+1]-t[h+1]))}return 0===a&&0===c?0:Math.abs((c-a)/a)},U.flatten=function(t){for(var e=t[0][0].length,r={vertices:[],holes:[],dimensions:e},n=0,o=0;o<t.length;o++){for(var i=0;i<t[o].length;i++)for(var a=0;a<e;a++)r.vertices.push(t[o][i][a]);o>0&&(n+=t[o-1].length,r.holes.push(n))}return r};function nt(t){return u(this,void 0,void 0,(function(){var e,r;return l(this,(function(n){switch(n.label){case 0:return r=t.rawMap(),t.isLeaflet()?r.eachLayer((function(t){t.getMaplibreMap?e=t.getMaplibreMap():t.getMapboxMap&&(e=t.getMapboxMap())})):e=r,e?[4,new Promise((function(t,r){function n(){e.loaded()&&(e.off("render",n),t())}e.on("render",n),n()}))]:[3,2];case 1:return n.sent(),[2,e];case 2:return[2,null]}}))}))}var ot=function(t){return new Promise((function(e,r){var n=new Int32Array(t.buffer).reduce((function(t,e){return Math.max(t,(n=(256*(255&(r=e))+(r>>8&255))/5,o=(256*(r>>16&255)+(r>>24&255))/5,Math.max(n,o)));var r,n,o}),0);e({maxHeight:Math.min(R,n)})}))},it=document.createElement("canvas"),at=it.getContext("2d",{antialias:!1,alpha:!1});null!==at&&(at.imageSmoothingEnabled=!1),it.width=L,it.height=L;var st,ut=[],lt=0,ft={width:0,height:0,tileLatLngBounds:new y(new w(0,0),new w(0,0)),imageData:new Uint8ClampedArray(0),visibleDEMPixelBounds:new g(new m(0,0),new m(0,0)),maxHeight:R,maxBuildingHeight:0,raster:[],demZoom:0,dirty:!1,canvasWidth:0,canvasHeight:0},ct=function(t){return u(void 0,void 0,void 0,(function(){var e,r,n,o,i,a,f,c,h,p,d,_,x,v,E,T,w,M,A,S,U,P,I,D,C,F,z,B,N,H,O,X,W,Z,j;return l(this,(function(G){switch(G.label){case 0:e=t.map,r=t.getFeatures,n=t.terrainSource,o=t.tileLoaded,i=t.gl,a=n.getSourceUrl,f=n.getElevation,c=n.maxZoom,h=n.tileSize,Y={map:e,getFeatures:r},p=u(void 0,void 0,void 0,(function(){var t,e,r,n;return l(this,(function(o){switch(o.label){case 0:t=Y.map,e=Y.getFeatures,o.label=1;case 1:return o.trys.push([1,3,,4]),[4,nt(t)];case 2:return r=o.sent(),[2,rt(e(r))];case 3:return n=o.sent(),console.log("Error merging buildings",n),[3,4];case 4:return[2,[]]}}))})),d=e.getZoom(),G.label=1;case 1:return G.trys.push([1,4,,5]),d=Math.min(c,d),_=Math.round(d),x=e.getBounds(),v=x.getNorthWest(),E=x.getSouthEast(),T=new g(e.project(v,d),e.project(E,d)),w=T.max.x-T.min.x,M=T.max.y-T.min.y,A=new g(e.project(v,_),e.project(E,_)),S=new m(A.min.x,A.min.y),U=A.max.x-A.min.x,P=A.max.y-A.min.y,(I=A.max.subtract(A.min)).y>I.x&&(S.x-=L,U+=512),D=function(t){for(var e=t.upperLeft,r=t.zoom,n=t.innerWidth,o=t.innerHeight,i=e.divideBy(L).floor(),a=i.x+Math.floor((n+L)/L),s=Math.min(i.y+Math.floor((o+L)/L),Math.pow(2,r)-1),u=[],l=i.x;l<=a;l++)for(var f=i.y;f<=s;f++)u.push({x:l,y:f,z:r});return u}({upperLeft:S,zoom:_,innerWidth:U,innerHeight:P}),C=function(t){t.sort((function(t,e){return t.y!==e.y?t.y-e.y:t.x-e.x}));var e=t.reduce((function(t,e){return e.x<t.x?e:t})).x,r=t.reduce((function(t,e){return e.y<t.y?e:t})).y;return t.map((function(t){var n=Math.pow(2,t.z);return{x:(t.x%n+n)%n,y:(t.y%n+n)%n,z:t.z,xOffset:(t.x-e)*L,yOffset:(t.y-r)*L}}))}(D),(F=JSON.stringify(C))===st&&_<c?[2,ft=s(s({},ft),{visibleDEMPixelBounds:A,demZoom:_,dirty:!0})]:(st=F,z={width:(K=C).reduce((function(t,e){return e.xOffset>t.xOffset?e:t})).xOffset+L,height:K.reduce((function(t,e){return e.yOffset>t.yOffset?e:t})).yOffset+L},[4,(q=C,k={width:B=z.width,height:N=z.height,crossOrigin:"Anonymous",getSourceUrl:a,getElevation:f,tileSize:h,tileLoaded:o},u(void 0,void 0,void 0,(function(){var t,e,r,n,o,i,a,s,f,c,h;return l(this,(function(p){switch(p.label){case 0:if(t=k.width,e=k.height,r=k.crossOrigin,n=k.getSourceUrl,o=k.getElevation,i=k.tileSize,a=k.tileLoaded,!at)return[3,5];s=new Uint8ClampedArray(2*t*e),ut.forEach((function(t){return t.src=""})),ut=[],lt=0,f=new Set,q.forEach((function(t){var e=i===L?t.x:Math.floor(t.x/2),r=i===L?t.y:Math.floor(t.y/2),o=i===L?t.z:t.z-1;f.add(n({x:e,y:r,z:o}))})),c=Array.from(f).map((function(e){return u(void 0,void 0,void 0,(function(){return l(this,(function(u){return[2,new Promise((function(a,u){var l=new Image;ut.push(l),l.onload=function(){q.filter((function(t){var r=i===L?t.x:Math.floor(t.x/2),o=i===L?t.y:Math.floor(t.y/2),a=i===L?t.z:t.z-1;return e===n({x:r,y:o,z:a})})).forEach((function(e){if(i===L)at.drawImage(l,0,0,L,L);else{var r=e.x%2*L,n=e.y%2*L;at.drawImage(l,r+1,n+1,L,L,0,0,L,L)}for(var a=at.getImageData(0,0,L,L).data,u=0;u<a.length;u+=4){var f=5*(o({r:a[u],g:a[u+1],b:a[u+2],a:0})||0),c=Math.floor(f/256),h=Math.floor(f%256);a[u/2]=c,a[u/2+1]=h}for(u=0;u<L;u++)s.set(a.slice(u*L*2,(u+1)*L*2),2*(e.yOffset*t+u*t+e.xOffset))})),a(null)},l.onerror=function(t){if(l.src!==l.originalSource)return u("new tiles requested");a(null)},l.crossOrigin=r||null,l.src=e,l.originalSource=l.src})).then((function(){lt++,a(lt,ut.length)}))]}))}))})),p.label=1;case 1:return p.trys.push([1,3,,4]),[4,Promise.all(c)];case 2:return p.sent(),[3,4];case 3:return h=p.sent(),console.log(c.length+" requests aborted",h),[2,null];case 4:return ut=[],[2,s];case 5:throw new Error("Could not get canvas context for merging tile images")}}))})))]);case 2:return null===(H=G.sent())?[2,ft=s(s({},ft),{visibleDEMPixelBounds:A,demZoom:_,dirty:!1})]:(O=function(t){var e=t.upperLeft,r=t.width,n=t.height,o=e.divideBy(L).floor().multiplyBy(L),i=o.add([r,n]);return new g(o,i)}({upperLeft:S,width:B,height:N}),X=new y(e.unproject(O.getTopLeft(),_),e.unproject(O.getBottomRight(),_)),W=0,[4,p]);case 3:return Z=G.sent(),W=function(t){var e=t.features,r=t.upperLeftTile,n=t.map,o=t.width,i=t.height,a=t.imageData,s=t.gl,u=r.x,l=r.y,f=r.z,c=b.program,h=b.positionAttributeLocation,p=b.xyzUniformLocation,d=b.dimensionsUniformLocation,_=b.heightMapUniformLocation,x=b.colorUniformLocation,g=b.positionBuffer,v=b.indexBuffer,y=b.targetTexture,E=0;s.useProgram(c),s.activeTexture(s.TEXTURE1);var T=s.createTexture();s.bindTexture(s.TEXTURE_2D,T),s.texParameteri(s.TEXTURE_2D,s.TEXTURE_WRAP_S,s.CLAMP_TO_EDGE),s.texParameteri(s.TEXTURE_2D,s.TEXTURE_WRAP_T,s.CLAMP_TO_EDGE),s.texParameteri(s.TEXTURE_2D,s.TEXTURE_MIN_FILTER,s.NEAREST),s.texParameteri(s.TEXTURE_2D,s.TEXTURE_MAG_FILTER,s.NEAREST),s.texImage2D(s.TEXTURE_2D,0,s.LUMINANCE_ALPHA,o,i,0,s.LUMINANCE_ALPHA,s.UNSIGNED_BYTE,a);var w=o*(n.getZoom()>15?2:1),M=i*(n.getZoom()>15?2:1);s.activeTexture(s.TEXTURE0),s.bindTexture(s.TEXTURE_2D,y),s.texImage2D(s.TEXTURE_2D,0,s.RGBA,w,M,0,s.RGBA,s.UNSIGNED_BYTE,null),n.getZoom()>15?(s.texParameteri(s.TEXTURE_2D,s.TEXTURE_MIN_FILTER,s.NEAREST),s.texParameteri(s.TEXTURE_2D,s.TEXTURE_MAG_FILTER,s.NEAREST)):(s.texParameteri(s.TEXTURE_2D,s.TEXTURE_MIN_FILTER,s.LINEAR),s.texParameteri(s.TEXTURE_2D,s.TEXTURE_MAG_FILTER,s.LINEAR)),s.texParameteri(s.TEXTURE_2D,s.TEXTURE_WRAP_S,s.CLAMP_TO_EDGE),s.texParameteri(s.TEXTURE_2D,s.TEXTURE_WRAP_T,s.CLAMP_TO_EDGE),s.viewport(0,0,w,M);var R=s.createFramebuffer();s.bindFramebuffer(s.FRAMEBUFFER,R);var A=s.COLOR_ATTACHMENT0;s.framebufferTexture2D(s.FRAMEBUFFER,A,s.TEXTURE_2D,y,0),s.bindBuffer(s.ARRAY_BUFFER,g),s.bindBuffer(s.ELEMENT_ARRAY_BUFFER,v),s.clearColor(0,0,0,0),s.clear(s.COLOR_BUFFER_BIT);var S=u*L,U=l*L,P=new m(S,U);s.uniform3f(p,S,U,f),s.uniform2f(d,o,i),s.uniform1i(_,1);var I=new Float32Array([-1,-1,1,-1,-1,1,1,1]);return s.enableVertexAttribArray(h),s.bufferData(s.ARRAY_BUFFER,I,s.STATIC_DRAW),s.vertexAttribPointer(h,2,s.FLOAT,!1,0,0),s.uniform4f(x,0,0,0,0),s.drawArrays(s.TRIANGLE_STRIP,0,4),e.forEach((function(t){var e=t.buildingHeight,r=t.aPosition,i=t.cuts,u=t.startPos,l=n.project({lng:u[0],lat:u[1]},f).subtract(P).floor(),c=256*a[l.y*o*2+2*l.x]+a[l.y*o*2+2*l.x+1]+5*e;if(!Number.isNaN(c)){var p=Math.floor(c/256)/256,d=Math.floor(c%256)/256;E=Math.max(E,c/5),s.uniform4f(x,p,d,0,1),s.bufferData(s.ARRAY_BUFFER,r,s.DYNAMIC_DRAW),s.vertexAttribPointer(h,2,s.FLOAT,!1,0,0),s.bufferData(s.ELEMENT_ARRAY_BUFFER,i,s.DYNAMIC_DRAW),s.drawElements(s.TRIANGLES,i.length,i.length>256?s.UNSIGNED_SHORT:s.UNSIGNED_BYTE,0)}})),s.deleteTexture(T),E}({upperLeftTile:C[0],width:B,height:N,map:e,features:Z,imageData:H,screenPixelBounds:T,gl:i}),R,ft={maxHeight:8848,maxBuildingHeight:W,width:B,height:N,tileLatLngBounds:X,imageData:H,visibleDEMPixelBounds:A,raster:C,demZoom:_,dirty:!0,canvasWidth:w,canvasHeight:M},[3,5];case 4:return j=G.sent(),console.error("Could not decode height map",j),[3,5];case 5:return[2,ft]}var q,k,K,Y}))}))},ht=.40909994067971484,pt=function(t){var e=t.valueOf()/864e5-10957.5,r=6.240059966692059+.017201969994578018*e,n=r+.017453292519943295*(1.9148*Math.sin(r)+.02*Math.sin(2*r)+3e-4*Math.sin(3*r))+1.796593062783907+Math.PI,o=Math.atan2(Math.sin(n)*Math.cos(ht),Math.cos(n));return{dec:Math.asin(Math.sin(ht)*Math.sin(n)),Hi:(4.889714432387314+6.3003876824396166*e-o)%(2*Math.PI)+2*Math.PI}},dt=function(t,e){return[t.r/255,t.g/255,t.b/255,e]},mt=function(t,e){var r=e.date,n=pt(r),o=n.dec,i=n.Hi;t.updateDate({dec:o,Hi:i})},_t=function(t,e){t.updateDateRange(s(s({},e),{getDeclination:pt}))},xt=function(t,e){var r=e.color,n=e.opacity,o=dt(r,n);t.updateColor({colorVec:o})};new y([0,0],[0,0]);var gt=function(t){var e=t.kernel,r=t.map,n=t.heightMap,o=t.now,i=t.color,a=t.opacity,u=t.maxZoom;try{var l=n.maxHeight,f=n.maxBuildingHeight,c=n.width,h=n.height,p=n.tileLatLngBounds,d=n.imageData,m=n.visibleDEMPixelBounds,_=n.demZoom;if(0===c||0===h)return;var x=m.min,g=m.max;if(!x||!g)return;var v=g.subtract(x).divideBy(_>u?Math.pow(2,_-u):1),y=v.x,E=v.y,T=r.project(p.getNorthWest(),_),w=x.divideBy(_>u?Math.pow(2,_-u):1).subtract(T),M=w.x,b=w.y,R=M/c,A=b/h,S=R+y/c,U=A+E/h,P=T.y/L/Math.pow(2,_),I=h/L/Math.pow(2,_),D=p.getWest(),C=Math.abs(p.getWest()-p.getEast())/c;!function(t,e){var r=e.color,n=e.opacity,o=e.date,i=e.imageData,a=e.maxBuildingHeight,u=dt(r,n),l=pt(o),f=l.dec,c=l.Hi;t.updateLocation(s({dec:f,Hi:c,colorVec:u,step:1},e)),ot(i).then((function(e){var r=e.maxHeight;t.updateMaxHeight({maxHeight:Math.max(r,a)})}))}(e,{imageData:d,maxHeight:l,maxBuildingHeight:f,width:c,height:h,date:o,heightMapZoom:_,mapZoom:r.getZoom(),xStart:R,yStart:A,xEnd:S,yEnd:U,topYCoord:P,ySize:I,color:i,opacity:a,west:D,dLng:C})}catch(t){console.error("EXCEPTION",t)}};var vt,yt=function(t){var e=function(){return!t.getPitch};return{project:function(r,n){if(e())return t.project(r,n);var o=r.lat;return new m(function(t,e){return(t+180)/360*Math.pow(2,e)*L}(r.lng,n),function(t,e){return(1-Math.log(Math.tan(t*Math.PI/180)+1/Math.cos(t*Math.PI/180))/Math.PI)/2*Math.pow(2,e)*L}(o,n))},unproject:function(r,n){return e()?t.unproject(r,n):new w((o=r.y,i=n,a=Math.PI-2*Math.PI*o/L/Math.pow(2,i),180/Math.PI*Math.atan(.5*(Math.exp(a)-Math.exp(-a)))),function(t,e){return t/L/Math.pow(2,e)*360-180}(r.x,n));var o,i,a},getZoom:function(){return e()?t.getZoom():t.getZoom()+1},getCenter:function(){return t.getCenter()},getBounds:function(){return t.getBounds()},eachLayer:function(r){e()&&t.eachLayer(r)},getBearing:function(){return e()?0:t.getBearing()},getPitch:function(){return e()?0:t.getPitch()},rawMap:function(){return t},isLeaflet:e}};function Et(t){var e=t.context,r=function(t){var e=t.gl,r=t.vSrc,n=t.fSrc,o=e.createShader(e.VERTEX_SHADER);e.shaderSource(o,r),e.compileShader(o);var i=e.createShader(e.FRAGMENT_SHADER);e.shaderSource(i,n),e.compileShader(i);var a=e.createProgram();return e.attachShader(a,o),e.attachShader(a,i),e.linkProgram(a),e.getProgramParameter(a,e.LINK_STATUS)||(console.error("Link failed: "+e.getProgramInfoLog(a)),console.error("vs info-log: "+e.getShaderInfoLog(o)),console.error("fs info-log: "+e.getShaderInfoLog(i))),a}({gl:e,vSrc:"precision lowp float;precision lowp int;precision lowp sampler2D;attribute vec2 aPos;varying vec2 vTexCoordCropped;varying vec2 vTexCoordFull;uniform float user_xStart;uniform float user_yStart;uniform float user_xEnd;uniform float user_yEnd;void main(void){gl_Position=vec4(aPos,0,1);vec4 textureSpace=gl_Position*0.5+0.5;vTexCoordCropped=vec2((user_xEnd-user_xStart)*textureSpace.x+user_xStart,(user_yEnd-user_yStart)*(1.0-textureSpace.y)+user_yStart);vTexCoordFull=vec2(textureSpace);}",fSrc:"#ifdef GL_FRAGMENT_PRECISION_HIGH\nprecision highp float;\n#else\nprecision mediump float;\n#endif\nprecision lowp int;precision lowp sampler2D;float atan2(float v1,float v2){if(v1==0.0||v2==0.0)return 0.0;return atan(v1,v2);}float _pow(float v1,float v2){if(v2==0.0)return 1.0;return pow(v1,v2);}float integerMod(float x,float y){float res=floor(mod(x,y));return res*(res>floor(y)-1.0 ? 0.0 : 1.0);}float divWithIntCheck(float x,float y){if(floor(x)==x&&floor(y)==y&&integerMod(x,y)==0.0){return float(int(x)/int(y));}return x/y;}float integerCorrectionModulo(float number,float divisor){if(number<0.0){number=abs(number);if(divisor<0.0){divisor=abs(divisor);}return-(number-(divisor*floor(divWithIntCheck(number,divisor))));}if(divisor<0.0){divisor=abs(divisor);}return number-(divisor*floor(divWithIntCheck(number,divisor)));}float getElevationFromSampler2D(sampler2D tex,float x,float y){vec4 result=texture2D(tex,vec2(x,y));return(result.r*256.0*256.0+result.g*256.0)/5000.0;}vec4 actualColor;void color(float r,float g,float b,float a){actualColor=vec4(r,g,b,a);}void color(float r,float g,float b){color(r,g,b,1.0);}void color(float r){color(r,r,r,1.0);}const int LOOP_MAX=1000;varying vec2 vTexCoordCropped;varying vec2 vTexCoordFull;uniform sampler2D user_a;uniform float user_width;uniform float user_height;uniform float user_maxHeight;uniform float user_zoom;uniform float user_topYCoord;uniform float user_ySize;uniform vec4 user_color;uniform float user_step;uniform float user_west;uniform float user_dLng;uniform float user_dec;uniform float user_Hi;uniform sampler2D user_sunExposureTexture;uniform bool user_renderToSunExposureTexture;uniform bool user_outputSunExposure;uniform float user_exposureTimeStep;float kernelResult;void kernel(){float maxHeight=user_maxHeight/1000.0;float user_x=vTexCoordCropped.x;float user_y=vTexCoordCropped.y;float user_z=getElevationFromSampler2D(user_a,user_x,user_y);float user_PI=3.141592653589793;float user_2PI=6.283185307179586;float earthRadiusInKm=6378.137;float user_deg=57.29577951308232;float user_y_coord=user_topYCoord+(user_y*user_ySize);float user_lat_coord=(user_y_coord-0.5)/-0.15915494309189532;float user_lat=(2.0*atan(exp(user_lat_coord)))-(user_PI/2.0);float user_rad=0.017453292519943295;float user_lng=(user_west+(user_dLng*user_x*user_width));float user_H=integerCorrectionModulo((user_Hi-(user_rad*-user_lng)),user_2PI);float sun_azimuth=atan2(sin(user_H),((cos(user_H)*sin(user_lat))-(tan(user_dec)*cos(user_lat))));float sun_altitude=asin(((sin(user_lat)*sin(user_dec))+((cos(user_lat)*cos(user_dec))*cos(user_H))));float user_zoom_factor=_pow(2.0,user_zoom);float user_kmPerPixel=divWithIntCheck(156.5430339296875,user_zoom_factor)*abs(cos(user_lat));float user_dx=((-sin(sun_azimuth)*cos(sun_altitude))*user_step)/user_width;float user_dy=((cos(sun_azimuth)*cos(sun_altitude))*user_step)/user_height;float user_dz=((sin(sun_altitude)*user_kmPerPixel)*user_step);float user_lit=1.0;float user_curvature=0.0;float cur_height=0.0;float user_distance=0.0;float user_startX=user_x;float user_startY=user_y;user_x+=user_dx;user_y+=user_dy;user_z+=user_dz;if((abs(1.0)<0.0)){kernelResult=0.0;return;}float minAngle=asin((earthRadiusInKm/(earthRadiusInKm+user_z)))-(user_PI/2.0);if(user_z<0.0||sun_altitude<minAngle){user_lit=0.0;}else{float xIter=ceil(user_dx<0.0 ? abs(user_x/user_dx):(1.0-user_x)/user_dx);float yIter=ceil(user_dy<0.0 ? abs(user_y/user_dy):(1.0-user_y)/user_dy);float zIter=ceil(user_dz<0.0 ? float(LOOP_MAX):(maxHeight-user_z)/user_dz);int iter=int(min(xIter,min(yIter,zIter)));float user_distance=(sqrt(pow(user_dx*user_width,2.0)+pow(user_dy*user_height,2.0))*user_kmPerPixel)/earthRadiusInKm;for(int safeI=0;safeI<LOOP_MAX;safeI++){if(safeI>iter){break;}cur_height=getElevationFromSampler2D(user_a,user_x,user_y);if(user_z<cur_height){user_curvature=earthRadiusInKm*(1.0-cos(user_distance*float(safeI+1)));if(user_z<(cur_height-user_curvature)){user_lit=0.0;iter=0;break;}}user_x+=user_dx;user_y+=user_dy;user_z+=user_dz;}}if((user_lit==1.0)){color(0.0,0.0,0.0,0.0);}else{color(user_color.r,user_color.g,user_color.b,user_color.a);}if(user_renderToSunExposureTexture){vec4 aggregateColor=texture2D(user_sunExposureTexture,vec2(vTexCoordFull.x,vTexCoordFull.y));if((user_lit==1.0)){color(aggregateColor.r,0.0,0.0,1.0);}else{color(aggregateColor.r+user_exposureTimeStep,user_color.g,user_color.b,1.0);}if(user_outputSunExposure){color(user_color.r,user_color.g,user_color.b,aggregateColor.r);}}}void main(void){kernel();gl_FragColor=actualColor;}"});e.useProgram(r);var n=e.createBuffer();e.bindBuffer(e.ARRAY_BUFFER,n);var o=new Float32Array([-1,-1,1,-1,-1,1,1,1]);e.bufferData(e.ARRAY_BUFFER,o,e.STATIC_DRAW);var i=e.getAttribLocation(r,"aPos");e.enableVertexAttribArray(i),e.vertexAttribPointer(i,2,e.FLOAT,!1,0,0),e.enable(e.BLEND),e.blendFunc(e.SRC_ALPHA,e.ONE_MINUS_SRC_ALPHA);var a=e.getUniformLocation(r,"user_a");e.uniform1i(a,0);var s=e.getUniformLocation(r,"user_width"),u=e.getUniformLocation(r,"user_height"),l=e.getUniformLocation(r,"user_maxHeight"),f=e.getUniformLocation(r,"user_zoom"),c=e.getUniformLocation(r,"user_topYCoord"),h=e.getUniformLocation(r,"user_ySize"),p=e.getUniformLocation(r,"user_step"),d=e.getUniformLocation(r,"user_west"),m=e.getUniformLocation(r,"user_dLng"),_=e.getUniformLocation(r,"user_dec"),x=e.getUniformLocation(r,"user_Hi"),g=e.getUniformLocation(r,"user_color"),v=e.getUniformLocation(r,"user_xStart"),y=e.getUniformLocation(r,"user_yStart"),E=e.getUniformLocation(r,"user_xEnd"),T=e.getUniformLocation(r,"user_yEnd"),w=e.getUniformLocation(r,"user_sunExposureTexture");e.uniform1i(w,2);var M=e.getUniformLocation(r,"user_renderToSunExposureTexture"),b=e.getUniformLocation(r,"user_outputSunExposure"),R=e.getUniformLocation(r,"user_exposureTimeStep"),L=function(){e.clear(e.COLOR_BUFFER_BIT),e.drawArrays(e.TRIANGLE_STRIP,0,4)};return{updateLocation:function(t){t.imageData;var o=t.width,a=t.height,w=t.maxHeight,M=t.heightMapZoom;t.mapZoom;var b=t.topYCoord,R=t.ySize,A=t.colorVec,S=t.step,U=t.west,P=t.dLng,I=t.dec,D=t.Hi,C=t.xStart,F=t.xEnd,z=t.yStart,B=t.yEnd;e.useProgram(r),e.bindFramebuffer(e.FRAMEBUFFER,null),e.bindBuffer(e.ARRAY_BUFFER,n),e.vertexAttribPointer(i,2,e.FLOAT,!1,0,0),e.uniform1f(s,o),e.uniform1f(u,a),e.uniform1f(l,w),e.uniform1f(f,M),e.uniform1f(c,b),e.uniform1f(h,R),e.uniform4fv(g,A),e.uniform1f(p,S),e.uniform1f(d,U),e.uniform1f(m,P),e.uniform1f(_,I),e.uniform1f(x,D),e.uniform1f(v,C),e.uniform1f(y,z),e.uniform1f(E,F),e.uniform1f(T,B),window.requestAnimationFrame(L)},updateViewport:function(t){var r=t.xStart,n=t.yStart,o=t.xEnd,i=t.yEnd;e.uniform1f(v,r),e.uniform1f(y,n),e.uniform1f(E,o),e.uniform1f(T,i),window.requestAnimationFrame(L)},updateDate:function(t){var r=t.dec,n=t.Hi;e.uniform1f(_,r),e.uniform1f(x,n),window.requestAnimationFrame(L)},updateDateRange:function(t){var r=t.start,n=t.end,o=t.getDeclination,i=t.emit;e.uniform1f(R,.04);var a=Math.floor((n.getTime()-r.getTime())/25),s=e.canvas.width,u=e.canvas.height,l=e.createTexture();e.activeTexture(e.TEXTURE1),e.bindTexture(e.TEXTURE_2D,l),e.texImage2D(e.TEXTURE_2D,0,e.RGBA,s,u,0,e.RGBA,e.UNSIGNED_BYTE,null),e.texParameteri(e.TEXTURE_2D,e.TEXTURE_WRAP_S,e.CLAMP_TO_EDGE),e.texParameteri(e.TEXTURE_2D,e.TEXTURE_WRAP_T,e.CLAMP_TO_EDGE),e.texParameteri(e.TEXTURE_2D,e.TEXTURE_MIN_FILTER,e.LINEAR),e.texParameteri(e.TEXTURE_2D,e.TEXTURE_MAG_FILTER,e.LINEAR);var f=e.createTexture();e.activeTexture(e.TEXTURE2),e.bindTexture(e.TEXTURE_2D,f),e.texImage2D(e.TEXTURE_2D,0,e.RGBA,s,u,0,e.RGBA,e.UNSIGNED_BYTE,null),e.texParameteri(e.TEXTURE_2D,e.TEXTURE_WRAP_S,e.CLAMP_TO_EDGE),e.texParameteri(e.TEXTURE_2D,e.TEXTURE_WRAP_T,e.CLAMP_TO_EDGE),e.texParameteri(e.TEXTURE_2D,e.TEXTURE_MIN_FILTER,e.LINEAR),e.texParameteri(e.TEXTURE_2D,e.TEXTURE_MAG_FILTER,e.LINEAR),e.uniform1i(M,1);var c=e.createFramebuffer();e.bindFramebuffer(e.FRAMEBUFFER,c);var h=e.COLOR_ATTACHMENT0;e.viewport(0,0,s,u);for(var p=0;p<25;p++){i("tilesloaded",p,24),p%2==0?(e.uniform1i(w,2),e.activeTexture(e.TEXTURE1),e.bindTexture(e.TEXTURE_2D,l),e.framebufferTexture2D(e.FRAMEBUFFER,h,e.TEXTURE_2D,l,0)):(e.uniform1i(w,1),e.activeTexture(e.TEXTURE2),e.bindTexture(e.TEXTURE_2D,f),e.framebufferTexture2D(e.FRAMEBUFFER,h,e.TEXTURE_2D,f,0));var d=o(new Date(r.getTime()+a*p)),m=d.dec,g=d.Hi;e.uniform1f(_,m),e.uniform1f(x,g),e.clear(e.COLOR_BUFFER_BIT),e.drawArrays(e.TRIANGLE_STRIP,0,4)}e.bindFramebuffer(e.FRAMEBUFFER,null),e.uniform1i(b,1),window.requestAnimationFrame((function(){L(),e.uniform1i(M,0),e.uniform1i(b,0),e.deleteTexture(l),e.deleteTexture(f)}))},updateColor:function(t){var r=t.colorVec;e.uniform4fv(g,r),window.requestAnimationFrame(L)},updateMaxHeight:function(t){var r=t.maxHeight;e.uniform1f(l,r)}}}t.Quality=void 0,(vt=t.Quality||(t.Quality={})).LOW="low",vt.MED="medium",vt.HIGH="high";var Tt=function(e){function r(){for(var r=[],n=0;n<arguments.length;n++)r[n]=arguments[n];var o=e.call(this)||this;o.options={date:new Date,color:"000",opacity:.3,quality:t.Quality.MED,showExposure:!1,apiKey:"",terrainSource:{maxZoom:15,tileSize:256,getSourceUrl:function(t){return t.x,t.y,t.z,"https://s3.amazonaws.com/elevation-tiles-prod/terrarium/7/17/45.png"},getElevation:function(t){return 256*t.r+t.g+t.b/256-32768}},getFeatures:function(t){return[]},debug:function(t){}};var i=r[0];if(o.options=Object.assign(o.options,i),!o.options.apiKey)throw new Error("Could not load ShadeMap: apiKey missing");fetch("https://shademap.app/sdk/load",{method:"POST",body:JSON.stringify({api_key:o.options.apiKey}),headers:{"Content-Type":"application/json"}}).then((function(t){return u(o,void 0,void 0,(function(){var e;return l(this,(function(r){switch(r.label){case 0:return 200===t.status?[3,2]:(e=Error.bind,[4,t.text()]);case 1:throw new(e.apply(Error,[void 0,r.sent()]));case 2:return[2]}}))}))})).catch((function(t){return u(o,void 0,void 0,(function(){return l(this,(function(e){if(200!==t.status)throw new Error("Could not load ShadeMap API");return[2]}))}))})),o._canvasElWidth=window.innerWidth,o._canvasElHeight=window.innerHeight;var a={preserveDrawingBuffer:!0,antialias:!1};return o._canvas=document.createElement("canvas"),o._gl=o._canvas.getContext("webgl",a)||o._canvas.getContext("experimental-webgl",a),o._compiledKernel=Et({context:o._gl}),o._color=o._parseColor(o.options.color),A(o._gl),o._reset=o._reset.bind(o),o._draw=o._draw.bind(o),o._resize=o._resize.bind(o),o}return a(r,e),r.prototype.onRemove=function(){return this._map&&(this._map.off("moveend",this._reset),this._map.off("resize",this._resize)),this},r.prototype.setDate=function(t){return this.options.date.getTime()!==t.getTime()?(this.options.date=t,this._compiledKernel&&(mt(this._compiledKernel,{date:this.options.date}),this._flush())):this.emit("idle"),this},r.prototype.setColor=function(t){return this.options.color!==t&&(this.options.color=t,this._color=this._parseColor(this.options.color),this._compiledKernel&&(xt(this._compiledKernel,{color:this._color,opacity:this.options.opacity}),this._flush())),this},r.prototype.setOpacity=function(t){return this.options.opacity!==t&&(this.options.opacity=t,this._compiledKernel&&(xt(this._compiledKernel,{color:this._color,opacity:this.options.opacity}),this._flush())),this},r.prototype.setQuality=function(t){return this.options.quality!==t&&(this.options.quality=t,this._resizeCanvas(),this._reset()),this},r.prototype.setShowExposure=function(t){if(this.options.showExposure!==t&&this._map&&this._compiledKernel){if(this.options.showExposure=t,!0===t){var e=yt(this._map).getCenter(),r=o.default.getTimes(this.options.date,e.lat,e.lng),n=r.sunrise,i=r.sunset;_t(this._compiledKernel,{start:n,end:i,emit:this.emit.bind(this)})}else mt(this._compiledKernel,{date:this.options.date});this._flush()}return this},r.prototype._resize=function(t,e){void 0===t&&(t=0),void 0===e&&(e=0),this.options.debug("_resize w:"+t+" h:"+e),this._canvasElWidth=t,this._canvasElHeight=e,this._resizeCanvas()},r.prototype._resizeCanvas=function(){var e=this._canvasElWidth*(this.options.quality===t.Quality.HIGH?2:1),r=this._canvasElHeight*(this.options.quality===t.Quality.HIGH?2:1),n=window.innerWidth*window.innerHeight*(this.options.quality===t.Quality.HIGH?2:1),o=e*r,i=Math.sqrt(n/o);this._canvas.width=e*i,this._canvas.height=r*i,this._gl.viewport(0,0,e*i,r*i)},r.prototype._reset=function(){return u(this,void 0,void 0,(function(){var e,r,n,o=this;return l(this,(function(i){switch(i.label){case 0:if(this.options.debug("_reset()"),!this._map)return[3,2];e=yt(this._map),r=void 0;try{r=e.getBounds()}catch(t){return console.error("Invalid bounds returned: ",t),[2,this]}return[4,ct({gl:this._gl,map:e,terrainSource:this.options.terrainSource,getFeatures:this.options.getFeatures,quality:t.Quality.MED,tileLoaded:function(t,e){return o.emit("tileloaded",t,e)}})];case 1:(n=i.sent()).dirty&&(this._resize(n.canvasWidth,n.canvasHeight),this._draw(n,r)),i.label=2;case 2:return[2,this]}}))}))},r.prototype._draw=function(t,e){var r=this;return this.options.debug("_draw()"),setTimeout((function(){if(r._canvas&&r._compiledKernel&&r._map){if(gt({kernel:r._compiledKernel,map:yt(r._map),heightMap:t,color:r._color,opacity:r.options.opacity,now:r.options.date,maxZoom:r.options.terrainSource.maxZoom}),r.options.showExposure){var n=r._map.getCenter(),i=o.default.getTimes(r.options.date,n.lat,n.lng),a=i.sunrise,s=i.sunset;_t(r._compiledKernel,{start:a,end:s,emit:r.emit.bind(r)})}r._repositionCanvas(e)}}),0),this},r.prototype.readPixel=function(t,e){var r=new Uint8Array(4);return this._gl.readPixels(t,e,1,1,this._gl.RGBA,this._gl.UNSIGNED_BYTE,r),r},r.prototype._repositionCanvas=function(t){},r.prototype._flush=function(){},r.prototype.flushSync=function(){this._gl.finish()},r.prototype._parseColor=function(t){t=t.replace("#","");var e={r:0,g:0,b:0};return/^([0-9A-F]{3}){1,2}$/i.test(t)&&(3===t.length?(e.r=parseInt(t[0]+t[0],16),e.g=parseInt(t[1]+t[1],16),e.b=parseInt(t[2]+t[2],16)):6===t.length&&(e.r=parseInt(t[0]+t[1],16),e.g=parseInt(t[2]+t[3],16),e.b=parseInt(t[4]+t[5],16))),e},r}(S),wt=function(t){function e(e){return t.call(this,e)||this}return a(e,t),e.prototype.addTo=function(t){return this.onAdd(t)},e.prototype.onAdd=function(t){var e=this;if(this._map=t,!this._canvasOverlay&&this._canvas){this._resizeCanvas();var r=this._map.getBounds();this._canvasOverlay=function(){for(var t=[],e=0;e<arguments.length;e++)t[e]=arguments[e];return new(c.bind.apply(c,f([void 0],t)))}(this._canvas,r),this._canvasOverlay.addTo(this._map)}return this._map.on("moveend",this._reset),this._map.on("resize",(function(){return e._resize(window.innerWidth,window.innerHeight)})),this._reset(),this},e.prototype._repositionCanvas=function(t){this._canvasOverlay&&this._canvasOverlay.setBounds(t)},e}(Tt),Mt="canvas-source",bt="attribution-source",Rt="canvas-layer",Lt="attribution-layer",At=function(t){function e(e){var r=t.call(this,e)||this;return r.id="shademap-layer",r.type="custom",r.options.terrainSource.maxZoom=14,r._refreshing=0,r._raf=0,r._resizeHandler=function(){return r._resize(window.innerWidth,window.innerHeight)},r._moveEndHandler=function(){return r._map&&r._map.getPitch()<=45&&r._reset()},r}return a(e,t),e.prototype.render=function(t,e){},e.prototype.addTo=function(t){return t.addLayer(this),this},e.prototype.onAdd=function(t){var e=this;this._map=t,this._resizeCanvas(),document.body.appendChild(this._canvas),this._canvas.style.display="none";var r=t.getBounds(),n=r.getNorthWest(),o=r.getNorthEast(),i=r.getSouthEast(),a=r.getSouthWest(),s=[[n.lng,n.lat],[o.lng,o.lat],[i.lng,i.lat],[a.lng,a.lat]];t.addSource(Mt,{type:"canvas",canvas:this._canvas,coordinates:s,animate:!1}),t.addLayer({id:Rt,type:"raster",source:Mt,paint:{"raster-fade-duration":0}}),t.addSource(bt,{type:"geojson",data:{type:"Feature",properties:{},geometry:{type:"Point",coordinates:[-122.210598,47.769799]}},attribution:'<a href="https://shademap.app/about">&copy; ShadeMap</a>'}),t.addLayer({id:Lt,type:"fill",source:bt});var u=t.getSource("canvas-source"),l=function(){e._refreshing>0&&(u.texture.update(e._canvas,{premultiply:!0}),u.fire({type:"data",dataType:"source",sourceDataType:"content"}),e._refreshing--,e.options.debug("repaint"),1===e._refreshing&&e.emit("idle")),e._raf=requestAnimationFrame(l)};return this._raf=requestAnimationFrame(l),this._map.on("moveend",this._moveEndHandler),this._map.on("resize",this._resizeHandler),this._moveEndHandler(),this},e.prototype.onRemove=function(){return this._map&&(this._map.off("moveend",this._moveEndHandler),this._map.off("resize",this._resizeHandler),this._map.removeLayer(Lt),this._map.removeLayer(Rt),this._map.removeSource(bt),this._map.removeSource(Mt)),cancelAnimationFrame(this._raf),document.body.removeChild(this._canvas),this.options.debug("onRemove called"),this},e.prototype.remove=function(){this._map&&this._map.removeLayer(this.id)},e.prototype._flush=function(){this._refreshing=2},e.prototype._repositionCanvas=function(t){if(this._map){var e=this._map.getSource("canvas-source");if(e){var r=t.getNorthWest(),n=t.getNorthEast(),o=t.getSouthEast(),i=t.getSouthWest(),a=[[r.lng,r.lat],[n.lng,n.lat],[o.lng,o.lat],[i.lng,i.lat]];e.setCoordinates(a),this._flush()}}return this},e}(Tt);void 0!==window.L&&(window.L.shadeMap=function(){for(var t=[],e=0;e<arguments.length;e++)t[e]=arguments[e];return new(wt.bind.apply(wt,f([void 0],t)))}),t.ShadeMapLeaflet=wt,t.ShadeMapMapbox=At,Object.defineProperty(t,"__esModule",{value:!0})}));
@@ -0,0 +1,102 @@
1
+ <!DOCTYPE html>
2
+ <html lang="en">
3
+
4
+ <head>
5
+ <meta charset="UTF-8" />
6
+ <meta name="viewport" content="width=device-width, initial-scale=1.0" />
7
+ <meta http-equiv="X-UA-Compatible" content="ie=edge" />
8
+ <link rel="stylesheet" href="https://unpkg.com/leaflet@1.7.1/dist/leaflet.css" />
9
+ <script src="https://unpkg.com/leaflet@1.7.1/dist/leaflet.js"></script>
10
+ <script src="../dist/leaflet-shadow-simulator.umd.min.js"></script>
11
+ <style>
12
+ body {
13
+ padding: 0px;
14
+ margin: 0px;
15
+ }
16
+
17
+ #mapid {
18
+ height: 100vh;
19
+ }
20
+
21
+ .leaflet-control-time {
22
+ padding-left: 40px;
23
+ }
24
+ </style>
25
+ <title>Shade Map Leaflet example</title>
26
+ </head>
27
+
28
+ <body>
29
+ <div id="mapid"></div>
30
+ <div class="leaflet-control-container">
31
+ <div class="leaflet-top leaflet-left">
32
+ <div class="leaflet-control-time leaflet-control">
33
+ <button id="decrement">-1 hour</button>
34
+ <button id="increment">+1 hour</button>
35
+ <button id="play">Play</button>
36
+ <button id="stop">Stop</button>
37
+ <button>
38
+ <a href="https://shademap.app/about" target="_blank">Get API key</a>
39
+ </button>
40
+ </div>
41
+ </div>
42
+ </div>
43
+ <script>
44
+ /* Leaflet setup */
45
+ var map = L.map("mapid").setView([47.69682, -121.92078], 9);
46
+ L.tileLayer("https://tile.openstreetmap.org/{z}/{x}/{y}.png", {
47
+ attribution:
48
+ 'Map data &copy; <a href="https://www.openstreetmap.org/copyright">OpenStreetMap</a> contributors',
49
+ maxZoom: 18,
50
+ }).addTo(map);
51
+ /* End Leaflet setup */
52
+
53
+
54
+ /* ShadeMap setup */
55
+ let now = new Date(1633358583454);
56
+ const shadeMap = L.shadeMap({
57
+ apiKey: "eyJhbGciOiJIUzI1NiJ9.eyJlbWFpbCI6InRwcGlvdHJvd3NraUBzaGFkZW1hcC5hcHAiLCJjcmVhdGVkIjoxNjYyNDkzMDY2Nzk0LCJpYXQiOjE2NjI0OTMwNjZ9.ovCrLTYsdKFTF6TW3DuODxCaAtGQ3qhcmqj3DWcol5g",
58
+ date: now,
59
+ color: '#01112f',
60
+ opacity: 0.7,
61
+ terrainSource: {
62
+ maxZoom: 15,
63
+ tileSize: 256,
64
+ getSourceUrl: ({ x, y, z }) => `https://s3.amazonaws.com/elevation-tiles-prod/terrarium/${z}/${x}/${y}.png`,
65
+ getElevation: ({ r, g, b, a }) => (r * 256 + g + b / 256) - 32768,
66
+ },
67
+ }).addTo(map);
68
+ /* End ShadeMap setup */
69
+
70
+ /* Controls setup */
71
+ let intervalTimer;
72
+ const increment = document.getElementById('increment');
73
+ const decrement = document.getElementById('decrement');
74
+ const play = document.getElementById('play');
75
+ const stop = document.getElementById('stop');
76
+
77
+ increment.addEventListener('click', () => {
78
+ now = new Date(now.getTime() + 3600000);
79
+ shadeMap.setDate(now);
80
+ }, false);
81
+
82
+ decrement.addEventListener('click', () => {
83
+ now = new Date(now.getTime() - 3600000);
84
+ shadeMap.setDate(now);
85
+ }, false);
86
+
87
+ play.addEventListener('click', () => {
88
+ intervalTimer = setInterval(() => {
89
+ now = new Date(now.getTime() + 60000);
90
+ shadeMap.setDate(now);
91
+ }, 100);
92
+ });
93
+
94
+ stop.addEventListener('click', () => {
95
+ clearInterval(intervalTimer);
96
+ })
97
+ /* End controls setup */
98
+
99
+ </script>
100
+ </body>
101
+
102
+ </html>
package/package.json ADDED
@@ -0,0 +1,29 @@
1
+ {
2
+ "name": "leaflet-shadow-simulator",
3
+ "version": "0.1.0",
4
+ "description": "Display terrain and structure shadows cast by the sun in a custom Leaflet layer",
5
+ "main": "dist/leaflet-shadow-simulator.umd.min.js",
6
+ "scripts": {
7
+ "test": "echo \"Error: no test specified\" && exit 1"
8
+ },
9
+ "repository": {
10
+ "type": "git",
11
+ "url": "git+https://github.com/ted-piotrowski/leaflet-shadow-simulator.git"
12
+ },
13
+ "keywords": [
14
+ "leaflet",
15
+ "shade",
16
+ "layer",
17
+ "shadow",
18
+ "simulator"
19
+ ],
20
+ "author": "Ted Piotrowski",
21
+ "license": "UNLICENSED",
22
+ "bugs": {
23
+ "url": "https://github.com/ted-piotrowski/leaflet-shadow-simulator/issues"
24
+ },
25
+ "homepage": "https://github.com/ted-piotrowski/leaflet-shadow-simulator#readme",
26
+ "dependencies": {
27
+ "suncalc": "^1.9.0"
28
+ }
29
+ }