【问题标题】:Reflection end point of intersecting two lines两条线相交的反射终点
【发布时间】:2021-08-25 06:00:14
【问题描述】:

如何计算相交两条线的反弹终点?

当给定以下两条线时,我能够使用以下函数计算两条线的交点。

export function intersection(line1, line2) {
  line1.y1 *= -1; line1.y2 *= -1; // for Webpage coordinates
  line2.y3 *= -1; line2.y4 *= -1; // for Webpage coordinates

  const [x1, y1, x2, y2] = line1;
  const [x3, y3, x4, y4] = line2;

  const  [a1, b1, c1] = [y2 - y1, x1 - x2, x2 * y1 - x1 * y2];
  if ( a1 === 0 && b1 === 0 ) return 'line1 does not have length';

  const [a2, b2, c2] = [y4 - y3, x3 - x4, x4 * y3 - x3 * y4];
  if ( a2 === 0 && b2 === 0 ) return 'line2 does not have length';
  
  const denom = a1 * b2 - a2 * b1;
  if (denom === 0) return 'lines are parallel';

  const x = (b1 * c2 - b2 * c1) / denom;   // (x,y) is the intersection
  const y = (a2 * c1 - a1 * c2) / denom;

  // check if two lines are actually crossing w/o extending it
  function getDist(x1, y1, x2, y2) {
    return Math.sqrt((x1 - x2) ** 2 + (y1 - y2) ** 2);
  }
  const distLine1 = getDist(x1, y1, x2, y2);
  const distLine2 = getDist(x3, y3, x4, y4);
  const distToXY1  = Math.max(getDist(x1, y1, x, y), getDist(x2, y2, x, y)) ;
  const distToXY2  = Math.max(getDist(x3, y3, x, y), getDist(x4, y4, x, y)) ;
  if (distToXY1 > distLine1 || distToXY2 > distLine2) 
    return 'lines does not meet';

  return {x, y};
}

演示:https://stackblitz.com/edit/intersection-of-two-lines?file=index.js

但是,我正在努力使用两条线找到两条线的反弹位置(或反射点)。

从line1(x1, x2, y1, y2)和line2(x1, x2, y1, y2)得到x/y位置的公式是什么?

【问题讨论】:

  • 你必须得到与你击中的那条垂直的线,并且另一边与那条线的角度相同
  • 就像在 3D 图形中反映法线
  • 类似...函数 reflectLines(x,y,x2,y2,xx,yy,xx2,yy2){var slope1=(y-y2)/(x-x2);var slope2 =(yy-yy2)/(xx-xx2);var angleFromOrigin=Math.asin(slope1); var angleFromOrigin2=Math.asin(slope2);var reciprical=1.0/(slope1);var reciprical2=1.0/(slope2);var angleToReciprical=Math.acos(reciprical/slope1);var angleToReciprical2=Math.acos(reciprical2/slope2 );var newSlope=sin(angleFromOrigin2+Math.rad(90)+angleToReciprical); var newSlope2=sin(angleFromOrigin+Math.rad(90)+angleToReciprical2);return [newSlope,newSlope2];} 我可能混淆了我的一些数学但类似的东西。

标签: javascript math


【解决方案1】:

您必须将“墙内”的红色矢量部分拆分为两个分量,一个与墙平行,另一个与墙垂直。然后你否定垂直分量并将它们重新加在一起。

class Line {
  constructor(x1, y1, x2, y2) {
    this.x1 = x1;
    this.y1 = y1;
    this.x2 = x2;
    this.y2 = y2;
    this.dx = x2 - x1;
    this.dy = y2 - y1;
  }
  intersect(o) {
    const d = this.dy * o.dx - this.dx * o.dy;
    if (d === 0) return null; // parallel
    const k = ((o.y1 - this.y1) * o.dx + (this.x1 - o.x1) * o.dy) / d;
    return {
      x: this.x1 + k * this.dx,
      y: this.y1 + k * this.dy
    };
  }
  bounce(o) {
    const i = this.intersect(o);
    if (!i) return null;
    // vector from intersection to end
    const v = {
      x: this.x2 - i.x,
      y: this.y2 - i.y
    };
    // split v into two perpendicular vectors, one parallel to o
    // the perpendicular one is o's direction rotated by 90°
    const p = { x: o.dy, y: -o.dx };
    // v.x = a * o.dx + b * p.x
    // v.y = a * o.dy + b * p.y
    // division by zero is impossible since o and p are perpendicular
    const a = (v.y * p.x - v.x * p.y) / (o.dy * p.x - o.dx * p.y);
    const b = (v.y * o.dx - v.x * o.dy) / (p.y * o.dx - p.x * o.dy);
    // negate b to mirror end of line on o
    return {
        x: i.x + a * o.dx - b * p.x,
      y: i.y + a * o.dy - b * p.y
    }
  }
}

const l1 = new Line(100, 300, 400, 100);
const l2 = new Line(100, 100, 400, 300);
console.log(l1.bounce(l2));

【讨论】:

【解决方案2】:

我想我已经接近答案了。

这是我的方法

  1. 从 line2 的交点和末端获取一个垂直的交汇点。
  2. 画一条线(起点:line2的终点,终点:垂直交汇点),然后将直线延伸两倍,得到终点。

https://stackblitz.com/edit/intersection-of-two-lines-nes7zy?view=preview

在演示中,这种方法看起来不错,如果数学专家可以确认这种方法,将不胜感激。

// https://stackoverflow.com/a/1811636/454252
function getPerpendicularPoint(iPoint, line1, line2) {
  const [x1, y1] = [iPoint.x, iPoint.y]; // start point
  const [x2, y2] = [line1[2], line1[3]]; // baseline end point
  const [x3, y3] = [line2[2], line2[3]]; // extended line end point

  const k = ((y2-y1) * (x3-x1) - (x2-x1) * (y3-y1)) / ((y2-y1)**2 + (x2-x1)**2);
  const x4 = x3 - k * (y2-y1);
  const y4 = y3 + k * (x2-x1);
  return {x: x4, y: y4};
}

//http://www.java2s.com/Tutorials/Javascript/Canvas_How_to/Shape/Extend_a_line_before_and_after_original_endpoints.htm
function getExtendedPoint(startPt, endPt, extent) {
  var dx = endPt.x - startPt.x;
  var dy = endPt.y - startPt.y;
  var x = startPt.x + dx * extent;
  var y = startPt.y + dy * extent;
  return {x, y};
}

let line1 = [100, 100, 400, 300];
let line2 = [100, 300, 400, 100];

const iPoint = {x: 250, y: 200}; // intersection(line1, line2);
const pPoint = getPerpendicularPoint(iPoint, line1, line2);
const ePoint = getExtendedPoint({x:line2[2], y:line2[3]}, pPoint, 2);

console.log(pPoint, ePoint);

【讨论】:

    猜你喜欢
    • 2011-02-25
    • 1970-01-01
    • 1970-01-01
    • 2011-01-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多