Hello all!
I'm new to the forums. I was having a strange issue, and was writing a post about it, but I figured out the solution as I typed more. I'll describe both the problem and the solution.
I'm using Inkscape to make "levels" for a video game I'm developing. One component of the workflow is to make objects (rect, path, etc.) in Inkscape that have coordinates I can rely on; I then take the SVG information, parse it, and turn (say) rect elements into static meshes usable in Box2D.
The problem that I'm having is that I need to resize the dimensions of the artboard, and doing so does something funky to the y-coordinates of everything made after the change. Specifically, resizing the artboard doesn't really change the origin (which is in the upper left of the original artboard), though it might seem to at first. You see, after the resize, if you create a rect and look at its XML, it will look like the x- and y-coordinates of it are giving credence to your new origin, as they will be exactly what you expect them to be. However, it will add in a "transform" attribute to the rect element that, if you add it to the x- and y- coordinates, will transform it back to the *original* origin. What's worse, if you move the rect around, Inkscape will actually perform the transform on the coordinates, and then your coordinates will be all off. In the instances I was working in, this only impacted the y-coordinate.
I know that sounded really confusing; it took me a hour to work out myself. To help illustrate the problem, I'll give you an example. I made a new image with the 1600x1200 template. I then resized it to 1000x1000, and made a rectangle that was 10 pixels large, whose upper right corner was at the new origin. What I got was this:
<rect
style="fill:none;stroke:#000000;stroke-width:0.09;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
id="rect3005"
width="10"
height="10"
x="0"
y="0"
transform="translate(0,200)" />
As you can see, there's a transform attribute, set to translate the rectangle 200 pixels back up towards the old origin (the original height was 1200px, and the new height is 1000px, so the 200px in the y-coordinate would move it back). But the current x=0 and y=0 reflect the NEW origin. On the surface, this might not be a big deal, as when I parse the XML, I could just remove the transform attributes. However, there's a problem: I then moved the rectangle back and forth two pixels (moving it, essentially, which will happen commonly), and Inkscape applied the transform to the x- and y-coordinates, giving me the following XML:
<rect
style="fill:none;stroke:#000000;stroke-width:0.09;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
id="rect3005"
width="10"
height="10"
x="0"
y="200" />
This is the exact same rect element. It is still at the "new" origin, but now has a y-coordinate of 200, the transform having been applied to it.
This is where I became confused; it would be a pain in the neck if I had to account for this during parsing. So, after fiddling with all of the options I could find -- relative coordinates, absolute coordinates, etc. -- I finally just figured that I would make a template with the coordinates already set. I tried saving a file into the templates directory, but that didn't work -- though it added the file as expected to the templates, it still had the "memory" of the old origin. So, I took the A4 template, and edited the svg element's width and height attributes as follows:
<svg
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
xmlns:xlink="http://www.w3.org/1999/xlink"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:cc="http://web.resource.org/cc/"
xmlns:dc="http://purl.org/dc/elements/1.1/"
width="1000px"
height="1000px">
Saving it, I then ran into no more problems. Without needing to resize the file in the program to my needs, I ran into no other problems. This was my solution.
It seems a bit weird to have to do all of that to resize the file without introducing the weird transform elements. I suppose I do have a question, after all: is there a way to do this in a more simple fashion?
Thanks for your time.
Making files without an automatic offset in the y-coordinate
Re: Making files without an automatic offset in the y-coordi
derrickst wrote:It seems a bit weird to have to do all of that to resize the file without introducing the weird transform elements. I suppose I do have a question, after all: is there a way to do this in a more simple fashion?
In you entire post you don't mention 'layer' a single time - I wonder why? ;)
Maybe you have noticed that Inkscape's GUI uses a different coordinate system than SVG (partly for legacy reasons, partly because drawing in the first quadrant of the Cartesian coordinate system is more natural for many drawing tasks):
In the GUI, the origin is located at the lower left corner of the page, with the y-axis pointing upwards.
In SVG, the origin is positioned at the upper left corner of the page, with the y-axis pointing downwards.
This results that when changing the page height (or resizing the page to a selection not aligned with the current page), all drawing content gets a new relative distance to the SVG origin (Inkscape keeps the objects positions relative to the GUI origin which now has a different offset to the SVG origin). These transforms (translations) are applied to existing top-level objects (layer groups in regular Inkscape SVG files) as explicit transforms (and not applied & flattened recursively to each and every object nested within each layer). Nothing special here - that's simply how SVG works (it does not enforce nor require to flatten and optimized transforms each time).
Tips that might help to reduce the number of unwanted transforms:
Make sure to have the preference setting for storing transforms set to 'Optimized' (this only affects regular paths, but not other types like Inkscape shapes (circle/ellipse, star/polygon, spiral), clones, groups, etc)).
If you resize the page area of an existing document: create a new layer, move the content of the old layer to the new layer (for regular paths, maybe you need to nudge the paths with the arrow keys to trigger a rewrite of the path data, for groups you may want to ungroup and regroup them again after moving to the new layer).
For new files to be used as templates: change the page size as needed. Then delete the empty default layer (it has a 'translate()' transformation as result of changing the page height), add a new (empty) layer, save as template. Work on that new layer.
Re: Making files without an automatic offset in the y-coordi
Oh! I guess I didn't even notice the transform attribute in the layer element. Now I feel kind of silly.
There's another solution as well: I went in and edited the XML of the layer element, deleting its translation attribute. I then deleted the transform attribute of the rect element I'd created. That seemed to do the trick as well.
Thank you for the insight.
There's another solution as well: I went in and edited the XML of the layer element, deleting its translation attribute. I then deleted the transform attribute of the rect element I'd created. That seemed to do the trick as well.
Thank you for the insight.
Re: Making files without an automatic offset in the y-coordi
thanks for the insights ~suv. would save as plain svg also help towards the goal of having fewer transforms? just curious that's all. I do understand that part and parcel of working with svg is those transforms and that either you deploy the svg to a svg viewer that understands or you export raster and the transform problem is irrelevant. it would be very relevant though to doing xslt things to svg that originated in inkscape.