之前在做光伏插件的时候用到了投影功能, 投影功能有很多应用场景, 今天我们来制作一个获取柜体 内部空间 的插件。
获取柜体内部空间▼ 思路分析 * 通过`InputPoint.pick`获取鼠标在内部空间点击的位置; * 通过`Model.raytest`获取当前点往XZY轴六个方向的投影面; * 通过获取内部空间的5个投影面推断出开口面;
1、获取鼠标当前位置▼ 我们定义一个工具类去实现释放鼠标左键的响应的事件, 再通过InputPoint.pick 获取点击模型上的点: 对应代码: class InnerSpace
# ...
# 左键松开事件
def onLButtonUp(_flags, x, y, view)
# 通过视图获取点坐标
pick_point = Sketchup::InputPoint.new
pick_point.pick(view, x, y)
pick_point.position
# ...
end
# ...
end
2、往6个方向投影▼ 再通过Model.raytest 往XYZ方向投影, 收集投影线击中的物体: 对应代码: # 构造XYZ轴的6个方向的raytest列表,获取投影元素
# spot = pick_point.position
item_list = []
[1, -1].each do |vec|
(0..2).each do |i|
cu_vec = Geom::Vector3d.new(0, 0, 0)
cu_vec[i] = vec
item_list << model.raytest([spot, cu_vec], true)
end
end
备注: 拾取到的点我们往面的法方向移动一点距离, 目的是为了保证有5个方向获能取到投影面。
解释一下model.raytest 的用法: .raytest(ray, wysiwyg_flag = true) ⇒ Array(Geom::Point3d, Array<Sketchup::Drawingelement>)?
入参: ray 是我们构造的一条射线,
用于指定投影的方向。 wysiwyg_flag 表示是否忽略隐藏的物体。
返回: 返回一个包含两个元素列表, 第一个元素是投影点, 第二个元素是投影击中物体的实体集合, 文档原话是:instance path array of the entity
比如点击一个组件ComponentInstance_a上的面face_a上的点point_a 那投影得到的对象是:**[point_a,[ComponentInstance_a,face_a]]**
3、提取内部5个投影面▼ # 解析投影元素,存储内部空间的5个面
inner_faces = []
item_list.each do |item|
# 过滤投影得到的面
item_faces = item[1].select { |i| i.is_a? Sketchup::Face }
# 去除没有投影面的
inner_faces << item_faces[0] unless item_faces.empty?
end
4、获取开口面顶点▼ 这里提供一种思路: 顶点关联的面在内部面之外,说明是开口处的点(前提是开口有个厚度面) 欢迎小伙伴们交流更好的解法。 对应代码: # 通过内部空间的5个面获取开口的顶点
def get_surface_points(inner_faces)
# 存储开口顶点集合
vertices_list = []
inner_faces.each do |f|
vertices_list += f.vertices
end
# 所有顶点去重,获取顶点的关联面
surface_vertices = []
vertices_list.uniq.each do |v|
# 顶点关联的面在内部面之外,说明是开口处的点(前提是开口有个厚度面)
diff_face = v.faces - inner_faces
surface_vertices << v unless diff_face.empty?
end
surface_vertices.map do |i|
i.position
end
end
总结 该能力目前已兼容组和组件, 基于该能力在获取到开口面之后, 我们应该做一些定制化的功能, 比如一键生成门板、把手等五金件。
不过笔者对设计行业了解不多, 具体是否有价值, 能应用在哪些方面等待各位小可爱去使用。
公众号回复 内部空间 获取体验插件。
SU自动化实战相关文章推荐:
SU自动化探索相关文章推荐:
SU插件开发相关文章推荐:
|