[python]通過一個矩形切割另外一個矩形
阿新 • • 發佈:2022-05-25
單例:
應用:
#!/bin/env python # -*- coding:utf-8 from typing import * import matplotlib.pyplot as plt from matplotlib.patches import Rectangle from random import randint as ri import random def getColor(): color: int color1 = ri(16, 255) color2 = ri(16, 255) color3 = ri(16, 255) color1 = hex(color1) color2 = hex(color2) color3 = hex(color3) ans = "#" + color1[2:] + color2[2:] + color3[2:] return ans def randomcolor(): colorArr = ['1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'] color = "" for i in range(6): color += colorArr[random.randint(0, 14)] return "#" + color def cut_rect_by_line(rect: tuple, line: tuple): """ :param rect: :param line: :return: """ rect_l = [] rect_r = [] rect_t = [] rect_b = [] if line[0] == 'x': if rect[0] < line[1] < rect[2]: rect_l = (rect[0], rect[1], line[1], rect[3]) rect_r = (line[1], rect[1], rect[2], rect[3]) elif line[1] <= rect[0]: rect_r = rect elif line[1] >= rect[2]: rect_l = rect elif line[0] == 'y': if rect[1] < line[1] < rect[3]: rect_t = (rect[0], line[1], rect[2], rect[3]) rect_b = (rect[0], rect[1], rect[2], line[1]) elif line[1] >= rect[3]: rect_b = rect elif line[1] <= rect[1]: rect_t = rect ret = { 't': rect_t, 'b': rect_b, 'l': rect_l, 'r': rect_r } return ret def cut_rect_by_rect(rect: tuple, sep_rect) -> Dict: line_map = {'t': ('y', sep_rect[3]), 'b': ('y', sep_rect[1]), 'l': ('x', sep_rect[0]), 'r': ('x', sep_rect[2])} frontier = [rect] ret_list = [] while frontier: rect_local = frontier.pop() temp_rect_lst = [] for k, v in line_map.items(): ret = cut_rect_by_line(rect_local, v) ret = [i for i in ret.values() if i and list(i) != list(rect_local)] temp_rect_lst.extend(ret) if not temp_rect_lst: ret_list.append(rect_local) frontier.extend(temp_rect_lst) frontier = list(set(frontier)) return list(set(ret_list)) class RingEdgeMap: OL = 'ol' OR = 'or' OT = 'ot' OB = 'ob' OLT = 'olt' ORT = 'ort' OLB = 'olb' ORB = 'orb' IL = 'il' IR = 'ir' IT = 'it' IB = 'ib' ILT = 'ilt' IRT = 'irt' ILB = 'ilb' IRB = 'irb' C = 'c' def get_rect_section(rect, sep_rect): rect_center = (rect[2] + rect[0]) / 2, (rect[3] + rect[1]) / 2 sep_rect_center = (sep_rect[2] + sep_rect[0]) / 2, (sep_rect[3] + sep_rect[1]) / 2 top = rect_center[1] > sep_rect[3] bottom = rect_center[1] < sep_rect[1] left = rect_center[0] < sep_rect[0] right = rect_center[0] > sep_rect[2] if left and top: return RingEdgeMap.OLT if left and bottom: return RingEdgeMap.OLB if right and top: return RingEdgeMap.ORT if right and bottom: return RingEdgeMap.ORB if left: return RingEdgeMap.OL if right: return RingEdgeMap.OR if top: return RingEdgeMap.OT if bottom: return RingEdgeMap.OB return RingEdgeMap.C if __name__ == '__main__': fig, ax = plt.subplots() ax.plot([10, 10], [10, 10]) rect = (0, 0, 100, 100) sep_rect = (30, 40, 90, 90) ax.add_patch(Rectangle((sep_rect[0], sep_rect[1]), sep_rect[2] - sep_rect[0], sep_rect[3] - sep_rect[1], fill=False, linewidth=1, color="red")) ax.add_patch(Rectangle((rect[0], rect[1]), rect[2] - rect[0], rect[3] - rect[1], fill=False, linewidth=1, color='blue')) rect_list = cut_rect_by_rect(rect, sep_rect=sep_rect) rect_list = list(set(rect_list)) i = 0 for rect in rect_list: i += 1 c = randomcolor() section_name = get_rect_section(rect, sep_rect) ax.add_patch(Rectangle((rect[0], rect[1]), rect[2] - rect[0], rect[3] - rect[1], fill=True, linewidth=1, color=c, alpha=0.1)) plt.text(x=(rect[2] + rect[0]) // 2, y=(rect[3] + rect[1]) // 2, color=c, s=section_name) plt.show()