Skip to content

Commit 4ad62a9

Browse files
committed
cleanup, use covjson-reader and covutils
1 parent 492e609 commit 4ad62a9

File tree

5 files changed

+282
-1814
lines changed

5 files changed

+282
-1814
lines changed

CoverageLayer.js

+171
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,171 @@
1+
// this function is taken from leaflet-coverage/src/layers/Grid.js#_getDomainBbox
2+
function getGridBbox (axes) {
3+
function extent (x, xBounds) {
4+
var xend = x.length - 1
5+
var xmin, xmax
6+
if (xBounds) {
7+
xmin = xBounds.get(0)[0]
8+
xmax = xBounds.get(xend)[1]
9+
} else {
10+
xmin = x[0]
11+
xmax = x[xend]
12+
}
13+
var xDescending = xmin > xmax
14+
if (xDescending) {
15+
var tmp = xmin
16+
xmin = xmax
17+
xmax = tmp
18+
}
19+
// we derive the size of the first/last grid cell if no bounds exist
20+
if (!xBounds && x.length > 1) {
21+
if (xDescending) {
22+
xmin -= (x[xend - 1] - x[xend]) / 2
23+
xmax += (x[0] - x[1]) / 2
24+
} else {
25+
xmin -= (x[1] - x[0]) / 2
26+
xmax += (x[xend] - x[xend - 1]) / 2
27+
}
28+
}
29+
return [xmin, xmax]
30+
}
31+
32+
var xAxis = axes.get('x')
33+
var yAxis = axes.get('y')
34+
var xextent = extent(xAxis.values, xAxis.bounds)
35+
var yextent = extent(yAxis.values, yAxis.bounds)
36+
37+
return [xextent[0], yextent[0], xextent[1], yextent[1]]
38+
}
39+
40+
var CovJSONGridLayer = function (cov, options) {
41+
var self = this
42+
this.cov = cov
43+
this.paramKey = options.paramKey
44+
Promise.all([cov.loadDomain(), cov.loadRange(this.paramKey)]).then(function (res) {
45+
self.domain = res[0]
46+
self.range = res[1]
47+
48+
self.paletteExtent = options.paletteExtent || CovUtils.minMaxOfRange(self.range)
49+
self._palette = hexToRgb(palette('tol-dv', 1000))
50+
51+
var bbox = getGridBbox(self.domain.axes)
52+
self._bbox = bbox
53+
54+
TiledCanvasLayer.call(self, new WorldWind.Sector(bbox[1], bbox[3], bbox[0], bbox[2]), 256, 256, options.displayName)
55+
})
56+
}
57+
58+
CovJSONGridLayer.prototype = Object.create(TiledCanvasLayer.prototype);
59+
60+
CovJSONGridLayer.prototype.drawCanvasTile = function (canvas, tile) {
61+
var ctx = canvas.getContext('2d')
62+
var tileWidth = tile.tileWidth
63+
var tileHeight = tile.tileHeight
64+
65+
var imgData = ctx.getImageData(0, 0, tileWidth, tileHeight)
66+
var rgba = xndarray(imgData.data, { shape: [tileHeight, tileWidth, 4] })
67+
68+
// data coordinates
69+
var lats = this.domain.axes.get('y').values
70+
var lons = this.domain.axes.get('x').values
71+
72+
// extended data bounding box
73+
var lonMin = this._bbox[0]
74+
var lonMax = this._bbox[2]
75+
var latMin = this._bbox[1]
76+
var latMax = this._bbox[3]
77+
78+
// tile coordinates
79+
var sector = tile.sector
80+
var tileLatMin = sector.minLatitude
81+
var tileLonMin = sector.minLongitude
82+
var tileLatMax = sector.maxLatitude
83+
var tileLonMax = sector.maxLongitude
84+
var tileLatStep = (tileLatMax - tileLatMin) / tileHeight
85+
var tileLonStep = (tileLonMax - tileLonMin) / tileWidth
86+
87+
// used for longitude wrapping
88+
var lonRange = [lonMin, lonMin + 360]
89+
90+
for (var tileX = 0; tileX < tileWidth; tileX++) {
91+
for (var tileY = 0; tileY < tileHeight; tileY++) {
92+
var lat = (tileHeight - 1 - tileY) * tileLatStep + tileLatMin
93+
var lon = tileX * tileLonStep + tileLonMin
94+
95+
// we first check whether the tile pixel is outside the bounding box
96+
// in that case we skip it as we do not want to extrapolate
97+
if (lat < latMin || lat > latMax) {
98+
continue
99+
}
100+
101+
lon = wrapNum(lon, lonRange, true)
102+
if (lon < lonMin || lon > lonMax) {
103+
continue
104+
}
105+
106+
// read the value of the corresponding grid cell
107+
var iLat = CovUtils.indexOfNearest(lats, lat)
108+
var iLon = CovUtils.indexOfNearest(lons, lon)
109+
var val = this.range.get({y: iLat, x: iLon})
110+
111+
// find the right color in the palette
112+
var colorIdx = scale(val, this._palette, this.paletteExtent)
113+
var color = this._palette[colorIdx]
114+
if (!color) {
115+
// out of scale
116+
continue
117+
}
118+
119+
// and draw it
120+
rgba.set(tileY, tileX, 0, color[0])
121+
rgba.set(tileY, tileX, 1, color[1])
122+
rgba.set(tileY, tileX, 2, color[2])
123+
rgba.set(tileY, tileX, 3, 255)
124+
}
125+
}
126+
127+
ctx.putImageData(imgData, 0, 0)
128+
}
129+
130+
// from https://github.com/Leaflet/Leaflet/blob/master/src/core/Util.js
131+
function wrapNum (x, range, includeMax) {
132+
var max = range[1]
133+
var min = range[0]
134+
var d = max - min
135+
return x === max && includeMax ? x : ((x - min) % d + d) % d + min
136+
}
137+
138+
function hexToRgb (colors) {
139+
return colors.map(function(color) {
140+
var c = parseInt(color, 16)
141+
return [c >> 16, (c >> 8) & 255, c & 255]
142+
})
143+
}
144+
145+
function scale (val, palette, extent) {
146+
// scale val to [0,paletteSize-1] using the palette extent
147+
// (IDL bytscl formula: http://www.exelisvis.com/docs/BYTSCL.html)
148+
var scaled = Math.trunc((palette.length - 1 + 0.9999) * (val - extent[0]) / (extent[1] - extent[0]))
149+
return scaled
150+
}
151+
152+
var CovJSONVectorLayer = function (cov, options) {
153+
// TODO maybe convert coverage to GeoJSON and use GeoJSONParser, return RenderableLayer
154+
}
155+
156+
var COVJSON_NS = 'http://covjson.org/def/domainTypes#'
157+
var CovJSONVectorDomainTypes = [
158+
'VerticalProfile','PointSeries','Point','MultiPointSeries','MultiPoint',
159+
'PolygonSeries','Polygon','MultiPolygonSeries','MultiPolygon','Trajectory',
160+
'Section'
161+
].map(function (name) { return COVJSON_NS + name })
162+
163+
var CovJSONLayer = function (cov, options) {
164+
if (cov.domainType === COVJSON_NS + 'Grid') {
165+
return new CovJSONGridLayer(cov, options)
166+
} else if (CovJSONVectorDomainTypes.indexOf(cov.domainType) !== -1) {
167+
return CovJSONVectorLayer(cov, options)
168+
} else {
169+
throw new Error('Unsupported CovJSON domain type: ' + cov.domainType)
170+
}
171+
}

