one

import math


def is_close(p1, p2, range_):
    """判断两个点是否在指定范围内"""
    return math.isclose(p1[0], p2[0], abs_tol=range_) and math.isclose(p1[1], p2[1], abs_tol=range_)


def check_connections(lines, range_):
    """检查每个线段端点的连接情况"""
    points = set()
    # 提取所有线段的端点,并存储到集合中以避免重复
    for line in lines:
        points.add((line[0], line[1]))
        points.add((line[2], line[3]))

    connections = {}

    # 转换集合为列表以便使用索引
    points = list(points)

    for i, point1 in enumerate(points):
        if point1 not in connections:
            connections[point1] = {"right_angle": [], "T_shape": []}

        # 检查与其他端点的直角连接
        for j, point2 in enumerate(points):
            if i != j and is_close(point1, point2, range_):
                if point2 not in connections[point1]["right_angle"]:
                    connections[point1]["right_angle"].append(point2)

        # 检查与其他线段的T型连接
        for line in lines:
            if point1 not in [(line[0], line[1]), (line[2], line[3])]:
                if line[0] == line[2]:  # 竖直线
                    if min(line[1], line[3]) <= point1[1] <= max(line[1], line[3]) and math.isclose(line[0], point1[0],
                                                                                                    abs_tol=range_):
                        connection = ((line[0], min(line[1], line[3])), (line[0], max(line[1], line[3])))
                        if connection not in connections[point1]["T_shape"]:
                            connections[point1]["T_shape"].append(connection)
                elif line[1] == line[3]:  # 水平线
                    if min(line[0], line[2]) <= point1[0] <= max(line[0], line[2]) and math.isclose(line[1], point1[1],
                                                                                                    abs_tol=range_):
                        connection = ((min(line[0], line[2]), line[1]), (max(line[0], line[2]), line[1]))
                        if connection not in connections[point1]["T_shape"]:
                            connections[point1]["T_shape"].append(connection)

    return connections


# 示例用法
lines = [
    (0, 0, 10, 0),  # 水平线
    (5, -5, 5, 5),  # 竖直线
    (10, 0, 20, 0),  # 水平线
    (15, -5, 15, 5),  # 竖直线
    (0, 0, 5, 5)  # 重复端点坐标的线段
]

range_ = 5  # 自定义范围
connections = check_connections(lines, range_)
for point, conn in connections.items():
    print(f"Point {point}:")
    print(f"  Right-angle connections: {conn['right_angle']}")
    print(f"  T-shape connections: {conn['T_shape']}")

  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.
  • 15.
  • 16.
  • 17.
  • 18.
  • 19.
  • 20.
  • 21.
  • 22.
  • 23.
  • 24.
  • 25.
  • 26.
  • 27.
  • 28.
  • 29.
  • 30.
  • 31.
  • 32.
  • 33.
  • 34.
  • 35.
  • 36.
  • 37.
  • 38.
  • 39.
  • 40.
  • 41.
  • 42.
  • 43.
  • 44.
  • 45.
  • 46.
  • 47.
  • 48.
  • 49.
  • 50.
  • 51.
  • 52.
  • 53.
  • 54.
  • 55.
  • 56.
  • 57.
  • 58.
  • 59.
  • 60.
  • 61.
  • 62.
  • 63.
  • 64.
  • 65.
  • 66.

有id

import math


def is_close(p1, p2, range_):
    """判断两个点是否在指定范围内"""
    return math.isclose(p1[0], p2[0], abs_tol=range_) and math.isclose(p1[1], p2[1], abs_tol=range_)


