无法获取轴上投影点的坐标 [英] Cannot get the coord of a projected point on an axis

查看:43
本文介绍了无法获取轴上投影点的坐标的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试执行一个函数,该函数获取点位置和一条轴(一条线)并返回该点在轴上的投影.

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 (or f(x) = C for vertical line) and the rad value for the a (where 0rad is right, and turn clockwise). So axis = {a, b, rad} or axis = {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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