It looks like you're new here. If you want to get involved, click one of these buttons!
Hi,
I took the Circle PCell example code and modified it so it's an ellipse with a box as the guiding shape.
As you move or drag the guiding shape around, the shape is correctly generated. I am generating the shape with its center given by two hidden parameters, cx and cy.
As you can expect, the actual origin of the PCell (the one you see when you press 'q', under Geometry tab, x and y; or the one that shows as a "+" on the layout when the PCell is selected) is unchanged through all of this. Because it's cx and cy that I am using to move the ellipse, not actually moving the instance itself.
I would like now to change the actual origin of the PCell. So, no matter how you drag and move the guiding shape, the origin of the PCell (the "+") is always at the center of the bounding box. So, it'd behave the same as it does now, except it would modify the x,y origin of the instance (and therefore the transformation of the instance in its parent cell) to keep the cell origin always in the center of the bounding box. I hope that makes sense.
For this I'd need access to the instance transformation. But I don't see how to do that from within the class PCellDeclarationHelper. Is there a way?
Thanks,
David
module MyLib
include RBA
# Remove any definition of our classes (this helps when
# reexecuting this code after a change has been applied)
MyLib.constants.member?(:Ellipse) && remove_const(:Ellipse)
MyLib.constants.member?(:MyLib) && remove_const(:MyLib)
# The PCell declaration for the circle
class Ellipse < PCellDeclarationHelper
include RBA
def initialize
# Important: initialize the super class
super
rada = 10.0
radb = rada / 2.0
# declare the parameters
param(:l, TypeLayer, "Layer", :default => LayerInfo::new(1, 0))
param(:s, TypeShape, "", :default => DBox.new(-rada,-radb,rada,radb))
param(:ra, TypeDouble, "Radius 'a'", :default => rada)
param(:rb, TypeDouble, "Radius 'b'", :default => radb)
param(:n, TypeInt, "Number of points", :default => 64)
# this hidden parameter is used to determine whether the radius has changed
# or the "s" handle has been moved
param(:rua, TypeDouble, "Radius 'a'", :default => 0.0, :hidden => true)
param(:rub, TypeDouble, "Radius 'b'", :default => 0.0, :hidden => true)
param(:cx, TypeDouble, "Center x", :default => 0.0, :hidden => true)
param(:cy, TypeDouble, "Center y", :default => 0.0, :hidden => true)
end
def display_text_impl
# Provide a descriptive text for the cell
"Ellipse(L=#{l.to_s},Ra=#{'%.3f' % ra.to_f},Rb=#{'%.3f' % rb.to_f}))"
end
def coerce_parameters_impl
# We employ coerce_parameters_impl to decide whether the handle or the
# numeric parameter has changed (by comparing against the effective
# radii rua,rub) and set rua,rub to the effective radius. We also update the
# numerical value or the shape, depending on which on has not changed.
rsa,rsb = nil,nil
if s.is_a?(DBox)
width = s.width
height = s.height
rsa = width / 2.0
rsb = height / 2.0
#extend = (width - height) / 2.0 # How far to extend the height, in order to match the width, to keep it square rather than rectangular
#s.bottom,s.top = s.bottom - extend, s.top + extend # Coerce the height of the guid shape to be the same as the width
end
if rsa && rsb && (ra-rua).abs < 1e-6 && (rb-rub).abs < 1e-6 # An edge of the guiding shape was dragged
set_rua rsa
set_rub rsb
set_ra rsa
set_rb rsb
# Coerce the center of the circle to lie at the new center of the bounding box
center = s.center
set_cx center.x
set_cy center.y
else
set_rua ra
set_rub rb
set_s DBox.new(-ra,-rb,ra,rb)
end
# n must be larger than or equal to 4
n > 4 || (set_n 4)
end
def can_create_from_shape_impl
# Implement the "Create PCell from shape" protocol: we can use any shape which
# has a finite bounding box
shape.is_box? || shape.is_polygon? || shape.is_path?
end
def parameters_from_shape_impl
# Implement the "Create PCell from shape" protocol: we set r and l from the shape's
# bounding box width and layer
set_r shape.bbox.width * layout.dbu / 2
set_l layout.get_info(layer)
end
def transformation_from_shape_impl
# Implement the "Create PCell from shape" protocol: we use the center of the shape's
# bounding box to determine the transformation
Trans.new(shape.bbox.center)
end
def produce_impl
# This is the main part of the implementation: create the layout
# compute the ellipse
dbu = layout.dbu
pts = []
da = Math::PI * 2 / n
n.times { |i|
x = cx + rua * Math::cos(i * da)
y = cy + rub * Math::sin(i * da)
dpoint = DPoint.new(x/dbu,y/dbu)
pts << Point.from_dpoint(dpoint)
}
# create the shape
cell.shapes(l_layer).insert(Polygon.new(pts))
end
end
# The library where we will put the PCell into
class MyLib < Library
def initialize
# Set the description
self.description = "My First Library"
# Create the PCell declarations
layout.register_pcell("Ellipse", Ellipse::new)
# That would be the place to put in more PCells ...
# Register us with the name "MyLib".
# If a library with that name already existed, it will be replaced then.
register("MyLib")
end
end
# Instantiate and register the library
MyLib::new
end
Comments
Hi David,
you cannot modify the cell's instantiation point from within the cell. Instance and cell live in different spaces (instance in the host layout, cell in the library). So basically it's not possible to access the instances properties from within the PCell code.
But apart from the "+" mark there should not be any difference in usage of the PCell, right?
Matthias
I see. Too bad, but it makes sense.
It is true, PCell will be the same. However I often use the origin of the cell as some kind of mental reference point -- e.g. the "+" is snapped to some relevant grid, or aligned to some other shape when I align the two shapes -- because it is visible. If you're dragging this guiding shape box all around, the "+" could be way over there when the cell is way over here. It's also hard to know where the exact center of the ellipse is unless it is marked. (Speaking of the ellipse, but in reality I have other more complicated PCells in mind)
I suppose I could put a point at the center, at least to mark the center.
Anyway thanks for your thoughts
David