沿着与多边形指定距离的线找到点

时间:2016-07-07 12:29:24

标签: python numpy geometry

给定由一系列点和无限线定义的二维闭合多边形,我想在该线上找到距离多边形指定距离的点。已知多边形是闭合的,不是相交的,并且不包含3个连续的共线点。一般来说,沿线有许多可能的点。理想情况下,我想找到它们全部,或者最接近一些初始猜测位置。我正在使用python,但任何语言的解决方案都会有所帮助。我相信scipy.spatial kdtree将是一个重要的组成部分,但我看不出如何做到整个解决方案。下面是一些用于定义问题的代码,它至少显示了一些涉及的案例:

import numpy as np
import matplotlib.pyplot as plt

poly = np.array([[0, 0],
                 [10, 0],
                 [10, 3],
                 [1, 1],
                 [1, 6],
                 [0, 6],
                 [.8, 4],
                 [0, 0]])

line = np.array([[-2, 4.5],
                 [12, 3]])

plt.plot(poly[:, 0], poly[:, 1])
plt.plot(line[:, 0], line[:, 1])
plt.xlim([-1, 11])
plt.ylim([-1, 7])
plt.show()

points = find_points_distance_from_polygon(poly, line, distance)

enter image description here

编辑:我正在寻找找到积分的算法。

更新: 到目前为止,我所尝试的是使用到每个点的距离的近似解。我的想法是,如果我通过沿每条线添加额外的点来细化多边形,那么这种方法可能足够准确。但是,如果距离很小,我将不得不添加很多点。我认为可能有更好的方法。

import scipy.spatial as spatial
import scipy.optimize as opt
import math

def find_point_distance_from_polygon_along_line(tree, line, dist, guess_ratio):
    def f(x):
        pt = line[0, :] + x * (line[1, :] - line[0, :])
        d, i = tree.query(pt)
        return math.fabs(d - dist)

    res = opt.minimize(f, [guess_ratio])
    return line[0, :] + res.x * (line[1, :] - line[0, :])

tree = spatial.cKDTree(poly)
pt = find_point_distance_from_polygon_along_line(tree, line, 1, 0)

对于图中的示例和0.5的距离,我期望在大约(.1,4.2),(1.5,4.1),(9.1,3.3)和(10.5,3.1)处找到4个点。我目前的计划会找到更多的点,特别是与多边形的相对边缘有一定距离的点。我希望连接线上的点和多边形的线在多边形的外部。

1 个答案:

答案 0 :(得分:0)

如果多边形边数合理,可以使用简单的线性算法。

让线的参数方程为

  <system.serviceModel>
    <behaviors>
      <endpointBehaviors>
        <behavior name="json">
          <webHttp defaultOutgoingResponseFormat="Json" helpEnabled="true" />
        </behavior>
      </endpointBehaviors>
    </behaviors>
    <services>
      <service name="APGame.Services.GameManager">
        <endpoint address="" binding="wsHttpBinding" contract="APGame.Contracts.IGameService" />
      </service>
      <service name="APGame.Services.PlayManager">
        <endpoint address="" behaviorConfiguration="json" binding="webHttpBinding" contract="APGame.Contracts.IPlayService" />
      </service>
    </services>
    <bindings>
      <wsHttpBinding>
        <binding transactionFlow="true" sendTimeout="00:20:00">
          <security mode="Transport">
            <transport clientCredentialType="Windows" />
          </security>
        </binding>
      </wsHttpBinding>
    </bindings>
    <serviceHostingEnvironment aspNetCompatibilityEnabled="true" multipleSiteBindingsEnabled="true">
      <serviceActivations>
        <add service="APGame.Services.GameManager" relativeAddress="GameService.svc" />
        <add service="APGame.Services.PlayManager" relativeAddress="PlayService.svc" />
      </serviceActivations>
    </serviceHostingEnvironment>
  </system.serviceModel>

其中L0是某个基点,dL是方向矢量,u是参数

和第i个分段的参数方程是

[ServiceContract]
public interface IPlayService
{
    [OperationContract]
    [WebInvoke(Method = "GET", UriTemplate = "/checktraining?g={groupGameId}")]
    bool? CheckTraining(int groupGameId);
}

其中P [i]是段的第一个点,Dir [i]是归一化方向向量,t是范围0..1中的参数

该行的任意点在参数

的给定段上有它的投影
L(u) = L0 + u * dL

和投影的法线长度(所需距离)是

P = P[i] + t * Dir[i]

将值u替换为等式1并检查参数t是否在0..1范围内(段内的投影)。如果是,则需要L(u)点。

然后检查到顶点的距离 - 求解

t = DotProduct(L(u) - P[i], Dir[i])    //equation 1