DrawBackEdges is on then Display back side edge doted

Hello,

Creating a small script
I want to display the back side draw line dotted when @model.rendering_options[“DrawBackEdges”] is on.
thanks

see attach image

require 'sketchup.rb'

module BoundingBoxViewer
  class BoundingBoxTool
    def initialize
      @model = Sketchup.active_model
      @selection = @model.selection
      @bounding_boxes = []
      @hovered_point = nil
      update_selection
      @ip = Sketchup::InputPoint.new
    end

    def activate
      @model.active_view.invalidate
    end

    def update_selection
      @bounding_boxes.clear
      @selection.each do |entity|
        if entity.is_a?(Sketchup::Group) || entity.is_a?(Sketchup::ComponentInstance)
          bbox = entity.bounds
          points = get_bounding_points(bbox)
          @bounding_boxes << points
        end
      end
      @model.active_view.invalidate
    end

    def get_bounding_points(bbox)
      corners = (0..7).map { |i| bbox.corner(i) }

      def midpoint(pt1, pt2)
        Geom::Point3d.new((pt1.x + pt2.x) / 2.0, (pt1.y + pt2.y) / 2.0, (pt1.z + pt2.z) / 2.0)
      end

      middle_z = (bbox.min.z + bbox.max.z) / 2.0

      def plane_points_at_height(bbox, z_height)
        p1 = Geom::Point3d.new(bbox.min.x, bbox.min.y, z_height)
        p2 = Geom::Point3d.new(bbox.max.x, bbox.min.y, z_height)
        p3 = Geom::Point3d.new(bbox.max.x, bbox.max.y, z_height)
        p4 = Geom::Point3d.new(bbox.min.x, bbox.max.y, z_height)

        [
          p1, p2, p3, p4,
          midpoint(p1, p2),
          midpoint(p2, p3),
          midpoint(p3, p4),
          midpoint(p4, p1),
          midpoint(midpoint(p1, p3), midpoint(p2, p4))
        ]
      end

      bottom_points = plane_points_at_height(bbox, bbox.min.z)
      middle_points = plane_points_at_height(bbox, middle_z)
      top_points    = plane_points_at_height(bbox, bbox.max.z)

      bottom_points + middle_points + top_points
    end

    def draw(view)
      return if @bounding_boxes.empty?

      view.drawing_color = "red"
      @bounding_boxes.each_with_index do |points, index|
        points.each_with_index do |pt, i|
          special_purple_points = [5,6,7,8,14,15,16,17,23,24,25,26]
          point_color = if (i + 1) == 18
                          "red"
                        elsif special_purple_points.include?(i + 1)
                          "purple"
                        else
                          "LawnGreen"
                        end
          
		  view.draw_points([pt], 8, 1, "Gray" )
		  view.draw_points([pt], 6, 2, point_color)
          
          screen_pt = view.screen_coords(pt)
          text_color = (i + 1 == 18) ? "red" : "black"
          view.draw_text([screen_pt.x + 5, screen_pt.y - 5], "#{i + 1}", size: 12, color: text_color)
        end

        dotted_line_pairs = [[10,11], [11,12], [12,13], [13,10]]
        view.drawing_color = "black"
        view.line_stipple = " - "
        dotted_line_pairs.each do |pair|
          p1, p2 = points[pair[0] - 1], points[pair[1] - 1]
          view.draw(GL_LINES, p1, p2) if p1 && p2
        end
		
		if @model.rendering_options["DrawBackEdges"] == true
		  view.line_stipple = " - "
		  view.line_width = 1
		  dotted_line_pairs.each do |pair|
            p1, p2 = points[pair[0] - 1], points[pair[1] - 1]
            view.draw(GL_LINES, p1, p2) if p1 && p2
		  end
		end
      end
 

      if @hovered_point
        view.drawing_color = "blue"
        view.draw_points([@hovered_point], 10, 1, "Gray")
        view.draw_points([@hovered_point], 8, 2, "Red")
      else
        @ip.draw(view) if @ip.valid?
      end

      view.invalidate
    end

    def onMouseMove(flags, x, y, view)
      best_distance = 10
      @hovered_point = nil

      @ip.pick(view, x, y)

      @bounding_boxes.each do |points|
        points.each do |pt|
          screen_pt = view.screen_coords(pt)
          distance = Geom::Point3d.new(screen_pt).distance([x, y])
          if distance < best_distance
            @hovered_point = pt
            best_distance = distance
          end
        end
      end

      if @hovered_point
        Sketchup.status_text = "Hovered Point: #{@hovered_point}"
      else
        Sketchup.status_text = ""
      end

      view.invalidate
    end
  end

  def self.run
    Sketchup.active_model.select_tool(BoundingBoxTool.new)
  end
end

# REMOVE "#" TO ACTIVATE TOOL DIRECT
BoundingBoxViewer.run

Let assume we have a line defined by two pts, some other place of code e.g.:
@pts = [Geom::Point3d.new(20, 0, 0), Geom::Point3d.new(0, 1, 0)]


def draw(view)
  #lets draw dashed line in a screen 2d, so it is allays visible
  pts2d = @pts.map{|pt| view.screen_coords(pt)}
  view.line_width = 1
  view.drawing_color = "red"
  view.line_stipple = "-"
  view.draw2d(GL_LINES, pts2d)
  
  #now, draw solid line in 3d space, so 
  # if the line behind some object it wont be visible
  # but if it is not covered by object it is visible
  # and visually same place as the 2d line, 
  # so the 2d line will covered by the 3d line
  view.line_width = 2
  view.drawing_color = "red"
  view.line_stipple = ""
  view.draw(GL_LINES, @pts)
end

So, you need to draw each line twice, first in 2D (in screen space) - dashed, and then in 3D -solid.


BTW, this is syntactically wrong:

See: View #line_stipple= instance_method

PS:
For efficiency better to convert the 3d points to screen cords somewhere else, which is less frequently called… :innocent:

1 Like

Hello Dezmo, :waving_hand:

Thank you for explain I revised code and working great. :slightly_smiling_face:
check video below

1 Like