我想知道如何确定两个点d1(920,52.1),d2(920,52)是否在这个橙色平行四边形内部,它由p1~p4组成。
正如您所看到的,平行四边形的基础不是x轴的平行。
是否有任何模块可以解决这类问题?或者我想在这个问题上得到一些数学帮助。
答案 0 :(得分:2)
对于平行四边形,有一种比一般多边形更简单的方法。以c,a,b的顺序获取三个相邻顶点的坐标,并基于AP
和AB
向量表示AC
向量 - 系数应在范围0..1
中。
请注意,Delphi和Python函数使用不同的参数顺序。在Delphi中,基点(a)先行,然后是邻居(b,c),而Python列表依次包含c,a,b(或b,a,c)点。
德尔福代码:
function PtInPlgm(ax, ay, bx, by, cx, cy, px, py: Integer): Boolean;
var
xb, yb, xc, yc, xp, yp, d: Integer;
bb, cc, oned: Double;
begin
Result := False;
xb := bx - ax;
yb := by - ay;
xc := cx - ax;
yc := cy - ay;
xp := px - ax;
yp := py - ay;
d := xb * yc - yb * xc;
if d <> 0 then begin
oned := 1 / d;
bb := (xp * yc - xc * yp) * oned;
cc := (xb * yp - xp * yb) * oned;
Result := (bb >= 0) and (cc >= 0) and (bb <= 1) and (cc <= 1);
end;
end;
Literal Python translation:
def point_inside_prlgm(x,y,poly):
inside = False
xb = poly[0][0] - poly[1][0]
yb = poly[0][1] - poly[1][1]
xc = poly[2][0] - poly[1][0]
yc = poly[2][1] - poly[1][1]
xp = x - poly[1][0]
yp = y - poly[1][1]
d = xb * yc - yb * xc;
if (d <> 0):
oned = 1.0 / d;
bb = (xp * yc - xc * yp) * oned
cc = (xb * yp - xp * yb) * oned
inside = (bb >= 0) & (cc >= 0) & (bb <= 1) & (cc <= 1)
return inside
print(point_inside_prlgm(1, 1, [[1, 2], [0, 0], [2, 0]]))
print(point_inside_prlgm(-1, 1, [[2, 1], [0, 0], [2, 0]]))
答案 1 :(得分:1)
以下解决方案使用针对平行四边形优化的象限步行算法。它是绕组数算法的衍生物。
该算法将测试点P放置在坐标系的中心,并按顺序遍历多边形的顶点,检查“正轴和负轴交叉”。如果轴交叉的数量是4的乘数(但不是0),则P在多边形内。直观地,P在多边形内,如果行走顶点“跨越所有四个半轴”。因此4的乘数。
该算法可以高度优化(特别适合汇编程序实现)和快速运行。
这是在Delphi中,使用与MBo的答案中给出的函数 PtInPlgm 相同的参数顺序
function PtInPlgm2( bx, by, ax, ay, cx, cy, px, py: double ): boolean;
var
Sum : integer;
dx, dy : double;
begin
Sum := 0;
dx := cx - bx + ax;
dy := cy - by + ay;
if ( px < ax ) <> ( px < bx ) then inc( Sum );
if ( py < ay ) <> ( py < by ) then inc( Sum );
if ( px < bx ) <> ( px < cx ) then inc( Sum );
if ( py < by ) <> ( py < cy ) then inc( Sum );
if ( px < cx ) <> ( px < dx ) then inc( Sum );
if ( py < cy ) <> ( py < dy ) then inc( Sum );
if ( px < dx ) <> ( px < ax ) then inc( Sum );
if ( py < dy ) <> ( py < ay ) then inc( Sum );
Result := (Sum mod 4 = 0) AND (Sum <> 0);
end;
我相信没关系,我没有提供Python实现
答案 2 :(得分:0)
我尝试使用Shapely,但我读到它的速度很慢。我的程序需要每分钟至少使用100次逻辑,因此我在互联网上查找关键字并找到此页面:http://www.ariel.com.au/a/python-point-int-poly.html
# determine if a point is inside a given polygon or not
# Polygon is a list of (x,y) pairs.
def point_inside_polygon(x,y,poly):
n = len(poly)
inside =False
p1x,p1y = poly[0]
for i in range(n+1):
p2x,p2y = poly[i % n]
if y > min(p1y,p2y):
if y <= max(p1y,p2y):
if x <= max(p1x,p2x):
if p1y != p2y:
xinters = (y-p1y)*(p2x-p1x)/(p2y-p1y)+p1x
if p1x == p2x or x <= xinters:
inside = not inside
p1x,p1y = p2x,p2y
return inside
它工作得足够快,不需要额外的模块。我认为用C语言编写代码并在Python中使用它可能是一个好主意。