Re: Declarative reflection transformation through a given axis

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 ;-)

Received on Saturday, 25 June 2016 10:28:49 UTC