1

我可以很容易地计算出两条线的交点。如果我从两个顶点开始:

(x1,y1)
(x2,y2)

我可以通过做计​​算斜率(y1-y2)/(x1-x2),然后计算截距

y1 - slope * x1

然后再做一次,所以我必须设置斜率和截距,然后这样做:

x = (intercept2 - intercept1) / (slope1 - slope2)
y = slope1 * x + intercept1
(免责声明:这甚至可能不起作用,但我已经得到了一些非常接近它的东西,它说明了我的一般技术)

这只适用于小数或非整数的数据类型。说顶点是:

(0,1)
(10,2)

计算斜率会导致(1-2)/(0-10),哪个-1/-10不是1/10,哪个是0

如何获得仅使用整数产生有效结果的代码?

编辑:我根本不能使用花车. 没有铸造,什么都没有。此外,值的上限为 65535。而且一切都是无符号的。

4

4 回答 4

3

高中减分数时,我们的老师教我们找到一个共同的分母

所以 1/4 - 1/6 = 3/12 - 2/12 = 1/12

所以对你的斜坡做同样的事情。

int slope1 = n1 / d1;  // numerator / denominator
int slope2 = n2 / d2;
// All divisions below should have 0 for remainder
int g = gcd( d1, d2 ); // gcd( 4, 6 ) = 2
int d = d1 * d2 / g; // common denominator (12 above)
int n = (d/d1) * n1 - (d/d2) * n2; // (1 in 1/12 above)
// n1/d1 - n2/d2 == n/d

我希望我做对了。

于 2014-01-20T00:58:23.523 回答
0

嗯..
(0,1)
(10,2)
和 (y1-y2)/(x1-x2)。嗯,这是对一条线的描述,而不是
两条线的交点。
据我所知,线条以 x * v 的形式描述,其中 x 是一个标量,v 是一个
向量。然后是
x * (0,1) = v2 和
x * (10, 2) = v2。
因此,只有当两个方程都存在一个解时,这些线才会相交,
当有无穷多个解时它们会重叠,并且当它们
平行时不会相交。
http://www.gamedev.net/topic/647810-intersection-point-of-two-vectors/
解释了基于点积的计算。

于 2014-01-20T01:06:41.617 回答
0

输入: 线 L 穿过(x1, y1)(x2, y2), 线 M 穿过(X1, Y1)(X2, Y2)

输出:(x, y)两条线L和M的交点

告诉 Wolfram Alphasolve y = (y1-y2)/(x1-x2)*(x-x1)+y1 and y = (Y1-Y2)/(X1-X2)*(x-X1)+Y1 for x, y得到这个解决方案:

但我不知道如何编写一个程序来为你的计算器实现上述解决方案,只使用uint16_tALU。

于 2014-01-20T05:18:18.627 回答
0

感谢 Graham Toal 的回答,下面是他们回答中链接 C 代码的原始 Rust 实现,修改为返回整条线的交点,而不是线段。它没有使用太多特定于 Rust 的魔法,因此应该很容易移植到其他语言。

该函数返回一个s 相交的Point地方Line,如果有的话,以及一个标志,表示交点是否位于两条相交的线上 ( true) 或不在 ( false) 上。

/// 2D integer point
struct Point {
    /// The x coordinate.
    pub x: i32,

    /// The y coordinate.
    pub y: i32,
}

/// Line primitive
struct Line {
    /// Start point
    pub start: Point,

    /// End point
    pub end: Point,
}

/// Check signs of two signed numbers
///
/// Fastest ASM output compared to other methods. See: https://godbolt.org/z/zVx9cD
fn same_signs(a: i32, b: i32) -> bool {
    a ^ b >= 0
}

/// Integer-only line segment intersection
///
/// If the point lies on both line segments, the second tuple argument will return `true`.
///
/// Inspired from https://stackoverflow.com/a/61485959/383609, which links to
/// https://webdocs.cs.ualberta.ca/~graphics/books/GraphicsGems/gemsii/xlines.c
fn intersection(l1: &Line, l2: &Line) -> Option<(Point, bool)> {
    let Point { x: x1, y: y1 } = l1.start;
    let Point { x: x2, y: y2 } = l1.end;
    let Point { x: x3, y: y3 } = l2.start;
    let Point { x: x4, y: y4 } = l2.end;

    // First line coefficients where "a1 x  +  b1 y  +  c1  =  0"
    let a1 = y2 - y1;
    let b1 = x1 - x2;
    let c1 = x2 * y1 - x1 * y2;

    // Second line coefficients
    let a2 = y4 - y3;
    let b2 = x3 - x4;
    let c2 = x4 * y3 - x3 * y4;

    let denom = a1 * b2 - a2 * b1;

    // Lines are colinear
    if denom == 0 {
        return None;
    }

    // Compute sign values
    let r3 = a1 * x3 + b1 * y3 + c1;
    let r4 = a1 * x4 + b1 * y4 + c1;

    // Sign values for second line
    let r1 = a2 * x1 + b2 * y1 + c2;
    let r2 = a2 * x2 + b2 * y2 + c2;

    // Flag denoting whether intersection point is on passed line segments. If this is false,
    // the intersection occurs somewhere along the two mathematical, infinite lines instead.
    //
    // Check signs of r3 and r4.  If both point 3 and point 4 lie on same side of line 1, the
    // line segments do not intersect.
    //
    // Check signs of r1 and r2.  If both point 1 and point 2 lie on same side of second line
    // segment, the line segments do not intersect.
    let is_on_segments = (r3 != 0 && r4 != 0 && same_signs(r3, r4))
        || (r1 != 0 && r2 != 0 && same_signs(r1, r2));

    // If we got here, line segments intersect. Compute intersection point using method similar
    // to that described here: http://paulbourke.net/geometry/pointlineplane/#i2l

    // The denom/2 is to get rounding instead of truncating. It is added or subtracted to the
    // numerator, depending upon the sign of the numerator.
    let offset = if denom < 0 { -denom / 2 } else { denom / 2 };

    let num = b1 * c2 - b2 * c1;
    let x = if num < 0 { num - offset } else { num + offset } / denom;

    let num = a2 * c1 - a1 * c2;
    let y = if num < 0 { num - offset } else { num + offset } / denom;

    Some((Point::new(x, y), is_on_segments))
}
于 2020-07-09T16:40:21.417 回答