首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >在python中,如何检查四个元组点是否形成正方形、矩形、平行四边形或菱形?

在python中,如何检查四个元组点是否形成正方形、矩形、平行四边形或菱形?
EN

Stack Overflow用户
提问于 2022-06-05 16:22:09
回答 1查看 127关注 0票数 -3

有四点作为元组;p1 = (2, 2), p2 = (2, 6), p3 = (6, 6) and p4 = (6, 2)。我希望这四个元组点通过4种不同类型的函数: isSquare(p1,p2,p3,p4),isRectangle(p1,p2,p3,p4),isParallelogram(p1,p2,p3,p4)和isRhombus(p1,p2,p4,)检查它的正方形、矩形、平行四边形还是菱形。

EN

回答 1

Stack Overflow用户

发布于 2022-06-05 17:43:49

编辑尝试2:相反,计算点之间的向量,找出唯一向量的数目和在同一点上相遇的向量之间的角度,以确定所需的四种形状中的哪一种(注意,这种方法要求按所连接的顺序排列点):

代码语言:javascript
复制
import numpy as np

def quadrilateral2(*args):
    if len(args) != 4:
        return 'Not a quadrilateral'
    args = np.array(args)
    vectors = np.array([args[i-1]-j for i, j in enumerate(args)])
    unique_vectors = np.unique(np.round(np.abs(vectors), 6), axis=0) #Round to avoid numerical errors: can change the number of digits to round to
    if len(unique_vectors) != 2:
        return 'Not a square, rectangle, rhombus or parallelogram'
    norms = [np.linalg.norm(i) for i in vectors]
    norm_vectors = [i/j for i, j in zip(vectors, norms)]
    unique_norms = set(round(i, 6) for i in norms) # Again, round for numerical errors
    angles = [np.arccos(np.dot(norm_vectors[i-1], j)) for i, j in enumerate(norm_vectors)]

    if all(i == np.pi/2 for i in angles):
        if len(unique_norms) == 1:
            return 'Square'
        if len(unique_norms) == 2:
            return 'Rectangle'
    
    elif len(set(round(i, 6) for i in angles)) == 2: #Again, round for numerical errors
        if len(unique_norms) == 1:
            return 'Rhombus'
        if len(unique_norms) == 2:
            return 'Parallelogram'
    else:
        return 'Not a square, rectangle, rhombus or parallelogram'

与以前的测试和作为注释的测试:

代码语言:javascript
复制
square = [(2, 2), (2, 4), (4,4), (4, 2)]
rectangle = [(2, 2), (2,8), (4, 8), (4, 2)]
rhombus = [(0, 0), (np.sqrt(8), 0), (2+np.sqrt(8), 2), (2, 2)]
parallelogram = [(2,2), (5, 2), (6,4), (3,4)]
print(quadrilateral2(*square))
print(quadrilateral2(*rectangle))
print(quadrilateral2(*rhombus))
print(quadrilateral2(*parallelogram))
print(quadrilateral2(*[[2, -3], [6, 5], [-2, 1], [-6, -7]]))
print(quadrilateral2(*[(0, 0), (0, -5), (3,2.5), (3, -2.5)]))
print(quadrilateral2(*[(0, 2), (0, -2), (-1,0), (1, 0)]))

输出:

代码语言:javascript
复制
Square
Rectangle
Rhombus
Parallelogram
Rhombus
Not a square, rectangle, rhombus or parallelogram
Not a square, rectangle, rhombus or parallelogram

免责声明:不适用于任何输入,但我认为如果输入保证为正方形、矩形、平行四边形或菱形,则可以工作。好的,我认为这很有效,但我还没有对它进行太多的测试。本质上,您需要计算所有给定点之间的唯一距离和唯一角度,然后使用所需形状的知识从这些距离和角度(如果有的话)确定形状:

代码语言:javascript
复制
import itertools
import numpy as np


def quadrilateral(*args):
    tol = 1e-4
    if not len(args) == 4:
        return 'Not a quadrilateral'
    #Calculate all permutations of the coordinates
    permutations = np.array(list(itertools.permutations(args, r=2)))
    #Calculate all distances
    distances = np.array(list(np.sqrt(sum((i[0]-i[1])**2)) for i in permutations))
    #Choose unique distances within a tolerance tol
    distances = distances[~(np.triu(np.abs(distances[:,None] - distances) <= tol,1)).any(0)]
    #Calculate all absolute angles
    angles = np.array(list(abs(np.arctan2(*(i[0]-i[1])[::-1])) for i in permutations))
    #Choose unique angles within a tolerance tol
    angles = sorted(angles[~(np.triu(np.abs(angles[:,None] - angles) <= tol,1)).any(0)])
    if len(distances) == 2 and all(np.pi*i/4 == j for i, j in enumerate(angles)):
            return "It's a square"
    elif len(distances) == 3:
        if len(angles) == 5:
            return "It's a rectangle"
        elif len(angles) == 8:
            return "It's a rhombus"
        else:
            return 'Not a square, rectangle, rhombus or parallelogram'
    elif len(distances) == 4 and len(angles) == 8:
        return "It's a parallelogram"
    else:
        return 'Not a square, rectangle, rhombus or parallelogram'

简单测试用例:

代码语言:javascript
复制
square = [(2, 2), (2, 4), (4,2), (4, 4)]
rectangle = [(2, 2), (4, 2), (2,8), (4, 8)]
rhombus = [(0, 0), (2, 2), (np.sqrt(8), 0), (2+np.sqrt(8), 2)]
parallelogram = [(2,2), (3,4), (5, 2), (6,4)]
print(quadrilateral(*square))
print(quadrilateral(*rectangle))
print(quadrilateral(*rhombus))
print(quadrilateral(*parallelogram))

输出:

代码语言:javascript
复制
It's a square
It's a rectangle
It's a rhombus
It's a parallelogram
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/72509103

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档