Rhino Python脚本:按指定高度复制和堆叠对象
在建筑设计和3D建模中,我们经常需要创建具有不同高度的多层结构。本文将介绍一个Rhino Python脚本,该脚本可以根据指定的高度列表,自动复制和堆叠选定的对象。这个脚本特别适用于快速创建概念性的建筑模型或层次化的3D结构。
脚本概述
这个脚本的主要功能是:
- 选择一个基础对象
- 根据预定义的高度列表复制这个对象
- 将复制的对象按照累计高度在Z轴方向上堆叠
让我们逐步解析这个脚本的结构和功能。
导入必要的模块
import rhinoscriptsyntax as rs
import scriptcontext as sc
这两行导入了Rhino Python脚本所需的基本模块。rhinoscriptsyntax
提供了与Rhino交互的主要功能,而scriptcontext
允许我们访问Rhino文档上下文。
定义主要函数
copy_and_move_object 函数
def copy_and_move_object(obj, distances):
bbox = rs.BoundingBox(obj)
if not bbox:
print("无法获取对象边界框")
return
initial_point = [(bbox[0][0] + bbox[6][0])/2, (bbox[0][1] + bbox[6][1])/2, bbox[0][2]]
cumulative_distances = []
total = 0
for d in distances:
total += d
cumulative_distances.append(total)
new_objects = []
for dist in cumulative_distances:
move_vector = [0, 0, dist]
new_obj = rs.CopyObject(obj)
if new_obj:
rs.MoveObject(new_obj, move_vector)
new_objects.append(new_obj)
else:
print("无法复制对象到距离 {}".format(dist))
return new_objects
这个函数是脚本的核心,它执行以下操作:
- 获取选定对象的边界框。
- 计算对象底部中心点作为初始参考点。
- 计算累积距离列表。
- 复制对象并按累积距离移动。
main 函数
def main():
obj = rs.GetObject("选择要复制的对象")
if not obj:
print("未选择对象")
return
distances = [d * 1000 for d in [2, 5.2, 10, 5.5, 5.5, 5.5, 6.5, 7, 6, 6, 4.5]]
new_objects = copy_and_move_object(obj, distances)
if new_objects:
print("成功创建了 {} 个新对象".format(len(new_objects)))
else:
print("未创建新对象")
sc.doc.Views.Redraw()
main
函数组织了整个脚本的执行流程:
- 提示用户选择一个对象。
- 定义高度列表(单位:毫米)。
- 调用
copy_and_move_object
函数。 - 输出结果信息。
- 刷新Rhino视图。
执行脚本
if __name__ == "__main__":
main()
这行代码确保脚本只在直接运行时执行main
函数,而不是在被导入为模块时执行。
使用说明
- 在Rhino中打开Python编辑器。
- 复制粘贴整个脚本。
- 运行脚本。
- 根据提示选择要复制的基础对象。
- 脚本将自动创建并堆叠对象副本。
自定义脚本
你可以通过修改distances
列表来自定义每层的高度。例如:
distances = [d * 1000 for d in [3, 4, 4, 4, 3.5, 3.5, 3.5]]
这将创建一个7层的结构,每层高度分别为3米、4米、4米、4米、3.5米、3.5米和3.5米。
结论
这个Rhino Python脚本展示了如何利用编程来自动化3D建模过程。通过简单的修改,你可以轻松创建各种复杂的多层结构,大大提高建模效率。无论是概念设计还是详细建模,这个脚本都能为你的工作流程带来便利。
代码
#coding=utf-8
import rhinoscriptsyntax as rs
import scriptcontext as sc
def copy_and_move_object(obj, distances):
# 获取对象的边界框
bbox = rs.BoundingBox(obj)
if not bbox:
print("无法获取对象边界框")
return
# 使用边界框的底部中心点作为初始点
initial_point = [(bbox[0][0] + bbox[6][0])/2, (bbox[0][1] + bbox[6][1])/2, bbox[0][2]]
cumulative_distances = []
total = 0
for d in distances:
total += d
cumulative_distances.append(total)
new_objects = []
for dist in cumulative_distances:
# 计算移动向量
move_vector = [0, 0, dist]
# 复制对象
new_obj = rs.CopyObject(obj)
if new_obj:
# 移动复制的对象
rs.MoveObject(new_obj, move_vector)
new_objects.append(new_obj)
else:
print("无法复制对象到距离 {}".format(dist))
return new_objects
def main():
obj = rs.GetObject("选择要复制的对象")
if not obj:
print("未选择对象")
return
# 使用图片中的高度数据,反向排列,并乘以1000(转换为毫米)
distances = [d * 1000 for d in [2, 5.2, 10, 5.5, 5.5, 5.5, 6.5, 7, 6, 6, 4.5]]
new_objects = copy_and_move_object(obj, distances)
if new_objects:
print("成功创建了 {} 个新对象".format(len(new_objects)))
else:
print("未创建新对象")
sc.doc.Views.Redraw()
if __name__ == "__main__":
main()