fork download
  1. import matplotlib.pyplot as plt
  2. import numpy as np
  3. from mpl_toolkits.mplot3d.art3d import Poly3DCollection
  4.  
  5. def draw_cube(ax, center, size, angle_deg, color, alpha=1.0, label=None):
  6. """
  7. 绘制一个旋转的立方体 (用于表示设备)
  8. center: (x, y) 中心点
  9. size: (length, width, height)
  10. angle_deg: 旋转角度
  11. """
  12. l, w, h = size
  13. cx, cy = center
  14. theta = np.radians(angle_deg)
  15.  
  16. # 计算底面四个角的坐标 (未旋转)
  17. # dx, dy 相对中心的偏移
  18. dx = np.array([-l/2, l/2, l/2, -l/2])
  19. dy = np.array([-w/2, -w/2, w/2, w/2])
  20.  
  21. # 旋转矩阵应用
  22. rot_x = dx * np.cos(theta) - dy * np.sin(theta)
  23. rot_y = dx * np.sin(theta) + dy * np.cos(theta)
  24.  
  25. # 加上中心坐标
  26. x = cx + rot_x
  27. y = cy + rot_y
  28. z = np.array([0, 0, 0, 0])
  29. z_top = np.array([h, h, h, h])
  30.  
  31. # 构建顶点
  32. verts = []
  33.  
  34. # 底面
  35. verts.append(list(zip(x, y, z)))
  36. # 顶面
  37. verts.append(list(zip(x, y, z_top)))
  38.  
  39. # 四个侧面
  40. for i in range(4):
  41. next_i = (i + 1) % 4
  42. verts.append([
  43. (x[i], y[i], 0),
  44. (x[next_i], y[next_i], 0),
  45. (x[next_i], y[next_i], h),
  46. (x[i], y[i], h)
  47. ])
  48.  
  49. ax.add_collection3d(Poly3DCollection(verts, facecolors=color, linewidths=1, edgecolors='k', alpha=alpha, label=label))
  50.  
  51. def draw_walls(ax, room_w, room_d, door_w, wall_h):
  52. """
  53. 绘制房间墙壁
  54. """
  55. door_start = (room_w - door_w) / 2
  56. door_end = (room_w + door_w) / 2
  57.  
  58. # 墙壁坐标定义 (x, y)
  59. # Wall 1: Top (0, 1660) to (2090, 1660)
  60. # Wall 2: Right (2090, 1660) to (2090, 0)
  61. # Wall 3: Left (0, 1660) to (0, 0)
  62. # Wall 4: Bottom Left (0, 0) to (door_start, 0)
  63. # Wall 5: Bottom Right (door_end, 0) to (2090, 0)
  64.  
  65. walls = [
  66. [(0, room_d), (room_w, room_d)], # Top
  67. [(room_w, room_d), (room_w, 0)], # Right
  68. [(0, room_d), (0, 0)], # Left
  69. [(0, 0), (door_start, 0)], # Bottom Left
  70. [(door_end, 0), (room_w, 0)] # Bottom Right
  71. ]
  72.  
  73. for w_start, w_end in walls:
  74. xs = [w_start[0], w_end[0], w_end[0], w_start[0]]
  75. ys = [w_start[1], w_end[1], w_end[1], w_start[1]]
  76. zs = [0, 0, wall_h, wall_h]
  77. verts = [list(zip(xs, ys, zs))]
  78. ax.add_collection3d(Poly3DCollection(verts, facecolors='lightgray', linewidths=1, edgecolors='gray', alpha=0.3))
  79.  
  80. # 参数设置
  81. room_w = 2090
  82. room_d = 1660
  83. door_w = 1400
  84. wall_h = 500 # 示意高度
  85. dev_l = 1710
  86. dev_w = 1140
  87. dev_h = 300 # 示意高度
  88.  
  89. fig = plt.figure(figsize=(15, 5))
  90.  
  91. # --- Subplot 1: Horizontal ---
  92. ax1 = fig.add_subplot(131, projection='3d')
  93. ax1.set_title("State A: Horizontal (Inside)\nFits Easily", fontsize=12, pad=20)
  94. draw_walls(ax1, room_w, room_d, door_w, wall_h)
  95. # Place horizontal: Centered
  96. draw_cube(ax1, (room_w/2, room_d/2), (dev_l, dev_w, dev_h), 0, '#4CAF50', alpha=0.8) # Green
  97. ax1.set_xlim(-200, room_w+200)
  98. ax1.set_ylim(-500, room_d+200)
  99. ax1.set_zlim(0, 1000)
  100. ax1.view_init(elev=50, azim=-90) # Top down view
  101. ax1.set_xlabel('Width (2090)')
  102. ax1.set_ylabel('Depth (1660)')
  103. ax1.set_zticks([])
  104.  
  105. # --- Subplot 2: Diagonal (The Squeeze) ---
  106. ax2 = fig.add_subplot(132, projection='3d')
  107. ax2.set_title("State B: Rotation (45 Deg)\nMust use Door Opening!", fontsize=12, color='red', pad=20)
  108. draw_walls(ax2, room_w, room_d, door_w, wall_h)
  109. # Place diagonal: 45 degrees.
  110. # Position it so top corner touches top wall roughly.
  111. # y_center + projected_half_length = 1660
  112. # projected_half_length at 45 deg = (1710/2 * sin45 + 1140/2 * cos45) approx.
  113. # To make it visual, we just center it but shifted down to use the door.
  114. draw_cube(ax2, (room_w/2, 600), (dev_l, dev_w, dev_h), 45, '#FF9800', alpha=0.8) # Orange
  115. ax2.text(room_w/2, 1700, 0, "Top Wall Limit", color='red', fontsize=8)
  116. ax2.text(room_w/2, -200, 0, "Sticks Out", color='red', fontsize=8)
  117. ax2.set_xlim(-200, room_w+200)
  118. ax2.set_ylim(-500, room_d+200)
  119. ax2.set_zlim(0, 1000)
  120. ax2.view_init(elev=50, azim=-90)
  121. ax2.set_zticks([])
  122.  
  123. # --- Subplot 3: Vertical ---
  124. ax3 = fig.add_subplot(133, projection='3d')
  125. ax3.set_title("State C: Vertical\nSticks Out ~50mm", fontsize=12, pad=20)
  126. draw_walls(ax3, room_w, room_d, door_w, wall_h)
  127. # Place vertical: 90 degrees.
  128. # Must stick out bottom. Top at 1660.
  129. # y_center = 1660 - 1710/2 = 805
  130. draw_cube(ax3, (room_w/2, 805), (dev_l, dev_w, dev_h), 90, '#2196F3', alpha=0.8) # Blue
  131. ax3.text(room_w/2 + 700, 0, 0, "Door Width 1400", color='blue', fontsize=8)
  132. ax3.set_xlim(-200, room_w+200)
  133. ax3.set_ylim(-500, room_d+200)
  134. ax3.set_zlim(0, 1000)
  135. ax3.view_init(elev=50, azim=-90)
  136. ax3.set_zticks([])
  137.  
  138. plt.tight_layout()
  139. plt.show()
  140.  
Success #stdin #stdout #stderr 3.6s 71260KB
stdin
Standard input is empty
stdout
Standard output is empty
stderr
Fontconfig error: No writable cache directories