我想知道如何找到以下點的坐標如果我知道前兩個點和到下一個點的距離。例如:
-----P1------P2----d---P3-----
資料:
- P1:
{ x: 0, y: 1 } - P2:
{ x: 2, y: 1 } - d:
2
搜索:
- P3:
x3?,y3?
對于此示例,結果將為 P3: { x: 4, y: 1 }。這是一個簡單的計算。當 P1 和 P2 在不同象限時,事情變得復雜,跟隨點的方向正在改變或線在一些傾斜角度下(為此我還沒有任何測驗)。
所有這些可能性都可以通過下圖來描述(不包括在某些傾斜角度下的線條):

現在,我最終得到了這樣的演算法:
interface Coordinates {
x: number,
y: number,
}
function getCoordinatesOfFollowingPointInDistanceToLastPointOnLine (p1: Coordinates, p2: Coordinates,
distance: number): Coordinates {
const lineSlope = (p2.y - p1.y) / (p2.x - p1.x);
const lineTiltAngle = Math.atan(lineSlope);
const p3x = Math.abs(p1.x) Math.abs(p2.x) > Math.abs(p1.x)
? p2.x distance * Math.cos(lineTiltAngle)
: p2.x - distance * Math.cos(lineTiltAngle);
const p3y = Math.abs(p1.y) Math.abs(p2.y) > Math.abs(p1.y)
? p2.y distance * Math.sin(lineTiltAngle)
: p2.y - distance * Math.sin(lineTiltAngle);
return {
x: Number(p3x.toFixed(3)),
y: Number(p3y.toFixed(3))
};
}
我已經測驗了我的演算法,但它在某些情況下不起作用(當線是水平的并且跟隨點在-∞方向時)。所有測驗如下所示:
getCoordinatesOfFollowingPointInDistanceToLastPointOnLine
Orientation Horizontal
Following point in ∞ direction
√ should calculate correctly position of P3 if P1 and P2 are in I quadrant (2 ms)
√ should calculate correctly position of P3 if P1 and P2 are in II quadrant (1 ms)
√ should calculate correctly position of P3 if P1 and P2 are in III quadrant
√ should calculate correctly position of P3 if P1 and P2 are in IV quadrant (1 ms)
√ should calculate correctly position of P3 if P1 in quadrant II and P2 in quadrant I (1 ms)
√ should calculate correctly position of P3 if P1 in quadrant IV and P2 in quadrant III (4 ms)
Following point in -∞ direction
× should calculate correctly position of P3 if P1 and P2 are in I quadrant (4 ms)
× should calculate correctly position of P3 if P1 and P2 are in II quadrant (1 ms)
× should calculate correctly position of P3 if P1 and P2 are in III quadrant (1 ms)
× should calculate correctly position of P3 if P1 and P2 are in IV quadrant
× should calculate correctly position of P3 if P1 in quadrant I and P2 in quadrant II
× should calculate correctly position of P3 if P1 in quadrant III and P2 in quadrant IV (1 ms)
Orientation Vertical
Following point in ∞ direction
√ should calculate correctly position of P3 if P1 and P2 are in I quadrant
√ should calculate correctly position of P3 if P1 and P2 are in II quadrant
√ should calculate correctly position of P3 if P1 and P2 are in III quadrant (1 ms)
√ should calculate correctly position of P3 if P1 and P2 are in IV quadrant
√ should calculate correctly position of P3 if P1 in quadrant IV and P2 in quadrant I
√ should calculate correctly position of P3 if P1 in quadrant III and P2 in quadrant II (1 ms)
Following point in -∞ direction
√ should calculate correctly position of P3 if P1 and P2 are in I quadrant (1 ms)
√ should calculate correctly position of P3 if P1 and P2 are in II quadrant
√ should calculate correctly position of P3 if P1 and P2 are in III quadrant
√ should calculate correctly position of P3 if P1 and P2 are in IV quadrant
√ should calculate correctly position of P3 if P1 in quadrant I and P2 in quadrant IV (1 ms)
√ should calculate correctly position of P3 if P1 in quadrant II and P2 in quadrant III
測驗代碼:
// Orientation Horizontal -> Following point in ∞ direction
test('should calculate correctly position of P3 if P1 and P2 are in I quadrant', () => {
const p1: Coordinates = { x: 0, y: 1 };
const p2: Coordinates = { x: 2, y: 1 };
const p3 = getCoordinatesOfFollowingPointInDistanceToLastPointOnLine(p1, p2, 2);
expect(p3.x).toBe(4);
expect(p3.y).toBe(1);
});
// Orientation Horizontal -> Following point in -∞ direction
test('should calculate correctly position of P3 if P1 and P2 are in I quadrant', () => {
const p1: Coordinates = { x: 2, y: 1 };
const p2: Coordinates = { x: 1, y: 1 };
const p3 = getCoordinatesOfFollowingPointInDistanceToLastPointOnLine(p1, p2, 2);
expect(p3.x).toBe(-1);
expect(p3.y).toBe(1);
});
// Orientation Vertical -> Following point in ∞ direction
test('should calculate correctly position of P3 if P1 and P2 are in I quadrant', () => {
const p1: Coordinates = { x: 1, y: 1 };
const p2: Coordinates = { x: 1, y: 2 };
const p3 = getCoordinatesOfFollowingPointInDistanceToLastPointOnLine(p1, p2, 2);
expect(p3.x).toBe(1);
expect(p3.y).toBe(4);
});
// Orientation Vertical -> Following point in ∞ direction
test('should calculate correctly position of P3 if P1 and P2 are in I quadrant', () => {
const p1: Coordinates = { x: 1, y: 2 };
const p2: Coordinates = { x: 1, y: 1 };
const p3 = getCoordinatesOfFollowingPointInDistanceToLastPointOnLine(p1, p2, 2);
expect(p3.x).toBe(1);
expect(p3.y).toBe(-1);
});
我可以添加一個if來檢測這種情況,但是如果線處于某個傾斜角度下怎么辦,那么這將很難決定如何計算下一點的坐標。所以,問題是:我的演算法應該如何讓它始終作業?
更新 1
我已經嘗試過@Andreas鏈接的演算法如何找到給定的第三點(直線上的2個點)和(從第三點到第一點的距離),但除非我做錯了什么,否則它對我不起作用。您可以在下面找到我是如何實作的:
function getCoordinatesOfFollowingPointInDistanceToLastPointOnLine (p1: Coordinates, p2: Coordinates,
distance: number): Coordinates {
const p1P2Distance = Math.sqrt((p2.x - p1.x) ** 2 (p2.y - p1.y) ** 2);
const xDirectionLength = (p2.x - p1.x) / p1P2Distance;
const yDirectionLength = (p2.y - p1.y) / p1P2Distance;
const p3x = p1.x distance * xDirectionLength;
const p3y = p1.y distance * yDirectionLength;
return {
x: Number(p3x.toFixed(3)),
y: Number(p3y.toFixed(3))
};
}
uj5u.com熱心網友回復:
我在評論中提到的問題中的公式有效。
您的更新計算P3自P1( p1.x ..., p1.y ...) 但它應該來自P2
我已經用陣列替換了你的測驗和物件,但公式是一樣的。
我不得不**用“舊”替換,Math.pow()否則第四次測驗會失敗,因為(p2.y - p1.y) ** 2結果是NaN.
(~~用于獲取整數而不是浮點數)
const testCases = [
/* P1, P2, distance, P3 */
[[0, 1], [2, 1], 2, [ 4, 1]],
[[2, 1], [1, 1], 2, [-1, 1]],
[[1, 1], [1, 2], 2, [ 1, 4]],
[[1, 2], [1, 1], 2, [ 1, -1]]
];
function getP3(p1, p2, distance) {
const p1p2d = Math.sqrt(Math.pow(p2[0] - p1[0], 2) Math.pow(p2[1] - p1[1], 2));
const dx = (p2[0] - p1[0]) / p1p2d;
const dy = (p2[1] - p1[1]) / p1p2d;
const p3x = p2[0] distance * dx;
const p3y = p2[1] distance * dy;
return [~~p3x, ~~p3y];
}
testCases.forEach(({0: p1, 1: p2, 2: d, 3: e}) => {
const p3 = getP3(p1, p2, d);
console.log(p3, e, p3[0] == e[0], p3[1] == e[1]);
})
轉載請註明出處,本文鏈接:https://www.uj5u.com/yidong/375607.html
標籤:javascript 打字稿 算法 三角学
