fork download
  1. import numpy as np
  2. import matplotlib.pyplot as plt
  3. from matplotlib.animation import FuncAnimation
  4. from mpl_toolkits.mplot3d import Axes3D
  5. from scipy.spatial.transform import Rotation as R
  6.  
  7. # 创建画布和3D坐标轴
  8. fig = plt.figure(figsize=(8, 8))
  9. ax = fig.add_subplot(111, projection='3d')
  10. ax.set_axis_off()
  11.  
  12. # 人体各部位参数配置(增强版)
  13. body_config = {
  14. 'head': {
  15. 'type': 'sphere',
  16. 'pos': (0, 0, 1.7),
  17. 'size': 0.2,
  18. 'color': '#FFDAB9' # 肤色
  19. },
  20. 'torso': {
  21. 'type': 'cylinder',
  22. 'start': (0, 0, 1.0),
  23. 'end': (0, 0, 0.5),
  24. 'radius': 0.3,
  25. 'color': '#87CEEB' # 天蓝色
  26. },
  27. 'arm_left': {
  28. 'type': 'cylinder',
  29. 'start': (-0.3, 0, 1.3),
  30. 'end': (-0.8, 0, 1.0),
  31. 'radius': 0.1,
  32. 'color': '#87CEEB'
  33. },
  34. 'arm_right': {
  35. 'type': 'cylinder',
  36. 'start': (0.3, 0, 1.3),
  37. 'end': (0.8, 0, 1.0),
  38. 'radius': 0.1,
  39. 'color': '#87CEEB'
  40. },
  41. 'leg_left': {
  42. 'type': 'cylinder',
  43. 'start': (-0.15, 0, 0.5),
  44. 'end': (-0.3, 0, 0.0),
  45. 'radius': 0.15,
  46. 'color': '#4682B4' # 深蓝色
  47. },
  48. 'leg_right': {
  49. 'type': 'cylinder',
  50. 'start': (0.15, 0, 0.5),
  51. 'end': (0.3, 0, 0.0),
  52. 'radius': 0.15,
  53. 'color': '#4682B4'
  54. }
  55. }
  56.  
  57. class BodyPart:
  58. """人体部件基类"""
  59. def __init__(self, config):
  60. self.config = config
  61.  
  62. def draw(self, ax):
  63. raise NotImplementedError
  64.  
  65. class Sphere(BodyPart):
  66. """球体部件(用于头部)"""
  67. def draw(self, ax):
  68. u = np.linspace(0, 2 * np.pi, 30)
  69. v = np.linspace(0, np.pi, 30)
  70. x = self.config['pos'][0] + self.config['size'] * np.outer(np.cos(u), np.sin(v))
  71. y = self.config['pos'][1] + self.config['size'] * np.outer(np.sin(u), np.sin(v))
  72. z = self.config['pos'][2] + self.config['size'] * np.outer(np.ones(np.size(u)), np.cos(v))
  73. ax.plot_surface(x, y, z, color=self.config['color'], alpha=0.8)
  74.  
  75. class Cylinder(BodyPart):
  76. """圆柱体部件(用于四肢和躯干)"""
  77. def draw(self, ax):
  78. start = np.array(self.config['start'])
  79. end = np.array(self.config['end'])
  80. vec = end - start
  81. length = np.linalg.norm(vec)
  82.  
  83. # 生成圆柱体基础网格
  84. theta = np.linspace(0, 2 * np.pi, 30)
  85. z = np.linspace(0, 1, 30)
  86. theta_grid, z_grid = np.meshgrid(theta, z)
  87.  
  88. # 计算截面坐标
  89. x_grid = self.config['radius'] * np.cos(theta_grid)
  90. y_grid = self.config['radius'] * np.sin(theta_grid)
  91. z_grid = length * z_grid
  92.  
  93. # 计算旋转矩阵
  94. target_dir = vec / length
  95. initial_dir = np.array([0, 0, 1])
  96. rotation_axis = np.cross(initial_dir, target_dir)
  97. rotation_angle = np.arccos(np.dot(initial_dir, target_dir))
  98. rotation = R.from_rotvec(rotation_axis * rotation_angle)
  99.  
  100. # 应用旋转和平移
  101. points = np.vstack([x_grid.ravel(), y_grid.ravel(), z_grid.ravel()])
  102. rotated_points = rotation.apply(points.T).T
  103. translated_points = rotated_points + start.reshape(-1, 1)
  104.  
  105. # 重塑网格形状
  106. x = translated_points[0].reshape(x_grid.shape)
  107. y = translated_points[1].reshape(y_grid.shape)
  108. z = translated_points[2].reshape(z_grid.shape)
  109.  
  110. ax.plot_surface(x, y, z, color=self.config['color'], alpha=0.8)
  111.  
  112. # 创建人体部件
  113. body_parts = []
  114. for part in body_config.values():
  115. if part['type'] == 'sphere':
  116. body_parts.append(Sphere(part))
  117. elif part['type'] == 'cylinder':
  118. body_parts.append(Cylinder(part))
  119.  
  120. # 绘制初始图形
  121. for part in body_parts:
  122. part.draw(ax)
  123.  
  124. # 设置视角范围和初始角度
  125. ax.set_xlim(-1, 1)
  126. ax.set_ylim
  127.  
Success #stdin #stdout 1.2s 68404KB
stdin
Standard input is empty
stdout
Standard output is empty