Closed matthew-e-brown closed 10 months ago
Oh, boy... I found more anchor weirdness while fiddling with these examples. I cannot come up with an explanation for this one. When rotations are present, content
elements seem to get whisked away on a magical journey.
I'd really hate to spam you with three issues back-to-back-to-back, so I'll just tack this on here...
See below: the square is translated (1, 2)
, then rotated 85deg
, and the circle is translated (10, -5)
and rotated -75deg
.
All three instances of content
that say "origin #" are placed directly at (0, 0)
with anchor: "left"
, but they end up nowhere near their dots.
This effect is compounded by both the magnitude of the rotation as well as the size of the content. What's more, it seems to add a ton of extra space around the canvas. These images are uploaded exactly as they are exported from Typst, with set page(width: auto, height: auto, margin: 1cm)
.
When I make the content longer: Image (far too tall to paste into this comment)
When I change 85deg
→ 89deg
: Image (just preposterously massive in height)
A potential hint here is that attempting to go all the way to 90 degrees causes the compiler to throw a divide-by-zero error (which is probably not desired either):
Hopefully this isn't the result of me missing some line in the manual somewhere. It does say that "content itself is not transformed," but I wouldn't expect that to rocket the coordinates off into the great beyond like this.
Thank you for bringing this up. Yes I need to clean this mess up… The content positioning is indeed very strange. Will have a look.
I had added super stupid code with #108 that lead to this content positioning. Opened a fix PR.
Awesome! You're fast. 😄
I think this can be closed because it got resolved in 0.2.0.
I think it makes sense to put this in a separate issue.
When working on my MWE for #252, I noticed something peculiar. While the circle's
top
andbottom
anchors are swapped,above
andbelow
seem to work fine:Code
```typst #import "@preview/cetz:0.1.2" #set page(width: auto, height: auto, margin: 1cm) #cetz.canvas(length: 1cm, { import cetz.draw: * circle((0, 0), name: "bob", radius: 5, stroke: 1pt + black) line((0, 0), (0, 3.5), mark: (end: ">", size: 0.25, fill: red), stroke: 1pt + red) line((0, 0), (3.5, 0), mark: (end: ">", size: 0.25, fill: green), stroke: 1pt + green) content((0, 3.75), $x$) content((3.75, 0), $y$) let anchors = ( "top", "top-left", "top-right", "bottom", "bottom-left", "bottom-right", "center", "left", "right", "above", "below", ) for pos in anchors { circle("bob." + pos, radius: 0.2, fill: gray, stroke: 0.5pt + black) let (y, anchor) = if pos == "above" or pos == "below" { (+0.3, "bottom") } else { (-0.3, "top") } content( (rel: (0, y)), anchor: anchor, frame: "rect", fill: white, stroke: 1pt + gray, padding: 0.15, text(size: 0.85em, raw(pos)) ) } }) ```This led me to snoop around and find where (I'm pretty sure)
above
andbelow
are set, and I found something else.https://github.com/johannes-wolf/cetz/blob/282e400b4e0ff583f2a3cabbffa507b94b6f53db/src/canvas.typ#L121-L154
Looking at this code, it seems to me that:
above
andbelow
are derived from the defaulttop
andbottom
anchors.custom-anchors-ctx
function for the element gets run. In the case ofcircle
, thetop
andbottom
anchors are overwritten with the (currently incorrect) ones defined in_circle-anchors
._circle-anchors
does not defineabove
/below
, they remain as they were, derived from the AABB.custom-anchors-ctx
anchors are transformed according to the current context before being inserted into theanchors
list.This results in
above
andbelow
being based on the element's AABB, buttop
andbottom
being based on the current transformation context:Code
```typst #cetz.canvas(length: 1cm, { import cetz.draw: * rotate(+22.5deg) { circle((0, 0), name: "bob", radius: 5, stroke: 1pt + black) line((0, 0), (0, 3.5), mark: (end: ">", size: 0.25, fill: red), stroke: 1pt + red) line((0, 0), (3.5, 0), mark: (end: ">", size: 0.25, fill: green), stroke: 1pt + green) content((0, 3.75), $x$) content((3.75, 0), $y$) } rotate(-22.5deg) let anchors = ( "top", "top-left", "top-right", "bottom", "bottom-left", "bottom-right", "center", "left", "right", "above", "below", ) for pos in anchors { circle("bob." + pos, radius: 0.2, fill: gray, stroke: 0.5pt + black) let (y, anchor) = if pos == "above" or pos == "below" { (+0.3, "bottom") } else { (-0.3, "top") } // https://github.com/johannes-wolf/cetz/issues/252 -- fixed manually to demonstrate // different issue let pos = if pos == "top" { "bottom" } else if pos == "bottom" { "top" } else { pos } content( (rel: (0, y)), anchor: anchor, frame: "rect", fill: white, stroke: 1pt + gray, padding: 0.15, text(size: 0.85em, raw(pos)) ) } }) ```In this case, it manifests as
above
andbelow
; but if there were any other cases of an element returning only some anchors fromcustom-anchors-ctx
, then any anchors not returned would remain in their default from-AABB state. The fact that most anchors do seem to get properly transformed and the comment saying, "add alternate names", both lead me to believe they are meant to be affected by rotations.