def check_connections(lines, range_):
    """检查每个线段端点的连接情况"""
    points = set()
    point_to_line_id = {}

    # 提取所有线段的端点,并存储到集合中以避免重复
    for line in lines:
        line_id = line[0]
        point1 = (line[1], line[2])
        point2 = (line[3], line[4])
        points.add(point1)
        points.add(point2)
        point_to_line_id[point1] = line_id
        point_to_line_id[point2] = line_id

    connections = {}
    # 转换集合为列表以便使用索引
    points = list(points)

    for i, point1 in enumerate(points):
        if point1 not in connections:
            connections[point1] = {"right_angle": [], "T_shape": []}

        # 检查与其他端点的直角连接
        for j, point2 in enumerate(points):
            if i != j and is_close(point1, point2, range_):
                if point2 not in connections[point1]["right_angle"]:
                    connections[point1]["right_angle"].append(point2)

        # 检查与其他线段的T型连接
        for line in lines:
            line_id = line[0]
            if point1 not in [(line[1], line[2]), (line[3], line[4])]:
                if line[1] == line[3]:  # 竖直线
                    if min(line[2], line[4]) <= point1[1] <= max(line[2], line[4]) and math.isclose(line[1], point1[0],
                                                                                                    abs_tol=range_):
                        connection = ((line[1], min(line[2], line[4])), (line[1], max(line[2], line[4])))
                        if connection not in connections[point1]["T_shape"]:
                            connections[point1]["T_shape"].append(connection)
                elif line[2] == line[4]:  # 水平线
                    if min(line[1], line[3]) <= point1[0] <= max(line[1], line[3]) and math.isclose(line[2], point1[1],
                                                                                                    abs_tol=range_):
                        connection = ((min(line[1], line[3]), line[2]), (max(line[1], line[3]), line[2]))
                        if connection not in connections[point1]["T_shape"]:
                            connections[point1]["T_shape"].append(connection)

    unused_points = set(points)

    # 去除有连接的端点
    for point, conn in connections.items():
        if conn['right_angle'] or conn['T_shape']:
            if point in unused_points:
                unused_points.remove(point)

    # 创建连接线
    connection_lines = []
    unused_points = list(unused_points)
    for i in range(0, len(unused_points) - 1, 2):
        p1 = unused_points[i]
        p2 = unused_points[i + 1]
        connection_lines.append((point_to_line_id[p1], p1[0], p1[1], p2[0], p2[1]))

    return connections, connection_lines


# 示例用法
lines = [
    (1, 0, 0, 10, 0),  # 线段1:水平线
    (2, 5, -5, 5, 5),  # 线段2:竖直线
    (3, 10, 0, 20, 0),  # 线段3:水平线
    (4, 15, -5, 15, 5),  # 线段4:竖直线
    (5, 0, 0, 5, 5)  # 线段5:重复端点坐标的线段
]

range_ = 5  # 自定义范围
connections, connection_lines = check_connections(lines, range_)
for point, conn in connections.items():
    print(f"Point {point}:")
    print(f"  Right-angle connections: {conn['right_angle']}")
    print(f"  T-shape connections: {conn['T_shape']}")

print("\nConnection lines:")
for conn_line in connection_lines:
    print(conn_line)

  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.
  • 15.
  • 16.
  • 17.
  • 18.
  • 19.
  • 20.
  • 21.
  • 22.
  • 23.
  • 24.
  • 25.
  • 26.
  • 27.
  • 28.
  • 29.
  • 30.
  • 31.
  • 32.
  • 33.
  • 34.
  • 35.
  • 36.
  • 37.
  • 38.
  • 39.
  • 40.
  • 41.
  • 42.
  • 43.
  • 44.
  • 45.
  • 46.
  • 47.
  • 48.
  • 49.
  • 50.
  • 51.
  • 52.
  • 53.
  • 54.
  • 55.
  • 56.
  • 57.
  • 58.
  • 59.
  • 60.
  • 61.
  • 62.
  • 63.
  • 64.
  • 65.
  • 66.
  • 67.
  • 68.
  • 69.
  • 70.
  • 71.
  • 72.
  • 73.
  • 74.
  • 75.
  • 76.
  • 77.
  • 78.
  • 79.
  • 80.
  • 81.
  • 82.
  • 83.
  • 84.
  • 85.
  • 86.
  • 87.
  • 88.
  • 89.
  • 90.
  • 91.
  • 92.
  • 93.

说明
提取线段端点:

使用字典 points 存储每个端点和对应的线段ID。
使用字典 connections 存储每个端点的连接情况。
检查连接情况:

遍历所有端点,检查每个端点与其他端点是否在给定范围内,如果是则记录为 right_angle 连接。
检查每个端点是否连接到其他线段上,如果是则记录为 T_shape 连接。
去除已连接端点:

使用集合 unused_points 存储未连接的端点,并去除有连接的端点。
创建连接线:

将未连接的端点成对连接起来,生成新的连接线。
这种方式避免了重复检查相同端点,简化了过程,同时保证功能完整


