你可以计算直线方程,然后计算每个点到该直线的距离。
例如:
import collections
import math
Point = collections.namedtuple('Point', "x, y")
def distance(pt, a, b, c):
return math.fabs(a * pt.x + b * pt.y + c) / math.sqrt(a**2 + b**2)
l1 = Point(676561.00, 4860927.00)
l2 = Point(676557.00, 4860939.00)
a = l2.y - l1.y
b = l1.x - l2.x
c = l2.x * l1.y - l2.y * l1.x
assert a * l1.x + b * l1.y + c == 0
assert a * l2.x + b * l2.y + c == 0
p100 = Point(676551.00, 4860935.00)
p200 = Point(676558.00, 4860922.00)
print(distance(p100, a, b, c))
print(distance(p200, a, b, c))
你得到:
6.957010852370434
4.427188724235731
编辑1:计算正交投影
你想要的是点p100和p200在直线(l1, l2)上的正交投影的坐标。
你可以按照以下方式进行计算:
import collections
import math
Point = collections.namedtuple('Point', "x, y")
def snap(pt, pt1, pt2):
v = Point(pt2.x - pt1.x, pt2.y - pt1.y)
dv = math.sqrt(v.x ** 2 + v.y ** 2)
bh = ((pt.x - pt1.x) * v.x + (pt.y - pt1.y) * pt2.y) / dv
h = Point(
pt1.x + bh * v.x / dv,
pt1.y + bh * v.y / dv
)
return h
l1 = Point(676561.00, 4860927.00)
l2 = Point(676557.00, 4860939.00)
p100 = Point(676551.00, 4860935.00)
p200 = Point(676558.00, 4860922.00)
s100 = snap(p100, l1, l2)
s200 = snap(p200, l1, l2)
print(s100)
print(p100)
你得到:
Point(x=-295627.7999999998, y=7777493.4)
Point(x=676551.0, y=4860935.0)
你可以检查捕捉点是否在直线上:
a = l2.y - l1.y
b = l1.x - l2.x
c = l2.x * l1.y - l2.y * l1.x
assert math.fabs(a * s100.x + b * s100.y + c) < 1e-6
assert math.fabs(a * s200.x + b * s200.y + c) < 1e-6
编辑2:对齐到线段
如果您想对齐到一条线段,您需要检查正交投影是否在线段内部。
- 如果正交投影在线段内部:它就是解决方案,
- 如果它靠近线段的一个端点,则该端点是解决方案。
您可以按照以下方式执行:
def distance_pts(pt1, pt2):
v = Point(pt2.x - pt1.x, pt2.y - pt1.y)
dv = math.sqrt(v.x ** 2 + v.y ** 2)
return dv
def snap(pt, pt1, pt2):
v = Point(pt2.x - pt1.x, pt2.y - pt1.y)
dv = distance_pts(pt1, pt2)
bh = ((pt.x - pt1.x) * v.x + (pt.y - pt1.y) * pt2.y) / dv
h = Point(pt1.x + bh * v.x / dv, pt1.y + bh * v.y / dv)
if 0 <= (pt1.x - h.x) / (pt2.x - h.y) < 1:
return h
elif distance_pts(h, pt1) < distance_pts(h, pt2):
return pt1
else:
return pt2
问题100和问题200的解决方案如下:
Point(x=676557.0, y=4860939.0)
Point(x=676551.0, y=4860935.0)
PIL
或Opencv
。 - jizhihaoSAMA