631 lines
24 KiB
Python
631 lines
24 KiB
Python
"""
|
||
流体障碍物组件
|
||
定义流体模拟中的静态或动态障碍物,支持多种形状和复杂的碰撞检测
|
||
"""
|
||
|
||
from panda3d.core import Vec3, Point3
|
||
import math
|
||
|
||
class FluidObstacle:
|
||
"""
|
||
流体障碍物类
|
||
定义流体模拟中的静态或动态障碍物,支持复杂的碰撞检测和响应
|
||
"""
|
||
|
||
# 障碍物类型
|
||
TYPE_BOX = "box"
|
||
TYPE_SPHERE = "sphere"
|
||
TYPE_CYLINDER = "cylinder"
|
||
TYPE_CONE = "cone"
|
||
TYPE_MESH = "mesh" # 三角网格
|
||
|
||
def __init__(self, position, size, obstacle_type=TYPE_BOX, mesh_data=None):
|
||
"""
|
||
初始化流体障碍物
|
||
|
||
Args:
|
||
position (Point3): 障碍物位置
|
||
size (Vec3): 障碍物尺寸
|
||
obstacle_type (str): 障碍物类型
|
||
mesh_data (dict): 网格数据(仅用于网格类型障碍物)
|
||
"""
|
||
self.position = position
|
||
self.size = size
|
||
self.obstacle_type = obstacle_type
|
||
self.mesh_data = mesh_data # 用于网格类型障碍物
|
||
|
||
# 障碍物属性
|
||
self.is_dynamic = False # 是否为动态障碍物
|
||
self.velocity = Vec3(0, 0, 0) # 动态障碍物速度
|
||
self.angular_velocity = Vec3(0, 0, 0) # 角速度
|
||
self.rotation = Vec3(0, 0, 0) # 旋转角度
|
||
|
||
# 物理属性
|
||
self.friction = 0.5 # 摩擦系数
|
||
self.restitution = 0.3 # 恢复系数
|
||
self.density = 1000.0 # 密度
|
||
self.mass = 1.0 # 质量
|
||
|
||
# 碰撞属性
|
||
self.collision_margin = 0.05 # 碰撞边缘
|
||
self.is_trigger = False # 是否为触发器(不产生物理反应)
|
||
|
||
# 阻力系数
|
||
self.drag_coefficient = 0.47 # 阻力系数(球体)
|
||
|
||
print(f"流体障碍物创建完成: {position}, 类型: {obstacle_type}")
|
||
|
||
def update(self, dt):
|
||
"""
|
||
更新障碍物状态
|
||
|
||
Args:
|
||
dt (float): 时间步长
|
||
"""
|
||
if self.is_dynamic:
|
||
# 更新动态障碍物位置
|
||
self.position += self.velocity * dt
|
||
|
||
# 更新旋转
|
||
self.rotation += self.angular_velocity * dt
|
||
|
||
# 应用重力(如果需要)
|
||
# self.velocity += Vec3(0, 0, -9.81) * dt
|
||
|
||
# 应用阻尼
|
||
self.velocity *= 0.99
|
||
self.angular_velocity *= 0.99
|
||
|
||
def handle_fluid_interaction(self, particle, dt):
|
||
"""
|
||
处理与流体粒子的交互
|
||
|
||
Args:
|
||
particle: 流体粒子对象
|
||
dt (float): 时间步长
|
||
"""
|
||
# 如果是触发器,只检测不产生物理反应
|
||
if self.is_trigger:
|
||
return self._check_collision(particle)
|
||
|
||
# 检查粒子是否与障碍物相交
|
||
collision_info = self._check_collision_detailed(particle)
|
||
if collision_info['is_colliding']:
|
||
# 计算碰撞响应
|
||
self._resolve_collision_advanced(particle, collision_info)
|
||
|
||
# 应用摩擦力
|
||
particle['velocity'] *= (1.0 - self.friction * dt)
|
||
|
||
# 应用阻力
|
||
self._apply_drag_force(particle, dt)
|
||
|
||
return collision_info['is_colliding']
|
||
|
||
def _check_collision_detailed(self, particle):
|
||
"""
|
||
详细的碰撞检测,返回碰撞信息
|
||
|
||
Args:
|
||
particle: 流体粒子对象
|
||
|
||
Returns:
|
||
dict: 碰撞信息
|
||
"""
|
||
collision_info = {
|
||
'is_colliding': False,
|
||
'normal': Vec3(0, 0, 0),
|
||
'penetration_depth': 0.0,
|
||
'contact_point': Point3(0, 0, 0)
|
||
}
|
||
|
||
if self.obstacle_type == self.TYPE_BOX:
|
||
return self._check_box_collision(particle)
|
||
elif self.obstacle_type == self.TYPE_SPHERE:
|
||
return self._check_sphere_collision(particle)
|
||
elif self.obstacle_type == self.TYPE_CYLINDER:
|
||
return self._check_cylinder_collision(particle)
|
||
elif self.obstacle_type == self.TYPE_CONE:
|
||
return self._check_cone_collision(particle)
|
||
elif self.obstacle_type == self.TYPE_MESH and self.mesh_data:
|
||
return self._check_mesh_collision(particle)
|
||
|
||
return collision_info
|
||
|
||
def _check_box_collision(self, particle):
|
||
"""
|
||
盒状碰撞检测
|
||
|
||
Args:
|
||
particle: 流体粒子对象
|
||
|
||
Returns:
|
||
dict: 碰撞信息
|
||
"""
|
||
collision_info = {
|
||
'is_colliding': False,
|
||
'normal': Vec3(0, 0, 0),
|
||
'penetration_depth': 0.0,
|
||
'contact_point': Point3(0, 0, 0)
|
||
}
|
||
|
||
pos = particle['position']
|
||
half_size = self.size * 0.5
|
||
min_bound = self.position - half_size
|
||
max_bound = self.position + half_size
|
||
|
||
# 检查是否在盒子内
|
||
if (min_bound.getX() - self.collision_margin <= pos.getX() <= max_bound.getX() + self.collision_margin and
|
||
min_bound.getY() - self.collision_margin <= pos.getY() <= max_bound.getY() + self.collision_margin and
|
||
min_bound.getZ() - self.collision_margin <= pos.getZ() <= max_bound.getZ() + self.collision_margin):
|
||
|
||
collision_info['is_colliding'] = True
|
||
|
||
# 计算法向量和穿透深度
|
||
# 找到最近的面
|
||
dx_min = abs(pos.getX() - min_bound.getX())
|
||
dx_max = abs(pos.getX() - max_bound.getX())
|
||
dy_min = abs(pos.getY() - min_bound.getY())
|
||
dy_max = abs(pos.getY() - max_bound.getY())
|
||
dz_min = abs(pos.getZ() - min_bound.getZ())
|
||
dz_max = abs(pos.getZ() - max_bound.getZ())
|
||
|
||
min_dist = min(dx_min, dx_max, dy_min, dy_max, dz_min, dz_max)
|
||
|
||
if min_dist == dx_min:
|
||
collision_info['normal'] = Vec3(-1, 0, 0)
|
||
collision_info['penetration_depth'] = dx_min
|
||
collision_info['contact_point'] = Point3(min_bound.getX(), pos.getY(), pos.getZ())
|
||
elif min_dist == dx_max:
|
||
collision_info['normal'] = Vec3(1, 0, 0)
|
||
collision_info['penetration_depth'] = dx_max
|
||
collision_info['contact_point'] = Point3(max_bound.getX(), pos.getY(), pos.getZ())
|
||
elif min_dist == dy_min:
|
||
collision_info['normal'] = Vec3(0, -1, 0)
|
||
collision_info['penetration_depth'] = dy_min
|
||
collision_info['contact_point'] = Point3(pos.getX(), min_bound.getY(), pos.getZ())
|
||
elif min_dist == dy_max:
|
||
collision_info['normal'] = Vec3(0, 1, 0)
|
||
collision_info['penetration_depth'] = dy_max
|
||
collision_info['contact_point'] = Point3(pos.getX(), max_bound.getY(), pos.getZ())
|
||
elif min_dist == dz_min:
|
||
collision_info['normal'] = Vec3(0, 0, -1)
|
||
collision_info['penetration_depth'] = dz_min
|
||
collision_info['contact_point'] = Point3(pos.getX(), pos.getY(), min_bound.getZ())
|
||
else: # dz_max
|
||
collision_info['normal'] = Vec3(0, 0, 1)
|
||
collision_info['penetration_depth'] = dz_max
|
||
collision_info['contact_point'] = Point3(pos.getX(), pos.getY(), max_bound.getZ())
|
||
|
||
return collision_info
|
||
|
||
def _check_sphere_collision(self, particle):
|
||
"""
|
||
球状碰撞检测
|
||
|
||
Args:
|
||
particle: 流体粒子对象
|
||
|
||
Returns:
|
||
dict: 碰撞信息
|
||
"""
|
||
collision_info = {
|
||
'is_colliding': False,
|
||
'normal': Vec3(0, 0, 0),
|
||
'penetration_depth': 0.0,
|
||
'contact_point': Point3(0, 0, 0)
|
||
}
|
||
|
||
pos = particle['position']
|
||
radius = self.size.getX() * 0.5
|
||
center = self.position
|
||
|
||
# 计算粒子到球心的距离
|
||
distance_vec = pos - center
|
||
distance = distance_vec.length()
|
||
|
||
# 检查是否碰撞
|
||
if distance <= radius + self.collision_margin:
|
||
collision_info['is_colliding'] = True
|
||
|
||
# 计算法向量
|
||
if distance > 0:
|
||
collision_info['normal'] = distance_vec.normalized()
|
||
else:
|
||
# 如果粒子在球心,使用默认法向量
|
||
collision_info['normal'] = Vec3(0, 0, 1)
|
||
|
||
# 计算穿透深度
|
||
collision_info['penetration_depth'] = radius + self.collision_margin - distance
|
||
|
||
# 计算接触点
|
||
collision_info['contact_point'] = center + collision_info['normal'] * radius
|
||
|
||
return collision_info
|
||
|
||
def _check_cylinder_collision(self, particle):
|
||
"""
|
||
圆柱碰撞检测
|
||
|
||
Args:
|
||
particle: 流体粒子对象
|
||
|
||
Returns:
|
||
dict: 碰撞信息
|
||
"""
|
||
collision_info = {
|
||
'is_colliding': False,
|
||
'normal': Vec3(0, 0, 0),
|
||
'penetration_depth': 0.0,
|
||
'contact_point': Point3(0, 0, 0)
|
||
}
|
||
|
||
pos = particle['position']
|
||
radius = self.size.getX() * 0.5
|
||
height = self.size.getZ()
|
||
center = self.position
|
||
|
||
# 计算在XY平面上到圆柱轴的距离
|
||
dx = pos.getX() - center.getX()
|
||
dy = pos.getY() - center.getY()
|
||
distance_xy = math.sqrt(dx*dx + dy*dy)
|
||
|
||
# 检查Z轴范围
|
||
min_z = center.getZ() - height/2.0
|
||
max_z = center.getZ() + height/2.0
|
||
in_z_range = min_z - self.collision_margin <= pos.getZ() <= max_z + self.collision_margin
|
||
|
||
# 检查是否在圆柱范围内
|
||
if distance_xy <= radius + self.collision_margin and in_z_range:
|
||
collision_info['is_colliding'] = True
|
||
|
||
# 计算法向量
|
||
if distance_xy > 0:
|
||
# 径向法向量
|
||
radial_normal = Vec3(dx, dy, 0).normalized()
|
||
|
||
# 检查是径向碰撞还是轴向碰撞
|
||
if pos.getZ() < min_z or pos.getZ() > max_z:
|
||
# 轴向碰撞
|
||
if pos.getZ() < min_z:
|
||
collision_info['normal'] = Vec3(0, 0, -1)
|
||
collision_info['contact_point'] = Point3(pos.getX(), pos.getY(), min_z)
|
||
else:
|
||
collision_info['normal'] = Vec3(0, 0, 1)
|
||
collision_info['contact_point'] = Point3(pos.getX(), pos.getY(), max_z)
|
||
collision_info['penetration_depth'] = min(abs(pos.getZ() - min_z), abs(pos.getZ() - max_z))
|
||
else:
|
||
# 径向碰撞
|
||
collision_info['normal'] = radial_normal
|
||
collision_info['contact_point'] = Point3(
|
||
center.getX() + radial_normal.getX() * radius,
|
||
center.getY() + radial_normal.getY() * radius,
|
||
pos.getZ()
|
||
)
|
||
collision_info['penetration_depth'] = radius + self.collision_margin - distance_xy
|
||
else:
|
||
# 粒子在圆柱轴上,使用默认法向量
|
||
collision_info['normal'] = Vec3(1, 0, 0)
|
||
collision_info['contact_point'] = Point3(center.getX() + radius, center.getY(), pos.getZ())
|
||
collision_info['penetration_depth'] = radius + self.collision_margin
|
||
|
||
return collision_info
|
||
|
||
def _check_cone_collision(self, particle):
|
||
"""
|
||
圆锥碰撞检测
|
||
|
||
Args:
|
||
particle: 流体粒子对象
|
||
|
||
Returns:
|
||
dict: 碰撞信息
|
||
"""
|
||
collision_info = {
|
||
'is_colliding': False,
|
||
'normal': Vec3(0, 0, 0),
|
||
'penetration_depth': 0.0,
|
||
'contact_point': Point3(0, 0, 0)
|
||
}
|
||
|
||
pos = particle['position']
|
||
radius = self.size.getX() * 0.5
|
||
height = self.size.getZ()
|
||
center = self.position
|
||
|
||
# 相对于圆锥底部的位置
|
||
rel_pos = pos - center
|
||
rel_pos.setZ(rel_pos.getZ() + height/2.0) # 调整坐标系使底部在z=0
|
||
|
||
# 计算在XY平面上到圆锥轴的距离
|
||
distance_xy = math.sqrt(rel_pos.getX()**2 + rel_pos.getY()**2)
|
||
|
||
# 检查是否在圆锥高度范围内
|
||
if 0 <= rel_pos.getZ() <= height + self.collision_margin:
|
||
# 计算圆锥在当前高度的半径
|
||
cone_radius_at_height = (rel_pos.getZ() / height) * radius
|
||
|
||
# 检查是否在圆锥内部
|
||
if distance_xy <= cone_radius_at_height + self.collision_margin:
|
||
collision_info['is_colliding'] = True
|
||
|
||
# 计算法向量和接触点
|
||
if rel_pos.getZ() <= self.collision_margin:
|
||
# 底面碰撞
|
||
collision_info['normal'] = Vec3(0, 0, -1)
|
||
collision_info['contact_point'] = Point3(pos.getX(), pos.getY(), center.getZ() - height/2.0)
|
||
collision_info['penetration_depth'] = self.collision_margin - rel_pos.getZ()
|
||
elif distance_xy <= self.collision_margin:
|
||
# 中心轴附近,特殊处理
|
||
collision_info['normal'] = Vec3(0, 0, 1)
|
||
collision_info['contact_point'] = Point3(center.getX(), center.getY(), pos.getZ())
|
||
collision_info['penetration_depth'] = self.collision_margin
|
||
else:
|
||
# 侧面碰撞
|
||
# 计算圆锥表面的法向量
|
||
radial_dir = Vec3(rel_pos.getX(), rel_pos.getY(), 0).normalized()
|
||
surface_normal = Vec3(
|
||
radial_dir.getX(),
|
||
radial_dir.getY(),
|
||
-radius / height # 圆锥的斜率
|
||
).normalized()
|
||
|
||
collision_info['normal'] = surface_normal
|
||
# 计算接触点
|
||
contact_radius = cone_radius_at_height
|
||
collision_info['contact_point'] = Point3(
|
||
center.getX() + radial_dir.getX() * contact_radius,
|
||
center.getY() + radial_dir.getY() * contact_radius,
|
||
pos.getZ()
|
||
)
|
||
collision_info['penetration_depth'] = cone_radius_at_height + self.collision_margin - distance_xy
|
||
|
||
return collision_info
|
||
|
||
def _check_mesh_collision(self, particle):
|
||
"""
|
||
网格碰撞检测(简化实现)
|
||
|
||
Args:
|
||
particle: 流体粒子对象
|
||
|
||
Returns:
|
||
dict: 碰撞信息
|
||
"""
|
||
collision_info = {
|
||
'is_colliding': False,
|
||
'normal': Vec3(0, 0, 0),
|
||
'penetration_depth': 0.0,
|
||
'contact_point': Point3(0, 0, 0)
|
||
}
|
||
|
||
# 对于网格碰撞检测,需要使用更复杂的算法
|
||
# 这里使用简化的包围盒检测
|
||
if self.mesh_data and 'vertices' in self.mesh_data:
|
||
vertices = self.mesh_data['vertices']
|
||
if vertices:
|
||
# 计算网格的包围盒
|
||
min_bound = Point3(float('inf'), float('inf'), float('inf'))
|
||
max_bound = Point3(float('-inf'), float('-inf'), float('-inf'))
|
||
|
||
for vertex in vertices:
|
||
min_bound.setX(min(min_bound.getX(), vertex.getX()))
|
||
min_bound.setY(min(min_bound.getY(), vertex.getY()))
|
||
min_bound.setZ(min(min_bound.getZ(), vertex.getZ()))
|
||
max_bound.setX(max(max_bound.getX(), vertex.getX()))
|
||
max_bound.setY(max(max_bound.getY(), vertex.getY()))
|
||
max_bound.setZ(max(max_bound.getZ(), vertex.getZ()))
|
||
|
||
# 应用位置偏移
|
||
min_bound += self.position
|
||
max_bound += self.position
|
||
|
||
pos = particle['position']
|
||
|
||
# 简单的包围盒检测
|
||
if (min_bound.getX() - self.collision_margin <= pos.getX() <= max_bound.getX() + self.collision_margin and
|
||
min_bound.getY() - self.collision_margin <= pos.getY() <= max_bound.getY() + self.collision_margin and
|
||
min_bound.getZ() - self.collision_margin <= pos.getZ() <= max_bound.getZ() + self.collision_margin):
|
||
|
||
collision_info['is_colliding'] = True
|
||
# 简化的法向量计算
|
||
collision_info['normal'] = Vec3(0, 0, 1)
|
||
collision_info['contact_point'] = pos
|
||
collision_info['penetration_depth'] = 0.1
|
||
|
||
return collision_info
|
||
|
||
def _resolve_collision_advanced(self, particle, collision_info):
|
||
"""
|
||
高级碰撞响应
|
||
|
||
Args:
|
||
particle: 流体粒子对象
|
||
collision_info (dict): 碰撞信息
|
||
"""
|
||
if not collision_info['is_colliding']:
|
||
return
|
||
|
||
# 获取碰撞信息
|
||
normal = collision_info['normal']
|
||
penetration_depth = collision_info['penetration_depth']
|
||
contact_point = collision_info['contact_point']
|
||
|
||
# 调整粒子位置以解决穿透
|
||
particle['position'] += normal * penetration_depth
|
||
|
||
# 计算碰撞响应
|
||
velocity = particle['velocity']
|
||
velocity_normal = normal * velocity.dot(normal)
|
||
velocity_tangent = velocity - velocity_normal
|
||
|
||
# 应用恢复系数
|
||
new_velocity_normal = -velocity_normal * self.restitution
|
||
new_velocity_tangent = velocity_tangent * (1.0 - self.friction)
|
||
|
||
# 更新粒子速度
|
||
particle['velocity'] = new_velocity_normal + new_velocity_tangent
|
||
|
||
# 如果是动态障碍物,也要更新障碍物的速度
|
||
if self.is_dynamic:
|
||
# 简化的动量交换
|
||
impulse = (velocity_normal - new_velocity_normal) * particle.get('mass', 1.0)
|
||
self.velocity -= impulse / self.mass
|
||
|
||
def _apply_drag_force(self, particle, dt):
|
||
"""
|
||
应用阻力
|
||
|
||
Args:
|
||
particle: 流体粒子对象
|
||
dt (float): 时间步长
|
||
"""
|
||
# 计算相对速度
|
||
relative_velocity = particle['velocity'] - self.velocity
|
||
speed = relative_velocity.length()
|
||
|
||
if speed > 0:
|
||
# 计算阻力大小
|
||
# F = 0.5 * ρ * v² * Cd * A
|
||
fluid_density = 1000.0 # 水的密度
|
||
cross_sectional_area = 0.01 # 简化的横截面积
|
||
drag_force_magnitude = 0.5 * fluid_density * speed * speed * self.drag_coefficient * cross_sectional_area
|
||
|
||
# 计算阻力方向(与速度方向相反)
|
||
drag_direction = -relative_velocity.normalized()
|
||
|
||
# 应用阻力到粒子
|
||
drag_force = drag_direction * drag_force_magnitude
|
||
particle['velocity'] += drag_force * dt / particle.get('mass', 1.0)
|
||
|
||
def set_dynamic(self, is_dynamic, velocity=None, angular_velocity=None):
|
||
"""
|
||
设置障碍物是否为动态
|
||
|
||
Args:
|
||
is_dynamic (bool): 是否为动态
|
||
velocity (Vec3): 线速度
|
||
angular_velocity (Vec3): 角速度
|
||
"""
|
||
self.is_dynamic = is_dynamic
|
||
if velocity:
|
||
self.velocity = velocity
|
||
if angular_velocity:
|
||
self.angular_velocity = angular_velocity
|
||
|
||
def set_physics_properties(self, friction=None, restitution=None, density=None, mass=None):
|
||
"""
|
||
设置物理属性
|
||
|
||
Args:
|
||
friction (float): 摩擦系数
|
||
restitution (float): 恢复系数
|
||
density (float): 密度
|
||
mass (float): 质量
|
||
"""
|
||
if friction is not None:
|
||
self.friction = max(0.0, min(1.0, friction))
|
||
if restitution is not None:
|
||
self.restitution = max(0.0, min(1.0, restitution))
|
||
if density is not None:
|
||
self.density = density
|
||
if mass is not None:
|
||
self.mass = mass
|
||
|
||
def set_collision_properties(self, margin=None, is_trigger=None):
|
||
"""
|
||
设置碰撞属性
|
||
|
||
Args:
|
||
margin (float): 碰撞边缘
|
||
is_trigger (bool): 是否为触发器
|
||
"""
|
||
if margin is not None:
|
||
self.collision_margin = max(0.0, margin)
|
||
if is_trigger is not None:
|
||
self.is_trigger = is_trigger
|
||
|
||
def apply_force(self, force, dt):
|
||
"""
|
||
对动态障碍物施加力
|
||
|
||
Args:
|
||
force (Vec3): 力向量
|
||
dt (float): 时间步长
|
||
"""
|
||
if self.is_dynamic:
|
||
# F = ma => a = F/m
|
||
acceleration = force / self.mass
|
||
self.velocity += acceleration * dt
|
||
|
||
def apply_torque(self, torque, dt):
|
||
"""
|
||
对动态障碍物施加扭矩
|
||
|
||
Args:
|
||
torque (Vec3): 扭矩向量
|
||
dt (float): 时间步长
|
||
"""
|
||
if self.is_dynamic:
|
||
# 简化的扭矩应用
|
||
self.angular_velocity += torque * dt / self.mass
|
||
|
||
def get_bounding_box(self):
|
||
"""
|
||
获取障碍物的包围盒
|
||
|
||
Returns:
|
||
tuple: (min_bound, max_bound)
|
||
"""
|
||
if self.obstacle_type == self.TYPE_BOX:
|
||
half_size = self.size * 0.5
|
||
min_bound = self.position - half_size
|
||
max_bound = self.position + half_size
|
||
return (min_bound, max_bound)
|
||
elif self.obstacle_type == self.TYPE_SPHERE:
|
||
radius = self.size.getX() * 0.5
|
||
min_bound = self.position - Vec3(radius, radius, radius)
|
||
max_bound = self.position + Vec3(radius, radius, radius)
|
||
return (min_bound, max_bound)
|
||
elif self.obstacle_type == self.TYPE_CYLINDER:
|
||
radius = self.size.getX() * 0.5
|
||
height = self.size.getZ() * 0.5
|
||
min_bound = self.position - Vec3(radius, radius, height)
|
||
max_bound = self.position + Vec3(radius, radius, height)
|
||
return (min_bound, max_bound)
|
||
elif self.obstacle_type == self.TYPE_CONE:
|
||
radius = self.size.getX() * 0.5
|
||
height = self.size.getZ() * 0.5
|
||
min_bound = self.position - Vec3(radius, radius, height)
|
||
max_bound = self.position + Vec3(radius, radius, height)
|
||
return (min_bound, max_bound)
|
||
else:
|
||
# 默认包围盒
|
||
half_size = self.size * 0.5
|
||
min_bound = self.position - half_size
|
||
max_bound = self.position + half_size
|
||
return (min_bound, max_bound)
|
||
|
||
def get_volume(self):
|
||
"""
|
||
计算障碍物体积
|
||
|
||
Returns:
|
||
float: 体积
|
||
"""
|
||
if self.obstacle_type == self.TYPE_BOX:
|
||
return self.size.getX() * self.size.getY() * self.size.getZ()
|
||
elif self.obstacle_type == self.TYPE_SPHERE:
|
||
radius = self.size.getX() * 0.5
|
||
return (4.0/3.0) * math.pi * (radius ** 3)
|
||
elif self.obstacle_type == self.TYPE_CYLINDER:
|
||
radius = self.size.getX() * 0.5
|
||
height = self.size.getZ()
|
||
return math.pi * (radius ** 2) * height
|
||
elif self.obstacle_type == self.TYPE_CONE:
|
||
radius = self.size.getX() * 0.5
|
||
height = self.size.getZ()
|
||
return (1.0/3.0) * math.pi * (radius ** 2) * height
|
||
else:
|
||
# 默认按盒状计算
|
||
return self.size.getX() * self.size.getY() * self.size.getZ() |