import get from 'lodash-es/get.js'
import floor from 'lodash-es/floor.js'
import cdbl from 'wsemi/src/cdbl.mjs'
import isnum from 'wsemi/src/isnum.mjs'
import isab from 'wsemi/src/isab.mjs'
import isu8arr from 'wsemi/src/isu8arr.mjs'
import isblob from 'wsemi/src/isblob.mjs'
import isestr from 'wsemi/src/isestr.mjs'
import iseobj from 'wsemi/src/iseobj.mjs'
import { fromArrayBuffer, fromBlob } from 'geotiff'
import ptXYtoObj from './ptXYtoObj.mjs'
/**
* 查詢點陣列[x,y]或點物件{x,y}於指定Tiff點陣圖內數值,若無則回傳def值
*
* Unit Test: {@link https://github.com/yuda-lyu/w-gis/blob/master/test/buildFindPointInTiff.test.mjs Github}
* @memberOf w-gis
* @returns {Object} 回傳函數物件,包含init、isInit、getPoint函數。init為初始化,輸入inp與opt,無輸出,isInit為回傳是否初始化布林值,無輸入。getPoint為查詢點位於點陣圖內數值,輸入p與opt。
* @example
*
* import b642u8arr from 'wsemi/src/b642u8arr.mjs'
* import buildFindPointInTiff from 'wsemi/src/buildFindPointInTiff.mjs'
*
* let p
* let r
*
* let b64Tif = `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`
* let u8a = b642u8arr(b64Tif)
* // lon 121.51338 121.51847
* // lat 25.046 25.05
*
* let BD = buildFindPointInTiff
* let bd = new BD()
* await bd.init(u8a)
*
* p = [121.51353, 25.04987]
* r = await bd.getPoint(p)
* console.log(r)
* // => 3.1814956665039062
*
* p = [121.51835, 25.04608]
* r = await bd.getPoint(p)
* console.log(r)
* // => 2.9800331592559814
*
* p = [121.51353, 25.05016]
* r = await bd.getPoint(p)
* console.log(r)
* // => 'unknow'
*
* p = [121.51353, 25.05016]
* r = await bd.getPoint(p, { def: '未知' })
* console.log(r)
* // => '未知'
*
*/
function Build() {
let bInit = false
let width = null
let height = null
let origin = null
let resolution = null
let image = null
async function init(inp, opt = {}) {
//type
let type = get(opt, 'type', '')
let cvAb = async (inp) => {
// let u8a = fs.readFileSync(fp)
// let ab = u8a.buffer
// inp = ab
//fromArrayBuffer
let r = await fromArrayBuffer(inp)
return r
}
let cvBlob = async (inp) => {
//fromBlob
let r = await fromBlob(inp)
return r
}
let cvU8a = async (inp) => {
//ab
let ab = inp.buffer
//fromArrayBuffer
let r = await fromArrayBuffer(ab)
return r
}
//tiff
let tiff = null
if (isestr(type)) {
if (type === 'ab') {
tiff = await cvAb(inp)
}
else if (type === 'u8a') {
tiff = await cvU8a(inp)
}
else if (type === 'blob') {
tiff = await cvBlob(inp)
}
else {
throw new Error(`invalid type[${type}]`)
}
}
else if (isab(inp)) {
tiff = await cvAb(inp)
}
else if (isu8arr(inp)) {
tiff = await cvU8a(inp)
}
else if (isblob(inp)) {
tiff = await cvBlob(inp)
}
else {
throw new Error(`inp is not an ArrayBuffer or a Blob`)
}
//getImage
image = await tiff.getImage()
//width, height
width = image.getWidth()
height = image.getHeight()
// console.log('width', width, 'height', height)
//origin
origin = image.getOrigin()
// console.log('origin', origin)
//resolution
resolution = image.getResolution()
// console.log('resolution', resolution)
//samplesPerPixel
// let samplesPerPixel = image.getSamplesPerPixel()
// console.log('samplesPerPixel', samplesPerPixel)
//bbox
// let bbox = image.getBoundingBox()
// console.log('bbox', bbox)
//bInit
bInit = true
}
function isInit() {
return bInit
}
async function getPoint(p, opt = {}) {
//check
if (!bInit) {
throw new Error('no init')
}
//pt
let pt = ptXYtoObj(p, opt)
//check
if (!iseobj(pt)) {
throw new Error('p need to be [x,y] or {x,y}')
}
//x
let x = get(pt, 'x', '')
if (!isnum(x)) {
throw new Error('p[0] or p.x is not an effective number')
}
x = cdbl(x)
//y
let y = get(pt, 'y', '')
if (!isnum(y)) {
throw new Error('p[1] or p.y is not an effective number')
}
y = cdbl(y)
//def
let def = get(opt, 'def', '')
if (!isestr(def)) {
def = 'unknow'
}
let _x = x - origin[0]
let _y = y - origin[1]
let rx = _x / resolution[0]
let ry = _y / resolution[1]
let ix = floor(rx)
let iy = floor(ry)
// console.log('ix', ix, 'iy', iy)
//check
if (ix < 0 || iy < 0 || ix > (width - 1) || iy > (height - 1)) {
return def
}
//intrep
let data = await image.readRasters({ window: [ix, iy, ix + 1, iy + 1] })
// console.log('data', data)
//v
let v = def
let _v = get(data, '0.0', '') //回傳為陣列, 第1個[0]是R, [1]為G, [2]為B
if (isnum(_v)) {
v = cdbl(_v)
}
return v
}
return {
init,
isInit,
getPoint,
}
}
export default Build