Sketchup.active_model.entities.add_edges not working correctly

Hi again everyone!

I’m trying to implement a simple SketchUp command that draws equidistant parallel lines inside a polygon – all of them perpendicular to a given edge. As an example, if the user selects the trapezoid below and the bottom edge, the following tiling should happen:

This works fine under my current implementation, whose main function I will include later.

However, if I start with something like

my command will only do the following:

As you can see, the tiling isn’t quite complete towards the right of the polygon (and neither it is to the left, but let’s ignore that aspect for now).

Now, if I comment out the line responsible for drawing edges and instead I call Sketchup.active_model.entities.add_cpoint, I do get the correct intersection points:

For brevity, I will only include the main function of my command, but you can assume that there is some logic dealing with line equations, intersections and point containment (hopefully correct!):

def tile(face, edge, width)
  start_point = edge.start.position
  
  # The face will change as we tile it, so save the original edges (except 
  # the currently selected one).
  other_face_edges = []
  
  face.edges.each do |face_edge|  
    if face_edge != edge
      other_face_edges << face_edge
    end
  end

  edge_line = Line.new(edge)
  max_inner_intervals = (edge.length / width).to_i
  
  # Ignore the hardcoded range for now; it will be done properly in the future.
  (0..12).each do |n|
    new_edge_point = get_point_on_edge(edge, start_point, width, n)
    perp_line = edge_line.perpendicular(new_edge_point)

    # Needed for n < 0 and n > max_inner_intervals.
    intersection_points = []
    
    other_face_edges.each do |face_edge|
      intersection_point = perp_line.intersect(Line.new(face_edge))
      
      if is_contained?(intersection_point, face_edge)
        # Handle one intersection point first.
        if 0 <= n && n <= max_inner_intervals
          Sketchup.active_model.entities.add_edges(new_edge_point, intersection_point)
        else
          intersection_points << intersection_point
          # The line adding a point for the bad case (this is used for debugging).
          # Sketchup.active_model.entities.add_cpoint(intersection_point)
        end
      end
    end
    
    if intersection_points.length == 2
      # The line that is supposed to add an edge between 2 points on the right.
      Sketchup.active_model.entities.add_edges(*intersection_points)
    end
  end
end

The problem happens at the very end: the call to add_edges only creates the line when n = 6 (I know, the (0..12) should be replaced with something more robust down the road, but this is just development work; n = 0 is the leftmost vertical line).

If I comment out this offending line and uncomment the one adding construction points I will end up with the last picture, thus showing that the intersections have been correctly computed. Therefore, I’m not sure what’s causing this behavior (I only have 2 points after all, so the line segment should be drawn without problems).

Thanks for reading and sorry for this rather long message! I would greatly appreciate your help!

It is a long post. I have asked others to drop by and see if they have ideas.

1 Like

I’m not at my computer right now, so I can’t test much. But have you tried printing intersection_points before the if block involving its length? I suspect it does not contain what you think and fails the length test.

This is what happens when I add

puts "n = #{n}, LENGTH = #{intersection_points.length}"

just before the last if statement with the call to add_edges commented out (i.e. no edges after n >= 6):

n = 0, LENGTH = 0
n = 1, LENGTH = 0
n = 2, LENGTH = 0
n = 3, LENGTH = 0
n = 4, LENGTH = 0
n = 5, LENGTH = 0
n = 6, LENGTH = 2
n = 7, LENGTH = 2
n = 8, LENGTH = 2
n = 9, LENGTH = 0
n = 10, LENGTH = 0
n = 11, LENGTH = 0
n = 12, LENGTH = 0

However, uncommenting the offending line (in order to get the edges displayed) gives the following:

n = 0, LENGTH = 0
n = 1, LENGTH = 0
n = 2, LENGTH = 0
n = 3, LENGTH = 0
n = 4, LENGTH = 0
n = 5, LENGTH = 0
n = 6, LENGTH = 2
n = 7, LENGTH = 1
n = 8, LENGTH = 1
n = 9, LENGTH = 0
n = 10, LENGTH = 0
n = 11, LENGTH = 0
n = 12, LENGTH = 0

This means that I only get 1 intersection point as opposed to 2 at n = 7 and n = 8, so something strange happens after the vertical line at n = 6 is drawn.

EDIT. Adding the following image to show that the construction points are getting messed up when the n = 6 line is drawn:

I wonder if breaking the short edge when the vertical line intersecting it is added causes SketchUp to redefine the end point of the original edge to be at the intersection and creates a new edge for the remainder. This new edge won’t be in your array of other edges.

3 Likes

Genius! That was actually the problem and I resolved it easily by saving the start.position and end.position attributes of other_face_edges instead of relying on the original Sketchup::Edge objects.

You made my day and I can’t thank you enough! :1st_place_medal:

You’re welcome!