import get from 'lodash-es/get.js'
import each from 'lodash-es/each.js'
import isNumber from 'lodash-es/isNumber.js'
import isearr from 'wsemi/src/isearr.mjs'
import isestr from 'wsemi/src/isestr.mjs'
import isnum from 'wsemi/src/isnum.mjs'
import isfun from 'wsemi/src/isfun.mjs'
import cdbl from 'wsemi/src/cdbl.mjs'
import _kriging from './interp2Kriging.mjs'
import aggregatePoints from './aggregatePoints.mjs'
import interp2Grid from './interp2Grid.mjs'
/**
* 不規則點資料先聚合再內插至規則網格
*
* Unit Test: {@link https://github.com/yuda-lyu/w-gis/blob/master/test/interp2Raster.test.mjs Github}
* @memberOf w-gis
* @param {Array} ops 輸入二維座標加觀測數據點陣列,為[{x:x1,y:y1,z:z1},{x:x2,y:y2,z:z2},...]點物件之陣列
* @param {Object} [opt={}] 輸入設定物件,預設{}
* @param {String} [opt.keyX='x'] 輸入點物件之x欄位字串,為座標,預設'x'
* @param {String} [opt.keyY='y'] 輸入點物件之y欄位字串,為座標,預設'y'
* @param {String} [opt.keyZ='z'] 輸入點物件之z欄位字串,為觀測值,預設'z'
* @param {String} [opt.modePick='min'] 輸入挑選方式字串,可選'min'、'max',預設'min'
* @param {Number} [opt.dx=0.000979087] 輸入網格x向間距數字,預設0.000979087,基於WGS84經緯度之數據點,代表約100m
* @param {Number} [opt.dx=0.000906247] 輸入網格y向間距數字,預設0.000906247,基於WGS84經緯度之數據點,代表約100m
* @param {Number} [opt.dxAgr=opt.dx*2] 輸入先聚合時網格x向間距數字,預設opt.dx*2
* @param {Number} [opt.dyAgr=opt.dy*2] 輸入先聚合時網格y向間距數字,預設opt.dy*2
* @param {Function} [opt.funValid=(x,y)=>{return true}] 輸入確認點座標(x,y)是否有效函數,回傳布林值,可使用Promise回傳,預設(x,y)=>{return true}
* @param {Function} [opt.funKriging=interp2Kriging] 輸入克利金處理函數,預設使用內建interp2Kriging
* @param {Function} [opt.funAdjust=(x,y,z)=>{return z}] 輸入內插後值調整函數,用於修正不合理值或做後處理,回傳布林值,可使用Promise回傳,預設(x,y,z)=>{return z}
* @param {Number} [opt.scale=1] 輸入當funKriging使用interp2Kriging時,正規化範圍數值,因處理多邊形時有數值容許誤差,故須通過縮放值域來減少問題,預設1是正規化0至1之間,使用scaleXY則是正規化為0至scaleXY之間,預設1
* @param {String} [opt.model='exponential'] 輸入當funKriging使用interp2Kriging時,擬合模式字串,可選'exponential'、'gaussian'、'spherical',預設'exponential'
* @param {Number} [opt.sigma2=0] 輸入當funKriging使用interp2Kriging時,自動擬合參數sigma2數值,預設0
* @param {Number} [opt.alpha=100] 輸入當funKriging使用interp2Kriging時,自動擬合參數alpha數值,預設100
* @returns {Object} 回傳規則網格物件,物件內grds為規則網格之二維陣列
* @example
*
* let ps
* let r
*
* ps = [
* { x: 121.48571681415929, y: 25.058614130434783, z: 95 },
* { x: 121.48500884955752, y: 25.062228260869563, z: 146 },
* { x: 121.47, y: 25.08125, z: 22 },
* { x: 121.53598230088495, y: 25.02475543478261, z: 223 },
* { x: 121.54582300884955, y: 25.074592391304346, z: 39 },
* { x: 121.52118584070796, y: 25.057472826086958, z: 191 },
* { x: 121.48083185840707, y: 25.02, z: 22 },
* { x: 121.50653097345132, y: 25.089429347826087, z: 249 },
* { x: 121.55, y: 25.09, z: 86 },
* { x: 121.52614159292035, y: 25.067364130434783, z: 125 }
* ]
* r = await interp2Raster(ps, { dx: 0.000979087 * 10, dy: 0.000906247 * 5 })
* console.log(JSON.stringify(r))
* // => {"xnum":9,"xmin":121.47,"xmax":121.55,"dx":0.00979087,"ynum":16,"ymin":25.02,"ymax":25.09,"dy":0.004531235,"zmin":25.008503223085306,"zmax":230.692207620399,"grds":[[53.29695613753195,90.9878283681276,143.06087191384637,200.32429562431122,230.692207620399,180.40204907064341,136.1530241094394,100.59943015055649,82.14770016468049],[33.18615340480098,82.53745908262893,136.89266690219813,189.57557481421284,211.01267466303997,174.01759815374774,129.8648554713684,90.3775726907702,69.76202213840641],[30.649106928513838,78.18086957161364,129.87666573494295,175.36672144691707,192.14083300446975,165.43595632681556,123.45781065492382,80.89449160839146,55.909387880686836],[44.35784386605923,78.19215023386876,123.34728621362704,162.59334238706708,178.14944804497486,158.24273885280672,118.72593945913597,77.34481966112054,47.557053415271795],[54.59624175640077,79.97235367298671,117.80692991239255,152.5691700549194,169.3604923358124,155.84955967852204,117.47530627008295,84.12984269825354,61.541566831759006],[61.921968156117515,81.52387857586544,113.0710912563389,145.1243482533917,165.07967283545923,161.80751391298088,126.65650015693579,97.96229710366745,79.82779997828177],[66.83219014217913,82.1918706583026,108.82981182150552,139.51924993924777,163.39654235447964,175.8727178307613,144.86370463051009,114.17834904512225,97.09515848645559],[69.71941699919188,82.20986544471259,105.48343246225039,134.8766711857756,161.6209193581903,185.51610085077323,159.2203228863815,129.86565172082058,112.88018028969536],[70.82153526794654,81.40365825844987,102.52998415554532,130.44222819267918,158.20368573475835,179.40458853522884,166.87690247501067,143.74286964403262,127.15417129624454],[70.24547760586455,79.10219254059587,98.72806515388253,125.74805126341245,153.60756995565745,173.79734055412013,171.50300218848182,155.95696527327257,140.05755661594753],[68.06294143513142,74.97983328526666,93.69964174320266,120.64337719371085,148.81678189404954,170.3067562843946,176.08450938057823,167.37076517487893,151.7970112583186],[64.40679807848441,68.87644483066734,87.36596771611377,115.20448065026856,144.34102924872468,168.44082899163902,181.65959964982952,178.91839896983052,162.45918562235704],[59.579516621263224,60.65421884945618,79.85418875855228,109.67073197494572,140.27156102781217,167.4089506411862,188.16721978253224,191.29745012452534,171.7427174412858],[54.25750734739524,50.16380421262544,71.68195808846065,104.45932666464594,136.53145068212558,166.22770388291246,194.18596156854792,204.55151424952277,178.67429685300704],[49.84400365402098,37.301157966447214,64.30077984326395,100.16770574008851,133.04693099333764,163.94549799236063,195.79253736299714,213.05406176918385,181.76602702017865],[48.51705283717487,25.008503223085306,60.667024580062325,97.41331557750496,129.82668100790102,160.1190717664935,189.93474888031673,202.82202458292304,180.33605168933383]],"pts":[{"x":121.48571681415929,"y":25.058614130434783,"z":95},{"x":121.47,"y":25.08125,"z":22},{"x":121.53598230088495,"y":25.02475543478261,"z":223},{"x":121.54582300884955,"y":25.074592391304346,"z":39},{"x":121.52118584070796,"y":25.057472826086958,"z":191},{"x":121.48083185840707,"y":25.02,"z":22},{"x":121.50653097345132,"y":25.089429347826087,"z":249},{"x":121.55,"y":25.09,"z":86},{"x":121.52614159292035,"y":25.067364130434783,"z":125}]}
*
* ps = [
* { x: 121.48571681415929, y: 25.058614130434783, z: 95 },
* { x: 121.48500884955752, y: 25.062228260869563, z: 146 },
* { x: 121.47, y: 25.08125, z: 22 },
* { x: 121.53598230088495, y: 25.02475543478261, z: 223 },
* { x: 121.54582300884955, y: 25.074592391304346, z: 39 },
* { x: 121.52118584070796, y: 25.057472826086958, z: 191 },
* { x: 121.48083185840707, y: 25.02, z: 22 },
* { x: 121.50653097345132, y: 25.089429347826087, z: 249 },
* { x: 121.55, y: 25.09, z: 86 },
* { x: 121.52614159292035, y: 25.067364130434783, z: 125 }
* ]
* r = await interp2Raster(ps, { dx: 0.000979087 * 10, dy: 0.000906247 * 5, dxAgr: 0.000979087 * 15, dyAgr: 0.000906247 * 7.5 })
* console.log(JSON.stringify(r))
* // => {"xnum":9,"xmin":121.47,"xmax":121.55,"dx":0.00979087,"ynum":16,"ymin":25.02,"ymax":25.09,"dy":0.004531235,"zmin":24.823924446215038,"zmax":231.7567577657555,"grds":[[53.62369559375291,97.28753826038451,151.99569385250032,206.01329420379795,231.7567577657555,181.74456038323083,136.9337797009959,100.82047078083103,82.07708777678545],[33.35769875360963,92.00300714953804,149.54057920145087,198.09758546908188,214.41704248676362,175.7821324384034,130.5283656577402,90.4093497431664,69.54075119287774],[33.694057708538715,92.54101428394036,147.39251200590925,187.06516519367833,197.62513561758846,167.6668963058992,123.98735585892726,80.78686225833944,55.66889834101754],[52.64381088478393,99.03900142300567,146.65595863609053,176.99055560470293,185.00298561118308,160.73147948072238,119.0363573373561,77.12115108746592,47.37939731126598],[66.61879668531361,107.79408272120735,147.016778115003,168.30294933707412,176.7095557492657,158.26543997764273,117.45655109967052,83.80309340175263,61.27750967567075],[75.2589561237669,113.5537749334791,144.98709654332248,159.8929007644603,172.0170905880976,163.84236052111794,126.4398496041521,97.63064967940787,79.59691654868394],[78.68117509942893,106.5552658165186,128.80117256854788,150.87976018747153,169.2068860796617,177.25446108422068,144.68301313512228,113.99037990431796,97.05253698651693],[78.27805645580389,92.10986466514447,109.16559772934329,141.9067311649439,165.99935683226428,186.4085110016602,159.21170852439775,129.94467107234337,113.13480709391158],[75.97241978508316,84.57378980579321,102.53683374775467,134.05122593259682,161.25691801191817,180.48459348365037,167.21602941206322,144.15358853414438,127.76309289265961],[72.80173195680102,79.76140615655008,97.9321023375592,127.31339852980325,155.6482200843788,174.98245027782707,172.19374986330374,156.6933278368807,141.02867176590735],[68.90918098278021,74.55268398871439,92.65277069488342,121.15239269012386,150.1775616972252,171.49822261670596,177.0133654786484,168.35817943753946,153.09719732545554],[64.2076980316679,67.96041083663675,86.26929074220435,115.22108595764789,145.29251688553296,169.59539950565747,182.68489882975817,180.02516814884666,164.02895337420648],[58.78869152147344,59.58502468707952,78.83089710760079,109.49913670429187,141.00843456843626,168.5245314234247,189.15870248800343,192.34693759552368,173.52110450762643],[53.17781904277413,49.19131322151639,70.82515273215796,104.26247139846541,137.18674389853737,167.33735247437988,195.08169367782963,205.34921468759225,180.6373824848832],[48.65930356588191,36.65719928223353,63.659890609431685,100.02829363193082,133.710205844732,165.11253891467507,196.727588357127,213.69062065298513,183.9600610036589],[47.296028443616365,24.823924446215038,60.196676193427145,97.36489712827152,130.55697396278424,161.41612787019466,191.2045850563283,204.15009289540566,182.84604795685374]],"pts":[{"x":121.48571681415929,"y":25.058614130434783,"z":95},{"x":121.48500884955752,"y":25.062228260869563,"z":146},{"x":121.47,"y":25.08125,"z":22},{"x":121.53598230088495,"y":25.02475543478261,"z":223},{"x":121.54582300884955,"y":25.074592391304346,"z":39},{"x":121.52118584070796,"y":25.057472826086958,"z":191},{"x":121.48083185840707,"y":25.02,"z":22},{"x":121.50653097345132,"y":25.089429347826087,"z":249},{"x":121.55,"y":25.09,"z":86},{"x":121.52614159292035,"y":25.067364130434783,"z":125}]}
*
*/
async function interp2Raster(ops, opt = {}) {
let dlng = 0.000979087
let dlat = 0.000906247
//check
if (!isearr(ops)) {
throw new Error(`ops`)
}
//keyX
let keyX = get(opt, 'keyX')
if (!isestr(keyX)) {
keyX = 'x'
}
//keyY
let keyY = get(opt, 'keyY')
if (!isestr(keyY)) {
keyY = 'y'
}
//keyZ
let keyZ = get(opt, 'keyZ')
if (!isestr(keyZ)) {
keyZ = 'z'
}
//dx
let dx = get(opt, 'dx')
if (!isnum(dx)) {
dx = dlng
}
dx = cdbl(dx)
//dy
let dy = get(opt, 'dy')
if (!isnum(dy)) {
dy = dlat
}
dy = cdbl(dy)
//dxAgr
let dxAgr = get(opt, 'dxAgr')
if (!isnum(dxAgr)) {
dxAgr = dy * 2
}
dxAgr = cdbl(dxAgr)
//dyAgr
let dyAgr = get(opt, 'dyAgr')
if (!isnum(dyAgr)) {
dyAgr = dy * 2
}
dyAgr = cdbl(dyAgr)
//modePick
let modePick = get(opt, 'modePick')
if (modePick !== 'min' && modePick !== 'max') {
modePick = 'min'
}
//funValid
let funValid = get(opt, 'funValid')
if (!isfun(funValid)) {
funValid = () => {
return true
}
}
//funKriging
let funKriging = get(opt, 'funKriging')
if (!isfun(funKriging)) {
funKriging = _kriging
}
//funAdjust
let funAdjust = get(opt, 'funAdjust')
if (!isfun(funAdjust)) {
funAdjust = (x, y, z) => {
return z
}
}
//xmin, xmax, ymin, ymax
let xmin = 1e20
let xmax = -1e20
let ymin = 1e20
let ymax = -1e20
each(ops, (m) => {
let v
v = get(m, keyX)
if (isNumber(v)) {
xmin = Math.min(v, xmin)
xmax = Math.max(v, xmax)
}
v = get(m, keyY)
if (isNumber(v)) {
ymin = Math.min(v, ymin)
ymax = Math.max(v, ymax)
}
})
// console.log('xmin', xmin, 'xmax', xmax)
// console.log('ymin', ymin, 'ymax', ymax)
//pts, 用dxAgr與dyAgr聚合提取點數據
let pts = aggregatePoints(ops, xmin, dxAgr, ymin, dyAgr, {
keyX,
keyY,
keyZ,
modePick,
})
// console.log('pts', take(pts, 5), size(pts))
//rg
let rg = await interp2Grid(pts, xmin, xmax, dx, ymin, ymax, dy, {
...opt, //須提供自定義參數給funKriging使用
funKriging,
funValid,
funAdjust,
returnGrid: true,
inverseKeyY: true,
})
// console.log('rg', rg)
// console.log('keys(rg)', keys(rg))
// keys(rg) [
// 'xnum', 'xmin', 'xmax',
// 'dx', 'ynum', 'ymin',
// 'ymax', 'dy', 'zmin',
// 'zmax', 'grds'
// ]
// console.log('rg.grds', rg.grds[0])
// rg.grds [
// 60.606247155177684, 62.92540214009434, 65.7312154911937, 68.9914947349822,
// 72.65919624422395, 76.67923534212574, 80.99475324860614, 85.55171796733839,
// ...
// ]
//save
rg.pts = pts
return rg
}
export default interp2Raster