@dataforsyningen/saul 3.4.0 → 3.5.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/assets/dk-terrain.tiff +0 -0
- package/assets/tiny-dk-terrain.tiff +0 -0
- package/index.js +3 -1
- package/modules/api.js +32 -5
- package/modules/saul-core.js +2 -2
- package/modules/saul-elevation.js +87 -33
- package/package.json +2 -2
- package/test/geotiff-experiments.js +250 -0
- package/test/saul-combined.test.js +5 -0
- package/test/saul-core.test.js +5 -1
- package/test/saul-elevation.test.js +5 -1
- package/test/saul-projection.test.js +4 -0
|
Binary file
|
|
Binary file
|
package/index.js
CHANGED
|
@@ -14,6 +14,7 @@ export {
|
|
|
14
14
|
getSTAC,
|
|
15
15
|
getDHM,
|
|
16
16
|
getTerrainGeoTIFF,
|
|
17
|
+
getDenmarkGeoTiff,
|
|
17
18
|
get,
|
|
18
19
|
post
|
|
19
20
|
} from './modules/api.js'
|
|
@@ -24,5 +25,6 @@ export {
|
|
|
24
25
|
} from './modules/saul-projection.js'
|
|
25
26
|
|
|
26
27
|
export {
|
|
27
|
-
getElevation
|
|
28
|
+
getElevation,
|
|
29
|
+
visualizeGeotiff
|
|
28
30
|
} from './modules/saul-elevation.js'
|
package/modules/api.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* SAUL API utilities
|
|
2
|
+
* SAUL API utilities
|
|
3
3
|
*/
|
|
4
4
|
|
|
5
5
|
import { fromArrayBuffer } from 'geotiff'
|
|
@@ -202,6 +202,11 @@ async function consumeGeoTIFF(raw_data) {
|
|
|
202
202
|
return image
|
|
203
203
|
}
|
|
204
204
|
|
|
205
|
+
function calcSizeRatio(sizeX, bbox) {
|
|
206
|
+
const ratio = ( bbox[0] - bbox[2] ) / ( bbox[1] - bbox[3] )
|
|
207
|
+
return Math.round(sizeX * ratio)
|
|
208
|
+
}
|
|
209
|
+
|
|
205
210
|
|
|
206
211
|
/** Fetches a GeoTIFF with elevation data matching the bounding box of a STAC API item (image)
|
|
207
212
|
* @param {object} stac_item - STAC API item from a featureCollection request
|
|
@@ -209,11 +214,12 @@ async function consumeGeoTIFF(raw_data) {
|
|
|
209
214
|
* @param {number} [resolution] - Resolution (1 - 0.01). Higher number means more pixels and better precision.
|
|
210
215
|
* @returns {object} GeoTiff data
|
|
211
216
|
*/
|
|
212
|
-
function getTerrainGeoTIFF(stac_item, auth, resolution = 0.05) {
|
|
217
|
+
function getTerrainGeoTIFF(stac_item, auth, resolution = 0.05, sizeX = 300) {
|
|
213
218
|
|
|
214
219
|
const bbox = stac_item.bbox
|
|
215
|
-
const
|
|
216
|
-
const
|
|
220
|
+
const sizeY = calcSizeRatio(sizeX, stac_item.bbox)
|
|
221
|
+
const width = stac_item.properties ? Math.round( stac_item.properties['proj:shape'][0] * resolution ) : sizeX
|
|
222
|
+
const height = stac_item.properties ? Math.round( stac_item.properties['proj:shape'][1] * resolution ) : sizeY
|
|
217
223
|
|
|
218
224
|
// GET request for DHM WCS data
|
|
219
225
|
let url = auth.API_DHM_WCS_BASEURL
|
|
@@ -232,6 +238,25 @@ function getTerrainGeoTIFF(stac_item, auth, resolution = 0.05) {
|
|
|
232
238
|
})
|
|
233
239
|
}
|
|
234
240
|
|
|
241
|
+
/**
|
|
242
|
+
* Fetches a geoTIFF with elevation data covering all of Denmark
|
|
243
|
+
* @param {Object} options
|
|
244
|
+
* @param {Object} options.src - URL to download a pre-generated GeoTiff.
|
|
245
|
+
* @param {Object} options.auth - API autentication data. See ../config.js.example for reference.
|
|
246
|
+
* @param {Number} options.size - Width of the geoTiff image to return
|
|
247
|
+
* @returns GeoTIFF raster with elevation data
|
|
248
|
+
*/
|
|
249
|
+
function getDenmarkGeoTiff(options) {
|
|
250
|
+
if (options.src) {
|
|
251
|
+
return fetch(options.src)
|
|
252
|
+
.then(response => response.arrayBuffer())
|
|
253
|
+
.then(arrayBuffer => consumeGeoTIFF(arrayBuffer))
|
|
254
|
+
} else {
|
|
255
|
+
const auth = options.auth
|
|
256
|
+
const size = options.size ? options.size : 1000
|
|
257
|
+
return getTerrainGeoTIFF({bbox: [430000,6040000,900000,6413000]}, auth, null, size)
|
|
258
|
+
}
|
|
259
|
+
}
|
|
235
260
|
|
|
236
261
|
export {
|
|
237
262
|
get,
|
|
@@ -239,5 +264,7 @@ export {
|
|
|
239
264
|
getSTAC,
|
|
240
265
|
postSTAC,
|
|
241
266
|
getDHM,
|
|
242
|
-
getTerrainGeoTIFF
|
|
267
|
+
getTerrainGeoTIFF,
|
|
268
|
+
getDenmarkGeoTiff,
|
|
269
|
+
consumeGeoTIFF
|
|
243
270
|
}
|
package/modules/saul-core.js
CHANGED
|
@@ -202,8 +202,8 @@ async function compareZ(options) {
|
|
|
202
202
|
const delta = Math.abs(world_xyz[2] - options.z)
|
|
203
203
|
|
|
204
204
|
// Check delta vs. limit. If the difference is too big, try building coordinates with the new z
|
|
205
|
-
// Make sure the recursive loop ends
|
|
206
|
-
if (options.iteration <
|
|
205
|
+
// Make sure the recursive loop ends after 20 iterations even if no precise z is found
|
|
206
|
+
if (options.iteration < 20 && delta > options.limit) {
|
|
207
207
|
options.iteration++
|
|
208
208
|
options.z = world_xyz[2]
|
|
209
209
|
return compareZ(options)
|
|
@@ -1,52 +1,106 @@
|
|
|
1
|
-
|
|
1
|
+
/**
|
|
2
|
+
* Maps a coordinate from the one coordinate system to another based on GeoTiff image dimensions.
|
|
3
|
+
* @param {Array} coord - EPSG:25832 X,Y coordinate pair
|
|
4
|
+
* @param {Array} bbox - Bounding box within input coordinate systtem. Consists of 2 EPSG:25832 coordinate pairs. Example: [x1,y1,x2,y2]
|
|
5
|
+
* @param {Array} imageDimensions - Width and height of a GeoTiff image. This will set the bounding box of the output coordinate system. Note: This coordinate system will have 0,0 set in the top right position of the image.
|
|
6
|
+
*/
|
|
7
|
+
function convertCoordinate(coord, bbox1, imageDimensions) {
|
|
8
|
+
|
|
9
|
+
// Extract the coordinates from the bounding boxes
|
|
10
|
+
const [x1_min, y1_min, x1_max, y1_max] = bbox1
|
|
2
11
|
|
|
12
|
+
// Extract the coordinate to convert
|
|
13
|
+
const [x1, y1] = coord
|
|
3
14
|
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
return [
|
|
15
|
+
// Calculate the width and height of both bounding boxes
|
|
16
|
+
const width1 = x1_max - x1_min
|
|
17
|
+
const height1 = y1_max - y1_min
|
|
18
|
+
const width2 = imageDimensions[0]
|
|
19
|
+
const height2 = imageDimensions[1]
|
|
20
|
+
|
|
21
|
+
// Calculate the relative position in the first coordinate system
|
|
22
|
+
const x_relative = (x1 - x1_min) / width1
|
|
23
|
+
const y_relative = (y1 - y1_min) / height1
|
|
24
|
+
|
|
25
|
+
// Calculate the new position in the second coordinate system
|
|
26
|
+
const x2 = Math.abs(x_relative * width2)
|
|
27
|
+
const y2 = height2 - Math.abs(y_relative * height2)
|
|
28
|
+
|
|
29
|
+
return [x2, y2]
|
|
19
30
|
}
|
|
20
31
|
|
|
21
|
-
/**
|
|
22
|
-
*
|
|
32
|
+
/**
|
|
33
|
+
* Calculates nearest elevation for given coordinate using geoTIFF terrain data
|
|
23
34
|
* @param {number} x - EPSG:25832 X coordinate
|
|
24
35
|
* @param {number} y - EPSG:25832 Y coordinate
|
|
25
|
-
* @param {object} geoTiff - GeoTiff data output from getTerrainGeoTIFF() method
|
|
36
|
+
* @param {object} geoTiff - GeoTiff data output from getTerrainGeoTIFF() or getDenmarkGeoTiff() method
|
|
26
37
|
* @returns {number} Elevation in meters
|
|
27
38
|
*/
|
|
28
39
|
async function getElevation(x, y, geoTiff) {
|
|
29
|
-
|
|
40
|
+
|
|
30
41
|
const bbox = geoTiff.getBoundingBox()
|
|
31
42
|
const height = geoTiff.getHeight()
|
|
32
43
|
const width = geoTiff.getWidth()
|
|
33
|
-
const bboxWidth = bbox[2] - bbox[0]
|
|
34
|
-
const bboxHeight = bbox[3] - bbox[1]
|
|
35
44
|
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
const
|
|
41
|
-
|
|
45
|
+
// Convert lat/lon to geotiff x/y
|
|
46
|
+
const [xPx, yPx] = convertCoordinate([x,y], bbox, [width, height])
|
|
47
|
+
|
|
48
|
+
// Fetch window of raster values around x/y
|
|
49
|
+
const window = [
|
|
50
|
+
Math.floor(xPx),
|
|
51
|
+
Math.floor(yPx),
|
|
52
|
+
Math.ceil(xPx),
|
|
53
|
+
Math.ceil(yPx)
|
|
54
|
+
]
|
|
55
|
+
|
|
56
|
+
// Fetch elevation value from geoTiff rasters
|
|
57
|
+
const elevation_data = await geoTiff.readRasters({
|
|
58
|
+
window: window,
|
|
59
|
+
fillValue: 0
|
|
60
|
+
})
|
|
61
|
+
|
|
62
|
+
return elevation_data[0][0]
|
|
63
|
+
}
|
|
42
64
|
|
|
43
|
-
|
|
44
|
-
|
|
65
|
+
/** Creates an ASCII visualization of a terrain GeoTiff. Useful for display in a terminal.
|
|
66
|
+
* NOTE: You may want to use a downsmapled GeoTiff to fit within your terminal window. A GeoTiff pixel is represented by 3 characters each.
|
|
67
|
+
* @param {object} gTiff - GeoTiff output from getTerrainGeoTIFF() or getDenmarkGeoTiff() method
|
|
68
|
+
*/
|
|
69
|
+
async function visualizeGeotiff(gTiff) {
|
|
70
|
+
console.log('--- GTIFF visualization ---')
|
|
71
|
+
const float32Arr = await gTiff.readRasters()
|
|
72
|
+
const tiffWidth = gTiff.getWidth()
|
|
73
|
+
const rasters = float32Arr[0]
|
|
74
|
+
let lines = []
|
|
75
|
+
let line = ''
|
|
76
|
+
for (let i = 0; i < rasters.length; i++) {
|
|
77
|
+
if (i % tiffWidth === 0) {
|
|
78
|
+
lines.push(line)
|
|
79
|
+
line = ''
|
|
80
|
+
}
|
|
81
|
+
line += zeroPadNumber(rasters[i])
|
|
82
|
+
}
|
|
83
|
+
for (const l of lines) {
|
|
84
|
+
console.log(l)
|
|
85
|
+
}
|
|
86
|
+
}
|
|
45
87
|
|
|
46
|
-
|
|
88
|
+
/** Converts numbers to strings in a 3-letter format. Ex. `002`, `0-3` (for negative numbers), or `123` */
|
|
89
|
+
function zeroPadNumber(input) {
|
|
90
|
+
if (input === 0) {
|
|
91
|
+
return "..."
|
|
92
|
+
} else if (input < 0) {
|
|
93
|
+
return `0${input.toFixed(0)}`
|
|
94
|
+
} else if (input < 10) {
|
|
95
|
+
return `00${Math.floor(input)}`
|
|
96
|
+
} else if (input < 100) {
|
|
97
|
+
return `0${Math.floor(input)}`
|
|
98
|
+
} else {
|
|
99
|
+
return `${Math.floor(input)}`
|
|
100
|
+
}
|
|
47
101
|
}
|
|
48
102
|
|
|
49
103
|
export {
|
|
50
|
-
|
|
51
|
-
|
|
104
|
+
getElevation,
|
|
105
|
+
visualizeGeotiff
|
|
52
106
|
}
|
package/package.json
CHANGED
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@dataforsyningen/saul",
|
|
3
|
-
"version": "3.
|
|
3
|
+
"version": "3.5.0",
|
|
4
4
|
"description": "This is a collection of stand-alone methods for photogrammetry calculations and API interactions for 'Danske Skråfotos'.",
|
|
5
5
|
"main": "index.js",
|
|
6
6
|
"type": "module",
|
|
7
7
|
"scripts": {
|
|
8
|
-
"test": "echo '
|
|
8
|
+
"test": "echo 'Tests require Node.js >= 18.0.0' && node ./test/saul-projection.test.js && node ./test/saul-core.test.js && node ./test/saul-combined.test.js && node ./test/saul-elevation.test.js",
|
|
9
9
|
"docs": "jsdoc ./modules/*.js --destination docs"
|
|
10
10
|
},
|
|
11
11
|
"repository": {
|
|
@@ -0,0 +1,250 @@
|
|
|
1
|
+
import auth from '../config.js'
|
|
2
|
+
import { getElevation, visualizeGeotiff } from '../modules/saul-elevation.js'
|
|
3
|
+
import { getImageXY, getWorldXYZ } from '../modules/saul-core.js'
|
|
4
|
+
import { getDenmarkGeoTiff, consumeGeoTIFF } from '../modules/api.js'
|
|
5
|
+
|
|
6
|
+
const geoTiffResolution = 1000
|
|
7
|
+
|
|
8
|
+
const worldxy = [533344, 6172951] // World XY Point in all images near Vejle
|
|
9
|
+
const image1xy = [8566,4105] // Point/Image XY in `image1`
|
|
10
|
+
const image1 = '2023_83_29_2_0019_00001130' // Vejle N
|
|
11
|
+
const image2 = '2023_83_29_4_0017_00001752' // Vejle E
|
|
12
|
+
const image3 = '2023_83_29_3_0019_00001149' // Veje S
|
|
13
|
+
const image4 = '2023_83_29_5_0022_00002826' // Vejle W
|
|
14
|
+
const image0 = '2023_83_29_1_0019_00001139' // Vejle Nadir
|
|
15
|
+
|
|
16
|
+
const point1 = [724400, 6175773] // Rådhuspladsen
|
|
17
|
+
const point2 = [595686, 6170394] // In the sea
|
|
18
|
+
const point3 = [542656, 6217825] // Near Himmelbjerg
|
|
19
|
+
const point4 = [480770, 6087529] // Marshes in the west
|
|
20
|
+
const point5 = [533394, 6173015] // Steep street in Vejle
|
|
21
|
+
const point6 = [533381, 6173108] // Vejle 2
|
|
22
|
+
const point7 = [533339, 6172860] // Vejle 3
|
|
23
|
+
|
|
24
|
+
const pointn = [596610, 6402161] // Skagen
|
|
25
|
+
const points = [692008, 6049902] // Gedser
|
|
26
|
+
const pointø = [892999, 6147725] // Christians Ø
|
|
27
|
+
const pointv = [441977, 6157385] // Blåvands hug
|
|
28
|
+
|
|
29
|
+
function fetchKote(worldXY) {
|
|
30
|
+
return fetch(`https://services.datafordeler.dk/DHMTerraen/DHMKoter/1.0.0/GEOREST/HentKoter?geop=POINT(${worldXY[0]} ${worldXY[1]})&elevationmodel=dtm&username=${auth.API_DHM_TOKENA}&password=${auth.API_DHM_TOKENB}`)
|
|
31
|
+
.then((response) => {
|
|
32
|
+
return response.json()
|
|
33
|
+
})
|
|
34
|
+
.then((kote) => {
|
|
35
|
+
return kote.HentKoterRespons.data[0].kote
|
|
36
|
+
})
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
function fetchImageData(imageId) {
|
|
40
|
+
return fetch(`https://api.dataforsyningen.dk/rest/skraafoto_api/v1.0/search?limit=1&crs=http://www.opengis.net/def/crs/EPSG/0/25832&ids=${imageId}&token=e88d7be6754140025ebeb63d57e991ae`)
|
|
41
|
+
.then((response) => response.json())
|
|
42
|
+
.then((data) => {
|
|
43
|
+
return data.features[0]
|
|
44
|
+
})
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
/*
|
|
48
|
+
* Example request to get terrain data for all of DK
|
|
49
|
+
* https://services.datafordeler.dk/DHMNedboer/dhm_wcs/1.0.0/WCS?SERVICE=WCS&COVERAGE=dhm_terraen&RESPONSE_CRS=epsg:25832&CRS=epsg:25832&FORMAT=GTiff&REQUEST=GetCoverage&VERSION=1.0.0&username=QKJBQATHVS&password=ytxCA8UGM5n0Z*zi&height=1000&width=1000&bbox=430000,6040000,900000,6413000
|
|
50
|
+
*/
|
|
51
|
+
|
|
52
|
+
console.log('-------------------------------------------------------')
|
|
53
|
+
console.log('-- Experiments with pan-Danish GeoTiff terrain model --')
|
|
54
|
+
console.log('-------------------------------------------------------')
|
|
55
|
+
|
|
56
|
+
/*
|
|
57
|
+
It should
|
|
58
|
+
- fetch geotiff from all of DK
|
|
59
|
+
- fetch image data from several images covering the same area
|
|
60
|
+
- should simulate a click in one image (img1 at [8566,4105])
|
|
61
|
+
- should calculate worldxyz 1 from that click
|
|
62
|
+
- should calculate imagexy in another image
|
|
63
|
+
- should calculate worldxyz 2 from that imagexy
|
|
64
|
+
- should compare worldxyz 1 and worldxyz 2
|
|
65
|
+
- should compare worldxyz 1 z and worldxyz 2 z and kote
|
|
66
|
+
*/
|
|
67
|
+
|
|
68
|
+
// Get GTiff from API
|
|
69
|
+
// const DKGeoTiff = await getDenmarkGeoTiff({auth: auth, size: geoTiffResolution})
|
|
70
|
+
|
|
71
|
+
// Get big GTiff
|
|
72
|
+
const DKGeoTiff = await getDenmarkGeoTiff({src: 'http://localhost:7701/dk-terrain.tiff'})
|
|
73
|
+
|
|
74
|
+
// Get tiny GTiff
|
|
75
|
+
//const DKGeoTiff = await getDenmarkGeoTiff({src: 'http://localhost:7701/tiny-dk-terrain.tiff'})
|
|
76
|
+
|
|
77
|
+
const imgData0 = await fetchImageData(image0)
|
|
78
|
+
const imgData1 = await fetchImageData(image1)
|
|
79
|
+
const imgData2 = await fetchImageData(image2)
|
|
80
|
+
const imgData3 = await fetchImageData(image3)
|
|
81
|
+
const imgData4 = await fetchImageData(image4)
|
|
82
|
+
|
|
83
|
+
// Simulate click in image north at [8566,4105]
|
|
84
|
+
const calcdWorldXYZ1 = await getWorldXYZ({
|
|
85
|
+
xy: image1xy,
|
|
86
|
+
image: imgData1,
|
|
87
|
+
terrain: DKGeoTiff
|
|
88
|
+
})
|
|
89
|
+
const calcdImageXY2 = getImageXY(imgData2, ...calcdWorldXYZ1)
|
|
90
|
+
const calcdWorldXYZ2 = await getWorldXYZ({
|
|
91
|
+
xy: calcdImageXY2,
|
|
92
|
+
image: imgData2,
|
|
93
|
+
terrain: DKGeoTiff
|
|
94
|
+
})
|
|
95
|
+
const calcdImageXY3 = getImageXY(imgData3, ...calcdWorldXYZ2)
|
|
96
|
+
const calcdWorldXYZ3 = await getWorldXYZ({
|
|
97
|
+
xy: calcdImageXY3,
|
|
98
|
+
image: imgData3,
|
|
99
|
+
terrain: DKGeoTiff
|
|
100
|
+
})
|
|
101
|
+
const calcdImageXY4 = getImageXY(imgData4, ...calcdWorldXYZ3)
|
|
102
|
+
const calcdWorldXYZ4 = await getWorldXYZ({
|
|
103
|
+
xy: calcdImageXY4,
|
|
104
|
+
image: imgData4,
|
|
105
|
+
terrain: DKGeoTiff
|
|
106
|
+
})
|
|
107
|
+
const calcdImageXY0 = getImageXY(imgData0, ...calcdWorldXYZ4)
|
|
108
|
+
const calcdWorldXYZ0 = await getWorldXYZ({
|
|
109
|
+
xy: calcdImageXY0,
|
|
110
|
+
image: imgData0,
|
|
111
|
+
terrain: DKGeoTiff
|
|
112
|
+
})
|
|
113
|
+
const calcdImageXY10 = getImageXY(imgData1, ...calcdWorldXYZ0)
|
|
114
|
+
const calcdWorldXYZ10 = await getWorldXYZ({
|
|
115
|
+
xy: calcdImageXY10,
|
|
116
|
+
image: imgData1,
|
|
117
|
+
terrain: DKGeoTiff
|
|
118
|
+
})
|
|
119
|
+
|
|
120
|
+
function getRandomPoint() {
|
|
121
|
+
const bbox = [430000,6040000,900000,6413000]
|
|
122
|
+
const width = bbox[2] - bbox[0]
|
|
123
|
+
const height = bbox[3] - bbox[1]
|
|
124
|
+
const randomX = bbox[0] + (Math.random() * width)
|
|
125
|
+
const randomY = bbox[1] + (Math.random() * height)
|
|
126
|
+
return [randomX, randomY]
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
const randomPoint1 = getRandomPoint()
|
|
130
|
+
const randomPoint2 = getRandomPoint()
|
|
131
|
+
const randomPoint3 = getRandomPoint()
|
|
132
|
+
const randomPoint4 = getRandomPoint()
|
|
133
|
+
const randomPoint5 = getRandomPoint()
|
|
134
|
+
const randomPoint6 = getRandomPoint()
|
|
135
|
+
const randomPoint7 = getRandomPoint()
|
|
136
|
+
const randomPoint8 = getRandomPoint()
|
|
137
|
+
const randomPoint9 = getRandomPoint()
|
|
138
|
+
const randomPoint10 = getRandomPoint()
|
|
139
|
+
|
|
140
|
+
console.log('From origin, use world coordinate to calculate image coordinate.')
|
|
141
|
+
console.log('Then uses that image coordinate to calculate world coordinate and feed it into the next image calculations.')
|
|
142
|
+
console.table({
|
|
143
|
+
origins: {worldxyz: worldxy, imagexy: image1xy},
|
|
144
|
+
image1: {worldxyz: calcdWorldXYZ1, imagexy: image1xy},
|
|
145
|
+
image2: {worldxyz: calcdWorldXYZ2, imagexy: calcdImageXY2},
|
|
146
|
+
image3: {worldxyz: calcdWorldXYZ3, imagexy: calcdImageXY3},
|
|
147
|
+
image4: {worldxyz: calcdWorldXYZ4, imagexy: calcdImageXY4},
|
|
148
|
+
image0: {worldxyz: calcdWorldXYZ0, imagexy: calcdImageXY0},
|
|
149
|
+
back_to_image1: {worldxyz: calcdWorldXYZ10, imagexy: calcdImageXY10}
|
|
150
|
+
})
|
|
151
|
+
|
|
152
|
+
console.log('Using image px coordinate to calculate a world coordinate and back again.')
|
|
153
|
+
console.table({
|
|
154
|
+
imageXY: {
|
|
155
|
+
original: [8566,4105],
|
|
156
|
+
'round-trip': getImageXY(imgData1, ...calcdWorldXYZ0)
|
|
157
|
+
}
|
|
158
|
+
})
|
|
159
|
+
|
|
160
|
+
console.log('Samle elevations fetched from kote API or calculated from GeoTiff:')
|
|
161
|
+
console.table({
|
|
162
|
+
'Rådhuspladsen': {
|
|
163
|
+
kote: await fetchKote(point1),
|
|
164
|
+
gtiff: await getElevation(...point1, DKGeoTiff)
|
|
165
|
+
},
|
|
166
|
+
'In the sea': {
|
|
167
|
+
kote: await fetchKote(point2),
|
|
168
|
+
gtiff: await getElevation(...point2, DKGeoTiff)
|
|
169
|
+
},
|
|
170
|
+
'Near Himmelbjerg': {
|
|
171
|
+
kote: await fetchKote(point3),
|
|
172
|
+
gtiff: await getElevation(...point3, DKGeoTiff)
|
|
173
|
+
},
|
|
174
|
+
'Marshes in the west': {
|
|
175
|
+
kote: await fetchKote(point4),
|
|
176
|
+
gtiff: await getElevation(...point4, DKGeoTiff)
|
|
177
|
+
},
|
|
178
|
+
'Vejle 1': {
|
|
179
|
+
kote: await fetchKote(point5),
|
|
180
|
+
gtiff: await getElevation(...point5, DKGeoTiff)
|
|
181
|
+
},
|
|
182
|
+
'Vejle 2': {
|
|
183
|
+
kote: await fetchKote(point6),
|
|
184
|
+
gtiff: await getElevation(...point6, DKGeoTiff)
|
|
185
|
+
},
|
|
186
|
+
'Vejle 3': {
|
|
187
|
+
kote: await fetchKote(point7),
|
|
188
|
+
gtiff: await getElevation(...point7, DKGeoTiff)
|
|
189
|
+
},
|
|
190
|
+
'Skagen': {
|
|
191
|
+
kote: await fetchKote(pointn),
|
|
192
|
+
gtiff: await getElevation(...pointn, DKGeoTiff)
|
|
193
|
+
},
|
|
194
|
+
'Gedser': {
|
|
195
|
+
kote: await fetchKote(points),
|
|
196
|
+
gtiff: await getElevation(...points, DKGeoTiff)
|
|
197
|
+
},
|
|
198
|
+
'Blåvand': {
|
|
199
|
+
kote: await fetchKote(pointv),
|
|
200
|
+
gtiff: await getElevation(...pointv, DKGeoTiff)
|
|
201
|
+
},
|
|
202
|
+
'Chr. Ø': {
|
|
203
|
+
kote: await fetchKote(pointø),
|
|
204
|
+
gtiff: await getElevation(...pointø, DKGeoTiff)
|
|
205
|
+
},
|
|
206
|
+
'Random 1': {
|
|
207
|
+
kote: await fetchKote(randomPoint1),
|
|
208
|
+
gtiff: await getElevation(...randomPoint1, DKGeoTiff)
|
|
209
|
+
},
|
|
210
|
+
'Random 2': {
|
|
211
|
+
kote: await fetchKote(randomPoint2),
|
|
212
|
+
gtiff: await getElevation(...randomPoint2, DKGeoTiff)
|
|
213
|
+
},
|
|
214
|
+
'Random 3': {
|
|
215
|
+
kote: await fetchKote(randomPoint3),
|
|
216
|
+
gtiff: await getElevation(...randomPoint3, DKGeoTiff)
|
|
217
|
+
},
|
|
218
|
+
'Random 4': {
|
|
219
|
+
kote: await fetchKote(randomPoint4),
|
|
220
|
+
gtiff: await getElevation(...randomPoint4, DKGeoTiff)
|
|
221
|
+
},
|
|
222
|
+
'Random 5': {
|
|
223
|
+
kote: await fetchKote(randomPoint5),
|
|
224
|
+
gtiff: await getElevation(...randomPoint5, DKGeoTiff)
|
|
225
|
+
},
|
|
226
|
+
'Random 6': {
|
|
227
|
+
kote: await fetchKote(randomPoint6),
|
|
228
|
+
gtiff: await getElevation(...randomPoint6, DKGeoTiff)
|
|
229
|
+
},
|
|
230
|
+
'Random 7': {
|
|
231
|
+
kote: await fetchKote(randomPoint7),
|
|
232
|
+
gtiff: await getElevation(...randomPoint7, DKGeoTiff)
|
|
233
|
+
},
|
|
234
|
+
'Random 8': {
|
|
235
|
+
kote: await fetchKote(randomPoint8),
|
|
236
|
+
gtiff: await getElevation(...randomPoint8, DKGeoTiff)
|
|
237
|
+
},
|
|
238
|
+
'Random 9': {
|
|
239
|
+
kote: await fetchKote(randomPoint9),
|
|
240
|
+
gtiff: await getElevation(...randomPoint9, DKGeoTiff)
|
|
241
|
+
},
|
|
242
|
+
'Random 10': {
|
|
243
|
+
kote: await fetchKote(randomPoint10),
|
|
244
|
+
gtiff: await getElevation(...randomPoint10, DKGeoTiff)
|
|
245
|
+
}
|
|
246
|
+
})
|
|
247
|
+
|
|
248
|
+
console.log('got DKGeotiff', (DKGeoTiff.source.arrayBuffer.byteLength / 1024), 'Kb', pointø)
|
|
249
|
+
|
|
250
|
+
//visualizeGeotiff(DKGeoTiff)
|
|
@@ -3,6 +3,9 @@
|
|
|
3
3
|
import auth from '../config.js'
|
|
4
4
|
import { getSTAC, getTerrainGeoTIFF,getZ, getWorldXYZ, getImageXY } from '../index.js'
|
|
5
5
|
|
|
6
|
+
console.log('---------------')
|
|
7
|
+
console.log('Combined tests ')
|
|
8
|
+
console.log('---------------')
|
|
6
9
|
|
|
7
10
|
// Vars
|
|
8
11
|
const resolution = 0.005 // Higher number means more points and better precision
|
|
@@ -86,9 +89,11 @@ function is_equalIsh(num1, num2, deviation = max_deviation) {
|
|
|
86
89
|
return true
|
|
87
90
|
}
|
|
88
91
|
}
|
|
92
|
+
|
|
89
93
|
function generateSTACurl(stac_item_id) {
|
|
90
94
|
return `/search?limit=1&crs=http://www.opengis.net/def/crs/EPSG/0/25832&ids=${ stac_item_id }`
|
|
91
95
|
}
|
|
96
|
+
|
|
92
97
|
async function enrichData(item) {
|
|
93
98
|
let new_item = Object.assign({}, item)
|
|
94
99
|
// add STAC item
|
package/test/saul-core.test.js
CHANGED
|
@@ -7,6 +7,10 @@ import auth from '../config.js'
|
|
|
7
7
|
import assert from 'assert'
|
|
8
8
|
import {getSTAC, world2image, image2world, getZ, iterate} from '../index.js'
|
|
9
9
|
|
|
10
|
+
console.log('---------------')
|
|
11
|
+
console.log(' Core tests ')
|
|
12
|
+
console.log('---------------')
|
|
13
|
+
|
|
10
14
|
/*
|
|
11
15
|
const item = await getSTAC('/collections/skraafotos2019/items/2019_83_37_2_0046_00001113', auth)
|
|
12
16
|
const world_x = 580341
|
|
@@ -64,7 +68,7 @@ try {
|
|
|
64
68
|
let xy = world2image(item, world_x, world_y, world_elevation)
|
|
65
69
|
|
|
66
70
|
assert(is_equalIsh(xy[0], image_x, 1), `world2image fail: The x coordinate values ${xy[0]} ${image_x} are not equal`)
|
|
67
|
-
assert(is_equalIsh(xy[1], image_y),
|
|
71
|
+
assert(is_equalIsh(xy[1], image_y, 1), `world2image fail: The y coordinate values ${xy[1]} ${image_y} are not equal`)
|
|
68
72
|
|
|
69
73
|
console.log("Test world2image OK")
|
|
70
74
|
|
|
@@ -5,6 +5,10 @@ import auth from '../config.js'
|
|
|
5
5
|
import assert from 'assert'
|
|
6
6
|
import { getElevation, get, getTerrainGeoTIFF, getZ, getWorldXYZ, world2image } from '../index.js'
|
|
7
7
|
|
|
8
|
+
console.log('---------------')
|
|
9
|
+
console.log('Elevation tests')
|
|
10
|
+
console.log('---------------')
|
|
11
|
+
|
|
8
12
|
// Vars
|
|
9
13
|
const stac_item = '2021_83_29_2_0019_00003995'
|
|
10
14
|
const fidelity = 0.03 // Higher number means more points and better precision
|
|
@@ -65,7 +69,7 @@ function compareElevations(x,y,geotiff) {
|
|
|
65
69
|
.then(elevation => {
|
|
66
70
|
getZ(x, y, auth)
|
|
67
71
|
.then(getz_e => {
|
|
68
|
-
assert(is_equalIsh(getz_e, elevation,
|
|
72
|
+
assert(is_equalIsh(getz_e, elevation, 2.7), `Elevations ${elevation} / ${getz_e} at ${x} ${y} are way apart`)
|
|
69
73
|
console.log(`Elevation at ${ x } ${ y } with delta ${Math.abs(elevation - getz_e).toFixed(2)} OK`)
|
|
70
74
|
})
|
|
71
75
|
})
|