import get from 'lodash-es/get.js'
import each from 'lodash-es/each.js'
import sortBy from 'lodash-es/sortBy.js'
import size from 'lodash-es/size.js'
import isestr from 'wsemi/src/isestr.mjs'
import iseobj from 'wsemi/src/iseobj.mjs'
import isearr from 'wsemi/src/isearr.mjs'
import isnum from 'wsemi/src/isnum.mjs'
import isbol from 'wsemi/src/isbol.mjs'
import cdbl from 'wsemi/src/cdbl.mjs'
import _interp1 from 'wsemi/src/interp1.mjs'
import ptsXtoArr from './ptsXtoArr.mjs'
import ptsXYtoArr from './ptsXYtoArr.mjs'
/**
* 針對不規則一維數據進行指定內插點數值
*
* @memberOf w-gis
* @param {Array} ps 輸入一維數據,格式可支援兩種,第一種各點為陣列[[x1,y1],[x2,y2],...],例如[[0.1,5],[0.2,12],...],第二種各點為物件,屬性至少要有x與y,格式為[{x:x1,y:y1},{x:x2,y:y2},...],例如[{x:0.1,y:5},{x:0.2,y:12},...],key值x與y可由opt更換
* @param {Number} x 輸入要內插點的x值
* @param {Object} [opt={}] 輸入設定物件,預設{}
* @param {String} [opt.method=''] 輸入內插方法,可選'linear'、'stairs'、'blocks',預設'linear'
* @param {String} [opt.keyX='x'] 輸入若數據為物件陣列,取物件x值時的key字串,預設為'x'
* @param {String} [opt.keyY='y'] 輸入若數據為物件陣列,取物件y值時的key字串,預設為'y'
* @param {Number} [opt.xMin=undefined] 輸入若mode='stairs',更改x範圍下限值,預設為undefined
* @param {Number} [opt.xMax=undefined] 輸入若mode='stairs',更改x範圍上限值,預設為undefined
* @returns {Number|Object} 回傳內插結果數值,或是無法內插時之錯誤訊息物件
* @example
*
* async function test() {
*
* let ps
* let p
* let r
*
* ps = [{ x: 243, y: 206 }, { x: 233, y: 225 }, { x: 21, y: 325 }, { x: 953, y: 28 }, { x: 1092, y: 290 }, { x: 744, y: 200 }, { x: 174, y: 3 }, { x: 537, y: 368 }, { x: 1151, y: 371 }, { x: 814, y: 252 }]
* p = {
* x: 243,
* }
* r = await interp1(ps, p)
* console.log(r)
* // => { x: 243, y: 206 }
*
* ps = [{ x: 243, y: 206 }, { x: 233, y: 225 }, { x: 21, y: 325 }, { x: 953, y: 28 }, { x: 1092, y: 290 }, { x: 744, y: 200 }, { x: 174, y: 3 }, { x: 537, y: 368 }, { x: 1151, y: 371 }, { x: 814, y: 252 }]
* p = {
* x: 283,
* }
* r = await interp1(ps, p)
* console.log(r)
* // => { x: 283, y: 228.0408163265306 }
*
* ps = [{ x: 243, y: 206 }, { x: 233, y: 225 }, { x: 21, y: 325 }, { x: 953, y: 28 }, { x: 1092, y: 290 }, { x: 744, y: 200 }, { x: 174, y: 3 }, { x: 537, y: 368 }, { x: 1151, y: 371 }, { x: 814, y: 252 }]
* p = {
* x: 1160,
* }
* r = await interp1(ps, p)
* console.log(r)
* // => { x: 1160, y: null }
*
* ps = [{ a: 243, b: 206 }, { a: 233, b: 225 }, { a: 21, b: 325 }, { a: 953, b: 28 }, { a: 1092, b: 290 }, { a: 744, b: 200 }, { a: 174, b: 3 }, { a: 537, b: 368 }, { a: 1151, b: 371 }, { a: 814, b: 252 }]
* p = {
* a: 243,
* }
* r = await interp1(ps, p, { keyX: 'a', keyY: 'b' })
* console.log(r)
* // => { a: 243, b: 206 }
*
* ps = [{ x: 243, y: 206 }, { x: 233, y: 225 }, { x: 21, y: 325 }, { x: 953, y: 28 }, { x: 1092, y: 290 }, { x: 744, y: 200 }, { x: 174, y: 3 }, { x: 537, y: 368 }, { x: 1151, y: 371 }, { x: 814, y: 252 }]
* p = [
* {
* x: 243,
* },
* {
* x: 283,
* },
* ]
* r = await interp1(ps, p)
* console.log(r)
* // => [ { x: 243, y: 206 }, { x: 283, y: 228.0408163265306 } ]
*
* ps = [{ x: 0.000243, y: 0.000206 }, { x: 0.000233, y: 0.000225 }, { x: 0.000021, y: 0.000325 }, { x: 0.000953, y: 0.000028 }, { x: 0.001092, y: 0.00029 }, { x: 0.000744, y: 0.000200 }, { x: 0.000174, y: 0.000003 }, { x: 0.000537, y: 0.000368 }, { x: 0.001151, y: 0.000371 }, { x: 0.000814, y: 0.000252 }]
* p = {
* x: 0.000243,
* }
* r = await interp1(ps, p)
* console.log(r)
* // => { x: 0.000243, y: 0.00020600000000000002 }
*
* ps = [{ x: 243, y: 206 }, { x: 233, y: 225 }, { x: 21, y: 325 }, { x: 953, y: 28 }, { x: 1092, y: 290 }, { x: 744, y: 200 }, { x: 174, y: 3 }, { x: 537, y: 368 }, { x: 1151, y: 371 }, { x: 814, y: 252 }]
* p = {
* x: 243,
* }
* r = interp1(ps, p, { useSync: true }) //使用interp2.wk.umd.js則不支援sync模式
* console.log(r)
* // => { x: 243, y: 206 }
*
* }
* test()
* .catch((err) => {
* console.log(err)
* })
*
*/
function interp1(psSrc, psTar, opt = {}) {
//check psSrc
if (!isearr(psSrc)) {
return {
err: 'psSrc is not an array'
}
}
//check psTar
if (!isnum(psTar) && !iseobj(psTar) && !isearr(psTar)) {
return {
err: 'psTar is not a number or an object or an array'
}
}
//isOne
let isOne = isnum(psTar) || iseobj(psTar)
if (isnum(psTar)) {
psTar = [cdbl(psTar)]
}
else if (iseobj(psTar)) {
psTar = [psTar]
}
//keyX
let keyX = get(opt, 'keyX')
if (!isestr(keyX)) {
keyX = 'x'
}
//keyY
let keyY = get(opt, 'keyY')
if (!isestr(keyY)) {
keyY = 'y'
}
//method
let method = get(opt, 'method')
if (method !== 'linear' && method !== 'stairs' && method !== 'blocks') {
method = 'linear'
}
//useSync
let useSync = get(opt, 'useSync')
if (!isbol(useSync)) {
useSync = false
}
//keyInd
let keyInd = 'ind'
//ptsXYtoArr
psSrc = ptsXYtoArr(psSrc, { keyX, keyY, keyInd })
//check psSrc
if (size(psSrc) === 0) {
return {
err: 'psSrc has no effective data'
}
}
// console.log('ptsXYtoArr psSrc', psSrc)
//sortBy
psSrc = sortBy(psSrc, 'x')
// console.log('psSrc', psSrc)
//ptsXtoArr
psTar = ptsXtoArr(psTar, { keyX, keyInd })
// console.log('psTar', psTar)
//check psTar
if (size(psTar) === 0) {
return {
err: 'psTar has no effective data'
}
}
// console.log('ptsXtoArr psTar', psTar)
//_sync
let _sync = () => {
//_interp1
let ts = _interp1(psSrc, psTar, {
...opt,
mode: method,
keyX: 'x', //已正規化至'x'
keyY: 'y', //已正規化至'y'
})
// console.log('_interp1 ts', ts)
//rs
let rs = []
each(psTar, (o, k) => {
let v = ts[k]
if (isnum(v)) {
v = cdbl(v)
}
else {
v = null
}
let r = {
[keyX]: o.x,
[keyY]: v,
}
rs.push(r)
})
// console.log('rs', rs)
//r
let r
if (isOne) {
r = rs[0]
}
else {
r = rs
}
// console.log('isOne', isOne, r)
return r
}
//_async
let _async = async () => {
let r = null
try {
r = _sync()
let err = get(r, 'err')
if (isestr(err)) {
return Promise.reject(err)
}
else {
return r
}
}
catch (err) {
console.log(err)
return Promise.reject(err.toString())
}
}
if (useSync) {
return _sync()
}
else {
return _async()
}
}
export default interp1