Staggered edges

I would like a script to be able to create a staggered edges similar to brickwork formation.
I have written a script that divides the edges and does a raytest to perpendicular edge, my issue at this stage is the script only works for squares/rectangles, how do I get it to work for irregular polygons? any help much appreciated, thank you.


mod = Sketchup.active_model # Open model
    ent = mod.entities # All entities in model
    sel = mod.selection # Current selection
  
    # Sorted edges length
    e = ent.grep(Sketchup::Edge)
    e_sort = e.sort{|a,b|
    a.length <=> b.length}
    
    # Vector of the longest edge
    vec = e_sort.last.start.position.vector_to e_sort.last.end.position
    
    # Get vector rotation the correct direction
    edge = e_sort.last
    fa = edge.faces[0]
    ang = 90.degrees
    ang = -ang if edge.reversed_in?(fa)
    
    # Edge point to rotate vector
    ec = edge.bounds.center
    
    # Rotate vector 90 degrees to get a perpendicular vector
    vec_trans = Geom::Transformation.rotation(ec, Z_AXIS, ang)
    rot = vec.transform!(vec_trans)
    
    # Select the Original vector
    vec2 = e_sort.last.start.position.vector_to e_sort.last.end.position
       
    # Cpoint spacing
    s = 3000.mm
    #Cpoint num
    num = vec2.length / s
    cpoints = []
    
    # Add Cpoints along edge
    (0..num).each { |i|
        sp = e_sort.last.start.position.offset(vec2,i*s)
        cpoints << sp
        #ep = e_sort[1].end.position.offset(vec2,i*s)
        cp = ent.add_cpoint(sp)
    }
    # Add Cpoint at the end pf edge
    ent.add_cpoint(e_sort.last.end.position)
    cpoints << e_sort.last.end.position
    
    # Raytest each Cpoint to the perpendicular edge
    cpoints.each{|cpt| 
      rayt = mod.raytest(cpt,rot)
      pt = rayt[0] 
      cp2 = ent.add_cpoint(pt)
      ent.add_line(cpt,pt)  
  }

1 Like

Did you find a solution for this?

One approach could be to utilize the Geom helper method (which tend to be much faster that trying to compute intersection yourself in pure Ruby.)

For instance, you could take the boundary and use point_in_polygon2D to see if any computed points for the segments you have are outside the bounday, if they are use intersect_line_line to crop?

1 Like

Thanks for your comment tt_su, I am struggling along with this. The below is the code I have written to divide the face perpendicular to the longest edge. Do you have suggestions for making this more efficient?

def divide_face
    mod = Sketchup.active_model # Open model
    ent = mod.entities # All entities in model
    sel = mod.selection # Current selection
      # select face
      face=ent.grep(Sketchup::Face).first
      #edges
      e = ent.grep(Sketchup::Edge)
      # find longest edge
      esort = e.sort{|a,b|
      a.length <=> b.length
      }
      edge = esort.last
      #longest edge start and end point
      p1=edge.start.position
      p2=edge.end.position
      # vector perpendicular to longest edge
      ang = 90.degrees
      ang = -ang if edge.reversed_in?(face)
      vector = edge.start.position.vector_to edge.end.position
      vector_trans = Geom::Transformation.rotation(edge.bounds.center, face.normal, ang)
      vector.transform!(vector_trans)
      # group face
      aent=mod.active_entities
      group = aent.add_group(face)
      group.name="Boundary"
      #scale longest line
      edge1=ent.add_line(p1,p2)
      point = edge1.bounds.center
      scale = 2
      tr = Geom::Transformation.scaling(point, scale)
      scale=ent.transform_entities(tr,edge1)
      s1=edge1.start.position
      s2=edge1.end.position
      #add perpendicular line
      perp=ent.add_line(edge1.bounds.center, edge1.bounds.center.offset(vector))
      # add longest edge
      longest=ent.add_line(s1,s2)  
      #line of the longest edge
     line=edge.line
     # length of perpendicualr edge
     len=edge.length
     dist=1220.mm
     perpl=perp.line
     tx=perpl[1].x*dist
     ty=perpl[1].y*dist
     tz=perpl[1].z*dist
     tt1=[tx,ty,tz]
     ent.add_cpoint(tt1)   
     point2=longest.bounds.center
     transform = Geom::Transformation.new(point2)
      point1 = tt1
      point3 = point1.transform(transform)
      ent.add_cpoint(point3) 
      space_line=ent.add_line(point2,point3)
      vec2 = point2.vector_to point3
      # num of offsets
      num=longest.length / dist
      # collect offset lines
      lines=[]
      #offset longest edge by perp vec dist
        for i in (0..num)
            line1=ent.add_line(longest.start.position.offset([vec2.x*i,vec2.y*i,vec2.z*i]),longest.end.position.offset([vec2.x*i,vec2.y*i,vec2.z*i]))
            lines << line1
        end
      #select lines same direction as perp
      parallel_edges=ent.select{|e|e.is_a?(Sketchup::Edge) && e.line[1].samedirection?(perp.start.position.vector_to perp.end.position)}
      ent.erase_entities(parallel_edges)
      tr_intersect=Geom::Transformation.new()
      ent.intersect_with( false, tr_intersect, ent, tr_intersect, true, ent.to_a)
      group.explode
     del=ent.select{|e|e.is_a?(Sketchup::Edge) && e.faces.length==0}
      cpoints=ent.grep(Sketchup::ConstructionPoint)
      ent.erase_entities(del,cpoints)
   end
divide_face