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