🌓
搜索
 找回密码
 立即注册

SketchUp插件开发(十七)开洞工具——绘制窗洞

平淡多好a 2022-8-24 13:29:24 95535

前面我们在墙的开的洞只是固定位置固定尺寸的窗洞,本篇中我们利用拾取点绘制任意位置任意尺寸的窗洞,和之前不同的也只是确定窗洞面的4个坐标点位置,其他的像添加窗洞面、推拉等操作和之前是一样的。实际上确定4个坐标点位置的过程也就是使用工具指定两个点构造出一个矩形的过程。

工具状态

类似于画线成墙工具,绘制开洞的操作中我们也需要给工具一个状态,让我们在操作过程中清楚当前是在确定首点还 确定尾点,所以首先需要一个变量记录工具状态,一个记录首点一个记录尾点。另外,因为我们是要在一堵墙上开洞并且先要在墙的一个面上确定位置,所以我们还需要记录这堵墙和墙的这个面。

# 工具激活
def activate
  @status = :start
  @start_pt = nil
  @end_pt = nil
​
  @wall = nil
  @face = nil
end

又见InputPoint

前面我们使用InputPoint类来获取三维坐标系中的一个模型坐标,这里我们还是会用到它,不止是使用它获取坐标,还需要用它来拾取当前坐标所在的面,毕竟我们是要在墙的面上开洞嘛,首先得确认我们捕捉到的点是在墙的面上才行。

这在SketchUp的API里叫做自由度,自由度分几个级别:

  • 在3维空间中,自由度为3,表示在3维空间中不受限制。
  • 在某个实体面上,自由度为2,表示在该实体面上不受限制。
  • 在某条边上或坐标轴上,自由度为1,表示在边上或轴上不受限制。
  • 在顶点或交点上,自由度为0,表示无自由度,位置只能是这个点。

一旦确定自由度之后就可以使用InputPoint对象来获取当前限制自由度的实体,这里我们只对点在面上感兴趣

ip = view.inputpoint(x, y)
if ip.degrees_of_freedom == 2
  p ip.face
end

把这段代码放在鼠标移动方法中时,随着鼠标的移动,可以在控制台看到当前鼠标点所在的面的对象

AyJyJS7gyJiYy26Y.jpg

确定起始点

确定开洞的起始点比较关键,这涉及到确定开洞的墙和绘制窗洞面的墙面。结合拾取墙和上面InputPoint的功能,我们可以先把墙和绘制窗洞面的墙面作一个判断。如果符合要求,则把墙和面记录下来,如果不符合要求则不作处理。

首先需要在鼠标移动时,把捕捉拾取到的信息记录下来

ph = view.pick_helper(x, y)
@wall = ph.best_picked
ip = view.inputpoint(x, y)
if ip.degrees_of_freedom == 2
  case @status
  when :start
    @face = ip.face
    @start_pt = ip.position
  end
end

然后在鼠标点击时对记录的信息作判断,判断生效才变换到下一工具状态

if @wall && @wall.attribute_dictionary('my_wall', false) && @face
  start_pt = @wall.get_attribute('my_wall', 'start')
  end_pt = @wall.get_attribute('my_wall', 'end')
  vector = end_pt - start_pt
  return unless @face.normal.perpendicular?(vector) && @face.normal.perpendicular?(Z_AXIS)
  @status = :end
end

确定结束点

确定结束点则比较简单,只需要当前拾取到的面和起始点时候的面是同一个,且和起始点可以构成一个矩形即可。同样,结束点也是在鼠标移动时获取

if ip.face == @face
  @end_pt = ip.position
end

在鼠标点击时判断确认

start_pt = @wall.get_attribute('my_wall', 'start')
end_pt = @wall.get_attribute('my_wall', 'end')
wall_vector = end_pt - start_pt
vector = @end_pt - @start_pt
return unless vector.valid?
return if vector.parallel?(wall_vector) || vector.parallel?(Z_AXIS)

创建窗洞

有了窗洞面的起始点和结束点之后,可以再依据墙的走向方向和高度方向确定出整个矩形的坐标,这可以通过点向直线投影来计算。然后添加一个窗洞面到墙面上,并推拉形成窗洞。

wall_vector = end_pt - start_pt
points = [@start_pt, @end_pt.project_to_line([@start_pt, wall_vector]),
          @end_pt, @start_pt.project_to_line([@end_pt, wall_vector])]
​
face = @wall.definition.entities.add_face(points)
face.pushpull(-thickness.mm)
o83162ZY4BhB31O6.jpg

除了以上的功能以外,在绘制过程中我们还可以添加视图绘制实时查看绘制的窗洞的大小来优化交互效果和体验,还可以通过增加用户输入功能来绘制指定大小的窗洞等,这些类似于画墙工具的优化项这里不再详细介绍。

更多内容可以关注“小众程序员”微信公众号获取。

扫一扫

0 回复

高级模式
游客
返回顶部