Anisotropic Scaling
general
false
false
true
edit_menu.selection_menu.sel_scale
ruby
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# DESCRIPTION: Anisotropic scaling macro for KLayout
module AnisotropicScaling
app = RBA::Application::instance
app.is_editable? || raise("KLayout must be run in editable mode to use this macro")
mw = app.main_window
view = mw.current_view
view || raise("No view open")
# check whether the selection does not contain any instances and whether there
# is any selection at all
anything = false
view.each_object_selected do |obj|
if obj.is_cell_inst?
raise("At least one instance was encountered as part of the selection.\nThese instances are not scaled. It is suggested to flatten the selection before using the anisotropic scaling function.")
end
anything = true
end
if !anything
raise("Nothing selected to scale")
end
# ask for the scaling factors
text = RBA::InputDialog::ask_string("Enter Scaling Factor", "Scaling factor (x,y)", "1.0,1.0")
if text
f = text.split(",")
f.size > 1 || f.push(f[0])
f = f.collect { |n| n.to_f }
fx = f[0]
fy = f[1]
# begin the transaction (undo/redo support)
view.transaction("Anisotropic scaling")
begin
# perform the scaling on every object
view.each_object_selected do |obj|
if !obj.is_cell_inst?
if obj.shape.is_polygon? || obj.shape.is_simple_polygon? || obj.shape.is_path?
# Anisotropic scaling of polygon (paths are converted as polygons
# because in the general case the width cannot be maintained)
poly = obj.shape.polygon
new_hull = []
poly.each_point_hull do |p|
new_hull.push(RBA::Point::new((p.x * fx + 0.5).floor, (p.y * fy + 0.5).floor))
end
poly.assign_hull(new_hull)
poly.holes.times do |hi|
new_hole = []
poly.each_point_hole(hi) do |p|
new_hole.push(RBA::Point::new((p.x * fx + 0.5).floor, (p.y * fy + 0.5).floor))
end
poly.assign_hole(hi, new_hole)
end
obj.shape.polygon = poly
elsif obj.shape.is_box?
# Anisotropic scaling of box
box = obj.shape.box
p1 = RBA::Point::new((box.p1.x * fx + 0.5).floor, (box.p1.y * fy + 0.5).floor)
p2 = RBA::Point::new((box.p2.x * fx + 0.5).floor, (box.p2.y * fy + 0.5).floor)
obj.shape.box = RBA::Box::new(p1, p2)
end
end
end
ensure
view.commit
view.cancel
end
end
end