<a
<h2>Affine Transformations</h2>
Starting since version <b>4.3.0</b> SpatiaLite supports several new SQL functions based on <a transformations</a>,<br>
Understanding and mastering all the underlaying mathematics could easily be a rather difficult task, more notably if you have absolutely no familiarity with this kind of operations.<br>
So we'll start slowly and smoothly by introducing first a very simple practical example based on kind of a joke about the geography of Italy and Sicily.
<h2>Fancy Geography and amusing Math</h2>
<table border="1" cellspacing="4" cellpadding="8">
<tr><td>
<h3>Preface</h3>
Look at a map of Italy; it appears obvious at first glance that Sicily is located in a very inconvenient position:
<ol>
<li>Sicily is placed too far South and too much close to North Africa; this implies an unpleasant torrid summer, and this later poses in turn many severe limitations to agricultural activities.</li>
<li>The <a of Messina</a> is exaggeratedly narrow, thus posing severe security risks to the navigation of capital ships, big container ships, cruise liners and supertankers.<br>
Even worst, from time to time some crazy politician starts strongly advocating the very stupid idea to build an incredibly costly <a crossing the Strait</a>, completely overlooking the very high seismic risk of this district and purposely forgetting to remember that in 1908 both towns of <a and Reggio Calabria</a> were completely destroyed by an earthquake followed by a tsunami.<br>
More than 120,000 peoples lost their lives, and it was one of the most frightening natural disasters registered in Europe during modern times.</li>
</ol>
So we'll immediately start a theoretical case study intended to identify a possible alternative location for Sicily.<br>
Incidentally we'll use the new SQL functions based on Affine Transformations for this task.<br>
Let's go on.
</td><td>
<img alt="sicily-0" border="1">

<tr><td>
<h3>Step #1: translating Sicily into a more convenient position</h3>
There is plenty of free room in the Lower Tyrrhenian Sea, so we'll start by applying a <a to Sicily: this practically means adding (or subtracting) a constant value to the coordinates on both <b>x</b> and <b>y</b> axes.<br>
After a very quick examination moving Sicily <b>150 km</b> (i.e. <b>150,000 m</b>) westward and <b>150 km</b> northward seems to be an absolutely reasonable choice.<br>
So using the Affine Transformation SQL functions we'll duly execute the following SQL statement:
<verbatim>
CREATE TABLE sicilia_1 AS
SELECT cod_reg,
   ATM_Transform(geometry,
      ATM_CreateTranslate(-150000, 150000)) AS geom
FROM sicilia_0;
SELECT RecoverGeometryColumn('sicilia_1', 'geom', 32632, 'MULTIPOLYGON', 'XY');
</verbatim>
<b>Remarks</b>:
<ul>
<li>all affine transformation related SQL function names start with an <b>ATM_</b> prefix: this simply stands for
<li><b>ATM_Transform()</b> is very similar to <b>ST_Transform()</b>; the most obvious difference is in that all transformation arguments are now expected to be passed under the form of an appropriate <b>BLOB-serialized</b> Affine Transformation Matrix.</li>
<li><b>ATM_CreateTranslate()</b> simply is an SQL function returning a <b>BLOB-serialized</b> Affine Transformation Matrix initialized in such a way to represent a simple <b>2D Translate</b> accordingly to <b>(tx, ty)</b> arguments.<br>
You could eventually define a complete <b>3D Translate</b> by passing <b>(tx, ty, tz)</b> arguments, but this isn't strictly required in our current example.
</ul>
</td><td>
<img alt="sicilia-1" border="1">

<tr><td>
<h3>Step #2: rotating Sicily so to get a nice horizontal alignment</h3>
Aligning the southern shores of Sicily to an almost horizontal line will surely lead to a more nicely ordered layout: so we have now to apply a <a rotation</a> of about <b>25.0 degrees</b>.<br>
Thanks to Affine Transformations, we can combine both the previous translation and the current rotation into a single movement (a so called <b>rototranslation</b>).<br>
We simply have to execute the following SQL statement:
<verbatim>CREATE TABLE sicilia_2 AS
SELECT cod_reg,
   ATM_Transform(geometry,
      ATM_Translate(-150000, 150000,
         ATM_Translate(cx, cy,
            ATM_Rotate(25,
               ATM_CreateTranslate(-cx, -cy))))) AS geom
