文章目录
- 1、功能描述
- 2、代码实现
- 3、效果展示
- 4、完整代码
- 5、涉及到的库函数
更多有趣的代码示例,可参考【Programming】
1、功能描述
用 python 实现,以 A和B两个点为边长,方向朝 C 绘制正方形
思路:
- 计算向量 AB 和 AC。
- 使用向量 AB 的长度作为正方形的边长。
- 确定正方形的旋转方向,使得一边朝向点 C。
- 计算正方形的四个顶点。
2、代码实现
导入必要的库函数
import numpy as np
import matplotlib.pyplot as plt
定义绘制函数 draw_square
,先将点转换为 numpy 数组,然后计算向量 AB 和 AC,接着计算 AB 的长度(正方形的边长)
def draw_square(A, B, C):
# 将点转换为 numpy 数组
A = np.array(A)
B = np.array(B)
C = np.array(C)
# 计算向量 AB 和 AC
AB = B - A
AC = C - A
# 计算 AB 的长度(正方形的边长)
side_length = np.linalg.norm(AB)
单位化向量 AB,并计算垂直于 AB 的单位向量,分顺时针 90° 和逆时针 90° 两个方向
# 单位化向量 AB,并计算垂直于 AB 的单位向量
AB_unit = AB / side_length
# 顺时针 y,-x 逆时针 -y,x
perpendicular_unit1 = np.array([AB_unit[1], -AB_unit[0]]) # 顺时针旋转 90 度
perpendicular_unit2 = np.array([-AB_unit[1], AB_unit[0]]) # 逆时针旋转 90 度
计算以 A 为原点,两个方向的单位向量与 AC向量的夹角,以确定绘制正方形的朝向
A1 = A + perpendicular_unit1
A2 = A + perpendicular_unit2
A1C = np.dot(AC, A1)
A2C = np.dot(AC, A2)
分如下几种情况,注意 A1C 和 A2C 相等的时候,说明 AC 与 AB 垂直,此时可以进一步根据距离去判断,如果连距离都相等,说明 C 在 AB(或者延长线) 上,此时方向不明确,打印提示错误信息
if A1C > A2C:
perpendicular_unit = perpendicular_unit1
elif A1C< A2C:
perpendicular_unit = perpendicular_unit2
else:
distance1 = np.sqrt((A1[0]-C[0])**2 + (A1[1]-C[1])**2)
distance2 = np.sqrt((A2[0] - C[0]) ** 2 + (A2[1] - C[1]) ** 2)
if distance1 < distance2:
perpendicular_unit = perpendicular_unit1
elif distance1 > distance2:
perpendicular_unit = perpendicular_unit2
else:
print("Error: C 与 AB 重合!")
return
计算顶点
# 计算正方形的四个顶点
# 起点是 A
vertex1 = A
vertex2 = A + AB_unit * side_length # A 沿着 AB 方向移动
vertex3 = vertex2 + perpendicular_unit * side_length # 从 vertex2 沿着垂直方向移动
vertex4 = vertex1 + perpendicular_unit * side_length # 从 vertex1 沿着垂直方向移动
绘制正方形
# 绘制正方形
square_vertices = [vertex1, vertex2, vertex3, vertex4, vertex1] # 回到起点以闭合
square_vertices = np.array(square_vertices)
plt.figure()
plt.plot(square_vertices[:, 0], square_vertices[:, 1], 'b-') # 绘制正方形边框
plt.scatter([A[0], B[0], C[0]], [A[1], B[1], C[1]], color=['red', 'green', 'orange']) # 绘制点 A, B, C
plt.text(A[0], A[1], ' A', fontsize=12, verticalalignment='bottom')
plt.text(B[0], B[1], ' B', fontsize=12, verticalalignment='bottom')
plt.text(C[0], C[1], ' C', fontsize=12, verticalalignment='bottom')
plt.axis('equal') # 保持比例
plt.title('Square with side AB oriented towards C')
plt.show()
3、效果展示
A = (0, 1)
B = (1, 0)
C = (-1, -1)
A = (0, 1)
B = (1, 0)
C = (1, 1)
A = (-1, 0)
B = (1, 0)
C = (0, -1)
A = (-1, 0)
B = (1, 0)
C = (0, 1)
A = (-1, -1)
B = (1, 1)
C = (-1, 1)
A = (-1, -1)
B = (1, 1)
C = (1, -1)
A = (0, -1)
B = (0, 1)
C = (-1, 0)
A = (0, -1)
B = (0, 1)
C = (1, 0)
A = (1, -1)
B = (-1, 1)
C = (-1, -1)
A = (1, -1)
B = (-1, 1)
C = (1, 1)
A = (1, 0)
B = (-1, 0)
C = (0, 1)
A = (1, 0)
B = (-1, 0)
C = (0, -1)
A = (1, 1)
B = (-1, -1)
C = (1, -1)
A = (1, 1)
B = (-1, -1)
C = (-1, 1)
A = (0, 1)
B = (0, -1)
C = (-1, 0)
A = (0, 1)
B = (0, -1)
C = (1, 0)
A = (0, 1)
B = (0, 3)
C = (0, 2)
输出
Error: C 与 AB 重合!
4、完整代码
import numpy as np
import matplotlib.pyplot as plt
def draw_square(A, B, C):
# 将点转换为 numpy 数组
A = np.array(A)
B = np.array(B)
C = np.array(C)
# 计算向量 AB 和 AC
AB = B - A
AC = C - A
# 计算 AB 的长度(正方形的边长)
side_length = np.linalg.norm(AB)
# 单位化向量 AB,并计算垂直于 AB 的单位向量
AB_unit = AB / side_length
# 顺时针 y,-x 逆时针 -y,x
perpendicular_unit1 = np.array([AB_unit[1], -AB_unit[0]]) # 顺时针旋转 90 度
perpendicular_unit2 = np.array([-AB_unit[1], AB_unit[0]]) # 逆时针旋转 90 度
A1 = A + perpendicular_unit1
A2 = A + perpendicular_unit2
A1C = np.dot(AC, A1)
A2C = np.dot(AC, A2)
if A1C > A2C:
perpendicular_unit = perpendicular_unit1
elif A1C< A2C:
perpendicular_unit = perpendicular_unit2
else:
distance1 = np.sqrt((A1[0]-C[0])**2 + (A1[1]-C[1])**2)
distance2 = np.sqrt((A2[0] - C[0]) ** 2 + (A2[1] - C[1]) ** 2)
if distance1 < distance2:
perpendicular_unit = perpendicular_unit1
elif distance1 > distance2:
perpendicular_unit = perpendicular_unit2
else:
print("Error: C 与 AB 重合!")
return
# 计算正方形的四个顶点
# 起点是 A
vertex1 = A
vertex2 = A + AB_unit * side_length # A 沿着 AB 方向移动
vertex3 = vertex2 + perpendicular_unit * side_length # 从 vertex2 沿着垂直方向移动
vertex4 = vertex1 + perpendicular_unit * side_length # 从 vertex1 沿着垂直方向移动
# 绘制正方形
square_vertices = [vertex1, vertex2, vertex3, vertex4, vertex1] # 回到起点以闭合
square_vertices = np.array(square_vertices)
plt.figure()
plt.plot(square_vertices[:, 0], square_vertices[:, 1], 'b-') # 绘制正方形边框
plt.scatter([A[0], B[0], C[0]], [A[1], B[1], C[1]], color=['red', 'green', 'orange']) # 绘制点 A, B, C
plt.text(A[0], A[1], ' A', fontsize=12, verticalalignment='bottom')
plt.text(B[0], B[1], ' B', fontsize=12, verticalalignment='bottom')
plt.text(C[0], C[1], ' C', fontsize=12, verticalalignment='bottom')
plt.axis('equal') # 保持比例
plt.title('Square with side AB oriented towards C')
plt.show()
if __name__ == "__main__":
# 示例使用
A = (0, 1)
B = (0, -1)
C = (1, 0)
draw_square(A, B, C)
5、涉及到的库函数
- numpy
- matplotlib
更多有趣的代码示例,可参考【Programming】