如果不需要ID,我们可以简化数据结构,只包含端点坐标。以下是改进后的代码:

import math

def is_close(p1, p2, range_):
    """判断两个点是否在指定范围内"""
    return math.isclose(p1[0], p2[0], abs_tol=range_) and math.isclose(p1[1], p2[1], abs_tol=range_)

def check_connections(lines, range_):
    """检查每个线段端点的连接情况"""
    points = {}
    connections = {}
    
    # 提取所有线段的端点,并存储到字典中以避免重复
    for line in lines:
        point1 = (line[0], line[1])
        point2 = (line[2], line[3])
        points[point1] = points.get(point1, 0) + 1
        points[point2] = points.get(point2, 0) + 1
    
    # 遍历所有端点,检查连接情况
    for point1 in points:
        if point1 not in connections:
            connections[point1] = {"right_angle": [], "T_shape": []}
        
        for point2 in points:
            if point1 != point2 and is_close(point1, point2, range_):
                connections[point1]["right_angle"].append(point2)
        
        for line in lines:
            if point1 not in [(line[0], line[1]), (line[2], line[3])]:
                if line[0] == line[2]:  # 竖直线
                    if min(line[1], line[3]) <= point1[1] <= max(line[1], line[3]) and math.isclose(line[0], point1[0], abs_tol=range_):
                        connections[point1]["T_shape"].append(((line[0], min(line[1], line[3])), (line[0], max(line[1], line[3]))))
                elif line[1] == line[3]:  # 水平线
                    if min(line[0], line[2]) <= point1[0] <= max(line[0], line[2]) and math.isclose(line[1], point1[1], abs_tol=range_):
                        connections[point1]["T_shape"].append(((min(line[0], line[2]), line[1]), (max(line[0], line[2]), line[1])))
    
    unused_points = set(points.keys())
    
    # 去除有连接的端点
    for point, conn in connections.items():
        if conn['right_angle'] or conn['T_shape']:
            unused_points.discard(point)
    
    # 创建连接线
    connection_lines = []
    unused_points = list(unused_points)
    for i in range(0, len(unused_points) - 1, 2):
        p1 = unused_points[i]
        p2 = unused_points[i + 1]
        connection_lines.append((p1[0], p1[1], p2[0], p2[1]))

    return connections, connection_lines

# 示例用法
lines = [
    (0, 0, 10, 0),  # 线段1:水平线
    (5, -5, 5, 5),  # 线段2:竖直线
    (10, 0, 20, 0),  # 线段3:水平线
    (15, -5, 15, 5),  # 线段4:竖直线
    (0, 0, 5, 5)  # 线段5:重复端点坐标的线段
]

range_ = 5  # 自定义范围
connections, connection_lines = check_connections(lines, range_)
for point, conn in connections.items():
    print(f"Point {point}:")
    print(f"  Right-angle connections: {conn['right_angle']}")
    print(f"  T-shape connections: {conn['T_shape']}")

print("\nConnection lines:")
for conn_line in connection_lines:
    print(conn_line)

  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.
  • 15.
  • 16.
  • 17.
  • 18.
  • 19.
  • 20.
  • 21.
  • 22.
  • 23.
  • 24.
  • 25.
  • 26.
  • 27.
  • 28.
  • 29.
  • 30.
  • 31.
  • 32.
  • 33.
  • 34.
  • 35.
  • 36.
  • 37.
  • 38.
  • 39.
  • 40.
  • 41.
  • 42.
  • 43.
  • 44.
  • 45.
  • 46.
  • 47.
  • 48.
  • 49.
  • 50.
  • 51.
  • 52.
  • 53.
  • 54.
  • 55.
  • 56.
  • 57.
  • 58.
  • 59.
  • 60.
  • 61.
  • 62.
  • 63.
  • 64.
  • 65.
  • 66.
  • 67.
  • 68.
  • 69.
  • 70.
  • 71.
  • 72.
  • 73.

说明
提取线段端点:

使用字典 points 存储每个端点及其出现的次数。
检查连接情况:

遍历所有端点,检查每个端点与其他端点是否在给定范围内,如果是则记录为 right_angle 连接。
检查每个端点是否连接到其他线段上,如果是则记录为 T_shape 连接。
去除已连接端点:

