@@ -45,7 +45,7 @@ const fileReader: FileReader = {
45
45
backend : undefined
46
46
} ;
47
47
48
- const omFileDataCache = new QuickLRU < string , TypedArray > ( {
48
+ const omFileDataCache = new QuickLRU < string , { values : TypedArray ; direction ?: TypedArray } > ( {
49
49
maxSize : 1024 ,
50
50
maxAge : ONE_HOUR_IN_MILLISECONDS
51
51
} ) ;
@@ -54,26 +54,47 @@ const TILE_SIZE = Number(import.meta.env.VITE_TILE_SIZE);
54
54
55
55
export const getValueFromLatLong = ( lat : number , lon : number , omUrl : string ) => {
56
56
const data = omFileDataCache . get ( omUrl ) ;
57
+ if ( data ) {
58
+ const values = data . values ;
57
59
58
- let indexObject ;
59
- if ( domain . grid . projection ) {
60
- indexObject = projectionGrid . findPointInterpolated ( lat , lon ) ;
61
- } else {
62
- indexObject = getIndexFromLatLong ( lat , lon , domain ) ;
63
- }
60
+ let indexObject ;
61
+ if ( domain . grid . projection ) {
62
+ indexObject = projectionGrid . findPointInterpolated ( lat , lon ) ;
63
+ } else {
64
+ indexObject = getIndexFromLatLong ( lat , lon , domain ) ;
65
+ }
64
66
65
- const { index, xFraction, yFraction } = indexObject ?? {
66
- index : 0 ,
67
- xFraction : 0 ,
68
- yFraction : 0
69
- } ;
67
+ const { index, xFraction, yFraction } = indexObject ?? {
68
+ index : 0 ,
69
+ xFraction : 0 ,
70
+ yFraction : 0
71
+ } ;
70
72
71
- if ( data && index ) {
72
- //const px = interpolateLinear(data, index, xFraction, yFraction);
73
- const px = interpolate2DHermite ( data , domain . grid . nx , index , xFraction , yFraction ) ;
74
- return px ;
75
- } else {
76
- return NaN ;
73
+ if ( values && index ) {
74
+ //const px = interpolateLinear(data, index, xFraction, yFraction);
75
+ const px = interpolate2DHermite (
76
+ values ,
77
+ domain . grid . nx ,
78
+ index ,
79
+ xFraction ,
80
+ yFraction
81
+ ) ;
82
+ if ( variable . value === 'wind' ) {
83
+ const direction = data . direction as TypedArray ;
84
+ const dir = interpolate2DHermite (
85
+ direction ,
86
+ domain . grid . nx ,
87
+ index ,
88
+ xFraction ,
89
+ yFraction
90
+ ) ;
91
+ return [ px , dir ] ;
92
+ } else {
93
+ return px ;
94
+ }
95
+ } else {
96
+ return NaN ;
97
+ }
77
98
}
78
99
} ;
79
100
@@ -115,37 +136,80 @@ const renderTile = async (url: string) => {
115
136
return tile ;
116
137
} ;
117
138
139
+ const getBorderPoints = ( ) => {
140
+ const points = [ ] ;
141
+ console . log ( nx , ny , dx , dy , projectionGrid ) ;
142
+ for ( let i = 0 ; i < projectionGrid . ny ; i ++ ) {
143
+ points . push ( [
144
+ projectionGrid . origin [ 0 ] ,
145
+ projectionGrid . origin [ 1 ] + i * projectionGrid . dy
146
+ ] ) ;
147
+ }
148
+ for ( let i = 0 ; i < projectionGrid . nx ; i ++ ) {
149
+ points . push ( [
150
+ projectionGrid . origin [ 0 ] + i * projectionGrid . dx ,
151
+ projectionGrid . origin [ 1 ] + projectionGrid . ny * projectionGrid . dy
152
+ ] ) ;
153
+ }
154
+ for ( let i = projectionGrid . ny ; i >= 0 ; i -- ) {
155
+ points . push ( [
156
+ projectionGrid . origin [ 0 ] + projectionGrid . nx * projectionGrid . dx ,
157
+ projectionGrid . origin [ 1 ] + i * projectionGrid . dy
158
+ ] ) ;
159
+ }
160
+ for ( let i = projectionGrid . nx ; i >= 0 ; i -- ) {
161
+ points . push ( [
162
+ projectionGrid . origin [ 0 ] + i * projectionGrid . dx ,
163
+ projectionGrid . origin [ 1 ]
164
+ ] ) ;
165
+ }
166
+
167
+ return points ;
168
+ } ;
169
+
118
170
const getTilejson = async ( fullUrl : string ) : Promise < TileJSON > => {
119
171
let minLon ;
120
172
let minLat ;
121
173
let maxLon ;
122
174
let maxLat ;
123
175
176
+ let bounds ;
124
177
if ( domain . grid . projection ) {
125
- // loop over all border points to get max / min lat / lon
126
-
127
- console . log ( projection . reverse ( 0 , dy * ny ) ) ;
128
- console . log ( projection . reverse ( dx * nx , 0 ) ) ;
129
- console . log ( projection . reverse ( dx * nx , dy * ny ) ) ;
130
- if ( Array === lonMin . constructor ) {
131
- minLon = lonMin [ 0 ] ;
132
- minLat = latMin [ 0 ] ;
133
- maxLon = lonMin [ 1 ] ;
134
- maxLat = latMin [ 1 ] ;
178
+ if ( domain . grid . projection . bounds ) {
179
+ bounds = domain . grid . projection . bounds ;
135
180
} else {
181
+ // loop over all border points to get max / min lat / lon
182
+ const borderPoints = getBorderPoints ( ) ;
183
+ const origin = projectionGrid . origin ;
184
+ const originLatLon = projection . reverse ( origin ) ;
136
185
minLon = lonMin ;
137
186
minLat = latMin ;
138
- maxLon = minLon + projection . reverse ( dx * nx , dy * ny ) [ 1 ] ;
139
- maxLat = minLat + projection . reverse ( dx * nx , dy * ny ) [ 0 ] ;
187
+ maxLon = lonMin ;
188
+ maxLat = latMin ;
189
+ for ( let borderPoint of borderPoints ) {
190
+ const borderPointLatLon = projection . reverse ( borderPoint ) ;
191
+ if ( borderPointLatLon [ 0 ] < minLat ) {
192
+ minLat = borderPointLatLon [ 0 ] ;
193
+ }
194
+ if ( borderPointLatLon [ 0 ] > maxLat ) {
195
+ maxLat = borderPointLatLon [ 0 ] ;
196
+ }
197
+ if ( borderPointLatLon [ 1 ] < minLon ) {
198
+ minLon = borderPointLatLon [ 1 ] ;
199
+ }
200
+ if ( borderPointLatLon [ 1 ] > maxLon ) {
201
+ maxLon = borderPointLatLon [ 1 ] ;
202
+ }
203
+ }
204
+ bounds = [ minLon , minLat , maxLon , maxLat ] ;
140
205
}
141
206
} else {
142
207
minLon = lonMin ;
143
208
minLat = latMin ;
144
209
maxLon = minLon + dx * nx ;
145
210
maxLat = minLat + dy * ny ;
211
+ bounds = [ minLon , minLat , maxLon , maxLat ] ;
146
212
}
147
- const bounds = [ minLon , minLat , maxLon , maxLat ] ;
148
- console . log ( bounds ) ;
149
213
150
214
return {
151
215
tilejson : '2.2.0' ,
@@ -168,6 +232,12 @@ export const omProtocol = async (
168
232
if ( fileReader . reader ) {
169
233
fileReader . reader . dispose ( ) ;
170
234
}
235
+ if ( fileReader . readeru ) {
236
+ fileReader . readeru . dispose ( ) ;
237
+ }
238
+ if ( fileReader . readerv ) {
239
+ fileReader . readerv . dispose ( ) ;
240
+ }
171
241
delete fileReader . reader ;
172
242
delete fileReader . backend ;
173
243
@@ -179,12 +249,15 @@ export const omProtocol = async (
179
249
180
250
nx = domain . grid . nx ;
181
251
ny = domain . grid . ny ;
182
- lonMin = domain . grid . lonMin ;
183
252
latMin = domain . grid . latMin ;
253
+ lonMin = domain . grid . lonMin ;
184
254
dx = domain . grid . dx ;
185
255
dy = domain . grid . dy ;
186
256
187
257
if ( domain . grid . projection ) {
258
+ const latitude = domain . grid . projection . latitude ?? domain . grid . latMin ;
259
+ const longitude = domain . grid . projection . longitude ?? domain . grid . lonMin ;
260
+
188
261
projectionName = domain . grid . projection . name ;
189
262
projection = new DynamicProjection (
190
263
projectionName ,
@@ -194,29 +267,91 @@ export const omProtocol = async (
194
267
projection ,
195
268
nx ,
196
269
ny ,
197
- latMin ,
198
- lonMin ,
270
+ latitude ,
271
+ longitude ,
199
272
dx ,
200
273
dy
201
274
) ;
202
275
}
203
276
204
- fileReader . backend = new MemoryHttpBackend ( {
205
- url : omUrl ,
206
- maxFileSize : 500 * 1024 * 1024 // 500 MB
207
- } ) ;
208
- fileReader . reader = await OmFileReader . create ( fileReader . backend ) . catch ( ( ) => {
209
- throw new Error ( `OMFile error: 404 file not found` ) ;
210
- } ) ;
211
- if ( fileReader . reader ) {
212
- const dimensions = fileReader . reader . getDimensions ( ) ;
213
-
214
- // Create ranges for each dimension
215
- const ranges = dimensions . map ( ( dim , _ ) => {
216
- return { start : 0 , end : dim } ;
277
+ if ( variable . value === 'wind' ) {
278
+ fileReader . backendu = new MemoryHttpBackend ( {
279
+ url : omUrl . replace ( 'wind.om' , 'wind_u_component_10m.om' ) ,
280
+ maxFileSize : 500 * 1024 * 1024 // 500 MB
281
+ } ) ;
282
+ fileReader . backendv = new MemoryHttpBackend ( {
283
+ url : omUrl . replace ( 'wind.om' , 'wind_v_component_10m.om' ) ,
284
+ maxFileSize : 500 * 1024 * 1024 // 500 MB
217
285
} ) ;
218
- const data = await fileReader . reader . read ( OmDataType . FloatArray , ranges ) ;
219
- omFileDataCache . set ( omUrl , data ) ;
286
+ fileReader . readeru = await OmFileReader . create ( fileReader . backendu ) . catch (
287
+ ( ) => {
288
+ throw new Error ( `OMFile error: 404 file not found` ) ;
289
+ }
290
+ ) ;
291
+ fileReader . readerv = await OmFileReader . create ( fileReader . backendv ) . catch (
292
+ ( ) => {
293
+ throw new Error ( `OMFile error: 404 file not found` ) ;
294
+ }
295
+ ) ;
296
+ if ( fileReader . readeru && fileReader . readerv ) {
297
+ const dimensions = fileReader . readeru . getDimensions ( ) ;
298
+
299
+ // Create ranges for each dimension
300
+ const ranges = dimensions . map ( ( dim , _ ) => {
301
+ return { start : 0 , end : dim } ;
302
+ } ) ;
303
+ const datau = await fileReader . readeru . read (
304
+ OmDataType . FloatArray ,
305
+ ranges
306
+ ) ;
307
+ const datav = await fileReader . readerv . read (
308
+ OmDataType . FloatArray ,
309
+ ranges
310
+ ) ;
311
+
312
+ const data : Float32Array < ArrayBuffer > = [ ] ;
313
+ const dataDirection : Float32Array < ArrayBuffer > = [ ] ;
314
+
315
+ for ( let [ i , dp ] of datau . entries ( ) ) {
316
+ data . push (
317
+ Math . sqrt ( Math . pow ( dp , 2 ) + Math . pow ( datav [ i ] , 2 ) ) *
318
+ 1.94384
319
+ ) ;
320
+
321
+ dataDirection . push (
322
+ ( Math . atan2 ( dp , datav [ i ] ) * ( 180 / Math . PI ) + 360 ) %
323
+ 360
324
+ ) ;
325
+ }
326
+
327
+ omFileDataCache . set ( omUrl , {
328
+ values : data ,
329
+ direction : dataDirection
330
+ } ) ;
331
+ }
332
+ } else {
333
+ fileReader . backend = new MemoryHttpBackend ( {
334
+ url : omUrl ,
335
+ maxFileSize : 500 * 1024 * 1024 // 500 MB
336
+ } ) ;
337
+ fileReader . reader = await OmFileReader . create ( fileReader . backend ) . catch (
338
+ ( ) => {
339
+ throw new Error ( `OMFile error: 404 file not found` ) ;
340
+ }
341
+ ) ;
342
+ if ( fileReader . reader ) {
343
+ const dimensions = fileReader . reader . getDimensions ( ) ;
344
+
345
+ // Create ranges for each dimension
346
+ const ranges = dimensions . map ( ( dim , _ ) => {
347
+ return { start : 0 , end : dim } ;
348
+ } ) ;
349
+ const data = await fileReader . reader . read (
350
+ OmDataType . FloatArray ,
351
+ ranges
352
+ ) ;
353
+ omFileDataCache . set ( omUrl , { values : data } ) ;
354
+ }
220
355
}
221
356
222
357
return {
0 commit comments