import matplotlib.pyplot as plt import matplotlib.patches as patches import numpy as np class Config: # ============================== # 당구대(국내 중대) 기본 치수 (mm) # ============================== table_length = 2720 table_width = 1486 play_length = 2448 play_width = 1224 ball_radius=65.5/2 한칸 = 306 # ============================== # Figure 설정 # ============================== fig, ax = plt.subplots(figsize=(14,7)) # ============================== # ⚪ 공/원 함수 # ============================== def draw_ball(x, y, r,facecolor="white", edgecolor=None, linewidth=1): """ x, y : 플레이영역 기준 좌표 (mm) r : 반지름 (mm) """ if edgecolor == None : edgecolor=facecolor circle = patches.Circle( (x, y), r, facecolor=facecolor, #'None':투명 edgecolor=edgecolor, linewidth=linewidth ) ax.add_patch(circle) # ============================== # ⚪ 화살표함수 # ============================== def draw_arrow(x1,y1,x2,y2,color="red",alpha=1.0, head_width=20): # arrow = (x1, y1, x2, y2) -> x1,y1에서 x2,y2로 가는 화살표 #x1, y1, x2, y2 = 300, 300, -250, 400 dx = x2 - x1 dy = y2 - y1 arrow = patches.FancyArrow( x1, y1, dx, dy, width=1, # 화살표 몸통 두께 head_width=head_width, # 화살표 머리 너비 head_length=30, # 화살표 머리 길이 length_includes_head=True, # 길이 계산 시 머리 포함 여부 color=color, alpha=alpha, zorder=100 ) ax.add_patch(arrow) def draw_당구대( # ============================== # 당구대(국내 중대) 기본 치수 (mm) # ============================== table_length = Config.table_length, table_width = Config.table_width, play_length = Config.play_length, play_width = Config.play_width, ball_radius= Config.ball_radius, 한칸 = Config.한칸 ): margin_x = (table_length - play_length) / 2 margin_y = (table_width - play_width) / 2 # 외부 프레임 outer = patches.Rectangle( (-margin_x,-margin_y), play_length+margin_x*2, play_width+margin_y*2, linewidth=1, edgecolor='saddlebrown', facecolor='#5a2d0c' ) ax.add_patch(outer) # 외부 프레임 1 outer1 = patches.Rectangle( (-50, -50), play_length+50*2, play_width+50*2, linewidth=1, edgecolor='navy', facecolor='#0b3d91' ) ax.add_patch(outer1) # 플레이 영역 play = patches.Rectangle( (0,0), play_length, play_width, linewidth=3, edgecolor="#000033" , #'navy', facecolor='#0b3d91' ) ax.add_patch(play) # ============================== # 좌표 격자 (100mm 간격) # ============================== grid_gap = 한칸 for x in np.arange(0, play_length+1, grid_gap): ax.plot( [x, x], [0,play_width], color='white', alpha=0.15 ) for y in np.arange(0, play_width+1, grid_gap): ax.plot( [0, play_length], [y, y], color='white', alpha=0.15 ) for x in np.arange(grid_gap/2, play_length+1, grid_gap): ax.plot( [x, x], [0, play_width], color='white', alpha=0.05 ) for y in np.arange(grid_gap/2, play_width+1, grid_gap): ax.plot( [0, play_length], [y, y], color='white', alpha=0.05 ) # ============================== # 포인트 표시 # ============================== radus=5 for x in np.arange(0, play_length+1, grid_gap): x1= x y1=-90; y2=play_width+90 draw_ball(x1,y1,r=radus,facecolor='white',edgecolor='white',linewidth=1) draw_ball(x1,y2,r=radus,facecolor='white',edgecolor='white',linewidth=1) for y in np.arange(0, play_width+1, grid_gap): x1=-90; x2=play_length+90 y1=y; #-95; y2=table_length-46 draw_ball(x1,y1,r=radus,facecolor='white',edgecolor='white',linewidth=1) draw_ball(x2,y1,r=radus,facecolor='white',edgecolor='white',linewidth=1) # ============================== # 화면 설정 # ============================== #ax.set_xlim(-margin_x*3, table_length + margin_x*3) #ax.set_ylim(-margin_y*3, table_width + margin_y*3) ax.set_aspect('equal') ax.axis('off') if __name__ == '__main__': draw_당구대() draw_ball(300,600,60,facecolor='red') draw_ball(300,300,60,facecolor='white') draw_ball(-250,600,60,facecolor='none',edgecolor='red',linewidth=1) draw_arrow(300, 300, -250, 600) plt.title("Billiards Table Coordinate System (mm)") plt.show()