Declarative reflection transformation through a given axis

Previous Topic Next Topic
 
classic Classic list List threaded Threaded
4 messages Options
Reply | Threaded
Open this post in threaded view
|

Declarative reflection transformation through a given axis

Developer, SleepingDog
Hi SVG people

I am working on prototyping code for a proposal for a SVG-based vector graphics library with reusable and replaceable components. This would include many objects with bilateral symmetry (humans, natural objects and artefacts).

To simplify authoring and editing, I was hoping that a SVG-based graphical editor tool would be able to define one side of an object (say, the left arm of a person) and have the other side generated automatically (in my case, via an XSLT transformation pipeline).

It would be a lot simpler if I could use a declarative reflection-through-an-axis transformation <https://en.wikipedia.org/wiki/Reflection_(mathematics)>; a bit like the existing rotation-around-a-point transformation.

This is a common requirement in vector graphics creation (in my experience) and typically has its own Reflect tool or operation (sometimes called mirroring, reflexion or flipping).

I am aware that scale using a -1 value in one dimension is available, but that does not really meet the common use case. I can actually derive the axis of symmetry from the components (there’s a cx and cy in the circles used for neck and torso connectors in my articulated human designs, for example), and pass this to my XSLT which can create the appropriate SVG <use> elements.

I have searched and not really found any solution or even workaround for SVG 1.1 (which Adobe Illustrator exports), so I wondered if either I had missed something or maybe reflection will feature in SVG 2?


Tavis Reddick
[hidden email]
https://github.com/sleepingdog

Reply | Threaded
Open this post in threaded view
|

Re: Declarative reflection transformation through a given axis

Dr. Olaf Hoffmann
Hello,

using SVG 1.1 or SVG tiny 1.2 this is either a specific transformation of the
matrix type or a combination of rotate, translate, scale, translate, rotate.
The CSS draft, the SVG 2 draft now refers to for transforms, does not provide
a specific simpler method for this as well, but it has a transform-origin
property, therefore noting this, you only need rotate, scale, rotate.

For example translate and rotate the object in such a way, that the mirror
axis becomes the x-axis, apply scale(1 -1), rotate and translate back.

Presumably to do this with XSLT you need an appropriate mathematical
representation of the mirror axis - this might be included as metadata
subelements in the document or directly as a line with those transformations
applied and indicated somehow with meta information to be the mirror axis.


Olaf



Reply | Threaded
Open this post in threaded view
|

Re: Declarative reflection transformation through a given axis

Juergen Roethig
In reply to this post by Developer, SleepingDog
Hi Tavis, hello world,

Developer, SleepingDog wrote:

>
> I am working on prototyping code for a proposal for a SVG-based vector graphics library with reusable and replaceable components. This would include many objects with bilateral symmetry (humans, natural objects and artefacts).
>
> To simplify authoring and editing, I was hoping that a SVG-based graphical editor tool would be able to define one side of an object (say, the left arm of a person) and have the other side generated automatically (in my case, via an XSLT transformation pipeline).
>
> It would be a lot simpler if I could use a declarative reflection-through-an-axis transformation <https://en.wikipedia.org/wiki/Reflection_(mathematics)>; a bit like the existing rotation-around-a-point transformation.
>
> This is a common requirement in vector graphics creation (in my experience) and typically has its own Reflect tool or operation (sometimes called mirroring, reflexion or flipping).
>
> I am aware that scale using a -1 value in one dimension is available, but that does not really meet the common use case. I can actually derive the axis of symmetry from the components (there’s a cx and cy in the circles used for neck and torso connectors in my articulated human designs, for example), and pass this to my XSLT which can create the appropriate SVG <use> elements.
>
> I have searched and not really found any solution or even workaround for SVG 1.1 (which Adobe Illustrator exports), so I wondered if either I had missed something or maybe reflection will feature in SVG 2?

Of course, there is a workaround (working in any SVG version, so far):
Do a combination of several transforms!

