给定一组带有线段的点,找到等距的点

Posted

技术标签:

【中文标题】给定一组带有线段的点,找到等距的点【英文标题】:Finding equally spaced points given a set of points with line segments in between 【发布时间】:2021-03-10 06:50:30 【问题描述】:

我目前正在编写地图,并试图将街道段分成相等的部分。如果街道段是直的,只需将街道段的长度除以您想要的任何因素即可。然而,弯曲的街道更难分成相等的部分,因为它们由多个部分组成。我想要做的是找出一种方法将街道段分成相等的点,不管它有多弯曲,或者每段有多长。我尝试参数化曲线以使其工作,但它仍然不起作用。要了解我所说的参数化是什么意思,请查看this。

目前,这就是我目前正在实施的方式。

        //street_seg_length is length of the ith street segment
        for (double j = 0.0; j < street_seg_length[i]; j+=inc)  
        
        double rem = j - int(j);
        //A street segment can be split up into multiple curve points. 
        //The more curve points, the curvier a road is
        LatLon from = curve_points_pos[i][int(j)];
        LatLon to = curve_points_pos[i][int(j)+1];
        //Returns cartesian coordinates from latitude and longitude of nth and n+1th curve point
        double x1 = x_from_lon(from.longitude());
        double y1 = y_from_lat(from.latitude());
        double x2 = x_from_lon(to.longitude());
        double y2 = y_from_lat(to.latitude());
        //arrowX, arrowY are supposed to be the coordinates of a point between 2 curve points
        double arrowX = (1 - rem)*x1 + rem*x2;
        double arrowY = (1 - rem) * y1 + rem * y2;
        
         
         
        
        
    

rem 是上篇文章中讨论的余数,j 与上篇文章中的 t 值相同,p 是第 n 个点,q 是上篇文章中讨论的第 n+1 个点。

有人可以解释我可以做些什么来实现这一目标或我做错了什么吗?我想在街段上找到等距的点,不管它有多弯曲。我是否正确遵循链接帖子中的算法?我相信我是,但很明显算法是错误的,或者我没有正确实现它,后者更有可能。

【问题讨论】:

您有问题吗? @MOehm 对不起,我猜有点含糊。我用我的问题更新了帖子的结尾。 double arrowX = (1 - rem)*x1 + rem*x2; 在这里,您希望rem 是介于01 之间的数字,其中rem = 0 表示arrowX = x1rem = 1 表示arrowX = x2。也许像rem = j / street_seg_length[i]; 这样的东西虽然没有足够的上下文可以确定,但几乎可以肯定不是rem = j - int(j); 是的,不清楚inc 是什么。您的代码需要做两件事:找出当前“箭头”在哪个段中,然后找出箭头在该段中的哪个位置。看起来好像你在混淆j 是什么,段索引或运行长度。您希望两者兼而有之,但这是不可能的。 @dxiv 感谢您的建议,但为什么不是 j - int(j)?如果 j 为 2.6,则 rem 将为 0.6,这就是我正在寻找的。另外,我怎样才能提供更多的上下文? 【参考方案1】:

您生成的路径 + 将具有等距点,但您的原始路径 o 具有不同长度的段。你有两个不同的事情要处理:

当前段的起点和终点的索引currnext 和 该段的插值变量t

这是curr / next 值的示例:

o    +        0 / 1       t = 0.0
|    |
|    +        0 / 1       t = 0.667
o    |
|    +        1 / 2       t = 0.2
|    |
|    +        1 / 2       t = 0.6
|    |
o    +        1 / 2       t = 1.0

所以你的算法是这样的:

找出总的和累积的段长度; 以curr = 0next = 1 开头。 在 n 个等距点上循环: 确定该点的总运行长度z 调整currnext,使curr ≤ z ≤ next。 确定t 并进行插值

这是一个将路径seg 拆分为相同长度的n 段的实现。 (它不是在 C++ 中,而是在 javascript 中,它直接处理 (x, y) 坐标而不是 lon/lat,但我想你可以理解它。)

function split(seg, n) 
    let acc = [];               // n + 1 accumulated lengths
    let len = 0;                // overall length
    let p = seg[0];              
    
    let res = [];               // array of n + 1 result points
    
    // find segemnt and overall lengths
    
    for (let i = 0; i < seg.length; i++) 
        let q = seg[i];
        len += Math.hypot(q.x - p.x, q.y - p.y);
        acc.push(len);

        p = q;
    
    
    acc.push(2 * len);          // sentinel

    let curr = 0;
    let next = 1;
    
    // create equidistant result points
    
    for (let i = 0; i < n; i++) 
        let z = len * i / n;        // running length of point i
        
        // advance to current segment
        
        while (z > acc[next]) 
            curr++;
            next++;
        
        
        // interpolate in segment
                
        let p = seg[curr];
        let q = seg[next];
        
        let t = (z - acc[curr]) / (acc[next] - acc[curr]);
        
        res.push(new Point(p.x * (1 - t) + q.x * t,
                           p.y * (1 - t) + q.y * t));
    
    
    // push end point (leave out when joining consecutive segments.)
    
    res.push(seg[seg.length - 1]);
    
    return res;

【讨论】:

非常感谢,这正是我过去几天一直坚持的问题。在对您的代码进行了一些修改后,我让它工作了。真的很感激:)

以上是关于给定一组带有线段的点,找到等距的点的主要内容,如果未能解决你的问题,请参考以下文章

给定一组多边形和一系列点,找出哪些多边形是所定位的点

给定数百万个点,找到位于线上或距线 0.2 毫米距离范围内的点 [关闭]

线段树CF1083C Max Mex

如何从球面上的当前点(纬度/经度)找到线段上最近的点

[SDOI2011]染色

Paint Tree