@gisatcz/deckgl-geolib 1.11.0-dev.0 → 1.11.0-dev.10

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.
@@ -1,42 +1,87 @@
1
- import { CompositeLayer } from '@deck.gl/core';
2
- import { TileLayer } from '@deck.gl/geo-layers';
1
+ import { CompositeLayer, CompositeLayerProps, DefaultProps, TextureSource, UpdateParameters } from '@deck.gl/core';
2
+ import { _Tile2DHeader as Tile2DHeader, _TileLoadProps as TileLoadProps, GeoBoundingBox, NonGeoBoundingBox, TileLayer, TileLayerProps } from '@deck.gl/geo-layers';
3
3
  import { BitmapLayer } from '@deck.gl/layers';
4
- import { _TerrainExtension as TerrainExtension } from '@deck.gl/extensions';
5
- import CogTiles from '../cogtiles/cogtiles.ts';
4
+ import type { MeshAttributes } from '@loaders.gl/schema';
6
5
  import { GeoImageOptions } from '../geoimage/geoimage.ts';
7
- declare class CogBitmapLayer extends CompositeLayer<any> {
6
+ export type TileBoundingBox = NonGeoBoundingBox | GeoBoundingBox;
7
+ export type ZRange = [minZ: number, maxZ: number];
8
+ export type Bounds = [minX: number, minY: number, maxX: number, maxY: number];
9
+ export type URLTemplate = string | string[] | null;
10
+ export declare const urlType: {
11
+ type: "object";
12
+ value: URLTemplate;
13
+ validate: (value: any, propType: any) => boolean;
14
+ equal: (value1: any, value2: any) => boolean;
15
+ };
16
+ export type ClampToTerrainOptions = {
17
+ terrainDrawMode?: string;
18
+ };
19
+ type MeshAndTexture = [MeshAttributes | null, TextureSource | null];
20
+ /** Props added by the CogBitmapLayer */
21
+ type _CogBitmapLayerProps = {
22
+ /** Image url that encodes raster data. * */
23
+ rasterData: URLTemplate;
24
+ /** Bounding box of the bitmap image, [minX, minY, maxX, maxY] in world coordinates. * */
25
+ bounds: Bounds | null;
26
+ /** Weather visualise the entire image with specified opacity (0-1) * */
27
+ opacity?: number;
28
+ /** Whether the rendered texture should be clamped to terrain * */
29
+ clampToTerrain?: ClampToTerrainOptions | boolean;
30
+ /**
31
+ * TODO
32
+ */
33
+ cogBitmapOptions: GeoImageOptions;
34
+ isTiled: boolean;
35
+ /**
36
+ * @deprecated Use `loadOptions.terrain.workerUrl` instead
37
+ */
38
+ workerUrl?: string;
39
+ };
40
+ /** All properties supported by CogBitmapLayer */
41
+ export type CogBitmapLayerProps = _CogBitmapLayerProps & TileLayerProps<MeshAndTexture> & CompositeLayerProps;
42
+ /** Render bitmap texture from cog raster images. */
43
+ export default class CogBitmapLayer<ExtraPropsT extends {} = {}> extends CompositeLayer<ExtraPropsT & Required<_CogBitmapLayerProps & Required<TileLayerProps<MeshAndTexture>>>> {
44
+ static defaultProps: DefaultProps<CogBitmapLayerProps>;
8
45
  static layerName: string;
9
- id: string;
10
- url: string;
11
- static displayName: string;
12
- cogTiles: CogTiles;
13
- tileSize: number;
14
46
  minZoom: number;
15
47
  maxZoom: number;
16
- blurredTexture: boolean;
17
- constructor(id: string, url: string, options: GeoImageOptions);
18
- initializeState(): void;
19
- init(url: string): Promise<void>;
20
- renderLayers(): TileLayer<any, {
21
- id: `${string}-${string}`;
22
- getTileData: (tileData: any) => Promise<string>;
48
+ state: {
49
+ initialized: boolean;
50
+ isTiled?: boolean;
51
+ terrain?: MeshAttributes;
52
+ zRange?: ZRange | null;
53
+ bitmapCogTiles: any;
23
54
  minZoom: number;
24
55
  maxZoom: number;
25
- tileSize: number;
26
- maxRequests: 6;
27
- extent: [number, number, number, number];
28
- renderSubLayers: (props: any) => BitmapLayer<{
29
- terrainDrawMode: any;
30
- data: null;
31
- image: any;
32
- bounds: [any, any, any, any];
33
- opacity: number;
34
- textureParameters: {
35
- minFilter: "linear" | "nearest";
36
- magFilter: "linear" | "nearest";
56
+ };
57
+ initializeState(context: any): Promise<void>;
58
+ init(): Promise<void>;
59
+ updateState({ props, oldProps }: UpdateParameters<this>): void;
60
+ getTiledBitmapData(tile: TileLoadProps): Promise<TextureSource>;
61
+ renderSubLayers(props: TileLayerProps<TextureSource> & {
62
+ id: string;
63
+ data: TextureSource;
64
+ tile: Tile2DHeader<TextureSource>;
65
+ }): BitmapLayer<{}>;
66
+ renderLayers(): TileLayer<any, {
67
+ getTileData: any;
68
+ renderSubLayers: any;
69
+ updateTriggers: {
70
+ getTileData: {
71
+ clampToTerrain: boolean | ClampToTerrainOptions;
37
72
  };
38
- extensions: TerrainExtension[];
39
- }>;
73
+ };
74
+ extent: any;
75
+ tileSize: any;
76
+ minZoom: number;
77
+ maxZoom: number;
78
+ maxRequests: number;
79
+ onTileLoad: (tile: Tile2DHeader<MeshAndTexture>) => void;
80
+ onTileUnload: (tile: Tile2DHeader<MeshAndTexture>) => void;
81
+ onTileError: (err: any, tile?: any) => void;
82
+ maxCacheSize: number;
83
+ maxCacheByteSize: number;
84
+ refinementStrategy: import("node_modules/@deck.gl/geo-layers/dist/tileset-2d/tileset-2d.js").RefinementStrategy;
40
85
  }>;
41
86
  }
42
- export default CogBitmapLayer;
87
+ export {};
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@gisatcz/deckgl-geolib",
3
- "version": "1.11.0-dev.0",
3
+ "version": "1.11.0-dev.10",
4
4
  "private": false,
5
5
  "main": "dist/cjs/index.js",
6
6
  "module": "dist/esm/index.js",
@@ -30,18 +30,17 @@
30
30
  "dependencies": {
31
31
  "@chunkd/source-http": "^11.1.0",
32
32
  "@cogeotiff/core": "^9.0.3",
33
- "@deck.gl/core": "^9.0.6",
34
- "@deck.gl/extensions": "^9.0.6",
35
- "@deck.gl/geo-layers": "^9.0.6",
36
- "@deck.gl/layers": "^9.0.6",
37
- "@deck.gl/mesh-layers": "^9.0.6",
38
- "@deck.gl/react": "^9.0.6",
39
- "@fortawesome/fontawesome-svg-core": "^6.4.0",
40
- "@loaders.gl/loader-utils": "^4.2.0",
41
- "@loaders.gl/schema": "^4.2.0",
42
- "@luma.gl/constants": "^9.0.9",
33
+ "@deck.gl/core": "^9.0.33",
34
+ "@deck.gl/extensions": "^9.0.33",
35
+ "@deck.gl/geo-layers": "^9.0.33",
36
+ "@deck.gl/layers": "^9.0.33",
37
+ "@deck.gl/mesh-layers": "^9.0.33",
38
+ "@deck.gl/react": "^9.0.33",
39
+ "@loaders.gl/loader-utils": "^4.3.1",
40
+ "@loaders.gl/schema": "^4.3.1",
41
+ "@luma.gl/constants": "^9.0.27",
43
42
  "@mapbox/martini": "^0.2.0",
44
- "@math.gl/web-mercator": "^4.0.1",
43
+ "@math.gl/web-mercator": "^4.1.0",
45
44
  "chroma-js": "^2.4.2",
46
45
  "geotiff": "^2.1.3",
47
46
  "jpeg-js": "^0.4.4",
@@ -1,113 +1,330 @@
1
- import { CompositeLayer } from '@deck.gl/core';
2
- import { TileLayer } from '@deck.gl/geo-layers';
1
+ import {
2
+ CompositeLayer, CompositeLayerProps, DefaultProps, log, TextureSource, UpdateParameters,
3
+ } from '@deck.gl/core';
4
+ import {
5
+ _Tile2DHeader as Tile2DHeader,
6
+ _TileLoadProps as TileLoadProps,
7
+ GeoBoundingBox,
8
+ NonGeoBoundingBox,
9
+ TileLayer,
10
+ TileLayerProps,
11
+ } from '@deck.gl/geo-layers';
3
12
  import { BitmapLayer } from '@deck.gl/layers';
4
13
  import { _TerrainExtension as TerrainExtension } from '@deck.gl/extensions';
5
- import { GL } from '@luma.gl/constants';
14
+ // import { GL } from '@luma.gl/constants';
6
15
  // import GL from '@luma.gl/constants';
7
16
  // GL.GL.CLIP_DISTANCE0_WEBGL
17
+ import type { MeshAttributes } from '@loaders.gl/schema';
8
18
  import CogTiles from '../cogtiles/cogtiles.ts';
9
19
 
10
20
  import { GeoImageOptions } from '../geoimage/geoimage.ts';
21
+ // import { TileBoundingBox, ZRange } from '../cogterrainlayer/CogTerrainLayer.js';
22
+ export type TileBoundingBox = NonGeoBoundingBox | GeoBoundingBox;
23
+
24
+ export type ZRange = [minZ: number, maxZ: number];
11
25
 
12
26
  // let needsRerender: boolean = false;
13
27
  // let extent = [0, 0, 0, 0]
28
+ export type Bounds = [minX: number, minY: number, maxX: number, maxY: number];
14
29
 
15
- class CogBitmapLayer extends CompositeLayer<any> {
16
- static layerName = 'CogBitmapLayer';
30
+ export type URLTemplate = string | string[] | null;
17
31
 
18
- // private _isLoaded: boolean;
32
+ export const urlType = {
33
+ type: 'object' as const,
34
+ value: null as URLTemplate,
35
+ validate: (value, propType) => (propType.optional && value === null)
36
+ || typeof value === 'string'
37
+ || (Array.isArray(value) && value.every((url) => typeof url === 'string')),
38
+ equal: (value1, value2) => {
39
+ if (value1 === value2) {
40
+ return true;
41
+ }
42
+ if (!Array.isArray(value1) || !Array.isArray(value2)) {
43
+ return false;
44
+ }
45
+ const len = value1.length;
46
+ if (len !== value2.length) {
47
+ return false;
48
+ }
49
+ for (let i = 0; i < len; i++) {
50
+ if (value1[i] !== value2[i]) {
51
+ return false;
52
+ }
53
+ }
54
+ return true;
55
+ },
56
+ };
57
+
58
+ export type ClampToTerrainOptions = {
59
+ terrainDrawMode?: string
60
+ }
61
+
62
+ const defaultProps: DefaultProps<CogBitmapLayerProps> = {
63
+ ...TileLayer.defaultProps,
64
+ // Image url that encodes height data
65
+ // elevationData: urlType,
66
+ // Image url to use as texture
67
+ // texture: { ...urlType, optional: true },
68
+ // Martini error tolerance in meters, smaller number -> more detailed mesh
69
+ // meshMaxError: { type: 'number', value: 4.0 },
70
+ // Bounding box of the terrain image, [minX, minY, maxX, maxY] in world coordinates
71
+ bounds: {
72
+ type: 'array', value: null, optional: true, compare: true,
73
+ },
74
+ rasterData: urlType,
75
+ // Color to use if texture is unavailable
76
+ // color: { type: 'color', value: [255, 255, 255] },
77
+ blurredTexture: true,
78
+ opacity: 1,
79
+ clampToTerrain: false,
80
+ // Object to decode height data, from (r, g, b) to height in meters
81
+ // elevationDecoder: {
82
+ // type: 'object',
83
+ // value: {
84
+ // rScaler: 1,
85
+ // gScaler: 0,
86
+ // bScaler: 0,
87
+ // offset: 0,
88
+ // },
89
+ // },
90
+ // Supply url to local terrain worker bundle. Only required if running offline and cannot access CDN.
91
+ workerUrl: '',
92
+ // Same as SimpleMeshLayer wireframe
93
+ // wireframe: false,
94
+ // material: true,
95
+
96
+ // loaders: [TerrainLoader],
97
+ };
98
+
99
+ // Turns array of templates into a single string to work around shallow change
100
+ function urlTemplateToUpdateTrigger(template: URLTemplate): string {
101
+ if (Array.isArray(template)) {
102
+ return template.join(';');
103
+ }
104
+ return template || '';
105
+ }
19
106
 
20
- id = '';
107
+ type MeshAndTexture = [MeshAttributes | null, TextureSource | null];
21
108
 
22
- url: string;
109
+ /** Props added by the CogBitmapLayer */
110
+ type _CogBitmapLayerProps = {
111
+ /** Image url that encodes raster data. * */
112
+ rasterData: URLTemplate;
23
113
 
24
- static displayName: string;
114
+ /** Bounding box of the bitmap image, [minX, minY, maxX, maxY] in world coordinates. * */
115
+ bounds: Bounds | null;
25
116
 
26
- cogTiles: CogTiles;
117
+ /** Weather visualise the entire image with specified opacity (0-1) * */
118
+ opacity?: number;
27
119
 
28
- tileSize: number;
120
+ /** Whether the rendered texture should be clamped to terrain * */
121
+ clampToTerrain?: ClampToTerrainOptions | boolean, // terrainDrawMode: 'drape',
122
+
123
+ /**
124
+ * TODO
125
+ */
126
+ cogBitmapOptions: GeoImageOptions;
127
+
128
+ isTiled: boolean;
129
+
130
+ /**
131
+ * @deprecated Use `loadOptions.terrain.workerUrl` instead
132
+ */
133
+ workerUrl?: string;
134
+ };
135
+
136
+ /** All properties supported by CogBitmapLayer */
137
+ export type CogBitmapLayerProps = _CogBitmapLayerProps &
138
+ TileLayerProps<MeshAndTexture> &
139
+ CompositeLayerProps;
140
+
141
+ /** Render bitmap texture from cog raster images. */
142
+ export default class CogBitmapLayer<ExtraPropsT extends {} = {}> extends CompositeLayer<
143
+ ExtraPropsT & Required<_CogBitmapLayerProps & Required<TileLayerProps<MeshAndTexture>>>
144
+ > {
145
+ static defaultProps = defaultProps;
146
+
147
+ static layerName = 'CogBitmapLayer';
29
148
 
30
149
  minZoom: number;
31
150
 
32
151
  maxZoom: number;
33
152
 
34
- blurredTexture: boolean;
35
-
36
- constructor(id:string, url:string, options:GeoImageOptions) {
37
- super({});
38
- this.id = id;
39
- // this.state = {
40
- // initialized: false,
41
- // };
42
- // this._isLoaded = false;
43
- this.cogTiles = new CogTiles(options);
44
- this.blurredTexture = options.blurredTexture;
45
- this.url = url;
46
- // setTimeout(() => {
47
- // this.init(url);
48
- // }, 500);
49
- }
153
+ state!: {
154
+ initialized: boolean;
155
+ isTiled?: boolean;
156
+ terrain?: MeshAttributes;
157
+ zRange?: ZRange | null;
158
+ bitmapCogTiles: any;
159
+ minZoom: number;
160
+ maxZoom: number;
161
+ };
162
+
163
+ // private _isLoaded: boolean;
164
+
165
+ // id = '';
166
+
167
+ // url: string;
168
+
169
+ // static displayName: string;
50
170
 
51
- initializeState() {
52
- this.state = {
171
+ // cogTiles: CogTiles;
172
+ //
173
+ // tileSize: number;
174
+ //
175
+
176
+ async initializeState(context: any) {
177
+ super.initializeState(context);
178
+
179
+ this.setState({
180
+ bitmapCogTiles: new CogTiles(this.props.cogBitmapOptions),
53
181
  initialized: false,
54
- };
182
+ });
183
+
184
+ await this.init();
185
+ }
186
+
187
+ async init() {
188
+ const cog = await this.state.bitmapCogTiles.initializeCog(this.props.rasterData);
189
+
190
+ const zoomRange = this.state.bitmapCogTiles.getZoomRange(cog);
191
+
192
+ const [minZoom, maxZoom] = zoomRange;
193
+
194
+ this.setState({ initialized: true, minZoom, maxZoom });
195
+ }
196
+
197
+ updateState({ props, oldProps }: UpdateParameters<this>): void {
198
+ const rasterDataChanged = props.rasterData !== oldProps.rasterData;
199
+ if (rasterDataChanged) {
200
+ const { rasterData } = props;
201
+ const isTiled = rasterData
202
+ && ((Array.isArray(rasterData)
203
+ || (rasterData.includes('{x}') && rasterData.includes('{y}'))) || this.props.isTiled);
204
+ this.setState({ isTiled });
205
+ }
206
+
207
+ // Reloading for single terrain mesh
208
+ const shouldReload = rasterDataChanged
209
+ // || props.meshMaxError !== oldProps.meshMaxError
210
+ // || props.elevationDecoder !== oldProps.elevationDecoder
211
+ || props.bounds !== oldProps.bounds;
212
+
213
+ if (!this.state.isTiled && shouldReload) {
214
+ // When state.isTiled, elevationData cannot be an array
215
+ // const terrain = this.loadTerrain(props as TerrainLoadProps);
216
+ // this.setState({ terrain });
217
+ }
55
218
 
56
- this.init(this.url);
219
+ // TODO - remove in v9
220
+ // @ts-ignore
221
+ if (props.workerUrl) {
222
+ log.removed('workerUrl', 'loadOptions.terrain.workerUrl')();
223
+ }
57
224
  }
58
225
 
59
- async init(url:string) {
60
- const cog = await this.cogTiles.initializeCog(url);
61
- this.setState({ initialized: true });
62
- this.tileSize = this.cogTiles.getTileSize(cog);
63
- const zoomRange = this.cogTiles.getZoomRange(cog);
64
- [this.minZoom, this.maxZoom] = zoomRange;
226
+ async getTiledBitmapData(tile: TileLoadProps): Promise<TextureSource> {
227
+ // TODO - pass signal to getTile
228
+ // abort request if signal is aborted
229
+ const tileData = await this.state.bitmapCogTiles.getTile(
230
+ tile.index.x,
231
+ tile.index.y,
232
+ tile.index.z,
233
+ // bounds,
234
+ // this.props.meshMaxError,
235
+ );
236
+ return tileData;
237
+ }
238
+
239
+ renderSubLayers(
240
+ props: TileLayerProps<TextureSource> & {
241
+ id: string;
242
+ data: TextureSource;
243
+ tile: Tile2DHeader<TextureSource>;
244
+ },
245
+ ) {
246
+ const SubLayerClass = this.getSubLayerClass('image', BitmapLayer);
247
+ const { blurredTexture } = this.state.bitmapCogTiles.options;
248
+
249
+ const { opacity, clampToTerrain } = this.props;
250
+
251
+ const { data } = props;
252
+
253
+ if (!data) {
254
+ return null;
255
+ }
256
+
257
+ const {
258
+ bbox: {
259
+ west, south, east, north,
260
+ },
261
+ } = props.tile;
262
+
263
+ return new SubLayerClass({ ...props, tileSize: this.state.bitmapCogTiles.tileSize }, {
264
+ data: null,
265
+ image: data,
266
+ _instanced: false,
267
+ bounds: [west, south, east, north],
268
+ opacity,
269
+ textureParameters: {
270
+ minFilter: blurredTexture ? 'linear' : 'nearest',
271
+ magFilter: blurredTexture ? 'linear' : 'nearest',
272
+ },
273
+ // TODO check if works!!!
274
+ extensions: clampToTerrain ? [new TerrainExtension()] : [],
275
+ ...(clampToTerrain?.terrainDrawMode
276
+ ? { terrainDrawMode: clampToTerrain.terrainDrawMode }
277
+ : {}),
278
+ });
65
279
  }
66
280
 
67
281
  renderLayers() {
68
- if (this.cogTiles.cog) {
69
- const layer = new TileLayer({
70
- id: `${this.id}-${String(performance.now())}`,
71
- getTileData: (tileData: any) => this.cogTiles.getTile(
72
- tileData.index.x,
73
- tileData.index.y,
74
- tileData.index.z,
75
- ),
76
- minZoom: this.minZoom,
77
- maxZoom: this.maxZoom,
78
- tileSize: this.tileSize,
79
- maxRequests: 6,
80
- extent: this.cogTiles.cog ? this.cogTiles.getBoundsAsLatLon(this.cogTiles.cog) : null,
81
-
82
- renderSubLayers: (props: any) => {
83
- const {
84
- bbox: {
85
- west, south, east, north,
86
- },
87
- } = props.tile;
88
-
89
- return new BitmapLayer(props, {
90
- data: null,
91
- image: props.data,
92
- bounds: [west, south, east, north],
93
- opacity: 1, // 0.6
94
- textureParameters: {
95
- minFilter: this.blurredTexture ? 'linear' : 'nearest',
96
- magFilter: this.blurredTexture ? 'linear' : 'nearest',
97
- },
98
- extensions: this.cogTiles?.options?.clampToTerrain ? [new TerrainExtension()] : [],
99
- ...(this.cogTiles?.options?.clampToTerrain?.terrainDrawMode
100
- ? { terrainDrawMode: this.cogTiles?.options?.clampToTerrain.terrainDrawMode }
101
- : {}),
102
- });
282
+ const {
283
+ rasterData,
284
+ blurredTexture,
285
+ opacity,
286
+ clampToTerrain,
287
+ // tileSize,
288
+ maxRequests,
289
+ onTileLoad,
290
+ onTileUnload,
291
+ onTileError,
292
+ maxCacheSize,
293
+ maxCacheByteSize,
294
+ refinementStrategy,
295
+ cogBitmapOptions,
296
+ } = this.props;
297
+ if (this.state.isTiled && this.state.initialized) {
298
+ const { tileSize } = this.state.bitmapCogTiles;
299
+
300
+ return new TileLayer(this.getSubLayerProps({
301
+ id: 'tiles',
302
+ }), {
303
+ getTileData: this.getTiledBitmapData.bind(this),
304
+ renderSubLayers: this.renderSubLayers.bind(this),
305
+ updateTriggers: {
306
+ getTileData: {
307
+ // rasterData: urlTemplateToUpdateTrigger(rasterData),
308
+ // blurredTexture,
309
+ // opacity,
310
+ // cogBitmapOptions,
311
+ clampToTerrain,
312
+ },
103
313
  },
314
+ extent: this.state.bitmapCogTiles.cog
315
+ ? this.state.bitmapCogTiles.getBoundsAsLatLon(this.state.bitmapCogTiles.cog) : null,
316
+ tileSize,
317
+ minZoom: this.state.minZoom,
318
+ maxZoom: this.state.maxZoom,
319
+ maxRequests,
320
+ onTileLoad,
321
+ onTileUnload,
322
+ onTileError,
323
+ maxCacheSize,
324
+ maxCacheByteSize,
325
+ refinementStrategy,
104
326
  });
105
- return layer;
106
327
  }
107
328
  return null;
108
329
  }
109
330
  }
110
-
111
- CogBitmapLayer.displayName = 'CogBitmapLayer';
112
-
113
- export default CogBitmapLayer;
@@ -17,6 +17,10 @@ export type Bounds = [minX: number, minY: number, maxX: number, maxY: number];
17
17
  const EARTH_CIRCUMFERENCE = 40075000.0;
18
18
  const EARTH_HALF_CIRCUMFERENCE = 20037500.0;
19
19
 
20
+ const CogTilesGeoImageOptionsDefaults = {
21
+ blurredTexture: true,
22
+ };
23
+
20
24
  class CogTiles {
21
25
  cog: Tiff;
22
26
 
@@ -37,7 +41,7 @@ class CogTiles {
37
41
  options: GeoImageOptions;
38
42
 
39
43
  constructor(options: GeoImageOptions) {
40
- this.options = options;
44
+ this.options = { ...CogTilesGeoImageOptionsDefaults, ...options };
41
45
  }
42
46
 
43
47
  async initializeCog(url: string) {
@@ -435,7 +435,9 @@ export default class GeoImage {
435
435
 
436
436
  for (let i = 0; i < arrayLength; i += 4) {
437
437
  let pixelColor = options.nullColor;
438
- if (options.noDataValue === undefined || dataArray[pixel] !== options.noDataValue) {
438
+ // FIXME
439
+ // eslint-disable-next-line max-len
440
+ if ((!Number.isNaN(dataArray[pixel])) && (options.noDataValue === undefined || dataArray[pixel] !== options.noDataValue)) {
439
441
  if (
440
442
  (options.clipLow != null && dataArray[pixel] <= options.clipLow)
441
443
  || (options.clipHigh != null && dataArray[pixel] >= options.clipHigh)
@@ -468,9 +470,6 @@ export default class GeoImage {
468
470
  pixelColor[3] = this.scale(dataArray[pixel], options.colorScaleValueRange[0]!, options.colorScaleValueRange.slice(-1)[0]!, 0, 255);
469
471
  }
470
472
  }
471
- // If pixel has null value
472
- } else if (Number.isNaN(dataArray[pixel])) {
473
- pixelColor = [0, 0, 0, 0];
474
473
  }
475
474
  // FIXME
476
475
  // eslint-disable-next-line