Assuming you have a mirror axis which is turned, e.g. 10 degrees
clockwise from the vertical, and which goes through some specific point,
e.g. 150, 100.

First, move the origin of your object to be reflected to the point which
is hit by your axis by "translate(-150 -100)".
Second, rotate the object opposite to the rotation of the mirror axis by
"rotate(-10)".
Third, reflect the object along the vertical axis by "scale(-1 1)".
Finally, turn and move the reflected object back to its "original"
rotation and place by "translate(150 100) rotate(10)".

The complete code reflecting a rather senseless group of objects may be
found in the following example ... it also includes the mirror axis just
for demonstration.

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN"
"http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<svg xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink" width="1000" height="600"
viewBox="0 0 500 300">
<title>Example for reflecting some object along an arbitrary axis</title>
<defs><style type="text/css"><![CDATA[
ellipse { stroke: green; stroke-width: 1px; fill: grey; }
rect { stroke: blue; stroke-width: 1px; fill: yellow; }
path { stroke: red; stroke-width: 1px; fill: none; }
text { stroke: violet; stroke-width: 1px; font-size: 5pt; }
line { stroke: black; stroke-width: 1px; }
]]></style>
</defs>
<g id="theoriginal" transform="translate(200 100)">
<title>original senseless drawing</title>
<ellipse cx="80" cy="10" rx="8" ry="6"/>
<rect x="10" y="10" width="20" height="10" />
<path d="M  10,34  Q  40,47   80,10 " id="mypath" />
<text><textPath startOffset="10" xlink:href="#mypath">Some test
text</textPath></text>
</g>
<line x1="0" y1="-50" x2="0" y2="50" transform="translate(150 100)
rotate(10) "><title>mirror axis</title></line>
<use xlink:href="#theoriginal" transform=" translate(150 100) rotate(10)
scale(-1 1) rotate(-10) translate(-150 -100) "><title>reflected
copy</title></use>
</svg>

HTH!

Regards,

Juergen Roethig

P.S.: Just realized that Olaf was faster with his answer. Nevertheless,
as I already wrote my answer, including even an example, before,
checking EMail again, I also send it, although it contains the same
workaround ;-)

Reply | Threaded
Open this post in threaded view
|

Re: Declarative reflection transformation through a given axis

Developer, SleepingDog
Hi Juergen and Olaf

Thank you very much for your quick help.

I was able to adapt the method in Juergen's code (in the simplest case, there was no rotation because the axis of symmetry was the y-axis, but I now know how to handle lines of arbitrary angle). I had seen one or two examples online but was unable to replicate the solution before, probably due to my rusty maths.

I have just slotted the solution into my XSLT transformation and got the desired result (a limb mirrored around a body’s central axis, given the x coordinate of the axis).


Tavis Reddick
[hidden email]


> On 25 Jun 2016, at 11:28, Juergen Roethig <[hidden email]> wrote:
>
> Assuming you have a mirror axis which is turned, e.g. 10 degrees clockwise from the vertical, and which goes through some specific point, e.g. 150, 100.
>
> First, move the origin of your object to be reflected to the point which is hit by your axis by "translate(-150 -100)".
> Second, rotate the object opposite to the rotation of the mirror axis by "rotate(-10)".
> Third, reflect the object along the vertical axis by "scale(-1 1)".
> Finally, turn and move the reflected object back to its "original" rotation and place by "translate(150 100) rotate(10)".
>
> The complete code …


> On 25 Jun 2016, at 11:18, Dr. Olaf Hoffmann <[hidden email]> wrote:
>
> using SVG 1.1 or SVG tiny 1.2 this is either a specific transformation of the
> matrix type or a combination of rotate, translate, scale, translate, rotate.
> The CSS draft, the SVG 2 draft now refers to for transforms, does not provide
> a specific simpler method for this as well, but it has a transform-origin
> property, therefore noting this, you only need rotate, scale, rotate.
>