多边形外扩——by Liang

import matplotlib
import matplotlib.pyplot as plt
import numpy as np
import math
import random


def generate_nonuniform_convex_polygon_points(n):
    if n < 3:
        raise ValueError("n must be greater than or equal to 3 for a convex polygon.")

    # 生成不同的边长
    side_lengths = [random.uniform(1, 20) for _ in range(n)]

    # 计算角度增量
    angle_increment = 2 * math.pi / n

    x_coords = []
    y_coords = []

    for i in range(n):
        angle = i * angle_increment
        x = side_lengths[i] * math.cos(angle)
        y = side_lengths[i] * math.sin(angle)
        x_coords.append(x)
        y_coords.append(y)

    # 添加第一个点闭合多边形和第二个点以求最后一个外扩点
    x_coords.append(x_coords[0])
    x_coords.append(x_coords[1])
    y_coords.append(y_coords[0])
    y_coords.append(y_coords[1])
    return x_coords, y_coords


# 指定边数
n = 7

# 生成凸多边形的坐标
x, y = generate_nonuniform_convex_polygon_points(n)

z = list(map(list, zip(x, y)))

# 画原始图形
plt.plot(x, y, marker='o', linestyle='-')


# 求两条直线的方向向量a和方向向量b
def xl(p0, p1, p2): # 此处的p0,p1,p2是(xi,yi)形式
    a = list(map(lambda x: x[0] - x[1], zip(p0, p1)))   # a是怕p0_p1的向量;
    b = list(map(lambda x: x[0] - x[1], zip(p1, p2)))   # b是篇p1_p2的向量
    return a, b


# 求两条直线的单位法向量afa,bfa
def fa(a, b):
    # a法向量
    afa = np.dot(np.array([[0, -1], [1, 0]]), a)
    afa = afa / np.linalg.norm(afa)
    # b法向量
    bfa = np.dot(np.array([[0, -1], [1, 0]]), b)  # 顺时针旋转向量90°
    bfa = bfa / np.linalg.norm(bfa)
    return afa, bfa


# 求两直线交点坐标   输入分别为向量a[,],扩张后a上点[,],向量b[,],扩张后b上点[,]
# 参数方程求交点
def j(a, ak, b, bk):
    #踩雷
    # theta1 = a[0] / math.sqrt((a[0] ** 2) + a[1] ** 2)
    # theta2 = b[0] / math.sqrt((b[0] ** 2) + b[1] ** 2)
    # t2 = (ak[0] - bk[0]) / (theta2 - (ak[0] - bk[0])/(ak[1] - bk[1]) * theta1)
    # x0 = bk[0] + t2 * theta2
    # y0 = bk[1] + t2 * theta2
    A = np.array([[b[0], -a[0]], [b[1], -a[1]]])
    X = np.array([[ak[0] - bk[0]], [ak[1] - bk[1]]])
    Ani = np.linalg.inv(A)
    T = np.dot(Ani, X)
    x0 = bk[0] + T[0] * b[0]
    y0 = bk[1] + T[0] * b[1]
    return x0, y0


def expend(z, l):
    n = len(z)
    xkuo = []    # 保存扩张后交点的横坐标
    ykuo = []    # 保存扩张后交点的纵坐标
    for i in range(0, n-2):
        xli = xl(z[i], z[i+1], z[i+2])
        xli = list(map(list, xli))  # 将xli转化为嵌套列表的形式
        faxl = fa(xli[0], xli[1])
        # 扩张后a,b上一点
        ak = list(map(lambda x: x[0] + x[1], zip(faxl[0] * l, z[i+1])))
        bk = list(map(lambda x: x[0] + x[1], zip(faxl[1] * l, z[i+1])))
        xj = j(xli[0], ak, xli[1], bk)
        xkuo.append(xj[0])
        ykuo.append(xj[1])
    xkuo.append(xkuo[0])    # 添加第一个交点横坐标闭合多边形
    ykuo.append(ykuo[0])    # 添加第一个交点纵坐标闭合多边形
    # print(xkuo)
    # print(ykuo)
    plt.plot(xkuo, ykuo, marker='o', linestyle='-')
    plt.show()


# if __name__ == '__main__':
expend(z,2)

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值