Snap-to-grid (post facto) function?

I've been having some issues with grid bumping up and
down (probably due to fat-fingering the bindkeys, unaware).
So I have cell instances and polygon interconnect that are
now placed at a variety of grids and it's a bit ugly.

I've looked for, but not found, any "snap to grid" utility
that I would use to get everything on the 1.0u grid again.
I only find mention of snapping as a piece of other functions'
activity in the forum. There is nothing about a snap function
for objects in the manual, only Rulers.

Wonder if someone has a macro script for this perhaps?
All I really want to do is strip decimal places (rounding to
closest, would be acceptable but not strictly necessary) in
object origin / vertices, but not by hand one object at a time.

Comments

  • Hi Jim,

    DRC has a snapping feature, but that will flatten your layer and turn all paths and boxes into polygons and remove texts.

    A dirty trick is to save your layout with 1 µm database unit and later with a finer DBU again. This will force snapping, but beware of manifold snap artefacts.

    Matthias

  • Hi Jim,

    A long time ago I made the example below when working my way into Ruby and scripting. The code is most likely not the "cleanest" but it works for me. Note that it is not recursive and the vectors of instance arrays are also put on grid (you might want to resolve instance arrays first).

    Cheers,

    Tomas

    module MyMacro

    Puts selected shapes (boxes, polygons and paths) and instances (origin and array parameters on a user-defined grid.

    This function is NOT recursive.

    include RBA

    app = Application.instance
    mw = app.main_window

    lv = mw.current_view
    cv = lv.active_cellview
    ly = cv.layout

    dbu = ly.dbu

    ok = Value.new(true)

    grid = QInputDialog.getDouble(mw, "getDouble()", "Value", 0.1, dbu, 10, 5, ok)

    if ok.value

    begin

    lv.transaction("Put selected objects on grid")

    if lv == nil
    raise "Shape Statistics: No view selected"
    end

    grid_dbu = grid/dbu

    instances_to_modify = []
    shapes_to_modify = []

    lv.each_object_selected do |sel|

    if sel.is_cell_inst?
    
     instances_to_modify.push(sel) 
    
    else 
    
     shapes_to_modify.push(sel)
    
    end
    

    end

    instances_to_modify.each do |instance|

    instance = instance.inst

    trans0 = instance.trans

    text = instance.trans.to_s
    text2 = text.gsub(",", "\s").split("\s")

    px = text2[1].to_i
    py = text2[2].to_i

    point1 = Point.new(-px,-py)
    trans1 = Trans.new(point1)

    px = ((px/grid_dbu).round.to_igrid_dbu).to_i
    py = ((py/grid_dbu).round.to_i
    grid_dbu).to_i

    point2 = Point.new(px,py)
    trans2 = Trans.new(point2)

    instance.trans=trans2trans1trans0

    a = instance.a
    b = instance.b

    ax = a.x
    ay = a.y
    bx = b.x
    by = b.y

    ax = ((ax/grid_dbu).round.to_igrid_dbu).to_i
    ay = ((ay/grid_dbu).round.to_i
    grid_dbu).to_i
    bx = ((bx/grid_dbu).round.to_igrid_dbu).to_i
    by = ((by/grid_dbu).round.to_i
    grid_dbu).to_i

    a = Point.new(ax,ay)
    b = Point.new(bx,by)

    instance.a=(a)
    instance.b=(b)

    end

    shapes_to_modify.each do |shape|

    if shape.shape.is_box?

    box = shape.shape
    
    p1 = box.box_p1
    p2 = box.box_p2
    p1x = p1.x
    p1y = p1.y
    p2x = p2.x
    p2y = p2.y
    
    p1x = ((p1x/grid_dbu).round.to_i*grid_dbu).to_i
    p1y = ((p1y/grid_dbu).round.to_i*grid_dbu).to_i
    p2x = ((p2x/grid_dbu).round.to_i*grid_dbu).to_i
    p2y = ((p2y/grid_dbu).round.to_i*grid_dbu).to_i
    
    p1 = Point.new(p1x,p1y)
    p2 = Point.new(p2x,p2y)
    box.box_p1=(p1)
    box.box_p2=(p2)
    

    elsif shape.shape.is_polygon?

    polygon = shape.shape
    
    hull = []
    
    polygon.each_point_hull do |point|
    
    px = point.x
    py = point.y
    
    px = ((px/grid_dbu).round.to_i*grid_dbu).to_i
    py = ((py/grid_dbu).round.to_i*grid_dbu).to_i
    
    point = Point.new(px,py)
    
    hull.push(point)
    
    end
    

    polygonnew = Polygon.new(hull)
    polygon.polygon=polygonnew

    elsif shape.shape.is_path?

    path = shape.shape
    
    points = []
    
    path.each_point do |point|
    
    px = point.x
    py = point.y
    
    px = ((px/grid_dbu).round.to_i*grid_dbu).to_i
    py = ((py/grid_dbu).round.to_i*grid_dbu).to_i
    
    point = Point.new(px,py)
    
    points.push(point)
    
    end
    

    width = path.path.width

    width = ((width/2/grid_dbu).round.to_i*grid_dbu).to_i * 2

    bgn_ext = path.path.bgn_ext

    end_ext = path.path.end_ext

    is_round = path.path.is_round?

    pathnew = Path.new(points, width, bgn_ext, end_ext, is_round)
    path.path=pathnew

    end

    end

    ensure
    lv.commit
    end

    end

    end

  • Hi Thomas,

    if you want to achieve readability, you can put a triple backtick line in front of and after your code. Then the code will be formatted as such (markdown). See http://en.wikipedia.org/wiki/Markdown for details.

    Kind regards,

    Matthias

  • Hi Matthias,

    Thanks for the tip, could not edit, so re-post below...


    module MyMacro # Puts selected shapes (boxes, polygons and paths) and instances (origin and array parameters on a user-defined grid. # This function is NOT recursive. include RBA app = Application.instance mw = app.main_window lv = mw.current_view cv = lv.active_cellview ly = cv.layout dbu = ly.dbu ok = Value.new(true) grid = QInputDialog.getDouble(mw, "getDouble()", "Value", 0.1, dbu, 10, 5, ok) if ok.value begin lv.transaction("Put selected objects on grid") if lv == nil raise "Shape Statistics: No view selected" end grid_dbu = grid/dbu instances_to_modify = [] shapes_to_modify = [] lv.each_object_selected do |sel| if sel.is_cell_inst? instances_to_modify.push(sel) else shapes_to_modify.push(sel) end end instances_to_modify.each do |instance| instance = instance.inst trans0 = instance.trans text = instance.trans.to_s text2 = text.gsub(",", "\s").split("\s") px = text2[1].to_i py = text2[2].to_i point1 = Point.new(-px,-py) trans1 = Trans.new(point1) px = ((px/grid_dbu).round.to_i*grid_dbu).to_i py = ((py/grid_dbu).round.to_i*grid_dbu).to_i point2 = Point.new(px,py) trans2 = Trans.new(point2) instance.trans=trans2*trans1*trans0 a = instance.a b = instance.b ax = a.x ay = a.y bx = b.x by = b.y ax = ((ax/grid_dbu).round.to_i*grid_dbu).to_i ay = ((ay/grid_dbu).round.to_i*grid_dbu).to_i bx = ((bx/grid_dbu).round.to_i*grid_dbu).to_i by = ((by/grid_dbu).round.to_i*grid_dbu).to_i a = Point.new(ax,ay) b = Point.new(bx,by) instance.a=(a) instance.b=(b) end shapes_to_modify.each do |shape| if shape.shape.is_box? box = shape.shape p1 = box.box_p1 p2 = box.box_p2 p1x = p1.x p1y = p1.y p2x = p2.x p2y = p2.y p1x = ((p1x/grid_dbu).round.to_i*grid_dbu).to_i p1y = ((p1y/grid_dbu).round.to_i*grid_dbu).to_i p2x = ((p2x/grid_dbu).round.to_i*grid_dbu).to_i p2y = ((p2y/grid_dbu).round.to_i*grid_dbu).to_i p1 = Point.new(p1x,p1y) p2 = Point.new(p2x,p2y) box.box_p1=(p1) box.box_p2=(p2) elsif shape.shape.is_polygon? polygon = shape.shape hull = [] polygon.each_point_hull do |point| px = point.x py = point.y px = ((px/grid_dbu).round.to_i*grid_dbu).to_i py = ((py/grid_dbu).round.to_i*grid_dbu).to_i point = Point.new(px,py) hull.push(point) end polygonnew = Polygon.new(hull) polygon.polygon=polygonnew elsif shape.shape.is_path? path = shape.shape points = [] path.each_point do |point| px = point.x py = point.y px = ((px/grid_dbu).round.to_i*grid_dbu).to_i py = ((py/grid_dbu).round.to_i*grid_dbu).to_i point = Point.new(px,py) points.push(point) end width = path.path.width width = ((width/2/grid_dbu).round.to_i*grid_dbu).to_i * 2 bgn_ext = path.path.bgn_ext end_ext = path.path.end_ext is_round = path.path.is_round? pathnew = Path.new(points, width, bgn_ext, end_ext, is_round) path.path=pathnew end end ensure lv.commit end end end
  • Very good ... that's better to read :-)

    I think something is wrong at the beginning (make sure the initial line is only three backticks). But that's just a small flaw.

Sign In or Register to comment.