给定由一系列点和无限线定义的二维闭合多边形,我想在该线上找到距离多边形指定距离的点。已知多边形是闭合的,不是相交的,并且不包含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)
编辑:我正在寻找找到积分的算法。
更新: 到目前为止,我所尝试的是使用到每个点的距离的近似解。我的想法是,如果我通过沿每条线添加额外的点来细化多边形,那么这种方法可能足够准确。但是,如果距离很小,我将不得不添加很多点。我认为可能有更好的方法。
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个点。我目前的计划会找到更多的点,特别是与多边形的相对边缘有一定距离的点。我希望连接线上的点和多边形的线在多边形的外部。
答案 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