javascript - 点の配列の補間
私は星座の境界を表す次のデータポイントを持っています。
let boundaries = [
{
ra: 344.46530375,
dec: 35.1682358
},
{
ra: 344.34285125,
dec: 53.1680298
},
{
ra: 351.45289375,
dec: 53.1870041
},
...
]
無関係ですが、これらはIAUの引用値から抽出されたものです。
しかし、これらの各点の間には、いわゆる「大円距離」または点iと点i+1の間の正距線距離が必要です。そのためには、指定された精度xで点iと点i+1の間を補間することができます。
私は次の関数を書きました。この関数はこの操作を実行できます(赤道座標系で行われることに注意する価値があります - デカルト座標系ではありません - そのため数学的には少し複雑ですが、大幅に複雑ではありません)。
2つの点の間を補間する関数は次の通りです(繁栄と安全のためにTypeScript ES6で記述されています):
/**
* getInterpolatedEquatorialCoordinates()
*
* @description This function takes in a start and end
* @param start EquatorialCoordinate
* @param end EquatorialCoordinate
* @param precision number
* @output returns the interpolated array of []EquatorialCoordinate points:
*/
export const getInterpolatedEquatorialCoordinates = (
start: EquatorialCoordinate,
end: EquatorialCoordinate,
precision: number
): Array<EquatorialCoordinate> => {
// The interpolated points array to return:
const points: Array<EquatorialCoordinate> = []
// Obtain the difference between the end coordinate's Right Ascension, RA, and the start coordinate's RA:
let nra = ((end.ra - start.ra)) % 360
if (nra > 180) nra = nra - 360
if (nra < -180) nra = nra + 360
// Obtain the "gradient" rate of change of RA:
const dra: number = nra / precision
// Obtain the difference between the end coordinate's Declination, dec, and the start coordinate's dec:
const ndec = ((end.dec - start.dec))
// Obtain the "gradient" rate of change of dec:
const ddec: number = ndec / precision
let i = 0
// Obtain the interpolated EquatorialCoordinate points for each step:
while (i < precision) {
i++
points.push({
ra: start.ra + (dra * i),
dec: start.dec + (ddec * i)
})
}
return points
}
私はこれを上記のboundariesの最初の二つの点の間でテストスイートにかけて、その数学的な妥当性を得ました:
test('getInterpolatedEquatorialCoordinates', function () {
const start = {
ra: 344.46530375,
dec: 35.1682358
}
const end = {
ra: 344.34285125,
dec: 53.1680298
}
const minRA = Math.min(start.ra, end.ra)
const minDec = Math.min(start.dec, end.dec)
const maxRA = Math.max(start.ra, end.ra)
const maxDec = Math.max(start.ra, end.ra)
const precision = 10
const points = getInterpolatedEquatorialCoordinates(start, end, precision)
const isRAAboveLowerThreshold = (
p: EquatorialCoordinate
) => p.ra >= minRA
const isRABelowUpperThreshold = (
p: EquatorialCoordinate
) => p.ra <= maxRA
const isDecAboveLowerThreshold = (
p: EquatorialCoordinate
) => p.dec >= minDec
const isDecBelowUpperThreshold = (
p: EquatorialCoordinate
) => p.dec <= maxDec
expect(points.length).toBeGreaterThan(0)
expect(points.length).toBe(precision)
expect(points.every(isRAAboveLowerThreshold)).toBe(true)
expect(points.every(isRABelowUpperThreshold)).toBe(true)
expect(points.every(isDecAboveLowerThreshold)).toBe(true)
expect(points.every(isDecBelowUpperThreshold)).toBe(true)
})
補間された出力点は次の通りです:
[
{ ra: 344.4530585, dec: 36.968215199999996 },
{ ra: 344.44081324999996, dec: 38.7681946 },
{ ra: 344.428568, dec: 40.568174 },
{ ra: 344.41632275, dec: 42.3681534 },
{ ra: 344.40407749999997, dec: 44.168132799999995 },
{ ra: 344.39183225, dec: 45.9681122 },
{ ra: 344.379587, dec: 47.7680916 },
{ ra: 344.36734175000004, dec: 49.568071 },
{ ra: 344.3550965, dec: 51.3680504 },
{ ra: 344.34285125, dec: 53.1680298 }
]
これは、私が満足する程度の精度であれば、どの精度でもうまく機能するようです。また、どの「方向」に進んでいるかに関係なく動作します。
質問:
今私がやりたいのは、上記の boundaries 配列のすべての点にこれを適用し、すべての点を一つにまとめた新しい配列を返すことです…
これを達成する最良の方法は何でしょうか?私はArray.prototype.mapメソッドを使おうとしましたが、まったく成功しませんでした…
次の「boundaries」について、期待される出力は以下の通りです。
let boundaries = [
{
ra: 344.46530375,
dec: 35.1682358
},
{
ra: 344.34285125,
dec: 53.1680298
},
...
]
let desiredOutput = [
{
ra: 344.46530375,
dec: 35.1682358
}, // Original Index 0
// Start Interpolated Intermediary Values
{
ra: 344.4530585,
dec: 36.968215199999996
},
{
ra: 344.44081324999996,
dec: 38.7681946
},
{
ra: 344.428568,
dec: 40.568174
},
{
ra: 344.41632275,
dec: 42.3681534
},
{
ra: 344.40407749999997,
dec: 44.168132799999995
},
{
ra: 344.39183225,
dec: 45.9681122
},
{
ra: 344.379587,
dec: 47.7680916
},
{
ra: 344.36734175000004,
dec: 49.568071
},
{
ra: 344.3550965,
dec: 51.3680504
},
{
ra: 344.34285125,
dec: 53.1680298
},
// End Interpolated Intermediary Values
{
ra: 344.34285125,
dec: 53.1680298
}, // Original Index 1
...
]
回答 #1
私はここで使用するのにArray.reduce()が最適なツールだと思います。
境界の配列と精度を受け取り、希望する赤道座標の配列を出力する関数を書くことができます。
const fillInBoundryPoints = (boundaries: EquatorialCoordinate[], precision: number) => {
return boundaries.reduce((acc, cur, i, arr) => {
if (i < arr.length - 1) {
acc.push(cur)
acc.push(...getInterpolatedEquatorialCoordinates(cur, arr[i + 1], precision))
}
return acc
}, [] as EquatorialCoordinate[])
}
あなたが次のように使用するもの:
const precision = 10
const boundaries: EquatorialCoordinate[] = [
{
ra: 344.46530375,
dec: 35.1682358
},
{
ra: 344.34285125,
dec: 53.1680298
}
]
const desiredOutput = fillInBoundryPoints(boundaries, precision)
出力 :
[
{ ra: 344.46530375, dec: 35.1682358 },
{ ra: 344.4530585, dec: 36.968215199999996 },
{ ra: 344.44081324999996, dec: 38.7681946 },
{ ra: 344.428568, dec: 40.568174 },
{ ra: 344.41632275, dec: 42.3681534 },
{ ra: 344.40407749999997, dec: 44.168132799999995 },
{ ra: 344.39183225, dec: 45.9681122 },
{ ra: 344.379587, dec: 47.7680916 },
{ ra: 344.36734175000004, dec: 49.568071 },
{ ra: 344.3550965, dec: 51.3680504 },
{ ra: 344.34285125, dec: 53.1680298 }
]
回答 #2
あなたはmapを使うこともできますが、このシナリオにはreduceの方が自然に適しています
boundaries.reduce((a,p,i,arr) => {
if ( i > 0 ) {
a.push(getInterpolatedEquatorialCoordinates(arr[i-1], p, precision))
}
return a;
}, [])
注意: 前の値を参照する代わりに map ケースを使用する場合は、先読みする必要がありますが、最後に undefined が生成されるため、それを切り取る必要があります
