给定两个点(x1,y1)(x2,y2),如何计算均匀位于给定点之间的线上的N个不同点

时间:2015-07-09 09:12:04

标签: c++ math geometry line point

我有两点,我想在给定线创建的线的顶部计算n个均匀分布的点。我怎么能在c ++中执行此操作?

4 个答案:

答案 0 :(得分:6)

Linear interpolation(图形社区亲切地称为 lerp )就是您想要的。给定端点,它可以使用参数t生成位于其间的点。

让结束点为A (Ax, Ay)B (Bx, By)。从AB的向量将由

给出
V = B − A = <Vx, Vy>
L(t) = A + tV

这实际上意味着从点A开始,我们使用标量V缩放向量t;点A被这个缩放的矢量所取代,因此我们得到的点取决于参数t的值。在t = 0时,我们会返回A,如果t = 1我们得到B,如果是0.5,我们会得到AB之间的中间点{1}}。

line A----|----|----|----B
   t 0    ¼    ½    ¾    1

适用于任何线路(坡度无关紧要)。现在出现N停止的问题。如果您需要N为10,那么t 1/N会因t = i/10而异,所以i,其中i = 0, t = 0 i = 1, t = 0.1 i = 2, t = 0.2 ⋮ i = 9, t = 0.9 i = 10, t = 1.0 将是循环迭代器。< / p>

#include <iostream>

struct Point {
    float x, y;
};

Point operator+ (Point const &pt1, Point const &pt2) {
    return { pt1.x + pt2.x, pt1.y + pt2.y };
}

Point operator- (Point const &pt1, Point const &pt2) {
    return { pt1.x - pt2.x, pt1.y - pt2.y };
}

Point scale(Point const &pt, float t) {
    return { pt.x * t, pt.y * t };
}

std::ostream& operator<<(std::ostream &os, Point const &pt) {
    return os << '(' << pt.x << ", " << pt.y << ')';
}

void lerp(Point const &pt1, Point const &pt2, float stops) {
    Point const v = pt2 - pt1;
    float t = 0.0f;
    for (float i = 0.0f; i <= stops; ++i) {
        t = i / stops;
        Point const p = pt1 + scale(v, t);
        std::cout << p << '\n';
    }
}

int main() {
    lerp({0.0, 0.0}, {5.0f, 5.0f}, 5.0f);
}

这是实现它的一种方法:

(0, 0)
(1, 1)
(2, 2)
(3, 3)
(4, 4)
(5, 5)

输出

t

除了

请注意,每次迭代Δt = 1 / N都会增加t。因此,在循环中更新t₀ = 0 t₁ = t₀ + Δt t₂ = t₁ + Δt ⋮ t₉ = t₈ + Δt t₁₀ = t₉ + Δt 的另一种方法是

{{1}}

但是,这不是很可并行化,因为循环的每次迭代都取决于前一次迭代。

答案 1 :(得分:2)

您可以使用以下ConcurrentHashMapgive_uniform_points_between(M, N, num_points)#num_points之间提供多个M点。我假设这条线不是垂直的(如果线可以是垂直的,请参见下文)。

N

演示: Live on Coliru

结果是:

  

( - 3,9);( - 2.3,7.6);( - 1.6,6.2);( - 0.9,4.8);( - 0.2,3.4);(0.5,2);(1.2,0.6); (1.9,-0.8);(2.6,-2.2);(3.3,-3.6);

<强>解释

从两个点std::vector<Point> give_uniform_points_between(const Point& M, const Point& N, const unsigned num_points) { std::vector<Point> result; // get equation y = ax + b float a = (N.y - M.y) / (N.x - M.x); float b = N.y - a * N.x; float step = std::fabs(M.x - N.x) / num_points; for (float x = std::min(M.x, N.x); x < std::max(M.x, N.x); x += step) { float y = a*x+b; result.push_back(Point{x,y}); } return result; } (x1,y1),你可以猜出通过这些点的线方程。

如果您不能有垂直线,则此等式采用(x2,y2)a*x + b*y + c = 0形式 其中y = a*x + b,你推导出如代码所示的b。

然后,您可以沿着您的线路改变a = (y2 - y1) / (x2 - x1)x,从最小值坐标开始。

您找到的所有这些y点都在您的行上并且应该统一分发(感谢固定的(x,y))。

答案 2 :(得分:1)

将行视为(x1,y1)+λ(x2-x1,y2-y1),即第一个点,再加上它们之间的向量的倍数。

当λ= 0时,您有第一个点,当λ= 1时,您有第二个点。 所以你只想在0和1之间取n个均匀分布的λ值。

你如何做到这一点取决于你的意思是:是否包括终点?

例如,你可以取λ= 0 /(n-1),λ= 1 /(n-1),λ= 2 /(n-1),......λ=(n-1)/( N-1)。 这将给出n个均匀分布的点,包括端点。

或者你可以取λ= 1 /(n + 1),λ= 2 /(n + 1),......λ= n /(n + 1)。 这将给出n个均匀分布的点,不包括端点。

答案 3 :(得分:0)

虽然数学不太好......

vector<Rect> Utils::createReactsOnLine(Point pt1, Point pt2, int numRects, int height, int width){

    float x1 = pt1.x;
    float y1 = pt1.y;
    float x2 = pt2.x;
    float y2 = pt2.y;

    float x_range = std::abs(x2 - x1);
    float y_range = std::abs(y2 - y1);

    // Find center points of rects on the line
    float x_step_size = x_range / (float)(numRects-1);
    float y_step_size = y_range / (float)(numRects-1);

    float x_min = std::min(x1,x2);
    float y_min = std::min(x1,x2);
    float x_max = std::max(x1,x2);
    float y_max = std::max(x1,x2);

    cout << numRects <<  endl;
    float next_x = x1;
    float next_y = y1;
    cout << "Next x, y: "<< next_x << "," <<  next_y <<  endl;
    for(int i = 0; i < numRects-1; i++){
        if (x1 < x2)
            next_x = next_x + x_step_size;
        else
            next_x = next_x - x_step_size;

        if (y1 < y2)
            next_y = next_y + y_step_size;
        else
            next_y = next_y - y_step_size;

        cout << "Next x, y: "<< next_x << "," <<  next_y <<  endl;
    }
    return vector<Rect>();
}