Anyone ever notice the bug in dbTransformPoint() when the orient is "R90" or "R270"?
I wrote skill code to place a poly via on Pcells automatically. But when I wanted to get the relative offset of the xy of a poly via (child of device) to the device's xy,I found that dbTransformPoint gives different results based on the orientation. Or am I somehow using dbTransformPoint() incorrectly?
The code below works except the values are minus'ed (negative values are positive, and visa-versa) when the orient is "R90" or "R270".
(foreach obj geGetSelectedSet() (foreach via (setof s obj~>children s~>objType=="stdVia") (printf "%6s (%6s) => %L\n" obj~>name obj~>orient dbTransformPoint(mapcar('difference via~>xy obj~>xy) list(0:0 obj~>orient 1.0)))))
I1 ( R90) => (-2.15 -2.05) I2 ( MYR90) => (2.15 2.05) I3 ( R180) => (2.15 2.05) I4 ( MX) => (2.15 2.05) I8 ( R270) => (-2.15 -2.05) I0 ( R0) => (2.15 2.05) I5 ( MY) => (2.15 2.05) I7 ( MXR90) => (2.15 2.05)Working with Virtuoso 6.17-64b
No, there's not a bug. It's really hard to see what you're comparing but it's very clear from some simple experiments that the transformation does the rotation of the coordinate around the origin, then applies the offset in the transformation. With the orientation if it's a compound orientation such as MYR90, it does it left to right (mirror in Y then rotate (anticlockwise) by 90 degrees).
So, for example:
orients=list("R90" "MYR90" "R180" "MX" "R270" "R0" "MY" "MXR90")xy=2.15:2.05first=foreach(mapcar orient orients cons(orient dbTransformPoint(xy list(0:0 orient 1))))
( ("R90" -2.05 2.15) ("MYR90" -2.05 -2.15) ("R180" -2.15 -2.05) ("MX" 2.15 -2.05) ("R270" 2.05 -2.15) ("R0" 2.15 2.05) ("MY" -2.15 2.05) ("MXR90" 2.05 2.15))
You can see that these are all correct. In your case the differences between the two origins are probably not the same so I'm not quite comparing like with what you're doing, but the transformation is absolutely correct.
second=foreach(mapcar orient orients cons(orient dbTransformPoint(xy list(-1:2.5 orient 1))))
( ("R90" -1.05 3.15) ("MYR90" -1.05 -1.15) ("R180" -1.15 -1.05) ("MX" 3.15 -1.05) ("R270" 3.05 -1.15) ("R0" 3.15 3.05) ("MY" -1.15 3.05) ("MXR90" 3.05 3.15))
You can see that this is just a fixed offset of -1:2.5 from above, so the offset is applied afterwards.
If you're just looking at the relative offset from the xy of the via to the xy of the device, isn't that just the difference in the xy values? I'm not sure why you would need to transform anything? Perhaps I've misunderstood what you're hoping to calculate?
I really doubted that I had found a bug, but I couldn't quite grasp what was going wrong. My goal with this code was to get the _relative_ offset between an absolute point to an instance's xy based on if the instance was at 0:0 "R0". I calculate the relative offset for the via by reading the shapes bBoxes in the PCell master. All of these values are relative to the device's origin. I then place the via by transforming the relative xy by using the device's transform. That works perfectly. But I also need to go the other way, take the absolute via xy and calculate the relative offset to the device. The via's xy is now an absolute value, so I need to transform that back to the relative offset from the device. Hence, my (incorrect) use of the dbTransformPoint.
After some thought and experimentation and some help from others. I came up with this code that calculates what I want.
(procedure getRelativeOffset(obj pt)(let (offset) ; return the x and y offset of a point relative to the obj~>xy as if the orientation was "R0" offset = dbInvertTransform(dbInvertTransform(list(mapcar('difference pt obj~>xy) obj~>orient 1.0))) car(offset)))(defun dbInvertTransform (transform) dbConcatTransform(transform cons(0:0 cdr(transform))))
The key revelation was that you can combine orientations by itself, twice (for R90 and R270), and get back to R0.R0+R0=R0R90+R90=R180R180+R180=R0R270+R270=R180MX+MX=R0MY+MY=R0MXR90+MXR90=R0MYR90+MYR90=R0