python检测线段是否含有勾

# -*- coding: utf-8 -*-#
import math

lines_dic = {
    "正常": [
        [[0, 0], [1, 1], [2, 2], [3, 3]],
        [[0, 0], [1, 1], [1, 2], [3, 5]]
    ],
    "勾": [
        [[0, 0], [1, 1], [2, 2], [3, 3], [4, 4], [2, 1]],
        [[1, 2], [0, 0], [1, 1], [2, 2], [3, 3], [4, 4]]
    ]

}


def get_point_line_distance(point, line):
    """
    :param point: (x,y)
    :param line: [(x1,y1),(x2,y2)]
    :return:
    """
    point_x = point[0]
    point_y = point[1]
    line_s_x = line[0][0]
    line_s_y = line[0][1]
    line_e_x = line[1][0]
    line_e_y = line[1][1]
    # 若直线与y轴平行,则距离为点的x坐标与直线上任意一点的x坐标差值的绝对值
    if line_e_x - line_s_x == 0:
        return math.fabs(point_x - line_s_x)
    # 若直线与x轴平行,则距离为点的y坐标与直线上任意一点的y坐标差值的绝对值
    if line_e_y - line_s_y == 0:
        return math.fabs(point_y - line_s_y)
    # 斜率
    k = (line_e_y - line_s_y) / (line_e_x - line_s_x)
    # 截距
    b = line_s_y - k * line_s_x
    return math.fabs(k * point_x - point_y + b) / math.pow(k * k + 1, 0.5)


def get_inflection_point(coordinates, line):
    """
    :param coordinates: 线段坐标
    :param line:线段开头和结尾
    :return:获取拐点
    """
    max_distance = -1
    inflection_point = None
    for index, point in enumerate(coordinates):
        distance = get_point_line_distance(point, line)
        if index != 0 and max_distance < distance or index == 0:
            max_distance = distance
            inflection_point = point
    return inflection_point


def cal_ang(point_1, point_2, point_3):
    """
    根据三点坐标计算夹角
    :param point_1: 点1坐标
    :param point_2: 点2坐标
    :param point_3: 点3坐标
    :return: 返回任意角的夹角值,这里只是返回点2的夹角
    """
    a = math.sqrt((point_2[0] - point_3[0]) * (point_2[0] - point_3[0]) + (point_2[1] - point_3[1]) * (point_2[1] - point_3[1]))
    b = math.sqrt((point_1[0] - point_3[0]) * (point_1[0] - point_3[0]) + (point_1[1] - point_3[1]) * (point_1[1] - point_3[1]))
    c = math.sqrt((point_1[0] - point_2[0]) * (point_1[0] - point_2[0]) + (point_1[1] - point_2[1]) * (point_1[1] - point_2[1]))
    A = math.degrees(math.acos((a * a - b * b - c * c) / (-2 * b * c)))
    B = math.degrees(math.acos((b * b - a * a - c * c) / (-2 * a * c)))
    C = math.degrees(math.acos((c * c - a * a - b * b) / (-2 * a * b)))
    return B


def check_line_tick(coordinates):
    """
    :param coordinates: 线段[[x,y],[x,y],[x,y]...]
    :return:False/True
    检测线段是否有勾
    """
    line = [coordinates[0], coordinates[-1]]
    inflection_point = get_inflection_point(coordinates, line)
    if inflection_point in line:
        return False
    angle = cal_ang(line[0], inflection_point, line[1])
    return angle < 90


if __name__ == '__main__':
    for name, lines_list in lines_dic.items():
        for lines in lines_list:
            print(name, check_line_tick(lines))

image

posted @ 2022-09-09 10:04  不能说的秘密  阅读(75)  评论(0编辑  收藏  举报