SketchUp的自动化实战 (三)随机贴图
今天来学习一个随机贴图插件,
学习两种不同的实现。
随机贴图插件功能是:
收集选择区域中面上的材质,
随机分配给其它没有材质的面、组、组件。
并思考两个问题:
一:对比另外一种高效解法
二:什么是四色定理
思路分析
-
对选中对象进行处理,收集所有面上的材质;
-
收集没有材质的面/组/组件;
-
遍历面/组/组件,从收集的材质中随机赋值到目标实体;
通过model.selection
获取当前选中的实体,
把面上的材质、没有材质的面、组、组件收集起来
对应代码:
model = Sketchup.active_model
ents = model.active_entities
sel = model.selection
# faces用来存储没有材质的面
# groups用来存储组/组件
# mats用来存储材质
faces = []
groups = []
mats = []
# 遍历选中实体,收集材质/面/组/组件
sel.each do |e|
if e.is_a? Sketchup::Face
if e.material || e.back_material
# 如果面上有材质,把材质收集到mats
mats << e.material if e.material
mats << e.back_material if e.back_material
else
# 如果面上没有材质,把面存起来
faces << e
end
end
# 把组/组件存起来
groups << e if e.is_a? Sketchup::Group
groups << e if e.is_a? Sketchup::ComponentInstance
end
通过mats.sample
从材质中随机取出一个元素,
并赋值到面/组/组件上。
对应代码:
# 赋值到没有材质的面上
faces.each do |e|
# 随机取出一种材质
mat = mats.sample
e.material = mat
e.back_material = mat
end
# 赋值到所有组/组件上
groups.each do |e|
e.material = mats.sample
end
至此,我们的随机贴图功能就实现了,
总共大概二十多行代码。
但是魔幻语言有着聪明的技巧和意想不到的奇效,
永远有发掘不完的奇技淫巧,
总能找到让人匪夷所思的 “there is another way”
我们来看下别人的魔幻解法:
model = Sketchup.active_model
# 获取有材质属性的对象
entities = model.selection.select { |e| e.respond_to?(:material) }
# 获取有材质的属性的对象的材质
materials = entities.map(&:material).uniq.compact!
# 把材质随机赋值到对象上
entities.each { |e| e.material = materials.sample}
解释一下:
e.respond_to?(:material)
表示当前实体是否有材质属性,
Array.select()
能返回一个新数组,
该数组包含给定块为其返回真值的所有数组元素。
我们得到的entities
其实就是包含了材质属性的所有实体。
entities.map(&:material)
表示收集有材质实体中的材质,
.uniq
表示对材质去重(如果你想保留材质最初的比例关系,可以去掉)
.compact!
表示去除数组中的nil
(不然会出现没上色的情况)
这几行代码有很多知识点可以细品:
Array
的enumerators
的三种方法:map
,collect
,select
RailsCast
中的map(&:name)
用法.uniq.compact
一些数组常用的方法
上面的两个解法,
都有一个缺陷,
那就是颜色是随机的,
运气不好会导致一块区域都是一种颜色。
四色定理是什么?
我们看下下面这张图,
只要四种颜色,
任何区域都不会和相邻的区域重色。
也就是说在不引起混淆的情况下一张地图只需四种颜色来标记就行。
那如果我们的随机贴图能实现四色猜想,
那视觉效果会比随机的效果要好很多。
下期我们一起来思考怎么实现四色猜想的效果
总结
学习别人的解法,
能学习到很多。
我们把上面两种解法集成到一个插件里面,
公众号回复 随机颜色 获取开源插件
SU自动化实战相关文章推荐:
SU自动化探索相关文章推荐:
SU插件开发相关文章推荐: