无法获取轴上投影点的坐标 [英] Cannot get the coord of a projected point on an axis
问题描述
我正在尝试执行一个函数,该函数获取点位置和一条轴(一条线)并返回该点在轴上的投影.
I'm trying to do a function who take a point position and an axis (a line) and return the projection of the point on the axis.
- 点仅由
{x,y}
坐标 表示 - 轴由
f(x)= ax + b
线性函数表示(或对于垂直线,f(x)= C
)和a
的rad
值(其中0rad为右,然后顺时针旋转).因此axis = {a,b,rad}
或axis = {c,rad}
.
- Point are simply represented by
{x, y}
coords - Axis are represented by an
f(x) = ax + b
linear function (orf(x) = C
for vertical line) and therad
value for thea
(where 0rad is right, and turn clockwise). Soaxis = {a, b, rad}
oraxis = {c, rad}
.
使用毕达哥拉斯方法应该是一个简单的数学问题,但我无法找到正确的解决方案.投影总是朝着其他方向看(但要看得很远).
It should be a simple mathematical problem using Pythagorean but i cannot get the right solution.. Projections are always looking on the other directions (but look at the good distance).
代码演示:
我在 25; 100
上创建了一个黑点,并乘以彩色轴.每个轴都有一个相关的点(相同的颜色),它们代表暗点在其上的投影.灰色都是垂直和水平示例,都可以正常工作,但是其他3个轴(红色,绿色和蓝色)是错误的.
I create a dark point on 25;100
and multiples coloured axis. Every axis have a related point (same color) who represent the projection of the dark point on it. Both grey are vertical and horizontal examples and work well but 3 others axis (Red, Green and Blue) are wrong.
我尝试多次重做 getProjectionOnAxis
函数,甚至尝试通过测试所有可能性来获得良好的结果(通过逆变量,使用另一个cos/sin/tan函数)并尝试捕获我的那样的问题,但无能为力,我永远都不会取得好结果.
I tried to redo getProjectionOnAxis
function multiple times, and even try to get the good results by testing all possibility (by inverse vars, using another cos/sin/tan function) and try to catch my issue like that but nothing to do I never get the good result.
const point = {x:25, y:100};
const axis = [
{a: 1, b: 25, rad:Math.PI/4, rgb: '255,0,0'}, // 45deg
{a: -.58, b: 220, rad:Math.PI/6, rgb: '0,255,0'}, // -30deg
{a: 3.73, b: -50, rad:5*Math.PI/12, rgb: '0,0,255'}, // 75deg
// Gray
{c: 150, rad:Math.PI/2, rgb: '100,100,100'},
{b: 150, rad:0},
];
const execute = () => {
const canvas = document.getElementById('canvas');
const ctx = canvas.getContext('2d');
drawPoint({...point, rgb:'0,0,0', ctx});
axis.forEach(_axis => {
drawAxis({axis:_axis, rgb: _axis.rgb, ctx, canvas});
const projected = getProjectionOnAxis({...point, axis: _axis});
drawPoint({...projected, rgb:_axis.rgb, ctx});
});
}
// --- Issue come from here ---
const getProjectionOnAxis = ({x,y,axis}) => {
// On vertical axis |
if (axis.c) {
return { x: axis.c, y };
}
// On horizontal axis _
if (!axis.a) {
return { x, y: axis.b };
}
// Projected on axis but perpendicular to X axis
const projectedOnX = {
x,
y: axis.a * x + axis.b,
}
// The distance between both points is the hypothenus of the triangle:
// point, projectedOnAxis, projectedOnX
// where point <-> projectedOnX is the hypothenus
// and point angle is same that axis
const distCornerToProjectedOnX = Math.abs(y - projectedOnX.y);
const distCornerToProjectedOnAxis = distCornerToProjectedOnX * Math.cos(axis.rad);
const projectedVector = {
x: distCornerToProjectedOnAxis * Math.cos(axis.rad),
y: distCornerToProjectedOnAxis * Math.sin(axis.rad),
};
return {
x: x + projectedVector.x,
y: y + projectedVector.y,
};
}
// --- Draw Functions ---
// Not really important for the issue
const drawPoint = ({x,y,rgb, ctx}) => {
ctx.save();
ctx.translate(x, y);
ctx.beginPath();
ctx.fillStyle = `rgba(${rgb},1)`;
ctx.arc(0, 0, 2, 0, Math.PI*2, true);
ctx.closePath();
ctx.fill();
ctx.restore();
};
const drawAxis = ({axis, rgb, ctx, canvas}) => {
if (axis.c) {
// Vertical axis
drawLine({
from: {x: axis.c, y:0},
to: {x:axis.c, y:canvas.height},
rgb, ctx
});
}
else if (!axis.a) {
// Horizontal axis
drawLine({
from: {x:0, y:axis.b},
to: {x:canvas.width, y:axis.b},
rgb, ctx
});
}
else {
// ax + b (here a != 0)
let to = {
x: canvas.width,
y: axis.a * canvas.width + axis.b,
};
if (to.y < 0) {
to = {
x: axis.b / - axis.a,
y: 0,
}
}
drawLine({
from: {x:0, y:axis.b},
to,
rgb, ctx
});
}
}
const drawLine = ({
from, to, rgb=null, ctx
}) => {
ctx.save();
ctx.translate(from.x, from.y);
ctx.beginPath();
ctx.strokeStyle = `rgba(${rgb},1)`;
ctx.moveTo(0, 0);
ctx.lineTo(to.x - from.x, to.y - from.y);
ctx.stroke();
ctx.restore();
};
execute();
html, body, canvas { margin: 0; padding: 0;}
<canvas id="canvas" width="500" height="500"></canvas>
这是我应该得到的职位:
This is the positions I should get:
PS:我真的不喜欢我管理轴的方式,也许它们是另一种(简单的)方式吗?
PS: I don't really like the way I manage my axis, maybe they are another (simple) way to do it ?
推荐答案
以参数形式将线(您的轴)表示为基点 A
和单位方向向量 d =(dx,dy)
.它是通用的表示形式,适用于所有斜坡.如果相对于OX轴具有倾斜角 fi
,则 dx = cos(fi),dy = sin(fi)
Represent line (your axis) in parametric form as base point A
and unit direction vector d = (dx, dy)
. It is universal representation suitable for all slopes. If you have slope angle fi
relative to OX axis, then dx=cos(fi), dy=sin(fi)
L = P0 + d * t
然后将点 C
投影到直线上(使用标量积)
Then projection of point C
onto line is (using scalar product)
AC = C - A
P = A + d * (d.dot.AC)
在坐标
dotvalue = dx * (C.x - A.x) + dy * (C.y - A.y)
P.x = A.x + d.x * dotvalue
P.y = A.y + d.y * dotvalue
这篇关于无法获取轴上投影点的坐标的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!