export function getDistance2D(point1, point2) { return Math.sqrt( Math.pow(Number(point1.x) - Number(point2.x), 2) + Math.pow(Number(point1.y) - Number(point2.y), 2) ) } // 斜率slope:指的是点位阵列排列的每行斜率。计算方法:取考察点“上下左右”(注意与x轴、y轴方向无必然关系)的邻居,即与它最近的四个邻居,分别计算邻居与它的连线的斜率,限定斜率范围是[0, +Infinity),不符合则计算其负倒数。 export function computePointDistanceAndRowSlope(rawWholeData) { // return 0.36 const sampleNumber = Math.min(1000, rawWholeData.length) let pointDistance = null let rowSlope = null while((pointDistance === null) || (rowSlope === null)) { const distanceList = [] const rowSlopeList = [] for (let index = 0; index < sampleNumber; index++) { const sampleIdx = Math.floor(Math.random() * rawWholeData.length) const sample = rawWholeData[sampleIdx] for (const neighbourId of sample.ids.slice(0, 4)) { if (neighbourId !== "-1") { distanceList.push(getDistance2D(sample, rawWholeData[neighbourId - 1])) let rowSlopeTemp = null if (Math.abs(Number(sample.x) - Number(rawWholeData[neighbourId - 1].x)) <= Number.EPSILON) { rowSlopeTemp = 0 } else if ((Number(sample.x) - Number(rawWholeData[neighbourId - 1].x)) < 0) { rowSlopeTemp = -1 / (Number(sample.x) - Number(rawWholeData[neighbourId - 1].x)) } else { rowSlopeTemp = (Number(sample.y) - Number(rawWholeData[neighbourId - 1].y)) / (Number(sample.x) - Number(rawWholeData[neighbourId - 1].x)) } rowSlopeList.push(rowSlopeTemp) } } } if (distanceList.length) { let sum = 0 for (const distItem of distanceList) { sum += distItem } pointDistance = sum / distanceList.length } if (rowSlopeList.length) { let sum = 0 for (const rowSlopeItem of rowSlopeList) { sum += rowSlopeItem } rowSlope = sum / rowSlopeList.length } } console.log('pointDistance: ', pointDistance, 'rowSlope: ', rowSlope) return [pointDistance, rowSlope] } export function getNeighbourLocations(centerPointPos, pointDistance, rowSlope) { // 返回的位置列表中位置顺序: // posRight // posBottom // posLeft // posTop // posTopRight // posBottomRight // posBottomLeft // posTopLeft // 注意,方位的确定与x轴、y轴无直接关联,而是由点位阵列中的行列(或者说行的斜率)决定的。 const alpha = Math.atan(rowSlope) const posRight = { x: centerPointPos.x + pointDistance * Math.cos(alpha), y: centerPointPos.y + pointDistance * Math.sin(alpha), } const posBottom = { x: centerPointPos.x + pointDistance * Math.cos(Math.PI / 2 - alpha), y: centerPointPos.y - pointDistance * Math.sin(Math.PI / 2 - alpha), } const posLeft = { x: centerPointPos.x - pointDistance * Math.cos(alpha), y: centerPointPos.y - pointDistance * Math.sin(alpha), } const posTop = { x: centerPointPos.x - pointDistance * Math.cos(Math.PI / 2 - alpha), y: centerPointPos.y + pointDistance * Math.sin(Math.PI / 2 - alpha), } // 相当于right的top const posTopRight = { x: posRight.x - pointDistance * Math.cos(Math.PI / 2 - alpha), y: posRight.y + pointDistance * Math.sin(Math.PI / 2 - alpha), } // 相当于right的bottom const posBottomRight = { x: posRight.x + pointDistance * Math.cos(Math.PI / 2 - alpha), y: posRight.y - pointDistance * Math.sin(Math.PI / 2 - alpha), } // 相当于left的bottom const posBottomLeft = { x: posLeft.x + pointDistance * Math.cos(Math.PI / 2 - alpha), y: posLeft.y - pointDistance * Math.sin(Math.PI / 2 - alpha), } // 相当于left的top const posTopLeft = { x: posLeft.x + pointDistance * Math.cos(alpha), y: posLeft.y + pointDistance * Math.sin(alpha), } return { posRight, posBottom, posLeft, posTop, posTopRight, posBottomRight, posBottomLeft, posTopLeft, } }