FROM (SELECT cod_reg, ST_X(centroid) AS cx, ST_Y(centroid) AS cy, geometry
      FROM (SELECT cod_reg, ST_Centroid(geometry) AS centroid, geometry
            FROM sicilia_0) AS g1
) AS g2;
SELECT RecoverGeometryColumn('sicilia_2', 'geom', 32632, 'MULTIPOLYGON', 'XY');
</verbatim>
<b>Remarks</b>:
<ul>
<li>correctly handling Rotate is a little bit more difficult.
Any rotation will always imply a <b>fixed center point</b>, and by default this is exactly placed at the coordinates origin: <b>(0,
<li>so a very naive attempt to directly invoke <b>ATM_Rotate(25)</b> will simply relocate Sicily in Southern Spain, and this absolutely isn't our intention.</li>
<li>what we really need is a more complex sequence of chained transformations:
<ol>
<li>we'll start first by creating a new <b>BLOB-Matrix</b> intended to relocate Sicily's <a exactly on the coordinates origin: <b>ATM_CreateTranslate(-cx,
<li>now we can safely chain the intended Rotate: <b>ATM_Rotate(25,
<li>after applying Rotate we have now to restore the initial position: <b>ATM_Translate(cx, cy,
<li>and finally we'll apply the Translation intended to reposition Sicily westward and northward: <b>ATM_Translate(-150000, 150000, atm-blob)</b><br>
<i>we've used two separate translations simply for didactic clarity: we could easily merge both them into a single translation:<br> ATM_Translate(cx - 150000, cy + 150000,
<li>this way <b>ATM_Transform()</b> will receive the final <b>BLOB-Matrix</b> resulting by chaining all the above transformation steps in the correct sequence.</li>

<li><b><u>Very important Affine Transformations <u>are not commutative</u>: the relative order of subsequent operations in a complex transformation chain should always be very carefully considered.</li>
<li>all the <b>FROM (SELECT ... FROM (SELECT ...) AS g1) AS g2</b> stuff simply is a rather trivial SQL trick based on two nested sub-queries.<br>
it's indented scope simply is avoiding to call too many times ST_Centroid(), ST_X() and ST_Y() in order to get the centroid coordinates.</li>
</ul>
</td><td>
<img alt="sicilia-2" border="1">

<tr><td>
<h3>Step #3: inflating and reshaping Sicily</h3>
An increased surface is surely welcome, because it automatically implies more agricultural lands: on the other hand shortening a little bit the length of the southern coastline will surely facilitate mobility and communications.<br>
So we'll now apply a <a transformation using two different values: <b>sx=0.9</b> and <b>sy=1.3</b>.<br>
Once again, Affine Transformations enable us to combine altogether both translate, rotate and scale into a single transformation.<br>
This is the corresponding SQL statement:
<verbatim>
CREATE TABLE sicilia_3 AS
SELECT cod_reg,
   ATM_Transform(geometry,
      ATM_Translate(-150000, 150000,
         ATM_Translate(cx, cy,
            ATM_Scale(0.9, 1.3,
               ATM_Rotate(25,
                  ATM_CreateTranslate(-cx, -cy)))))) AS geom
FROM (SELECT cod_reg, ST_X(centroid) AS cx, ST_Y(centroid) AS cy, geometry
      FROM (SELECT cod_reg, ST_Centroid(geometry) AS centroid, geometry
            FROM sicilia_0) AS g1
) AS g2;
SELECT RecoverGeometryColumn('sicilia_3', 'geom', 32632, 'MULTIPOLYGON', 'XY');
</verbatim>
<b>Remarks</b>:
<ul>
<li>there is nothing really new in this: we'll simply chain yet another transformation in the appropriate sequence order.</li>
<li><b>ATM_Scale(sx, sy)</b> is intended for the simpler <b>2D</b> case.</li>
<li>in the more general <b>3D</b> case you can invoke <b>ATM_Scale(sx, sy,
</ul>
</td><td>
<img alt="sicilia-3" border="1">

<tr><td>
<h3>Step #4: final touch: reflecting Sicily</h3>
A reflected Sicily presents many interesting advantages: we'll examine all them in full detail in the final conclusions of the present study.<br>
So we'll now apply a final <a transformation; this simply corresponds to a <b>180 degrees</b> rotation around the <b>Y axis</b>.<br>
And the following is the final SQL statement applying all the above transformations in a single shot:
<verbatim>CREATE TABLE sicilia_2 AS
CREATE TABLE sicilia_4 AS
SELECT cod_reg,
   ATM_Transform(geometry,
      ATM_Translate(-150000, 150000,
         ATM_Translate(cx, cy,
            ATM_YRoll(180,
               ATM_Scale(0.9, 1.3,
                  ATM_Rotate(25,
                     ATM_CreateTranslate(-cx, -cy))))))) AS geom
FROM (SELECT cod_reg, ST_X(centroid) AS cx, ST_Y(centroid) AS cy, geometry
      FROM (SELECT cod_reg, ST_Centroid(geometry) AS centroid, geometry
            FROM sicilia_0) AS g1
) AS g2;
SELECT RecoverGeometryColumn('sicilia_4', 'geom', 32632, 'MULTIPOLYGON', 'XY');
</verbatim>
<b>Remarks</b>:
<ul>
<li>there are several possible rotations supported by Affine Transformation:
<ol>
<li><b>ATM_Rotate()</b> always intends a <b>2D</b> rotation, i.e. a rotation centered around the <b>Z
<li>In the more general <b>3D</b> case there are three possible rotations, one for each axis.</li>
<li>the corresponding SQL functions are: <b>ATM_XRoll(angle)</b>, <b>ATM_YRoll(angle)</b> and
<li><i><u>Note</u>: ATM_ZRoll() and ATM_Rotate() simply are two different alias-names for the same identical SQL

</ul>
</td><td>
<img alt="sicilia-4" border="1">

<tr><td>
<h3>Final considerations and conclusions</h3>
<ol>
<li><b>Agriculture</b>: after its relocation Sicily will gain much more agricultural land and will enjoy a more favourable climate: still sunny and warm but much less arid.<br>
This will certainly sustain a noticeable development of many economic activities.</li>
<li><b>Transportation systems</b>: the suggested new layout for the Lower Tyrrhenian Sea strongly facilitates the development of maritime transports. Sicily could now become the central hub of a highly efficient network of high-speed and high-frequency ferry connections:
<ul>
<li>Palermo will now directly face Naples; Civitavecchia (Rome) seems to be a second obvious terminal for direct connections leading to Central Italy.</li>
<li>Messina will acquire a decisive strategic role, and will become the terminal for ferry connections leading to Central and Northern Italy: Civitavecchia, Leghorn and Genoa are the obvious destinations.</li>
<li>A less relevant (but anyway interesting) ferry link will join Trapani and Reggio Calabria.</li>
<li>Sardinia will strongly benefit from the new layout; Cagliari will be directly connected to Syracuse (or may be Augusta), and Olbia to Messina.<br>This means definitely breaking the secular insulation of Sardinia, that will now start enjoying a stronger and more effective integration with Southern Italy.</li>
<li>Last but not least: at a more strategic level it's absolutely obvious that now supertankers, big container ships and cruise liners can freely circumnavigate Sicily in any direction under uncompromised safety conditions.<br>
And consequently all Tyrrhenian harbors will now be directly connected both to Eastern and Western Mediterranean: this will surely induce a remarkable growth in the volumes of international traffics they could potentially attract.</li>

<li><b>Heavy industry</b>: the new transportation system strongly centered around maritime communications will surely induce an active rebirth of shipyards, a flourishing traditional excellence of many southern regions in past times but nowadays a declining activity.</li>
<li><b>Tourism</b>: a rearranged Lower Tyrrhenian Sea will certainly promote a strong development of international tourism.<br>
It's worth noting that the proposed layout will give birth to a wonderful island group extending between Sicily and southern Lazio - Campania; the Pontine, Aeolian and Gulf of Naples islands will be practically merged into a single archipelago.<br>
Several of these islands actually are active volcanoes, and the new island chain will directly join Mount Etna and Mount Vesuvius.<br>
So this area will represent the most impressive volcanic field of Europe and will certainly become a strong touristic attraction thanks to its nicely sunny weather and pleasant climate.
</li>
<li><b>Internal commerce</b>: we can easily forecast a strong growth in volume of internal exchanges thanks to the better connectivity based on maritime transports.<br>
Just a single example: Sardinia should now be able to export its finest sheep cheese on Calabrian markets whilst Calabria could freely export its renown red hot chilly peppers to Sardinia; not only both regions will widely befit from increased exchange volumes, but Sicily as well will take profit from flourishing logistic and by other commercial intermediation activities.</li>
<li><b>Practical realization</b>: the present study clearly demonstrates that there is nothing in Mathematics, Geometry or Geography forbidding the practical realization of the suggested idea.<br>
Unhappily the current state of the art in Geology still poses many puzzling problems not yet fully resolved.<br>
Anyway we are hopefully expecting that future advancements in Tectonics will possibly allow to overcome any remaining issue. More specifically a better knowledge of interactions between the crust and the upper mantle along the Moho and a deeper comprehension of the micro-plaques mechanics will certainly help; we are rather confident in future research achievements on these fields.
</ol>
</td><td>
<img alt="italy-2.0" border="1">

</table><br><hr>
<h2>Boring Math: a more formal presentation</h2>
Playtime's over: we'll now start a most serious explanation.<br><br>
An Affine Transformation can be represented in the form of a square matrix; the simpler <b>2D</b> case requires a <b>3 x 3</b> matrix, and the followings are the possible arrangements corresponding to each elementary transformation:<br><br>
<table>
<tr><td rowspan="4" valign="middle">General layout</td>

<tr><td>|</td><td
<tr><td>\</td><td align="center">0</td><td align="center">0</td><td
<tr><td
<tr><td rowspan="4" valign="middle">Identity</td>
align="center">1</td><td align="center">0</td><td
<tr><td>|</td><td align="center">0</td><td align="center">1</td><td
<tr><td>\</td><td align="center">0</td><td align="center">0</td><td
<tr><td
<tr><td rowspan="4" valign="middle">Translate(<b>tx</b>,
align="center">1</td><td align="center">0</td><td
<tr><td>|</td><td align="center">0</td><td align="center">1</td><td
<tr><td>\</td><td align="center">0</td><td align="center">0</td><td
<tr><td
<tr><td rowspan="4" valign="middle">Scale(<b>sx</b>,
align="center">0</td><td
<tr><td>|</td><td align="center">0</td><td
<tr><td>\</td><td align="center">0</td><td align="center">0</td><td
<tr><td
<tr><td rowspan="4"

<tr><td>|</td><td
<tr><td>\</td><td align="center">0</td><td align="center">0</td><td

</table><br>
A <b>3D</b> affine transformation requires a <b>4 x 4</b> matrix.<br>
As you can easily notice there is an obvious direct relation between a 3D matrix and a 2D matrix; notice the cells showing a gray background.<br><br>
<table>
<tr><td rowspan="5" valign="middle">General layout&nbsp;&nbsp;&nbsp;</td>
align="center"
<tr><td>|</td><td align="center"
<tr><td>|</td><td align="center" align="center" align="center" align="center"
<tr><td>\</td><td align="center">0</td><td align="center">0</td><td align="center" bgcolor="#d0d0d0">0</td><td
<tr><td
<tr><td rowspan="5" valign="middle">Identity</td>
align="center">1</td><td align="center">0</td><td align="center">0</td><td
<tr><td>|</td><td align="center">0</td><td align="center">1</td><td align="center">0</td><td
<tr><td>\</td><td align="center">0</td><td align="center">0</td><td align="center">1</td><td
<tr><td>\</td><td align="center">0</td><td align="center">0</td><td align="center">0</td><td
<tr><td
<tr><td rowspan="5" valign="middle">Translate(<b>tx</b>, <b>ty</b>,
align="center">1</td><td align="center">0</td><td align="center">0</td><td
<tr><td>|</td><td align="center">0</td><td align="center">1</td><td align="center">0</td><td
<tr><td>|</td><td align="center">0</td><td align="center">0</td><td align="center">1</td><td
<tr><td>\</td><td align="center">0</td><td align="center">0</td><td align="center">0</td><td
<tr><td
<tr><td rowspan="5" valign="middle">Scale(<b>sx</b>, <b>sy</b>,
align="center">0</td><td align="center">0</td><td
<tr><td>|</td><td align="center">0</td><td align="center">0</td><td
<tr><td>|</td><td align="center">0</td><td align="center">0</td><td
<tr><td>\</td><td align="center">0</td><td align="center">0</td><td align="center">0</td><td
<tr><td
<tr><td rowspan="5" valign="middle">X
align="center">1</td><td align="center">0</td><td align="center">0</td><td
<tr><td>|</td><td align="center">0</td><td
<tr><td>|</td><td align="center">0</td><td
<tr><td>\</td><td align="center">0</td><td align="center">0</td><td align="center">0</td><td
<tr><td
<tr><td rowspan="5" valign="middle">Y
align="center">0</td><td
<tr><td>|</td><td align="center">0</td><td align="center">1</td><td align="center">0</td><td
<tr><td>|</td><td align="center">0</td><td
<tr><td>\</td><td align="center">0</td><td align="center">0</td><td align="center">0</td><td
<tr><td
<tr><td rowspan="5" valign="middle">Z
align="center">0</td><td
<tr><td>|</td><td align="center">0</td><td
<tr><td>|</td><td align="center">0</td><td align="center">0</td><td align="center">1</td><td
<tr><td>\</td><td align="center">0</td><td align="center">0</td><td align="center">0</td><td

</table>
<br><hr>
<h3>applying an Affine Transformation</h3>
In order to materialize an affine transformation we simply have to compute  <b>(x', y', z')</b> coordinates starting from <b>(x, y, z)</b> for every point or vertex found in the input Geometry accordingly to the following formulae:
<ul>
<li><b>x' = a*x + b*y + c*z +
<li><b>y' = d*x + e*y + f*z +
<li><b>z' = g*x + h*y + i*z +
</ul><br>
in the simpler <b>2D</b> case this will assume the reduced form:
<ul>
<li><b>x' = a*x + b*y +
<li><b>y' = d*x + e*y +
</ul><br>
As you can notice, applying an Affine Transformation does not requires computing any trigonometric function.<br>
Trigonometric functions are very costly in computational terms, so applying an Affine Transformation is an intrinsically efficient mechanism because simply depends on multiplications and additions.<br>
<br><hr>
<h3>chaining two (or even more) Affine Transformations in a single operation</h3>
Affine transformation matrices have another astonishing property.<br>
We can <a two different affine transformation matrices thus obtaining a third matrix, and this latest once applied will contain both transformations and in the right sequence.<br>
There is no limit; we can infinitively chain as many transformations as required, we'll simply have to continue multiplying all matrices one after the other carefully respecting the appropriate sequence.<br>
At the end of the process we'll always get just a single affine transformation matrix faithfully representing any individual transformation in the chain.
<table bgcolor="#ffc000" cellpadding="10"><tr><td>
The multiplication between two matrices <u>is not a commutative operation</u>: the relative order of operands is absolutely
<h3>multiplying two matrices</h3>
Multiplication is not really a simple operation when matrices are involved and requires a rather complex procedure; the following example shows how to multiply two <b>4 x 4</b> matrices.<br>
<table cellspacing="4" cellpadding="4">
<tr><td>
<table>

<tr><td>|</td><td
<tr><td>|</td><td
<tr><td>\</td><td
</table>
</td><td valign="middle">*</td>
<td>
<table>

<tr><td>|</td><td
<tr><td>|</td><td
<tr><td>\</td><td
</table>
</td>
</td><td valign="middle">=</td>
<td>
<table>
align="center">
+
+
+

+
+
+

+
+
+

+
+
+

<tr><td>|</td><td align="center">
+
+
+

+
+
+

+
+
+

+
+
+

<tr><td>|</td><td align="center">
+
+
+

+
+
+

+
+
+

+
+
+

<tr><td>\</td><td align="center">
+
+
+

+
+
+

+
+
+

+
+
+

</table>

<h3>identity matrix</h3>
An identity matrix simply corresponds to an affine transformation lacking any actual effect: at the end of the process the transformed geometry will be exactly the same as before.<br>
Moreover an identity matrix plays a special role in multiplication: the resulting matrix will always be exactly the same of the other matrix.<br>
(<i>it's more or less the equivalent of multiplying e.g. <b>8*1=8</b> in an ordinary scalar multiplication</i>).<br><br>
<hr>
<h3>Boring SQL functions: a formal explanation</h3>
<table border="1" cellspacing="4" cellpadding="8" bgcolor="#fff0d0">
<tr><th bgcolor="#C3B091">SQL Function</th><th
<tr><td><b>ATM_Transform ( BLOB Geometry , BLOB AT-matrix ) : BLOB Geometry</td><td>Will return a new Geometry by applying an Affine Transformation to the input Geometry.<br>
The output Geometry will preserve the original SRID, dimensions and type.<br>
NULL will be returned on invalid
<tr><td><b>ATM_IsValid ( BLOB AT-matrix ) : BOOLEAN</td><td>Will check if a BLOB do really correspond to an encoded Affine Transformation Matrix then returning TRUE or FALSE.<br>
-1 will be returned if the argument isn't of the BLOB
<tr><td><b>ATM_AsText ( BLOB AT-matrix ) : TEXT</td><td>Will return a text serialized representation of the Matrix.<br>
NULL will be returned on invalid
<tr><td><b>ATM_Multiply ( BLOB AT-matrix-A , BLOB AT-matrix-B ) : BLOB AT-matrix</td><td>Will multiply Matrix-B by Matrix-A then returning the resulting Matrix.<br>
NULL will be returned on invalid arguments.<hr>
<u>Note</u>: the transformation defined by Matrix-A (left operand) will always happen <u>after</u> applying all transformations defined by Matrix-B (right
<tr><th colspan="2" bgcolor="#F0E68C" align="center">SQL functions creating and initializing a new Affine Transformation
<tr><td><b>ATM_Create ( void ) : BLOB return an Identity Affine Transformation Matrix.<br>
NULL if any error
<tr><td><b>ATM_Create ( double a , double b , double d , double e , double xoff , double yoff ) : BLOB return a 2D Affine Transformation Matrix initialized with explicit values.<br>
NULL if any error occurs or on invalid
<tr><td><b>ATM_Create ( double a , double b , double c , double d , double e , double f , double g , double h , double i , double xoff , double yoff , double double zoff ) : BLOB return a 3D Affine Transformation Matrix initialized with explicit values.<br>
NULL if any error occurs or on invalid
<tr><td><b>ATM_CreateTranslate ( double tx , double ty ) : BLOB AT-matrix</b><br>
<b>ATM_CreateTranslate ( double tx , double ty , double tz ) : BLOB return an Affine Transformation Matrix initialized respectively as a 2D or 3D Translate.<br>
NULL if any error occurs or on invalid
<tr><td><b>ATM_CreateScale ( double sx , double sy ) : BLOB AT-matrix</b><br>
<b>ATM_CreateScale ( double sx , double sy , double sz ) : BLOB return an Affine Transformation Matrix initialized respectively as a 2D or 3D Scale.<br>
NULL if any error occurs or on invalid
<tr><td><b>ATM_CreateRotate ( double angle ) : BLOB AT-matrix</b><br>
<b>ATM_CreateZRoll ( double angle ) : BLOB return an Affine Transformation Matrix initialized as Rotation around the Z axis.<br>
NULL if any error occurs or on invalid arguments.<hr>
The angle is always expected to be measured in decimal degrees. The direction of rotation is defined such that positive angles rotate in the direction from the positive X axis toward the positive Y axis. With the default axis orientation  positive angles rotate in a counterclockwise direction.<hr>
<u>Note</u>: this is the unique rotation allowed on a purely 2D
<tr><td><b>ATM_CreateXRoll ( double angle ) : BLOB return an Affine Transformation Matrix initialized as Rotation around the X axis.<br>
NULL if any error occurs or on invalid
<tr><td><b>ATM_CreateYRoll ( double angle ) : BLOB return an Affine Transformation Matrix initialized as Rotation around the Y axis.<br>
NULL if any error occurs or on invalid
<tr><th colspan="2" bgcolor="#F0E68C" align="center">SQL functions supporting chaining two Affine Transformation
<tr><td><b>ATM_Translate ( double tx , double ty , BLOB AT-matrix ) : BLOB AT-matrix</b><br>
<b>ATM_Translate ( double tx , double ty , double tz , BLOB AT-matrix ) : BLOB return an Affine Transformation Matrix by chaining respectively a 2D or 3D Translate and another Affine Transformation.<br>
NULL if any error occurs or on invalid
<tr><td><b>ATM_Scale ( double sx , double sy , BLOB AT-matrix ) : BLOB AT-matrix</b><br>
<b>ATM_Scale ( double sx , double sy , double sz , BLOB AT-matrix ) : BLOB return an Affine Transformation Matrix by chaining respectively a 2D or 3D Scale and another Affine Transformation.<br>
NULL if any error occurs or on invalid
<tr><td><b>ATM_Rotate ( double angle , BLOB AT-matrix ) : BLOB AT-matrix</b><br>
<b>ATM_ZRoll ( double angle , BLOB AT-matrix ) : BLOB return an Affine Transformation Matrix by chaining a Rotation around the Z axis and another Affine Transformation.<br>
NULL if any error occurs or on invalid
<tr><td><b>ATM_XRoll ( double angle ) : BLOB return an Affine Transformation Matrix by chaining a Rotation around the X axis and another Affine Transformation.<br>
NULL if any error occurs or on invalid
<tr><td><b>ATM_YRoll ( double angle ) : BLOB return an Affine Transformation Matrix by chaining a Rotation around the Y axis and another Affine Transformation.<br>
NULL if any error occurs or on invalid
<tr><td></td><td>
<u>Note</u>: all the above functions simply are convenience methods intended to avoid any need to repeatedly call <b>ATM_Multiply()</b>.
<verbatim>
SELECT ATM_Multiply(ATM_CreateRotate(15),
                    ATM_Multiply(ATM_CreateScale(1.1, 1.2, 1.3),
                                 ATM_CreateTranslate(10, 20, 30)));

SELECT ATM_Rotate(15,
          ATM_Scale(1.1, 1.2, 1.3,
             ATM_CreateTranslate(10, 20, 30)));

SELECT ATM_Rotate(15,
          ATM_Scale(1.1, 1.2, 1.3,
             ATM_Translate(10, 20, 30,
                ATM_Create())));
</verbatim>
All three statements will return exactly the same identical Affine Transformation Matrix; anyway the second notation is obviously most concise and more practical than the other two.

<table><br><br>
<b>Note</b>: the SQL interface supporting Affine Trasformations is designed in such a way that any complexity and difficulty required in order to directly handle complex matricial operations is completely hidden.<br>
You are simply required to chain several elementary transformations, each one of them basically simple, in the correct sequence and that's absolutely all.<br>
<b>ATM</b> SQL functions will <i><u>magically and keep care of any mathematical complexity.<br><br>
<hr><br>
<a