TiledCanvasLayer.js

+46
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
var TiledCanvasLayer = function (sector, tileWidth, tileHeight, displayName) {
2+
WorldWind.TiledImageLayer.call(this, sector, new WorldWind.Location(90, 180), 19, "image/x-canvas", displayName, tileWidth, tileHeight);
3+
}
4+
5+
TiledCanvasLayer.prototype = Object.create(WorldWind.TiledImageLayer.prototype);
6+
7+
/**
8+
* overrides TiledImageLayer.prototype.retrieveTileImage
9+
*/
10+
TiledCanvasLayer.prototype.retrieveTileImage = function (dc, tile, suppressRedraw) {
11+
if (this.currentRetrievals.indexOf(tile.imagePath) < 0) {
12+
if (this.absentResourceList.isResourceAbsent(tile.imagePath)) {
13+
return;
14+
}
15+
16+
var imagePath = tile.imagePath,
17+
cache = dc.gpuResourceCache,
18+
canvas = dc.currentGlContext.canvas,
19+
layer = this;
20+
21+
var canvas = document.createElement('canvas');
22+
canvas.width = tile.tileWidth;
23+
canvas.height = tile.tileHeight;
24+
25+
this.drawCanvasTile(canvas, tile);
26+
27+
var texture = layer.createTexture(dc, tile, canvas);
28+
layer.removeFromCurrentRetrievals(imagePath);
29+
30+
if (texture) {
31+
cache.putResource(imagePath, texture, texture.size);
32+
33+
layer.currentTilesInvalid = true;
34+
layer.absentResourceList.unmarkResourceAbsent(imagePath);
35+
36+
if (!suppressRedraw) {
37+
// Send an event to request a redraw.
38+
var e = document.createEvent('Event');
39+
e.initEvent(WorldWind.REDRAW_EVENT_TYPE, true, true);
40+
canvas.dispatchEvent(e);
41+
}
42+
}
43+
44+
this.currentRetrievals.push(imagePath);
45+
}
46+
}

0 commit comments

Comments
 (0)