-
Notifications
You must be signed in to change notification settings - Fork 12
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Account for transforms in layer metadata #40
Conversation
This single entry point will be reused by all layers
@brisvag @andy-sweet I don't have a test but this is working! As you can see in the commit list it's been a journey. 😅 Re testing: indeed @andy-sweet I immediately ran into annoying differences in the test svg, like width and height being 128.0 instead of 128 and translate being -0 instead of 0. Maybe as a test dependency we could add https://pypi.org/project/svgelements/, which would help us test actual semantic info about the produced svg vs the reference svg, rather than straight-up text? Maybe the same can be done with the plain xml tree but I have little experience working with it... |
And all it took was one PR! The diff itself (as a reviewer of the PR) is very easy to read, especially with the rendered visual diff provided by GitHub.
I.e. I don't think we should block this PR. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I did some very brief manual testing with a points layer, and behavior was as expected after reading this PR. I made some optional suggestions and there are lots of future improvements, but nothing that should block this being merged.
<svg height="128.0" width="128.0" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"><g transform="translate(-0.0 -0.0)"><circle cx="0" cy="0" r="8.0" stroke="rgb(0, 255, 255)" fill="rgb(255, 0, 0)" transform="matrix(1.0 0.0 0.0 1.0 0.0 0.0) translate(0.0 0.0) rotate(0.0) skewY(0.0) scale(1.0 1.0)" stroke-width="0.8" opacity="0.5" /><circle cx="128" cy="0" r="10.0" stroke="rgb(255, 0, 255)" fill="rgb(0, 128, 0)" transform="matrix(1.0 0.0 0.0 1.0 0.0 0.0) translate(0.0 0.0) rotate(0.0) skewY(0.0) scale(1.0 1.0)" stroke-width="5.0" opacity="0.5" /><circle cx="128" cy="128" r="12.0" stroke="rgb(255, 255, 0)" fill="rgb(0, 0, 255)" transform="matrix(1.0 0.0 0.0 1.0 0.0 0.0) translate(0.0 0.0) rotate(0.0) skewY(0.0) scale(1.0 1.0)" stroke-width="12.0" opacity="0.5" /></g></svg> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Given there is a top-level group element (in xml_to_svg
) and the transform for all the circles is the same, I would expect the transform to be defined once there and for each circle to have no transform.
Does that make sense? Or am I misunderstanding something about the SVG spec?
Doesn't necessarily block this PR, but might be worth doing if it's simple and makes the PR smaller.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I just realized we are using that transform to shift everything so the view-box can start at 0, so maybe this isn't as easy as I'd hoped.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
yeah so actually you're both right and wrong... There should be one transform per layer. When I looked at the svg changes I thought "huh, I guess he put each point in a different layer. No idea why you would do that, maybe to test multiple layers, but ok." But now I look at the code and I see that there's one transform per shape!
The top level transform is indeed used to make a tight boundary around the data. But looking at the svg spec again it does look like I can nest things with g
elements: https://developer.mozilla.org/en-US/docs/Web/SVG/Element/g, so a layer should actually go in a g element and the transforms should go in there. I'll have a look shortly.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
After looking at the code a bit I'm not super confident about the updates, and they will definitely require updating the reference svg, so I'd like to experiment after this PR. I'm going to merge and create issues for the remaining work. Thanks for the review @andy-sweet!
translate = meta.get('translate', [0, 0])[::-1] | ||
rotmat = meta.get('rotate', [[1, 0], [0, 1]]) | ||
rotate = np.degrees(np.arctan2(rotmat[0][1], rotmat[1][1])) | ||
# 'shear' in napari specifies the skew along the y-axis in CSS/SVG, but |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I love the detailed comments here.
Co-authored-by: Andy Sweet <[email protected]>
Closes #26
I haven't accounted for point/line extent in this PR. This was broken before
this and will stay broken after this, but is a somewhat orthogonal problem so
I'd rather leave it to a subsequent PR.
Similarly, we could optimise by pro-actively removing the no-op transforms from
the SVG before writing it out. I can do that here but I would rather focus on
getting it working first and then optimising later.