python - 矩形的其他两个点给出两个点和宽度
问题描述
给定附图中黑色显示的两个点,我需要找到矩形的另外两个点。缺失的点以黄色显示,宽度为红色,我也有。矩形可以任意旋转。
我也知道这些点是在矩形的同一侧还是相反侧。
如图所示,我需要解决四种可能的安排。
解决方案
由于您已将 python 标签添加到您的问题中,我假设您想使用 python 解决此问题。
两种情景
- 给定的点代表对角线 (1)
- 或给定的点代表一条边 (2)
(1) 对角线法:
Diagonal Approach Sketch (就在这里,我们用的是泰勒斯定理。如果你不知道,就去查吧。它很有用。)
(2) 边缘方法:
Python代码
这是纯粹的计算。只需更改此脚本末尾的属性即可。
import math
import numpy as np
# lovely method by mujjiga
# from https://stackoverflow.com/questions/55816902/finding-the-intersection-of-two-circles
# returns intersections of two circles
def get_intersections(x0, y0, r0, x1, y1, r1):
# circle 1: (x0, y0), radius r0
# circle 2: (x1, y1), radius r1
d = math.sqrt((x1-x0)**2 + (y1-y0)**2)
# non intersecting
if d > r0 + r1:
return None
# One circle within other
if d < abs(r0-r1):
return None
# coincident circles
if d == 0 and r0 == r1:
return None
else:
a = (r0**2-r1**2+d**2)/(2*d)
h = math.sqrt(r0**2-a**2)
x2 = x0+a*(x1-x0)/d
y2 = y0+a*(y1-y0)/d
x3 = x2+h*(y1-y0)/d
y3 = y2-h*(x1-x0)/d
x4 = x2-h*(y1-y0)/d
y4 = y2+h*(x1-x0)/d
return (x3, y3, x4, y4)
# returns None or 4 possible points
def get_unknown_points(p1, p2, width, is_diagonal):
# convert tuples/lists to nummpy arrays
p1 = np.array(p1, dtype=float)
p2 = np.array(p2, dtype=float)
# vector from p1 to p2
p1_to_p2 = p2 - p1
# magnitude/length of this vector
length = np.linalg.norm(p2 - p1)
if is_diagonal:
mid = p1 + 0.5 * p1_to_p2
mid_radius = length * 0.5
points = get_intersections(
p1[0], p1[1], width, mid[0], mid[1], mid_radius)
# no intersections found
if points is None:
return None
other_points = get_intersections(
p2[0], p2[1], width, mid[0], mid[1], mid_radius)
# return the two different possibilities
possibilities = []
possibilities.append(
((points[0], points[1]), (other_points[0], other_points[1])))
possibilities.append(
((points[2], points[3]), (other_points[2], other_points[3])))
return possibilities
# p1 and p2 do not represent the diagonal
else:
# get a perpendicular vector regarding p1_to_p2 (taken from https://stackoverflow.com/questions/33658620/generating-two-orthogonal-vectors-that-are-orthogonal-to-a-particular-direction)
perpendicular_vector = np.random.randn(2)
perpendicular_vector -= perpendicular_vector.dot(
p1_to_p2) * p1_to_p2 / np.linalg.norm(p1_to_p2)**2
# make length of vector correspond to width
perpendicular_vector /= np.linalg.norm(perpendicular_vector)
perpendicular_vector *= width
# add this vector to p1 and p2 and return both possibilities
possibilities = []
possibilities.append(
((p1[0] + perpendicular_vector[0], p1[1] + perpendicular_vector[1]), (p2[0] + perpendicular_vector[0], p2[1] + perpendicular_vector[1])))
possibilities.append(
((p1[0] - perpendicular_vector[0], p1[1] - perpendicular_vector[1]), (p2[0] - perpendicular_vector[0], p2[1] - perpendicular_vector[1])))
return possibilities
# change these properties
p1 = (4, 5)
p2 = (5, 1)
diagonal = True
width = 1
points = get_unknown_points(p1, p2, width, diagonal)
# output
if points is None:
print("There are no points that can be calculated from the points given!")
else:
print(
f"Possibilty 1: \n\tPoint1: {points[0][0]} \n\tPoint2: {points[0][1]}")
print(
f"Possibilty 2: \n\tPoint1: {points[1][0]} \n\tPoint2: {points[1][1]}")
可视化
如果您想直观地查看结果,只需将这些代码行附加到上脚本的末尾即可。
import matplotlib.pyplot as plt
# displaying results
if points is not None:
p1 = np.array(p1, dtype=float)
p2 = np.array(p2, dtype=float)
fig, ax = plt.subplots()
ax.set_xlim((-1, 10))
ax.set_ylim((-1, 10))
if diagonal:
dist = np.linalg.norm(p2 - p1)
mid = p1 + 0.5 * (p2 - p1)
mid_radius = dist * 0.5
circle2 = plt.Circle(mid, mid_radius, color='orange', fill=False)
circle3 = plt.Circle(p1, width, color='g', fill=False)
circle1 = plt.Circle(p2, width, color='g', fill=False)
ax.add_artist(circle1)
ax.add_artist(circle2)
ax.add_artist(circle3)
plt.plot(p1, p2, '.', color='black')
print(points[0][1])
plt.plot([points[0][0][0], points[0][1][0]], [
points[0][0][1], points[0][1][1]], '.', color='red')
plt.plot([points[1][0][0], points[1][1][0]], [
points[1][0][1], points[1][1][1]], '.', color='blue')
plt.gca().set_aspect('equal', adjustable='box')
plt.show()
结果
推荐阅读
- html - 选择单选按钮后显示单元格边框
- c++ - 对地图值进行自定义迭代器时出现 C++ 错误
- c++ - 带指针的字典
- node.js - Discord.js 每个服务器前缀错误“TypeError:无法读取属性 'ID' of null”
- gradle - Travis 上的 Gradle 内存不足
- npm - 无法在命令提示符下更新或执行“expo”命令
- flutter - Flutter typeahead 显示所有建议 ontap 字段(不需要)
- python - 使用python在查询中添加多个addants
- php - follow and unfollow like instagrm system in codeigniter
- reactjs - React-Redux - How to redirect the page after storing the data in redux store?