在上一篇中我们已经把墙的尺寸和相关参数记录下来,接下来我们就可以获取到这些参数在墙上开洞了。在本篇中,我们暂且简单处理,点击一堵墙就在该墙上开一次洞。洞的大小取墙和长和高的一半,位置在墙的中心处。开过洞的墙做记录,不再可以开洞。 开洞工具首先我们还是要先创建一个开洞工具,用来执行开洞的交互和功能。 # 创建窗洞工具
class CreateHoleTool
# 初始化
def initialize
end
# 鼠标左键按下
def onLButtonDown(flags, x, y, view)
end
end
在这个工具中,我们只需要一个鼠标左键点击的交互操作就可以了,点击一次在墙上开一次洞。 和画墙工具一样,我们需要再添加一个按钮,用来激活开洞工具 CREATE_HOLE_TOOL = CreateHoleTool.new
cmd = UI::Command.new('窗洞工具') {
model = Sketchup.active_model
model.select_tool(CREATE_HOLE_TOOL)
}
toolbar.add_item(cmd)
选择要开洞的墙由于我们可以用画墙工具画很多墙,所以要想在指定的墙上开洞首先我们需要先指定要在哪堵墙上开洞。这里涉及到一个很重要的类PickHelper,这个类主要用来根据指定二维屏幕坐标点位置拾取模型当前层中最合适的实体,也就是我们眼睛看到的屏幕点位置的实体。 PickHelper对象是视图对象的一个辅助对象,所以它并不能单独创建,而是通过视图对象来获取 或获取对象并执行拾取 ph = view.pick_helper(x, y)
相当于 ph = view.pick_helper
ph.do_pick(x, y)
然后获取PickHelper对象拾取到的最佳实体 如果没有拾取到任何实体entity为空,否则entity就是我们眼睛看到的应该拾取到的实体。所以在鼠标左键按下操作中我们可以来拾取到墙 # 鼠标左键按下
def onLButtonDown(flags, x, y, view)
ph = view.pick_helper(x, y)
wall = ph.best_picked
p wall
end
激活工具之后,在我们画好的墙上点击,可以看到控制台输出了我们拾取到的实体 计算窗洞面的坐标确定了要开洞的墙之后,可以从墙上获取墙的参数,利用这些参数计算出来窗洞面的四个点坐标,然后创建窗洞面并推拉开洞。 首先我们要确定这是我们创建的墙,这可以通过墙实体是否有'my_wall'字典来判断, dict = wall.attribute_dictionary('my_wall', false)
如果dict为空,则这不是我们创建的墙,获取不到墙的参数,也不能在上面开洞。如果不为空,则可能继续获取到墙的参数 start_pt = wall.get_attribute('my_wall', 'start')
end_pt = wall.get_attribute('my_wall', 'end')
thickness = wall.get_attribute('my_wall', 'thickness')
height = wall.get_attribute('my_wall', 'height')
我们要创建窗洞面应该在墙的两个主面其中一个上的,这两个主面应该是平行于墙的走向向量并平行于Z轴的。根据这些条件,我们可以把墙的主面过滤出来,任取其中一个 vector = end_pt - start_pt
faces = wall.definition.entities.select { |entity|
next unless entity.is_a?(Sketchup::Face)
next unless entity.normal.perpendicular?(vector)
next unless entity.normal.perpendicular?(Z_AXIS)
true
}
face = faces[0]
获取到这个主面之后,实际上我们只是获取到这个面所在的平面,创建的窗洞面就位于这个平面上。所以由墙的参数计算出来的所有的点都要向这个面的投影才是窗洞面的最终坐标。 根据墙的起始和终止点坐标及墙的高度,我们可以计算出墙的中心点,投影到主面上就是我们窗洞面的中心点 mid_pt = Geom.linear_comination(0.5, start_pt, 0.5, end_pt)
mid_pt.offset!(Z_AXIS, height / 2)
mid_pt = mid_pt.project_to_plane(face.plane)
得到中心点之后,可以沿墙的走向向量及高度方向进行偏移,得到四个顶点坐标 points = []
points[0] = mid_pt.offset(vector, -vector.length / 4).offset(Z_AXIS, -height / 4)
points[1] = points[0].offset(vector, vector.length / 2)
points[2] = points[1].offset(Z_AXIS, height / 2)
points[3] = points[2].offset(vector, -vector.length / 2)
创建窗洞有了窗洞面的顶点坐标就可以创建出窗洞面了,再推拉墙的厚度即可以得到一个开洞的墙 face = wall.definition.entities.add_face(points)
face.pushpull(-thickness)
更多内容可以关注“小众程序员”微信公众号获取。
|