【零基础】SU固定底面的批量组件缩放
零基础 本系列将回顾和串联往期几篇文章中的部分内容,并通过具体的例子作尽可能详尽的操作介绍。其中的部分细节和特殊情况将不再重复描述,专注于 零基础 和 step-by-step 两个属性。
【本期导览】 | |
一、适用场景 二、单个组件变换 三、定义垂直缩放 四、批量应用变换 五、引入随机范围 | “固定底面的批量组件缩放”指的是,每一个组件的最低点和水平位置保持不变,垂直方向上进行指定比例的拉伸。 |
一、适用场景
当模型中有多个位于不同高度的组件,并且需要分别将这些组件在垂直方向上进行拉伸或压缩时,直接使用缩放工具必然导致高度差的改变。因此就需要单独对每一个组件进行一个缩放操作。例如现在需要将这些位于不同高度的树模型统一压缩成原本高度的0.6倍:
二、单个组件变换
在批量变换之前首先需要解决单个组件的固定底面的缩放,而包括组件在内的所有图元的缩放都可以使用图元容器类(Entities)的 .transform_entities 方法。此方法有两个参数:第一个参数是变换类(Transformation)参数,表示一个几何变换;第二个参数则表示需要变换的图元。如果按照变换 t 的规则来变换 ins 图元,用代码表示为:
ins.parent.entities.transform_entities(t,ins)
其中, .parent 方法返回的是 ins 图元所在的模型,其返回的类型可以是模型类(Model),或者组件定义类(ComponentDefinition)。如果返回结果是前者,就表明 ins 图元就在当前模型最外层的结构(即一打开SU就能点选到它本身,图元不在任何一个组件或者群组内);返回结果为后者则说明 ins 图元在某个组件或者群组之中(需要双击打开其所在的群组或组件才能点选和编辑)。其后的 .entities 方法返回以上两种可能结构的图元容器定义, .transform_entities 方法就定义在这个类中。
关于模型类(Model)和图元容器类(Entities)的区别和联系在教程 [SU-R10] 中有详细的介绍。
接下来就需要解决如何表示垂直缩放的变换了。
三、定义垂直缩放
根据变换类(Transformation) .scaling 类方法的定义,缩放需要确定的缩放中心和三个方向的缩放比例总共4个参数。因为是垂直缩放,所以水平方向的两个轴缩放比例维持不变,均为1。除了垂直方向的缩放比例是人为规定的,只剩下了缩放中心需要确定。由于要求底面高度和水平位置不变,因此缩放中心应是底面的中心。
在之前组件自由落体的篇目 [SU-2021-06] 中,已经介绍过了获得组件底面中心的方法:
b=instance.bounds
bc=b.center-Geom::Vector3d.new([0,0,b.depth/2])
简言之就是通过图元类的 .bounds 方法获得其三维范围(BoundingBox),然后根据这个类定义的 .center 和 .depth 方法获取三维范围的中心和高度,根据高度的一半创建垂直于水平面的向量,最后通过点坐标与向量的计算得到底面中心点坐标 bc。
有关范围类(BoundingBox)的详细教程可查看此篇教程 [SU-R07]。
而确定了三个方向缩放比例和缩放中心以后,就可以通过变换类(Transformation)的 .scaling 类方法创建相应的变换参数,例如以 bc 为缩放中心的垂直缩放0.6倍可以定义成:
t=Geom::Transformation.scaling(bc,1,1,0.6)
有关变换类(Transformation)的详细教程可查看此篇教程 [SU-R08]。
那么对于一个 ent 图元,使其固定底面高度和水平位置在垂直方向上缩放 factor 倍就可以表示为以下这个自定义方法:
def vert_scaling(ent,factor)
b=ent.bounds
bop=b.center-Geom::Vector3d.new(0,0,b.depth/2)
t=Geom::Transformation.scaling(bop,1,1,factor)
ent.parent.entities.transform_entities(t,ent)
end
四、批量应用变换
解决了单个组件的垂直缩放后,只需要简单地使用选区类(Selection)的 .each 迭代器方法,就可以实现批量变换过程:
Sketchup.active_model.selection.each{|i|
vert_scaling(i,0.6)
}
其中, |i| 定义迭代变量,相当于将选中的每一个图元代入到 i 之中,分别执行一次 {} 中的代码。但是批量操作有一个问题,如果仅仅使用如上的代码批量操作,会给撤销带来困难。因为以上代码执行时,选中了多少个图元,就相当于单独执行了多少次缩放工具。相应地,如果要撤销也需要连续撤销这么多次,这是很危险的,尤其是缩放图元过多可能会导致一个操作占用了所有的可撤销步骤。因此还需要在迭代器前后增加一个更新可撤销步骤的代码,将整段代码打包成一个可撤销操作:
Sketchup.active_model.start_operation("Operation Name",true)
#一系列代码操作,它们造成的修改可以通过一次撤销还原
Sketchup.active_model.commit_operation
最终将整个过程打包成一个带缩放比例参数 factor 的方法:
def sel_vert_scaling(factor)
Sketchup.active_model.start_operation("Vertical Scaling",true)
Sketchup.active_model.selection.each{|i|
vert_scaling(i,factor)
}
Sketchup.active_model.commit_operation
end
这样一来只需要选择需要批量缩放的所有图元,然后执行以下代码:
sel_vert_scaling(0.6)
即可实现一个可以安全撤销的批量固定底面标高的缩放操作,以下是执行这段代码后的效果:
五、引入随机范围
当然,在植树的这个例子中,还可以在一定范围内给每一个树赋予一个随机的垂直缩放比例,以达到相对更自由的模型效果。这可以在上文中定义的 sel_vert_scaling 方法中,将 factor 参数改为一个范围参数 range,这个参数不再是数值类型,而是范围类(Range)。
范围类参数形如 0.6..1.4,通过规定两个数轴上的位置,从而框定一个确定的数值范围。通过 .min 和 .max 方法可以取得其上下界。通过 rand 随机函数和相应的简易计算可以生成一个介于两者之间的数值,以这个数值替代上文的固定缩放比例,即可实现以范围内随机数值为缩放比例的批量垂直缩放操作。
def sel_vert_scaling_rand(range)
Sketchup.active_model.start_operation("Vertical Scaling",true)
delta=range.max-range.min
Sketchup.active_model.selection.each{|i|
vert_scaling(i,delta*rand()+range.min)
}
Sketchup.active_model.commit_operation
end
执行以下代码:
sel_vert_scaling_rand(0.6..1.4)
即可得到如下效果:
以下是一个更为直观的例子:
(完)
本篇文章尽量从最浅层的内容开始解释,其中出现了几何计算、空间范围、几何变换和选区读取等内容,可以参考以下几个篇目:
也可以参考更系统的教程:
本文编号:SU-2021-09