Skip to content
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

can't easily get element's bounding box in device coordinates #68

Closed
medovina opened this issue Nov 9, 2020 · 4 comments
Closed

can't easily get element's bounding box in device coordinates #68

medovina opened this issue Nov 9, 2020 · 4 comments

Comments

@medovina
Copy link

medovina commented Nov 9, 2020

I've been experimenting with using svgSalamander for rendering in a game written in Java. Overall it seems to work quite well.

However, I ran into one issue that caused me some trouble. The SVG I'm rendering in the game is fairly complex, so I can't afford to rerender the entire image every time anything changes. So when I update an SVG element (e.g. by changing its color), I'd like to call the Swing method repaint() with the element's bounding box, so that only the region around the element will be repainted. In my experiments I've found that's much faster.

The problem is getting the element's bounding box in device coordinates. svgSalamander does provide a method RenderableElement.getBoundingBox(), which at first looked like exactly what I needed. However, after a bunch of experimentation and reading the svgSalamander source code, I figured out that if I call getBoundingBox() on an SVG element such as a Polygon, I get a bounding box in image coordinates (not device coordinates) in the coordinate system of the element's parent, not the entire SVG image. In other words, even if elements that are higher up in the element hierarchy have their own transforms defined in the SVG file, getBoundingBox() does not apply those transforms. It only applies the transform (if any) defined by the element's immediate parent.

Now, because the documentation is sparse, I'm not sure whether this behavior is by design or a bug. In any case, I worked around it in my application as follows. After I update an SVG element, I call getBoundingBox() to get its bounding box. I then walk up the hierarchy of SVG elements by calling the getParent() method repeatedly. For each ancestor, I call getXForm() to get its transformation, if any. If there is one, I apply it to the bounding box.

When I'm done, I have a bounding box in the coordinates of the entire image. I now need to transform this to device coordinates. The transform viewXform in the SVGRoot object is exactly what I need, but I can't use it because as far as I can tell there is no publicly accessible method that will retrieve this transform or apply it for me. So instead I have to do the work myself. I know the image size (I can get it by calling getBoundingBox() on the SVGRoot object before I specify a viewport) and I know the viewport size, which is defined by my application. So I can construct a transformation between these.

Still, this is a bit inconvenient, and it took me quite a while to figure this out. I'd think this would be a common use case, so it would be great to have some way to get an element's bounding box in device coordinates directly. If there's some easy way to do this today which I haven't noticed, I'd be happy to hear about it.

@blackears
Copy link
Owner

The coordinates you fetch will be in local coordinate space, so you are doing the right thing to calculate the coordinates in world space. I've added a new method to SVGRoot called calcViewportTransform() that you should be able to use to calculate the viewport transform.

@medovina
Copy link
Author

Great, thanks for the fix! I don't see any new commits, however - will your change be in the repository soon?

@blackears
Copy link
Owner

Should be there now. Sorry.

@medovina
Copy link
Author

Great, thanks!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants