1
- import type { LayerProps , PickingInfo } from "@deck.gl/core" ;
2
- import { project32 } from "@deck.gl/core" ;
3
1
import type { BitmapLayerPickingInfo , BitmapLayerProps } from "@deck.gl/layers" ;
4
2
import { BitmapLayer } from "@deck.gl/layers" ;
3
+ import type { colorTablesArray } from "@emerson-eps/color-tables/" ;
4
+ import { getRgbData } from "@emerson-eps/color-tables" ;
5
5
import type { Color , LayerProps , PickingInfo } from "@deck.gl/core" ;
6
6
import { project32 } from "@deck.gl/core" ;
7
7
import type {
@@ -18,6 +18,7 @@ import type { ContinuousLegendDataType } from "../../components/ColorLegend";
18
18
import type { ShaderModule } from "@luma.gl/shadertools" ;
19
19
import type { Model } from "@luma.gl/engine" ;
20
20
import type { Texture } from "@luma.gl/core" ;
21
+ import * as png from "@vivaxy/png" ;
21
22
22
23
function getImageData (
23
24
colorMapName : string ,
@@ -108,6 +109,10 @@ export interface ColormapLayerProps
108
109
*/
109
110
colorMapClampColor : Color | undefined | boolean ;
110
111
112
+ // If set will calculate contour lines and hillshading based on this map instead.
113
+ // Default undfined.
114
+ heightMapUrl : string ;
115
+
111
116
// Non public properties:
112
117
reportBoundingBox ?: React . Dispatch < ReportBoundingBoxAction > ;
113
118
}
@@ -133,9 +138,70 @@ const defaultProps = {
133
138
hillshading : false ,
134
139
contourReferencePoint : 0 ,
135
140
contourInterval : 50 , // 50 meter by default
141
+
142
+ propertiesUrl : "" ,
136
143
} ;
137
144
138
145
export default class ColormapLayer extends BitmapLayer < ColormapLayerProps > {
146
+ initializeState ( ) : void {
147
+ super . initializeState ( ) ;
148
+
149
+ const createPropertyTexture = async ( ) => {
150
+ const response = await fetch ( this . props . heightMapUrl ) ;
151
+ if ( ! response . ok ) {
152
+ console . error ( "Could not load " , this . props . heightMapUrl ) ;
153
+ } else {
154
+ const blob = await response . blob ( ) ;
155
+ const contentType = response . headers . get ( "content-type" ) ;
156
+ const isPng = contentType === "image/png" ;
157
+ if ( isPng ) {
158
+ const heightMapTexture = await new Promise ( ( resolve ) => {
159
+ const fileReader = new FileReader ( ) ;
160
+ fileReader . readAsArrayBuffer ( blob ) ;
161
+ fileReader . onload = ( ) => {
162
+ const arrayBuffer = fileReader . result ;
163
+ const imgData = png . decode (
164
+ arrayBuffer as ArrayBuffer
165
+ ) ;
166
+ const w = imgData . width ;
167
+ const h = imgData . height ;
168
+
169
+ console . log ( "png metadata" , w , h ) ;
170
+ const data = imgData . data ; // array of int's
171
+ const n = data . length ;
172
+ const buffer = new ArrayBuffer ( n ) ;
173
+ const view = new DataView ( buffer ) ;
174
+ for ( let i = 0 ; i < n ; i ++ ) {
175
+ view . setUint8 ( i , data [ i ] ) ;
176
+ }
177
+
178
+ const array = new Uint8Array ( buffer ) ;
179
+ const propertyTexture =
180
+ this . context . device . createTexture ( {
181
+ sampler : {
182
+ addressModeU : "clamp-to-edge" ,
183
+ addressModeV : "clamp-to-edge" ,
184
+ minFilter : "linear" ,
185
+ magFilter : "linear" ,
186
+ } ,
187
+ width : w ,
188
+ height : h ,
189
+ format : "rgba8unorm" ,
190
+ data : array as Uint8Array ,
191
+ } ) ;
192
+ resolve ( propertyTexture ) ;
193
+ } ;
194
+ } ) ;
195
+ this . setState ( {
196
+ ...this . state ,
197
+ heightMapTexture,
198
+ } ) ;
199
+ }
200
+ }
201
+ } ;
202
+ createPropertyTexture ( ) ;
203
+ }
204
+
139
205
setShaderModuleProps (
140
206
...props : Parameters < Model [ "shaderInputs" ] [ "setProps" ] >
141
207
) : void {
@@ -181,7 +247,7 @@ export default class ColormapLayer extends BitmapLayer<ColormapLayerProps> {
181
247
const colorMapRangeMin = this . props . colorMapRange ?. [ 0 ] ?? valueRangeMin ;
182
248
const colorMapRangeMax = this . props . colorMapRange ?. [ 1 ] ?? valueRangeMax ;
183
249
184
- const colormap = this . context . device . createTexture ( {
250
+ const colormapTexture = this . context . device . createTexture ( {
185
251
width : 256 ,
186
252
height : 1 ,
187
253
format : "rgb8unorm-webgl" ,
@@ -192,7 +258,29 @@ export default class ColormapLayer extends BitmapLayer<ColormapLayerProps> {
192
258
) ,
193
259
} ) ;
194
260
195
- this . state . model ?. setBindings ( { colormap } ) ;
261
+ // eslint-disable-next-line
262
+ // @ts -ignore
263
+ let heightMapTexture = this . state . heightMapTexture ;
264
+ const isHeightMapTextureDefined =
265
+ typeof heightMapTexture !== "undefined" ;
266
+
267
+ if ( ! isHeightMapTextureDefined ) {
268
+ // Create a dummy texture
269
+ heightMapTexture = this . context . device . createTexture ( {
270
+ sampler : {
271
+ addressModeU : "clamp-to-edge" ,
272
+ addressModeV : "clamp-to-edge" ,
273
+ minFilter : "linear" ,
274
+ magFilter : "linear" ,
275
+ } ,
276
+ width : 1 ,
277
+ height : 1 ,
278
+ format : "rgba8unorm" ,
279
+ data : new Uint8Array ( [ 1 , 1 , 1 , 1 ] ) ,
280
+ } ) ;
281
+ }
282
+
283
+ this . state . model ?. setBindings ( { colormapTexture, heightMapTexture } ) ;
196
284
197
285
const bitmapResolution = this . props . image
198
286
? [
@@ -236,6 +324,7 @@ export default class ColormapLayer extends BitmapLayer<ColormapLayerProps> {
236
324
isClampColor,
237
325
colorMapClampColor,
238
326
isColorMapClampColorTransparent,
327
+ isHeightMapTextureDefined,
239
328
rgbScaler : this . props . valueDecoder . rgbScaler ,
240
329
floatScaler : this . props . valueDecoder . floatScaler ,
241
330
offset : this . props . valueDecoder . offset ,
@@ -320,6 +409,7 @@ uniform mapUniforms {
320
409
bool isClampColor;
321
410
vec3 colorMapClampColor;
322
411
bool isColorMapClampColorTransparent;
412
+ bool isHeightMapTextureDefined;
323
413
vec3 rgbScaler; // r, g and b multipliers
324
414
float floatScaler; // value multiplier
325
415
float offset; // translation of the r, g, b sum
@@ -352,6 +442,7 @@ type Map2DUniformsType = {
352
442
isClampColor : boolean ;
353
443
colorMapClampColor : [ number , number , number ] ;
354
444
isColorMapClampColorTransparent : boolean ;
445
+ isHeightMapTextureDefined : boolean ;
355
446
rgbScaler : [ number , number , number ] ;
356
447
floatScaler : number ;
357
448
offset : number ;
@@ -376,6 +467,7 @@ const map2DUniforms = {
376
467
isClampColor : "u32" ,
377
468
colorMapClampColor : "vec3<f32>" ,
378
469
isColorMapClampColorTransparent : "u32" ,
470
+ isHeightMapTextureDefined : "u32" ,
379
471
rgbScaler : "vec3<f32>" ,
380
472
floatScaler : "f32" ,
381
473
offset : "f32" ,
0 commit comments