[交互式SVG组件]Isometric projection

http://www.petercollingridge.co.uk/interactive-svg-components/isometric-projection

 

Isometeric projections are commonly used in technical drawings and used to be used in some computer game graphics. In an isometeric projection the three axes appear 120° from each other and are equally foreshortened. It can be achieved by rotating an object 45° in the plane of the screen and ~35.3° through the horizontal axis (see Wikipedia for more information).

We start with an image, such as this floor plan.

If we rotate this image 45° now, it will move almost off screen as rotations are always centred on the point (0, 0).

Translation

So we first translate our image so the point around which we want to rotate it (probably the centre of the image) is now at the point (0, 0). For example, the centre of this image is at (150, 80), so we translate the room by wrappping it in a group ike so:

view source
print ?
1 <g transform="translate(-150, -80)">
2   room shapes...
3 </g>

Rotation in the plane of the screen

We can now rotate our image. A rotation of 45° in the plane of the screen is easy enough with transform="rotate(45)", but a rotation through the horizontal axis is more tricky. The solution is to use matrices. A rotation in the plane of the screen is a rotation through the z-axis and given by the following 3x3 matrix:

[交互式SVG组件]Isometric projection_第1张图片

Because SVGs are 2D, they don't bother with the final row of this matrix (although it is important for intermediate steps as we'll see). SVG matrices are given as a single line of parameters in the order (column 1, row 1), (column 1, row 2), (column 2, row 1) and so on. Therefore we can replace transform="rotate(45)" with:

view source
print ?
1 transform="matrix(0.707 0.707 -0.707 0.707 0 0)"

Rotation through the horizontal axis

Rotating something through the horizontal (or x-) axis means effectively tilting the image away from us. Such a rotation is given by the following 3x3 matrix:

[交互式SVG组件]Isometric projection_第2张图片

In an isometric projection, the angle the camera moves is ~35.3°, however, this assumes that what we're looking at is lying on the floor (i.e. the xz-plane). Our image is "upright", in the xy-plane, so we actually need to rotate by 90°-35.3°. Theta is therefore 54.7°.

If we now multiply Rz(45°) by Rx(54.7°) we get:

[交互式SVG组件]Isometric projection_第3张图片

Or in SVG terms:

view source
print ?
1 transform="matrix(0.707 0.409 -0.707 0.409 0 -0.816)"

We can now add this to a group that contains the group with the translate transformation.

Translation back to the centre

Finally, we need to move our image back to the centre of the screen. We can do this a few ways. We could leave the image where it is and change the viewBox to be centred on (0, 0):

viewBox="-150, -80, 300, 160"

Alternatively, we could just add another group with a translation back:

view source
print ?
1 <g transform="translate(150, 80)">

You may find that you have to tweak the translation a bit to ensure the corners stay within the bounds of the image.

Finally, if you're feeling very adventurous or want to minimise the size of the SVG and processing require to display it, you can combine the two translation matrices with the rotation matrix. The first translation matrix, T1, is given by:

[交互式SVG组件]Isometric projection_第4张图片

The second translation matrix, T2, would be the same, but with positive 150 and 80. If we multiply T2 x Riso x T1 we get:

view source
print ?
1 <g transform="matrix(0.707 0.409 -0.707 0.409 100.51 -14.78)">

Note that this transformation will only work well if you want to rotate about the point (150, 80). As you can see from the file sizes below, we've saved ourselves 94 bytes.

Attachment Size
room_plan.svg 637 bytes
room_plan_translation.svg 675 bytes
room_plan_rotate_without_translate.svg 666 bytes
room_plan_isometric.svg 794 bytes
room_plan_isometric_matrix.svg 700 bytes

你可能感兴趣的:([交互式SVG组件]Isometric projection)