Ruby code to draw non-simple, non-convex polygons in view#draw

The view#draw draw method in the Ruby API is limited by the GL_POLYGON parameter to handle only simple, convex polygons. That means it will glitch if you have a polygon with holes or that is not convex.

Does anyone have working code to handle non-simple (e.g. with holes) non-convex polygons that you would be willing to share? I suppose it requires triangulating the polygon, but I haven’t yet found code to do that for this general case in 3D.

# tr_face = determine the @face trasformation
mesh = @face.mesh
mesh.transform!( tr_face )
(1..mesh.count_polygons).each{|i|
  points = mesh.polygon_points_at(i)
  view.draw(GL_POLYGON, points)
}
2 Likes

You can use the method Geom.tesselate

class Tool
  def initialize
    face = Sketchup.active_model.selection[0]
    @loops = face.loops.map { |loop| loop.vertices.map { |vertex| vertex.position } }
  end

  def onMouseMove(flags, x, y, view)
    view.invalidate
  end

  def draw(view)
    outer = @loops[0]
    inner = @loops[1..-1]
    view.drawing_color = 'red'
    view.draw(GL_TRIANGLES, Geom.tesselate(outer, *inner))
  end
end

Sketchup.active_model.select_tool Tool.new

3 Likes

Thanks @dezmo, that works a charm so long as the SketchUp version is 2022 or later - which applies in my case because I’m working on an overlay and they are only 2023 or later.

1 Like

That works too. I wonder how the performance differs from @Dezmo’s idea? Would probably need a very complicated polygon to even detect a difference!

If you need to generate triangles but there is no existing face, you can use Geom.tesselate.

In my case there is always a pre-existing face that the overlay is drawing atop.