使用集合 unused_points 存储未连接的端点,并去除有连接的端点。
创建连接线:

将未连接的端点成对连接起来,生成新的连接线。
这样,我们可以简化数据结构,只包含端点坐标,并保持原有的功能。

+++++++++++++++++++++

字典类型:

import math


def is_close(p1, p2, range_):
    """判断两个点是否在指定范围内"""
    return math.isclose(p1[0], p2[0], abs_tol=range_) and math.isclose(p1[1], p2[1], abs_tol=range_)


def check_connections(lines, range_):
    """检查每个线段端点的连接情况"""
    points = {}
    connections = {}

    # 提取所有线段的端点,并存储到字典中以避免重复
    for line in lines:
        line_id = line[0]
        point1 = (line[1], line[2])
        point2 = (line[3], line[4])
        points[point1] = line_id
        points[point2] = line_id

    # 遍历所有端点,检查连接情况
    for point1 in points:
        if point1 not in connections:
            connections[point1] = {"right_angle": [], "T_shape": []}

        for point2 in points:
            if point1 != point2 and is_close(point1, point2, range_):
                connections[point1]["right_angle"].append(point2)

        for line in lines:
            if point1 not in [(line[1], line[2]), (line[3], line[4])]:
                if line[1] == line[3]:  # 竖直线
                    if min(line[2], line[4]) <= point1[1] <= max(line[2], line[4]) and math.isclose(line[1], point1[0],
                                                                                                    abs_tol=range_):
                        connections[point1]["T_shape"].append(
                            ((line[1], min(line[2], line[4])), (line[1], max(line[2], line[4]))))
                elif line[2] == line[4]:  # 水平线
                    if min(line[1], line[3]) <= point1[0] <= max(line[1], line[3]) and math.isclose(line[2], point1[1],
                                                                                                    abs_tol=range_):
                        connections[point1]["T_shape"].append(
                            ((min(line[1], line[3]), line[2]), (max(line[1], line[3]), line[2])))

    unused_points = set(points.keys())

    # 去除有连接的端点
    for point, conn in connections.items():
        if conn['right_angle'] or conn['T_shape']:
            unused_points.discard(point)

    # 创建连接线
    connection_lines = []
    unused_points = list(unused_points)
    for i in range(0, len(unused_points) - 1, 2):
        p1 = unused_points[i]
        p2 = unused_points[i + 1]
        connection_lines.append((points[p1], p1[0], p1[1], p2[0], p2[1]))

    return connections, connection_lines


# 示例用法
lines = [
    (1, 0, 0, 10, 0),  # 线段1:水平线
    (2, 5, -5, 5, 5),  # 线段2:竖直线
    (3, 10, 0, 20, 0),  # 线段3:水平线
    (4, 15, -5, 15, 5),  # 线段4:竖直线
    (5, 0, 0, 5, 5)  # 线段5:重复端点坐标的线段
]

range_ = 5  # 自定义范围
connections, connection_lines = check_connections(lines, range_)
for point, conn in connections.items():
    print(f"Point {point}:")
    print(f"  Right-angle connections: {conn['right_angle']}")
    print(f"  T-shape connections: {conn['T_shape']}")

print("\nConnection lines:")
for conn_line in connection_lines:
    print(conn_line)

  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.
  • 15.
  • 16.
  • 17.
  • 18.
  • 19.
  • 20.
  • 21.
  • 22.
  • 23.
  • 24.
  • 25.
  • 26.
  • 27.
  • 28.
  • 29.
  • 30.
  • 31.
  • 32.
  • 33.
  • 34.
  • 35.
  • 36.
  • 37.
  • 38.
  • 39.
  • 40.
  • 41.
  • 42.
  • 43.
  • 44.
  • 45.
  • 46.
  • 47.
  • 48.
  • 49.
  • 50.
  • 51.
  • 52.
  • 53.
  • 54.
  • 55.
  • 56.
  • 57.
  • 58.
  • 59.
  • 60.
  • 61.
  • 62.
  • 63.
  • 64.
  • 65.
  • 66.
  • 67.
  • 68.
  • 69.
  • 70.
  • 71.
  • 72.
  • 73.
  • 74.
  • 75.
  • 76.
  • 77.
  • 78.
  • 79.
  • 80.
  • 81.