You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@sis.apache.org by de...@apache.org on 2016/07/22 13:07:12 UTC
svn commit: r1753786 [1/2] - in /sis/site/trunk: book/en/annexes.html
book/en/referencing.html book/fr/annexes.html book/fr/referencing.html
content/book/en/developer-guide.html content/book/fr/developer-guide.html
Author: desruisseaux
Date: Fri Jul 22 13:07:12 2016
New Revision: 1753786
URL: http://svn.apache.org/viewvc?rev=1753786&view=rev
Log:
Moved the chapter about affine transforms to the annexes.
Modified:
sis/site/trunk/book/en/annexes.html
sis/site/trunk/book/en/referencing.html
sis/site/trunk/book/fr/annexes.html
sis/site/trunk/book/fr/referencing.html
sis/site/trunk/content/book/en/developer-guide.html
sis/site/trunk/content/book/fr/developer-guide.html
Modified: sis/site/trunk/book/en/annexes.html
URL: http://svn.apache.org/viewvc/sis/site/trunk/book/en/annexes.html?rev=1753786&r1=1753785&r2=1753786&view=diff
==============================================================================
--- sis/site/trunk/book/en/annexes.html (original)
+++ sis/site/trunk/book/en/annexes.html Fri Jul 22 13:07:12 2016
@@ -372,6 +372,132 @@ public class MyTest extends Parameterize
<h2 id="DesignNote">Design notes</h2>
<p>Following chapters explain the rational behind some implementation choices done in Apache <abbr>SIS</abbr>.</p>
+
+ <h3 id="AffineTransform">Affine transform</h3>
+ <p>
+ Among the many kinds of operations performed by <abbr>GIS</abbr> softwares on spatial coordinates,
+ <cite>affine transforms</cite> are both relatively simple and very common.
+ Affine transforms can represent any combination of scales, shears, flips, rotations and translations,
+ which are <em>linear</em> operations.
+ Affine transforms can not handle <em>non-linear</em> operations like map projections,
+ but the affine transform capabilities nevertheless cover many other cases:
+ </p>
+ <ul>
+ <li>Axis order changes, for example from (<var>latitude</var>, <var>longitude</var>) to (<var>longitude</var>, <var>latitude</var>).</li>
+ <li>Axis direction changes, for example the <var>y</var> axis oriented toward down in images.</li>
+ <li>Prime meridian rotations, for example from <cite>Paris</cite> to <cite>Greenwich</cite> prime meridian.</li>
+ <li>Dimensionality changes, for example from 3-dimensional coordinates to 2-dimensional coordinates by dropping the height.</li>
+ <li>Unit conversion, for example from feet to metres.</li>
+ <li>Pixel to geodetic coordinate, for example the conversion represented in the <code>.tfw</code> files associated to some <abbr>TIFF</abbr> images.</li>
+ <li>Part of map projections, for example the <cite>False Easting</cite>, <cite>False Northing</cite> and <cite>Scale factor</cite> parameters.</li>
+ </ul>
+ <p>
+ Affine transforms can be concatenated efficiently.
+ No matter how many affine transforms are chained, the result can be represented by a single affine transform.
+ This property is more easily seen when affine transforms are represented by matrices:
+ in order to concatenate those operations, we only need to multiply those matrices.
+ The “pixel to geographic coordinate conversions” case below gives an example.
+ </p>
+
+ <div class="example">
+ <p><b>Example:</b>
+ given an image with pixel coordinates represented by (<var>x</var>,<var>y</var>) tuples
+ and given the following assumptions:
+ </p>
+ <ul>
+ <li>There is no shear, no rotation and no flip.</li>
+ <li>All pixels have the same width in degrees of longitude.</li>
+ <li>All pixels have the same height in degrees of latitude.</li>
+ <li>Pixel indices are positive integers starting at (0,0) inclusive.</li>
+ </ul>
+ <p>Then conversions from pixel coordinates (<var>x</var>,<var>y</var>)
+ to geographic coordinates (<var>λ</var>,<var>φ</var>) can be represented by the following equations,
+ where <var>N</var><sub><var>x</var></sub> is the image width and
+ <var>N</var><sub><var>y</var></sub> the image height in number of pixels:
+ </p><p>
+ <xi:include href="../math/PixelToGeographicTerms.html"/>
+ </p><p>
+ Above equations can be represented in matrix form as below:
+ </p><p>
+ <xi:include href="../math/PixelToGeographic.html"/>
+ </p><p>
+ In this particular case, scale factors <var>S</var> are the pixel size in degrees
+ and translation terms <var>T</var> are the geographic coordinate of an image corner
+ (not necessarily the lower-left corner if some axes have been flipped).
+ This straightforward interpretation holds because of above-cited assumptions, but
+ matrix coefficients become more complex if the image has shear or rotation
+ or if pixel coordinates do not start at (0,0).
+ However it is not necessary to use more complex equations for supporting more generic cases.
+ The following example starts with an “initial conversion” matrix
+ where the <var>S</var> and <var>T</var> terms are set to the most straightforward values.
+ Then the <var>y</var> axis direction is reversed for matching the most common convention in image coordinate systems (change 1),
+ and axis are swapped resulting in latitude before longitude (change 2).
+ Note that when affine transform concatenations are written as matrix multiplications, operations are ordered from right to left:
+ <var>A</var>×<var>B</var>×<var>C</var> is equivalent to first applying operation <var>C</var>,
+ then operation <var>B</var> and finally operation <var>A</var>.
+ </p>
+ <table class="hidden"><tr>
+ <th>Change 2</th><th></th>
+ <th>Change 1</th><th></th>
+ <th>Initial conversion</th><th></th>
+ <th>Concatenated operation</th>
+ </tr><tr>
+ <td style="vertical-align: middle"><xi:include href="../math/AxisSwapping2D.html"/></td>
+ <td style="vertical-align: middle; padding-left: 15px; padding-right: 15px">×</td>
+ <td style="vertical-align: middle"><xi:include href="../math/InverseAxisY.html"/></td>
+ <td style="vertical-align: middle; padding-left: 15px; padding-right: 15px">×</td>
+ <td style="vertical-align: middle"><xi:include href="../math/PixelToGeographicSameAxisDirections.html"/></td>
+ <td style="vertical-align: middle; padding-left: 15px; padding-right: 15px">=</td>
+ <td style="vertical-align: middle"><xi:include href="../math/PixelToGeographicReverseOrderAndY.html"/></td>
+ </tr></table>
+ <p>
+ A key principle is that there is no need to write Java code dedicated to above kinds of axis changes.
+ Those operations, and many other, can be handled by matrix algebra.
+ This approach makes easier to write generic code and improves performance.
+ Apache <abbr>SIS</abbr> follows this principle by using affine transforms for every operations
+ that can be performed by such transform.
+ For instance there is no code dedicated to changing order of ordinate values in a coordinate.
+ </p>
+ </div>
+
+ <h4 id="AffineTransformAPI">Integration with graphical libraries</h4>
+ <p>
+ About all graphical libraries support some kind of coordinate operations, usually as <cite>affine transforms</cite>
+ or a slight generalization like <cite>perspective transforms</cite>.
+ Each library defines its own <abbr>API</abbr>. Some examples are listed below:
+ </p>
+ <table>
+ <caption>Affine transform implementations in graphical libraries</caption>
+ <tr><th>Library</th> <th>Transform implementation</th> <th>Dimensions</th></tr>
+ <tr><td>Java2D</td> <td><code>java.awt.geom.AffineTransform</code></td> <td>2</td></tr>
+ <tr><td>Java3D</td> <td><code>javax.media.j3d.Transform3D</code></td> <td>3</td></tr>
+ <tr><td>JavaFX</td> <td><code>javafx.scene.transform.Affine</code></td> <td>2 or 3</td></tr>
+ <tr><td>Java Advanced Imaging (<abbr>JAI</abbr>)</td> <td><code>javax.media.jai.PerspectiveTransform</code></td> <td>2</td></tr>
+ <tr><td>Android</td> <td><code>android.graphics.Matrix</code></td> <td>2</td></tr>
+ </table>
+ <p>
+ However in many cases, affine or perspective transforms are the only kind of coordinate operations supported by the graphical library.
+ Apache <abbr>SIS</abbr> needs to handle a wider range of operations, in which affine transforms are only special cases.
+ In particular most map projections and datum shifts can not be represented by affine transforms.
+ <abbr>SIS</abbr> also needs to support arbitrary number of dimensions,
+ while above-cited <abbr>API</abbr> restrict the use to a fixed number of dimensions.
+ For those reasons <abbr>SIS</abbr> can not use directly the above-cited <abbr>API</abbr>.
+ Instead, <abbr>SIS</abbr> uses the more abstract <code>org.opengis.referencing.transform.MathTransform</code> interface.
+ But in the special case where the transform is actually affine, <abbr>SIS</abbr> may try to use an existing implementation,
+ in particular Java2D. The following Java code can be used in situations where the Java2D object is desired:
+ </p>
+ <pre>MathTransform mt = ...; // Any math transform created by Apache SIS.
+if (mt instanceof AffineTransform) {
+ AffineTransform at = (AffineTransform) mt;
+ // Use Java2D API from here.
+}</pre>
+ <p>
+ Apache <abbr>SIS</abbr> uses Java2D on a <em>best effort</em> basis only.
+ The above cast is not guaranteed to succeed,
+ even when the <code>MathTransform</code> meets the requirements allowing Java2D usage.
+ </p>
+
+
<h3 id="MatrixLibrary">Specificities of a matrix library for <abbr>GIS</abbr></h3>
<p>
<abbr>GIS</abbr> make an extensive usage of matrices for displaying maps or for transforming coordinates.
Modified: sis/site/trunk/book/en/referencing.html
URL: http://svn.apache.org/viewvc/sis/site/trunk/book/en/referencing.html?rev=1753786&r1=1753785&r2=1753786&view=diff
==============================================================================
--- sis/site/trunk/book/en/referencing.html (original)
+++ sis/site/trunk/book/en/referencing.html Fri Jul 22 13:07:12 2016
@@ -406,130 +406,6 @@ public class MyApp {
}</pre>
- <h4 id="AffineTransform">Affine transform</h4>
- <p>
- Among the many kinds of operations performed by <abbr>GIS</abbr> softwares on spatial coordinates,
- <cite>affine transforms</cite> are both relatively simple and very common.
- Affine transforms can represent any combination of scales, shears, flips, rotations and translations,
- which are <em>linear</em> operations.
- Affine transforms can not handle <em>non-linear</em> operations like map projections,
- but the affine transform capabilities nevertheless cover many other cases:
- </p>
- <ul>
- <li>Axis order changes, for example from (<var>latitude</var>, <var>longitude</var>) to (<var>longitude</var>, <var>latitude</var>).</li>
- <li>Axis direction changes, for example the <var>y</var> axis oriented toward down in images.</li>
- <li>Prime meridian rotations, for example from <cite>Paris</cite> to <cite>Greenwich</cite> prime meridian.</li>
- <li>Dimensionality changes, for example from 3-dimensional coordinates to 2-dimensional coordinates by dropping the height.</li>
- <li>Unit conversion, for example from feet to metres.</li>
- <li>Pixel to geodetic coordinate, for example the conversion represented in the <code>.tfw</code> files associated to some <abbr>TIFF</abbr> images.</li>
- <li>Part of map projections, for example the <cite>False Easting</cite>, <cite>False Northing</cite> and <cite>Scale factor</cite> parameters.</li>
- </ul>
- <p>
- Affine transforms can be concatenated efficiently.
- No matter how many affine transforms are chained, the result can be represented by a single affine transform.
- This property is more easily seen when affine transforms are represented by matrices:
- in order to concatenate those operations, we only need to multiply those matrices.
- The “pixel to geographic coordinate conversions” case below gives an example.
- </p>
-
- <div class="example">
- <p><b>Example:</b>
- given an image with pixel coordinates represented by (<var>x</var>,<var>y</var>) tuples
- and given the following assumptions:
- </p>
- <ul>
- <li>There is no shear, no rotation and no flip.</li>
- <li>All pixels have the same width in degrees of longitude.</li>
- <li>All pixels have the same height in degrees of latitude.</li>
- <li>Pixel indices are positive integers starting at (0,0) inclusive.</li>
- </ul>
- <p>Then conversions from pixel coordinates (<var>x</var>,<var>y</var>)
- to geographic coordinates (<var>λ</var>,<var>φ</var>) can be represented by the following equations,
- where <var>N</var><sub><var>x</var></sub> is the image width and
- <var>N</var><sub><var>y</var></sub> the image height in number of pixels:
- </p><p>
- <xi:include href="../math/PixelToGeographicTerms.html"/>
- </p><p>
- Above equations can be represented in matrix form as below:
- </p><p>
- <xi:include href="../math/PixelToGeographic.html"/>
- </p><p>
- In this particular case, scale factors <var>S</var> are the pixel size in degrees
- and translation terms <var>T</var> are the geographic coordinate of an image corner
- (not necessarily the lower-left corner if some axes have been flipped).
- This straightforward interpretation holds because of above-cited assumptions, but
- matrix coefficients become more complex if the image has shear or rotation
- or if pixel coordinates do not start at (0,0).
- However it is not necessary to use more complex equations for supporting more generic cases.
- The following example starts with an “initial conversion” matrix
- where the <var>S</var> and <var>T</var> terms are set to the most straightforward values.
- Then the <var>y</var> axis direction is reversed for matching the most common convention in image coordinate systems (change 1),
- and axis are swapped resulting in latitude before longitude (change 2).
- Note that when affine transform concatenations are written as matrix multiplications, operations are ordered from right to left:
- <var>A</var>×<var>B</var>×<var>C</var> is equivalent to first applying operation <var>C</var>,
- then operation <var>B</var> and finally operation <var>A</var>.
- </p>
- <table class="hidden"><tr>
- <th>Change 2</th><th></th>
- <th>Change 1</th><th></th>
- <th>Initial conversion</th><th></th>
- <th>Concatenated operation</th>
- </tr><tr>
- <td style="vertical-align: middle"><xi:include href="../math/AxisSwapping2D.html"/></td>
- <td style="vertical-align: middle; padding-left: 15px; padding-right: 15px">×</td>
- <td style="vertical-align: middle"><xi:include href="../math/InverseAxisY.html"/></td>
- <td style="vertical-align: middle; padding-left: 15px; padding-right: 15px">×</td>
- <td style="vertical-align: middle"><xi:include href="../math/PixelToGeographicSameAxisDirections.html"/></td>
- <td style="vertical-align: middle; padding-left: 15px; padding-right: 15px">=</td>
- <td style="vertical-align: middle"><xi:include href="../math/PixelToGeographicReverseOrderAndY.html"/></td>
- </tr></table>
- <p>
- A key principle is that there is no need to write Java code dedicated to above kinds of axis changes.
- Those operations, and many other, can be handled by matrix algebra.
- This approach makes easier to write generic code and improves performance.
- Apache <abbr>SIS</abbr> follows this principle by using affine transforms for every operations
- that can be performed by such transform.
- For instance there is no code dedicated to changing order of ordinate values in a coordinate.
- </p>
- </div>
-
- <h4 id="AffineTransformAPI">Integration with graphical libraries</h4>
- <p>
- About all graphical libraries support some kind of coordinate operations, usually as <cite>affine transforms</cite>
- or a slight generalization like <cite>perspective transforms</cite>.
- Each library defines its own <abbr>API</abbr>. Some examples are listed below:
- </p>
- <table>
- <caption>Affine transform implementations in graphical libraries</caption>
- <tr><th>Library</th> <th>Transform implementation</th> <th>Dimensions</th></tr>
- <tr><td>Java2D</td> <td><code>java.awt.geom.AffineTransform</code></td> <td>2</td></tr>
- <tr><td>Java3D</td> <td><code>javax.media.j3d.Transform3D</code></td> <td>3</td></tr>
- <tr><td>JavaFX</td> <td><code>javafx.scene.transform.Affine</code></td> <td>2 or 3</td></tr>
- <tr><td>Java Advanced Imaging (<abbr>JAI</abbr>)</td> <td><code>javax.media.jai.PerspectiveTransform</code></td> <td>2</td></tr>
- <tr><td>Android</td> <td><code>android.graphics.Matrix</code></td> <td>2</td></tr>
- </table>
- <p>
- However in many cases, affine or perspective transforms are the only kind of coordinate operations supported by the graphical library.
- Apache <abbr>SIS</abbr> needs to handle a wider range of operations, in which affine transforms are only special cases.
- In particular most map projections and datum shifts can not be represented by affine transforms.
- <abbr>SIS</abbr> also needs to support arbitrary number of dimensions,
- while above-cited <abbr>API</abbr> restrict the use to a fixed number of dimensions.
- For those reasons <abbr>SIS</abbr> can not use directly the above-cited <abbr>API</abbr>.
- Instead, <abbr>SIS</abbr> uses the more abstract <code>org.opengis.referencing.transform.MathTransform</code> interface.
- But in the special case where the transform is actually affine, <abbr>SIS</abbr> may try to use an existing implementation,
- in particular Java2D. The following Java code can be used in situations where the Java2D object is desired:
- </p>
- <pre>MathTransform mt = ...; // Any math transform created by Apache SIS.
-if (mt instanceof AffineTransform) {
- AffineTransform at = (AffineTransform) mt;
- // Use Java2D API from here.
-}</pre>
- <p>
- Apache <abbr>SIS</abbr> uses Java2D on a <em>best effort</em> basis only.
- The above cast is not guaranteed to succeed,
- even when the <code>MathTransform</code> meets the requirements allowing Java2D usage.
- </p>
-
<h3 id="TransformDerivative">Partial derivatives of coordinate operations</h3>
<p>
<span style="color: red">TODO</span>
Modified: sis/site/trunk/book/fr/annexes.html
URL: http://svn.apache.org/viewvc/sis/site/trunk/book/fr/annexes.html?rev=1753786&r1=1753785&r2=1753786&view=diff
==============================================================================
--- sis/site/trunk/book/fr/annexes.html (original)
+++ sis/site/trunk/book/fr/annexes.html Fri Jul 22 13:07:12 2016
@@ -379,6 +379,141 @@ public class MyTest extends Parameterize
<h2 id="DesignNote">Notes de design</h2>
<p>Les chapitres suivants expliquent les raisons derrières certains choix d'implémentation de Apache <abbr>SIS</abbr>.</p>
+
+ <h3 id="AffineTransform">Utilisation des transformations affines</h3>
+ <p>
+ Parmi les sortes d’opérations qu’un <abbr>SIG</abbr> doit effectuer sur les coordonnées spatiales,
+ les <cite>transformations affines</cite> sont à la fois relativement simples et très fréquentes.
+ Les transformations affines peuvent représenter n’importe quelle combinaison d’échelles, de cisaillements,
+ de retournements, de rotations ou de translations, qui sont toutes des <cite>opérations linéaires</cite>.
+ Les transformations affines ne peuvent pas effectuer des opérations <cite>non-linéaires</cite>
+ telles que les projections cartographiques, mais couvrent néanmoins de nombreux autres cas:
+ </p>
+ <ul>
+ <li>Changer l’ordre des axes, par exemple de (<var>latitude</var>, <var>longitude</var>) vers (<var>longitude</var>, <var>latitude</var>).</li>
+ <li>Changer la direction des axes, par exemple l’axe des <var>y</var> qui pointe habituellement vers le bas dans les images.</li>
+ <li>Changer le méridien d’origine, par exemple du méridien de <cite>Paris</cite> vers celui de <cite>Greenwich</cite>.</li>
+ <li>Changer le nombre de dimensions, par exemple passer des coordonnées 3D vers 2D en supprimant la hauteur.</li>
+ <li>Convertir des unités de mesures, par exemple convertir des pieds en mètres.</li>
+ <li>Convertir des coordonnées pixels en coordonnées géographiques,
+ par exemple la conversion exprimée dans les fichiers <code>.tfw</code> qui accompagnent certaines images <abbr>TIFF</abbr>.</li>
+ <li>Prendre en charge une petite partie des projections cartographiques,
+ par exemple les paramètres <cite>False Easting</cite>, <cite>False Northing</cite> et <cite>Scale factor</cite>.</li>
+ </ul>
+ <p>
+ Les transformations affines peuvent se combiner efficacement.
+ Peu importe le nombre de transformations affines que l’on enchaîne, le résultat sera exprimable par une seule transformation affine.
+ Cette propriété est plus facilement visible lorsque les transformations affines sont exprimées sous forme de matrices:
+ pour combiner les opérations, il suffit de multiplier les matrices.
+ Le cas des conversions des coordonnées pixels en coordonnées géographiques ci-dessous donne un exemple.
+ </p>
+
+ <div class="example">
+ <p><b>Exemple:</b>
+ supposons que nous disposons d’une image dont les coordonnées des pixels sont représentées par (<var>x</var>,<var>y</var>).
+ Supposons aussi que les contraintes suivantes sont respectées:
+ </p>
+ <ul>
+ <li>Il n’y a ni cisaillement, ni rotation, ni retournement de l’image.</li>
+ <li>Tous les pixels ont la même largeur en degrés de longitude.</li>
+ <li>Tous les pixels ont la même hauteur en degrés de latitude.</li>
+ <li>Les coordonnées des pixels commencent à (0,0) inclusivement.</li>
+ </ul>
+ <p>Alors la conversion des coordonnées pixels (<var>x</var>,<var>y</var>)
+ vers les coordonnées géographiques (<var>λ</var>,<var>φ</var>)
+ peut être représentée par les équations suivantes,
+ où <var>N</var><sub><var>x</var></sub> est la largeur
+ et <var>N</var><sub><var>y</var></sub> la hauteur de l’image en nombre de pixels.
+ </p><p>
+ <xi:include href="../math/PixelToGeographicTerms.html"/>
+ </p><p>
+ Les équations ci-dessus peuvent être représentées sous forme de matrices comme ci-dessous:
+ </p><p>
+ <xi:include href="../math/PixelToGeographic.html"/>
+ </p><p>
+ Dans ce cas particulier, les facteurs d’échelles <var>S</var> correspondent à la taille des pixels en degrés
+ et les termes de translations <var>T</var> correspondent aux coordonnées géographiques d’un coin de l’image
+ (pas nécessairement le coin inférieur gauche si certains axes ont été retournés).
+ Cette interprétation directe n’est possible que lorsque les contraintes énumérées plus haut sont respectées.
+ Les coefficients des matrices deviennent plus complexes si l’image a un cisaillement ou une rotation,
+ ou si les coordonnées des pixels ne commencent pas à (0,0).
+ Toutefois il n’est pas nécessaire d’utiliser des équations plus complexes pour gérer des cas plus génériques.
+ L’exemple ci-dessous prend comme point de départ la matrice d’une « conversion initiale »
+ dans laquelle les coefficients <var>S</var> et <var>T</var> sont les valeurs relativement simples données ci-dessus.
+ Ensuite la direction de l’axe des <var>y</var> est inversée de manière à correspondre
+ à la convention habituelle des systèmes de coordonnées des images (changement 1),
+ et les axes sont intervertis de manière à avoir la latitude avant la longitude (changement 2).
+ Notez que les concaténations de transformations affines écrites sous forme de multiplications matricielles
+ se lisent de droite à gauche:
+ <var>A</var>×<var>B</var>×<var>C</var> est équivalent à d’abord appliquer l’opération <var>C</var>,
+ suivit de l’opération <var>B</var> et finalement l’opération <var>A</var>.
+ </p>
+ <table class="hidden"><tr>
+ <th>Changement 2</th><th></th>
+ <th>Changement 1</th><th></th>
+ <th>Conversion initiale</th><th></th>
+ <th>Opérations combinées</th>
+ </tr><tr>
+ <td style="vertical-align: middle"><xi:include href="../math/AxisSwapping2D.html"/></td>
+ <td style="vertical-align: middle; padding-left: 15px; padding-right: 15px">×</td>
+ <td style="vertical-align: middle"><xi:include href="../math/InverseAxisY.html"/></td>
+ <td style="vertical-align: middle; padding-left: 15px; padding-right: 15px">×</td>
+ <td style="vertical-align: middle"><xi:include href="../math/PixelToGeographicSameAxisDirections.html"/></td>
+ <td style="vertical-align: middle; padding-left: 15px; padding-right: 15px">=</td>
+ <td style="vertical-align: middle"><xi:include href="../math/PixelToGeographicReverseOrderAndY.html"/></td>
+ </tr></table>
+ <p>
+ Un principe clé est qu’il n’y a pas besoin d’écrire un code dédié à ce type d’opérations sur les axes.
+ Ces opérations, et bien d’autres, sont prises en compte naturellement par l’algèbre matricielle.
+ On y gagne en généricité du code et en performance.
+ Apache <abbr>SIS</abbr> suit ce principe en utilisant les tranformations affine pour toutes les opérations
+ où elles peuvent s’appliquer.
+ Il n’y a par exemple aucun code dédié au changement de l’ordre des ordonnées dans une coordonnée.
+ </p>
+ </div>
+
+ <h4 id="AffineTransformAPI">Intégration avec les bibliothèques graphiques</h4>
+ <p>
+ A peu près toutes les bibliothèques graphiques supportent une forme de transformation de coordonnées,
+ souvent les <cite>transformations affines</cite> ou une légère généralisation.
+ Chaque bibliothèque défini son propre <abbr>API</abbr>.
+ Quelques exemples sont:
+ </p>
+ <table>
+ <caption>Implémentations des transformations affines dans des bibliothèques graphiques</caption>
+ <tr><th>Bibliothèque</th> <th>Implementation de la transformation</th> <th>Dimensions</th></tr>
+ <tr><td>Java2D</td> <td><code>java.awt.geom.AffineTransform</code></td> <td>2</td></tr>
+ <tr><td>Java3D</td> <td><code>javax.media.j3d.Transform3D</code></td> <td>3</td></tr>
+ <tr><td>JavaFX</td> <td><code>javafx.scene.transform.Affine</code></td> <td>2 ou 3</td></tr>
+ <tr><td>Java Advanced Imaging (<abbr>JAI</abbr>)</td> <td><code>javax.media.jai.PerspectiveTransform</code></td> <td>2</td></tr>
+ <tr><td>Android</td> <td><code>android.graphics.Matrix</code></td> <td>2</td></tr>
+ </table>
+ <p>
+ Toutefois dans plusieurs cas, les transformations affines sont les seuls types d’opérations supportées par la bibliothèque graphique.
+ Apache <abbr>SIS</abbr> a besoin de gérer un plus grand nombre de type d’opérations,
+ parmi lesquelles les transformations affines ne sont que des cas particuliers.
+ Les projections cartographiques et les changements de référentiels notamment,
+ ne peuvent pas être représentés par des transformations affines.
+ <abbr>SIS</abbr> a aussi besoin de transformer des points ayant un nombre arbitraire de dimensions,
+ alors que les <abbr>API</abbr> cités ci-haut restreignent leur usage à un nombre fixe de dimensions.
+ Pour ces raisons, <abbr>SIS</abbr> ne peut pas utiliser directement ces <abbr>API</abbr>.
+ <abbr>SIS</abbr> utilise plutôt une interface plus abstraite, <code>org.opengis.referencing.transform.MathTransform</code>.
+ Mais dans le cas particulier où la transformation est réellement affine, <abbr>SIS</abbr> peut essayer d’utiliser
+ une implémentation existante, surtout Java2D.
+ Par exemple le code suivant peut être utilisé dans les situations où un objet Java2D est désiré:
+ </p>
+ <pre>MathTransform mt = ...; // N’importe quelle instance créée par Apache SIS.
+if (mt instanceof AffineTransform) {
+ AffineTransform at = (AffineTransform) mt;
+ // Utiliser l’API de Java2D API à partir d’ici.
+}</pre>
+ <p>
+ Toutefois <abbr>SIS</abbr> n’utilisera Java2D que sur une base opportuniste.
+ Le forçage de type ci-haut n’est pas garantit de réussir, même si l’instance de
+ <code>MathTransform</code> répond aux conditions qui devrait permettre un usage de Java2D.
+ </p>
+
+
<h3 id="MatrixLibrary">Particularités d’une bibliothèque de calculs matriciels pour un <abbr>SIG</abbr></h3>
<p>
Les <abbr>SIG</abbr> font un usage intensif de matrices afin d’afficher leurs cartes ou transformer des coordonnées.
Modified: sis/site/trunk/book/fr/referencing.html
URL: http://svn.apache.org/viewvc/sis/site/trunk/book/fr/referencing.html?rev=1753786&r1=1753785&r2=1753786&view=diff
==============================================================================
--- sis/site/trunk/book/fr/referencing.html (original)
+++ sis/site/trunk/book/fr/referencing.html Fri Jul 22 13:07:12 2016
@@ -410,139 +410,6 @@ public class MyApp {
}</pre>
- <h4 id="AffineTransform">Les transformations affines</h4>
- <p>
- Parmi les sortes d’opérations qu’un <abbr>SIG</abbr> doit effectuer sur les coordonnées spatiales,
- les <cite>transformations affines</cite> sont à la fois relativement simples et très fréquentes.
- Les transformations affines peuvent représenter n’importe quelle combinaison d’échelles, de cisaillements,
- de retournements, de rotations ou de translations, qui sont toutes des <cite>opérations linéaires</cite>.
- Les transformations affines ne peuvent pas effectuer des opérations <cite>non-linéaires</cite>
- telles que les projections cartographiques, mais couvrent néanmoins de nombreux autres cas:
- </p>
- <ul>
- <li>Changer l’ordre des axes, par exemple de (<var>latitude</var>, <var>longitude</var>) vers (<var>longitude</var>, <var>latitude</var>).</li>
- <li>Changer la direction des axes, par exemple l’axe des <var>y</var> qui pointe habituellement vers le bas dans les images.</li>
- <li>Changer le méridien d’origine, par exemple du méridien de <cite>Paris</cite> vers celui de <cite>Greenwich</cite>.</li>
- <li>Changer le nombre de dimensions, par exemple passer des coordonnées 3D vers 2D en supprimant la hauteur.</li>
- <li>Convertir des unités de mesures, par exemple convertir des pieds en mètres.</li>
- <li>Convertir des coordonnées pixels en coordonnées géographiques,
- par exemple la conversion exprimée dans les fichiers <code>.tfw</code> qui accompagnent certaines images <abbr>TIFF</abbr>.</li>
- <li>Prendre en charge une petite partie des projections cartographiques,
- par exemple les paramètres <cite>False Easting</cite>, <cite>False Northing</cite> et <cite>Scale factor</cite>.</li>
- </ul>
- <p>
- Les transformations affines peuvent se combiner efficacement.
- Peu importe le nombre de transformations affines que l’on enchaîne, le résultat sera exprimable par une seule transformation affine.
- Cette propriété est plus facilement visible lorsque les transformations affines sont exprimées sous forme de matrices:
- pour combiner les opérations, il suffit de multiplier les matrices.
- Le cas des conversions des coordonnées pixels en coordonnées géographiques ci-dessous donne un exemple.
- </p>
-
- <div class="example">
- <p><b>Exemple:</b>
- supposons que nous disposons d’une image dont les coordonnées des pixels sont représentées par (<var>x</var>,<var>y</var>).
- Supposons aussi que les contraintes suivantes sont respectées:
- </p>
- <ul>
- <li>Il n’y a ni cisaillement, ni rotation, ni retournement de l’image.</li>
- <li>Tous les pixels ont la même largeur en degrés de longitude.</li>
- <li>Tous les pixels ont la même hauteur en degrés de latitude.</li>
- <li>Les coordonnées des pixels commencent à (0,0) inclusivement.</li>
- </ul>
- <p>Alors la conversion des coordonnées pixels (<var>x</var>,<var>y</var>)
- vers les coordonnées géographiques (<var>λ</var>,<var>φ</var>)
- peut être représentée par les équations suivantes,
- où <var>N</var><sub><var>x</var></sub> est la largeur
- et <var>N</var><sub><var>y</var></sub> la hauteur de l’image en nombre de pixels.
- </p><p>
- <xi:include href="../math/PixelToGeographicTerms.html"/>
- </p><p>
- Les équations ci-dessus peuvent être représentées sous forme de matrices comme ci-dessous:
- </p><p>
- <xi:include href="../math/PixelToGeographic.html"/>
- </p><p>
- Dans ce cas particulier, les facteurs d’échelles <var>S</var> correspondent à la taille des pixels en degrés
- et les termes de translations <var>T</var> correspondent aux coordonnées géographiques d’un coin de l’image
- (pas nécessairement le coin inférieur gauche si certains axes ont été retournés).
- Cette interprétation directe n’est possible que lorsque les contraintes énumérées plus haut sont respectées.
- Les coefficients des matrices deviennent plus complexes si l’image a un cisaillement ou une rotation,
- ou si les coordonnées des pixels ne commencent pas à (0,0).
- Toutefois il n’est pas nécessaire d’utiliser des équations plus complexes pour gérer des cas plus génériques.
- L’exemple ci-dessous prend comme point de départ la matrice d’une « conversion initiale »
- dans laquelle les coefficients <var>S</var> et <var>T</var> sont les valeurs relativement simples données ci-dessus.
- Ensuite la direction de l’axe des <var>y</var> est inversée de manière à correspondre
- à la convention habituelle des systèmes de coordonnées des images (changement 1),
- et les axes sont intervertis de manière à avoir la latitude avant la longitude (changement 2).
- Notez que les concaténations de transformations affines écrites sous forme de multiplications matricielles
- se lisent de droite à gauche:
- <var>A</var>×<var>B</var>×<var>C</var> est équivalent à d’abord appliquer l’opération <var>C</var>,
- suivit de l’opération <var>B</var> et finalement l’opération <var>A</var>.
- </p>
- <table class="hidden"><tr>
- <th>Changement 2</th><th></th>
- <th>Changement 1</th><th></th>
- <th>Conversion initiale</th><th></th>
- <th>Opérations combinées</th>
- </tr><tr>
- <td style="vertical-align: middle"><xi:include href="../math/AxisSwapping2D.html"/></td>
- <td style="vertical-align: middle; padding-left: 15px; padding-right: 15px">×</td>
- <td style="vertical-align: middle"><xi:include href="../math/InverseAxisY.html"/></td>
- <td style="vertical-align: middle; padding-left: 15px; padding-right: 15px">×</td>
- <td style="vertical-align: middle"><xi:include href="../math/PixelToGeographicSameAxisDirections.html"/></td>
- <td style="vertical-align: middle; padding-left: 15px; padding-right: 15px">=</td>
- <td style="vertical-align: middle"><xi:include href="../math/PixelToGeographicReverseOrderAndY.html"/></td>
- </tr></table>
- <p>
- Un principe clé est qu’il n’y a pas besoin d’écrire un code dédié à ce type d’opérations sur les axes.
- Ces opérations, et bien d’autres, sont prises en compte naturellement par l’algèbre matricielle.
- On y gagne en généricité du code et en performance.
- Apache <abbr>SIS</abbr> suit ce principe en utilisant les tranformations affine pour toutes les opérations
- où elles peuvent s’appliquer.
- Il n’y a par exemple aucun code dédié au changement de l’ordre des ordonnées dans une coordonnée.
- </p>
- </div>
-
- <h4 id="AffineTransformAPI">Intégration avec les bibliothèques graphiques</h4>
- <p>
- A peu près toutes les bibliothèques graphiques supportent une forme de transformation de coordonnées,
- souvent les <cite>transformations affines</cite> ou une légère généralisation.
- Chaque bibliothèque défini son propre <abbr>API</abbr>.
- Quelques exemples sont:
- </p>
- <table>
- <caption>Implémentations des transformations affines dans des bibliothèques graphiques</caption>
- <tr><th>Bibliothèque</th> <th>Implementation de la transformation</th> <th>Dimensions</th></tr>
- <tr><td>Java2D</td> <td><code>java.awt.geom.AffineTransform</code></td> <td>2</td></tr>
- <tr><td>Java3D</td> <td><code>javax.media.j3d.Transform3D</code></td> <td>3</td></tr>
- <tr><td>JavaFX</td> <td><code>javafx.scene.transform.Affine</code></td> <td>2 ou 3</td></tr>
- <tr><td>Java Advanced Imaging (<abbr>JAI</abbr>)</td> <td><code>javax.media.jai.PerspectiveTransform</code></td> <td>2</td></tr>
- <tr><td>Android</td> <td><code>android.graphics.Matrix</code></td> <td>2</td></tr>
- </table>
- <p>
- Toutefois dans plusieurs cas, les transformations affines sont les seuls types d’opérations supportées par la bibliothèque graphique.
- Apache <abbr>SIS</abbr> a besoin de gérer un plus grand nombre de type d’opérations,
- parmi lesquelles les transformations affines ne sont que des cas particuliers.
- Les projections cartographiques et les changements de référentiels notamment,
- ne peuvent pas être représentés par des transformations affines.
- <abbr>SIS</abbr> a aussi besoin de transformer des points ayant un nombre arbitraire de dimensions,
- alors que les <abbr>API</abbr> cités ci-haut restreignent leur usage à un nombre fixe de dimensions.
- Pour ces raisons, <abbr>SIS</abbr> ne peut pas utiliser directement ces <abbr>API</abbr>.
- <abbr>SIS</abbr> utilise plutôt une interface plus abstraite, <code>org.opengis.referencing.transform.MathTransform</code>.
- Mais dans le cas particulier où la transformation est réellement affine, <abbr>SIS</abbr> peut essayer d’utiliser
- une implémentation existante, surtout Java2D.
- Par exemple le code suivant peut être utilisé dans les situations où un objet Java2D est désiré:
- </p>
- <pre>MathTransform mt = ...; // N’importe quelle instance créée par Apache SIS.
-if (mt instanceof AffineTransform) {
- AffineTransform at = (AffineTransform) mt;
- // Utiliser l’API de Java2D API à partir d’ici.
-}</pre>
- <p>
- Toutefois <abbr>SIS</abbr> n’utilisera Java2D que sur une base opportuniste.
- Le forçage de type ci-haut n’est pas garantit de réussir, même si l’instance de
- <code>MathTransform</code> répond aux conditions qui devrait permettre un usage de Java2D.
- </p>
-
<h3 id="TransformDerivative">Dérivées partielles des opérations</h3>
<p>
La section précédente indiquait comment calculer les coordonnées d’un point géographique dans une projection au choix.
Modified: sis/site/trunk/content/book/en/developer-guide.html
URL: http://svn.apache.org/viewvc/sis/site/trunk/content/book/en/developer-guide.html?rev=1753786&r1=1753785&r2=1753786&view=diff
==============================================================================
--- sis/site/trunk/content/book/en/developer-guide.html (original)
+++ sis/site/trunk/content/book/en/developer-guide.html Fri Jul 22 13:07:12 2016
@@ -60,9 +60,7 @@ Partially translated by <i>Christina Hou
<li><a href="#CRSFactory">Constructing programmatically</a></li>
<li><a href="#CRS_UserCode">Adding new CRS definitions</a></li></ul></li>
<li><a href="#CoordinateOperation">Coordinate operations</a><ul>
-<li><a href="#MathTransform">Executing an operation on coordinate values</a><ul>
-<li><a href="#AffineTransform">Affine transform</a></li>
-<li><a href="#AffineTransformAPI">Integration with graphical libraries</a></li></ul></li>
+<li><a href="#MathTransform">Executing an operation on coordinate values</a></li>
<li><a href="#TransformDerivative">Partial derivatives of coordinate operations</a><ul>
<li><a href="#DerivativeAndEnvelope">Transform derivatives applied to envelopes</a></li>
<li><a href="#DerivativeAndRaster">Transform derivatives applied to rasters</a></li>
@@ -86,6 +84,8 @@ Partially translated by <i>Christina Hou
<li><a href="#GeoAPI-validators">Instance validations</a></li>
<li><a href="#GeoAPI-tests">Executing pre-defined tests</a></li></ul></li>
<li><a href="#DesignNote">Design notes</a><ul>
+<li><a href="#AffineTransform">Affine transform</a><ul>
+<li><a href="#AffineTransformAPI">Integration with graphical libraries</a></li></ul></li>
<li><a href="#MatrixLibrary">Specificities of a matrix library for GIS</a><ul>
<li><a href="#NonSquareMatrix">What to do with non-square matrices (and why)</a></li>
<li><a href="#MatrixLibrarySummary">Apache SIS matrix library</a></li></ul></li></ul></li></ul></li>
@@ -1381,9 +1381,7 @@ or the use of <code>isWhitespace(…)
<li><a href="#CRSFactory">Constructing programmatically</a></li>
<li><a href="#CRS_UserCode">Adding new CRS definitions</a></li></ul></li>
<li><a href="#CoordinateOperation">Coordinate operations</a><ul>
-<li><a href="#MathTransform">Executing an operation on coordinate values</a><ul>
-<li><a href="#AffineTransform">Affine transform</a></li>
-<li><a href="#AffineTransformAPI">Integration with graphical libraries</a></li></ul></li>
+<li><a href="#MathTransform">Executing an operation on coordinate values</a></li>
<li><a href="#TransformDerivative">Partial derivatives of coordinate operations</a><ul>
<li><a href="#DerivativeAndEnvelope">Transform derivatives applied to envelopes</a></li>
<li><a href="#DerivativeAndRaster">Transform derivatives applied to rasters</a></li>
@@ -1764,408 +1762,81 @@ Note that all geographic coordinates bel
}</pre>
-<h4 id="AffineTransform"><span class="section-number">3.3.1.1.</span> Affine transform</h4>
-<p>
-Among the many kinds of operations performed by <abbr>GIS</abbr> softwares on spatial coordinates,
-<cite>affine transforms</cite> are both relatively simple and very common.
-Affine transforms can represent any combination of scales, shears, flips, rotations and translations,
-which are <em>linear</em> operations.
-Affine transforms can not handle <em>non-linear</em> operations like map projections,
-but the affine transform capabilities nevertheless cover many other cases:
-</p>
-<ul>
-<li>Axis order changes, for example from (<var>latitude</var>, <var>longitude</var>) to (<var>longitude</var>, <var>latitude</var>).</li>
-<li>Axis direction changes, for example the <var>y</var> axis oriented toward down in images.</li>
-<li>Prime meridian rotations, for example from <cite>Paris</cite> to <cite>Greenwich</cite> prime meridian.</li>
-<li>Dimensionality changes, for example from 3-dimensional coordinates to 2-dimensional coordinates by dropping the height.</li>
-<li>Unit conversion, for example from feet to metres.</li>
-<li>Pixel to geodetic coordinate, for example the conversion represented in the <code>.tfw</code> files associated to some <abbr>TIFF</abbr> images.</li>
-<li>Part of map projections, for example the <cite>False Easting</cite>, <cite>False Northing</cite> and <cite>Scale factor</cite> parameters.</li>
-</ul>
+<h3 id="TransformDerivative"><span class="section-number">3.3.2.</span> Partial derivatives of coordinate operations</h3>
<p>
-Affine transforms can be concatenated efficiently.
-No matter how many affine transforms are chained, the result can be represented by a single affine transform.
-This property is more easily seen when affine transforms are represented by matrices:
-in order to concatenate those operations, we only need to multiply those matrices.
-The “pixel to geographic coordinate conversions” case below gives an example.
-</p>
-
-<div class="example">
-<p><b>Example:</b>
-given an image with pixel coordinates represented by (<var>x</var>,<var>y</var>) tuples
-and given the following assumptions:
+<span style="color: red">TODO</span>
</p>
-<ul>
-<li>There is no shear, no rotation and no flip.</li>
-<li>All pixels have the same width in degrees of longitude.</li>
-<li>All pixels have the same height in degrees of latitude.</li>
-<li>Pixel indices are positive integers starting at (0,0) inclusive.</li>
-</ul>
-<p>Then conversions from pixel coordinates (<var>x</var>,<var>y</var>)
-to geographic coordinates (<var>λ</var>,<var>φ</var>) can be represented by the following equations,
-where <var>N</var><sub><var>x</var></sub> is the image width and
-<var>N</var><sub><var>y</var></sub> the image height in number of pixels:
-</p><p>
-
<math xmlns="http://www.w3.org/1998/Math/MathML" alttext="MathML capable browser required" display="block">
+<mi>P</mi><mo>(</mo><mi>λ</mi><mo>,</mo><mi>φ</mi><mo>)</mo>
+<mo>=</mo>
+<mfenced close="]" open="[">
<mtable>
-<mtr>
-<mtd><mo>λ</mo></mtd>
-<mtd><mo>=</mo></mtd>
-<mtd><msub><mi>S</mi><mrow>λ</mrow></msub><mi>x</mi><mo>+</mo><msub><mi>T</mi><mrow>λ</mrow></msub></mtd>
-<mtd><mtext> where </mtext></mtd>
-<mtd><msub><mi>S</mi><mrow>λ</mrow></msub></mtd>
-<mtd><mo>=</mo></mtd>
-<mtd>
-<mfrac>
-<mrow>
-<msub><mi>λ</mi><mrow>max</mrow></msub><mo>-</mo>
-<msub><mi>λ</mi><mrow>min</mrow></msub>
-</mrow><mrow>
-<msub><mi>N</mi><mrow><mi>x</mi></mrow></msub>
-</mrow>
-</mfrac>
-</mtd>
-<mtd><mtext> and </mtext></mtd>
-<mtd><msub><mi>T</mi><mrow>λ</mrow></msub></mtd>
-<mtd><mo>=</mo></mtd>
-<mtd><msub><mi>λ</mi><mrow>min</mrow></msub></mtd>
-</mtr>
-<mtr>
-<mtd><mo>φ</mo></mtd>
-<mtd><mo>=</mo></mtd>
-<mtd><msub><mi>S</mi><mrow>φ</mrow></msub><mi>y</mi><mo>+</mo><msub><mi>T</mi><mrow>φ</mrow></msub></mtd>
-<mtd><mtext> where </mtext></mtd>
-<mtd><msub><mi>S</mi><mrow>φ</mrow></msub></mtd>
-<mtd><mo>=</mo></mtd>
-<mtd>
-<mfrac>
-<mrow>
-<msub><mi>φ</mi><mrow>max</mrow></msub><mo>-</mo>
-<msub><mi>φ</mi><mrow>min</mrow></msub>
-</mrow><mrow>
-<msub><mi>N</mi><mrow><mi>y</mi></mrow></msub>
-</mrow>
-</mfrac>
-</mtd>
-<mtd><mtext> and </mtext></mtd>
-<mtd><msub><mi>T</mi><mrow>φ</mrow></msub></mtd>
-<mtd><mo>=</mo></mtd>
-<mtd><msub><mi>φ</mi><mrow>min</mrow></msub></mtd>
-</mtr>
+<mtr><mtd><mi>x</mi><mo>(</mo><mi>λ</mi><mo>,</mo><mi>φ</mi><mo>)</mo></mtd></mtr>
+<mtr><mtd><mi>y</mi><mo>(</mo><mi>λ</mi><mo>,</mo><mi>φ</mi><mo>)</mo></mtd></mtr>
</mtable>
+</mfenced>
</math>
-</p><p>
-Above equations can be represented in matrix form as below:
-</p><p>
+<p>The map projection partial derivate at this point can be represented by the Jacobian matrix:</p>
<math xmlns="http://www.w3.org/1998/Math/MathML" alttext="MathML capable browser required" display="block">
-<mfenced close="]" open="[">
-<mtable>
-<mtr><mtd><mi>λ</mi></mtd></mtr>
-<mtr><mtd><mi>φ</mi></mtd></mtr>
-<mtr><mtd><mn>1</mn></mtd></mtr>
-</mtable>
-</mfenced>
+<msup><mi>P</mi><mo>′</mo></msup><mo>(</mo><mi>λ</mi><mo>,</mo><mi>φ</mi><mo>)</mo>
+<mo>=</mo>
+<msub><mi>JAC</mi><mrow><mi>P</mi><mo>(</mo><mi>λ</mi><mo>,</mo><mi>φ</mi><mo>)</mo></mrow></msub>
<mo>=</mo>
<mfenced close="]" open="[">
<mtable>
<mtr>
-<mtd><msub><mi>S</mi><mrow>λ</mrow></msub></mtd>
-<mtd><mn>0</mn></mtd>
-<mtd><msub><mi>T</mi><mrow>λ</mrow></msub></mtd>
-</mtr>
-<mtr>
-<mtd><mn>0</mn></mtd>
-<mtd><msub><mi>S</mi><mrow>φ</mrow></msub></mtd>
-<mtd><msub><mi>T</mi><mrow>φ</mrow></msub></mtd>
+<mtd><mfrac><mrow><mo>∂</mo><mi>x</mi><mo>(</mo><mi>λ</mi><mo>,</mo><mi>φ</mi><mo>)</mo></mrow><mrow><mo>∂</mo><mi>λ</mi></mrow></mfrac></mtd>
+<mtd><mfrac><mrow><mo>∂</mo><mi>x</mi><mo>(</mo><mi>λ</mi><mo>,</mo><mi>φ</mi><mo>)</mo></mrow><mrow><mo>∂</mo><mi>φ</mi></mrow></mfrac></mtd>
</mtr>
<mtr>
-<mtd><mn>0</mn></mtd>
-<mtd><mn>0</mn></mtd>
-<mtd><mn>1</mn></mtd>
+<mtd><mfrac><mrow><mo>∂</mo><mi>y</mi><mo>(</mo><mi>λ</mi><mo>,</mo><mi>φ</mi><mo>)</mo></mrow><mrow><mo>∂</mo><mi>λ</mi></mrow></mfrac></mtd>
+<mtd><mfrac><mrow><mo>∂</mo><mi>y</mi><mo>(</mo><mi>λ</mi><mo>,</mo><mi>φ</mi><mo>)</mo></mrow><mrow><mo>∂</mo><mi>φ</mi></mrow></mfrac></mtd>
</mtr>
</mtable>
</mfenced>
-<mo>×</mo>
-<mfenced close="]" open="[">
-<mtable>
-<mtr><mtd><mi>x</mi></mtd></mtr>
-<mtr><mtd><mi>y</mi></mtd></mtr>
-<mtr><mtd><mn>1</mn></mtd></mtr>
-</mtable>
-</mfenced>
</math>
-</p><p>
-In this particular case, scale factors <var>S</var> are the pixel size in degrees
-and translation terms <var>T</var> are the geographic coordinate of an image corner
-(not necessarily the lower-left corner if some axes have been flipped).
-This straightforward interpretation holds because of above-cited assumptions, but
-matrix coefficients become more complex if the image has shear or rotation
-or if pixel coordinates do not start at (0,0).
-However it is not necessary to use more complex equations for supporting more generic cases.
-The following example starts with an “initial conversion” matrix
-where the <var>S</var> and <var>T</var> terms are set to the most straightforward values.
-Then the <var>y</var> axis direction is reversed for matching the most common convention in image coordinate systems (change 1),
-and axis are swapped resulting in latitude before longitude (change 2).
-Note that when affine transform concatenations are written as matrix multiplications, operations are ordered from right to left:
-<var>A</var>×<var>B</var>×<var>C</var> is equivalent to first applying operation <var>C</var>,
-then operation <var>B</var> and finally operation <var>A</var>.
+
+<p>
+<span style="color: red">TODO</span>
</p>
+
<table class="hidden"><tr>
-<th>Change 2</th><th/>
-<th>Change 1</th><th/>
-<th>Initial conversion</th><th/>
-<th>Concatenated operation</th>
-</tr><tr>
-<td style="vertical-align: middle">
+<td><img alt="Exemple de dérivées d’une projection cartographique" src="../images/Derivatives.png" style="border: solid 1px"/></td>
+<td style="padding-left: 30px; vertical-align: middle">
+<p>where vectors are related to the matrix by:</p>
<math xmlns="http://www.w3.org/1998/Math/MathML" alttext="MathML capable browser required" display="block">
+<mtable><mtr>
+<mtd>
+<mover><mi>U</mi><mo>→</mo></mover><mo>=</mo>
<mfenced close="]" open="[">
<mtable>
<mtr>
-<mtd><mn>0</mn></mtd>
-<mtd><mn>1</mn></mtd>
-<mtd><mn>0</mn></mtd>
-</mtr>
-<mtr>
-<mtd><mn>1</mn></mtd>
-<mtd><mn>0</mn></mtd>
-<mtd><mn>0</mn></mtd>
-</mtr>
-<mtr>
-<mtd><mn>0</mn></mtd>
-<mtd><mn>0</mn></mtd>
-<mtd><mn>1</mn></mtd>
-</mtr>
-</mtable>
-</mfenced>
-</math>
-</td>
-<td style="vertical-align: middle; padding-left: 15px; padding-right: 15px">×</td>
-<td style="vertical-align: middle">
-<math xmlns="http://www.w3.org/1998/Math/MathML" display="block">
-<mfenced close="]" open="[">
-<mtable>
-<mtr>
-<mtd><mn>1</mn></mtd>
-<mtd><mn>0</mn></mtd>
-<mtd><mn>0</mn></mtd>
-</mtr>
-<mtr>
-<mtd><mn>0</mn></mtd>
-<mtd><mn>-1</mn></mtd>
-<msub><mi>N</mi><mrow><mi>y</mi></mrow></msub>
+<mtd><mfrac><mrow><mo>∂</mo><mi>x</mi></mrow><mrow><mo>∂</mo><mi>λ</mi></mrow></mfrac></mtd>
</mtr>
<mtr>
-<mtd><mn>0</mn></mtd>
-<mtd><mn>0</mn></mtd>
-<mtd><mn>1</mn></mtd>
+<mtd><mfrac><mrow><mo>∂</mo><mi>y</mi></mrow><mrow><mo>∂</mo><mi>λ</mi></mrow></mfrac></mtd>
</mtr>
</mtable>
</mfenced>
-</math>
-</td>
-<td style="vertical-align: middle; padding-left: 15px; padding-right: 15px">×</td>
-<td style="vertical-align: middle">
-<math xmlns="http://www.w3.org/1998/Math/MathML" display="block">
+</mtd>
+<mtd><mtext>et</mtext></mtd>
+<mtd>
+<mover><mi>V</mi><mo>→</mo></mover><mo>=</mo>
<mfenced close="]" open="[">
<mtable>
<mtr>
-<mtd><mfrac>
-<mrow>
-<msub><mi>λ</mi><mrow>max</mrow></msub><mo>-</mo>
-<msub><mi>λ</mi><mrow>min</mrow></msub>
-</mrow><mrow>
-<msub><mi>N</mi><mrow><mi>x</mi></mrow></msub>
-</mrow>
-</mfrac></mtd>
-<mtd><mn>0</mn></mtd>
-<mtd><msub><mi>λ</mi><mrow>min</mrow></msub></mtd>
-</mtr>
-<mtr>
-<mtd><mn>0</mn></mtd>
-<mtd><mfrac>
-<mrow>
-<msub><mi>φ</mi><mrow>max</mrow></msub><mo>-</mo>
-<msub><mi>φ</mi><mrow>min</mrow></msub>
-</mrow><mrow>
-<msub><mi>N</mi><mrow><mi>y</mi></mrow></msub>
-</mrow>
-</mfrac></mtd>
-<mtd><msub><mi>φ</mi><mrow>min</mrow></msub></mtd>
+<mtd><mfrac><mrow><mo>∂</mo><mi>x</mi></mrow><mrow><mo>∂</mo><mi>φ</mi></mrow></mfrac></mtd>
</mtr>
<mtr>
-<mtd><mn>0</mn></mtd>
-<mtd><mn>0</mn></mtd>
-<mtd><mn>1</mn></mtd>
+<mtd><mfrac><mrow><mo>∂</mo><mi>y</mi></mrow><mrow><mo>∂</mo><mi>φ</mi></mrow></mfrac></mtd>
</mtr>
</mtable>
</mfenced>
-</math>
-</td>
-<td style="vertical-align: middle; padding-left: 15px; padding-right: 15px">=</td>
-<td style="vertical-align: middle">
-<math xmlns="http://www.w3.org/1998/Math/MathML" display="block">
-<mfenced close="]" open="[">
-<mtable>
-<mtr>
-<mtd><mn>0</mn></mtd>
-<mtd><mo>-</mo><mfrac>
-<mrow>
-<msub><mi>φ</mi><mrow>max</mrow></msub><mo>-</mo>
-<msub><mi>φ</mi><mrow>min</mrow></msub>
-</mrow><mrow>
-<msub><mi>N</mi><mrow><mi>y</mi></mrow></msub>
-</mrow>
-</mfrac></mtd>
-<mtd><msub><mi>φ</mi><mrow>max</mrow></msub></mtd>
-</mtr>
-<mtr>
-<mtd><mfrac>
-<mrow>
-<msub><mi>λ</mi><mrow>max</mrow></msub><mo>-</mo>
-<msub><mi>λ</mi><mrow>min</mrow></msub>
-</mrow><mrow>
-<msub><mi>N</mi><mrow><mi>x</mi></mrow></msub>
-</mrow>
-</mfrac></mtd>
-<mtd><mn>0</mn></mtd>
-<mtd><msub><mi>λ</mi><mrow>min</mrow></msub></mtd>
-</mtr>
-<mtr>
-<mtd><mn>0</mn></mtd>
-<mtd><mn>0</mn></mtd>
-<mtd><mn>1</mn></mtd>
-</mtr>
-</mtable>
-</mfenced>
-</math>
-</td>
-</tr></table>
-<p>
-A key principle is that there is no need to write Java code dedicated to above kinds of axis changes.
-Those operations, and many other, can be handled by matrix algebra.
-This approach makes easier to write generic code and improves performance.
-Apache <abbr title="Spatial Information System">SIS</abbr> follows this principle by using affine transforms for every operations
-that can be performed by such transform.
-For instance there is no code dedicated to changing order of ordinate values in a coordinate.
-</p>
-</div>
-
-<h4 id="AffineTransformAPI"><span class="section-number">3.3.1.2.</span> Integration with graphical libraries</h4>
-<p>
-About all graphical libraries support some kind of coordinate operations, usually as <cite>affine transforms</cite>
-or a slight generalization like <cite>perspective transforms</cite>.
-Each library defines its own <abbr title="Application Programming Interface">API</abbr>. Some examples are listed below:
-</p>
-<table>
-<caption>Affine transform implementations in graphical libraries</caption>
-<tr><th>Library</th> <th>Transform implementation</th> <th>Dimensions</th></tr>
-<tr><td>Java2D</td> <td><code>java.awt.geom.AffineTransform</code></td> <td>2</td></tr>
-<tr><td>Java3D</td> <td><code>javax.media.j3d.Transform3D</code></td> <td>3</td></tr>
-<tr><td>JavaFX</td> <td><code>javafx.scene.transform.Affine</code></td> <td>2 or 3</td></tr>
-<tr><td>Java Advanced Imaging (<abbr>JAI</abbr>)</td> <td><code>javax.media.jai.PerspectiveTransform</code></td> <td>2</td></tr>
-<tr><td>Android</td> <td><code>android.graphics.Matrix</code></td> <td>2</td></tr>
-</table>
-<p>
-However in many cases, affine or perspective transforms are the only kind of coordinate operations supported by the graphical library.
-Apache <abbr title="Spatial Information System">SIS</abbr> needs to handle a wider range of operations, in which affine transforms are only special cases.
-In particular most map projections and datum shifts can not be represented by affine transforms.
-<abbr>SIS</abbr> also needs to support arbitrary number of dimensions,
-while above-cited <abbr>API</abbr> restrict the use to a fixed number of dimensions.
-For those reasons <abbr>SIS</abbr> can not use directly the above-cited <abbr>API</abbr>.
-Instead, <abbr>SIS</abbr> uses the more abstract <code class="GeoAPI">org.opengis.referencing.transform.MathTransform</code> interface.
-But in the special case where the transform is actually affine, <abbr>SIS</abbr> may try to use an existing implementation,
-in particular Java2D. The following Java code can be used in situations where the Java2D object is desired:
-</p>
-<pre><code class="GeoAPI">MathTransform</code> mt = ...; <code class="comment">// Any math transform created by Apache SIS.
-</code><b>if</b> (mt <b>instanceof</b> AffineTransform) {
- AffineTransform at = (AffineTransform) mt;
- <code class="comment">// Use Java2D API from here.
-</code>}</pre>
-<p>
-Apache <abbr>SIS</abbr> uses Java2D on a <em>best effort</em> basis only.
-The above cast is not guaranteed to succeed,
-even when the <code class="GeoAPI">MathTransform</code> meets the requirements allowing Java2D usage.
-</p>
-
-<h3 id="TransformDerivative"><span class="section-number">3.3.2.</span> Partial derivatives of coordinate operations</h3>
-<p>
-<span style="color: red">TODO</span>
-</p>
-
-<math xmlns="http://www.w3.org/1998/Math/MathML" alttext="MathML capable browser required" display="block">
-<mi>P</mi><mo>(</mo><mi>λ</mi><mo>,</mo><mi>φ</mi><mo>)</mo>
-<mo>=</mo>
-<mfenced close="]" open="[">
-<mtable>
-<mtr><mtd><mi>x</mi><mo>(</mo><mi>λ</mi><mo>,</mo><mi>φ</mi><mo>)</mo></mtd></mtr>
-<mtr><mtd><mi>y</mi><mo>(</mo><mi>λ</mi><mo>,</mo><mi>φ</mi><mo>)</mo></mtd></mtr>
-</mtable>
-</mfenced>
-</math>
-
-<p>The map projection partial derivate at this point can be represented by the Jacobian matrix:</p>
-
-<math xmlns="http://www.w3.org/1998/Math/MathML" alttext="MathML capable browser required" display="block">
-<msup><mi>P</mi><mo>′</mo></msup><mo>(</mo><mi>λ</mi><mo>,</mo><mi>φ</mi><mo>)</mo>
-<mo>=</mo>
-<msub><mi>JAC</mi><mrow><mi>P</mi><mo>(</mo><mi>λ</mi><mo>,</mo><mi>φ</mi><mo>)</mo></mrow></msub>
-<mo>=</mo>
-<mfenced close="]" open="[">
-<mtable>
-<mtr>
-<mtd><mfrac><mrow><mo>∂</mo><mi>x</mi><mo>(</mo><mi>λ</mi><mo>,</mo><mi>φ</mi><mo>)</mo></mrow><mrow><mo>∂</mo><mi>λ</mi></mrow></mfrac></mtd>
-<mtd><mfrac><mrow><mo>∂</mo><mi>x</mi><mo>(</mo><mi>λ</mi><mo>,</mo><mi>φ</mi><mo>)</mo></mrow><mrow><mo>∂</mo><mi>φ</mi></mrow></mfrac></mtd>
-</mtr>
-<mtr>
-<mtd><mfrac><mrow><mo>∂</mo><mi>y</mi><mo>(</mo><mi>λ</mi><mo>,</mo><mi>φ</mi><mo>)</mo></mrow><mrow><mo>∂</mo><mi>λ</mi></mrow></mfrac></mtd>
-<mtd><mfrac><mrow><mo>∂</mo><mi>y</mi><mo>(</mo><mi>λ</mi><mo>,</mo><mi>φ</mi><mo>)</mo></mrow><mrow><mo>∂</mo><mi>φ</mi></mrow></mfrac></mtd>
-</mtr>
-</mtable>
-</mfenced>
-</math>
-
-<p>
-<span style="color: red">TODO</span>
-</p>
-
-<table class="hidden"><tr>
-<td><img alt="Exemple de dérivées d’une projection cartographique" src="../images/Derivatives.png" style="border: solid 1px"/></td>
-<td style="padding-left: 30px; vertical-align: middle">
-<p>where vectors are related to the matrix by:</p>
-<math xmlns="http://www.w3.org/1998/Math/MathML" alttext="MathML capable browser required" display="block">
-<mtable><mtr>
-<mtd>
-<mover><mi>U</mi><mo>→</mo></mover><mo>=</mo>
-<mfenced close="]" open="[">
-<mtable>
-<mtr>
-<mtd><mfrac><mrow><mo>∂</mo><mi>x</mi></mrow><mrow><mo>∂</mo><mi>λ</mi></mrow></mfrac></mtd>
-</mtr>
-<mtr>
-<mtd><mfrac><mrow><mo>∂</mo><mi>y</mi></mrow><mrow><mo>∂</mo><mi>λ</mi></mrow></mfrac></mtd>
-</mtr>
-</mtable>
-</mfenced>
-</mtd>
-<mtd><mtext>et</mtext></mtd>
-<mtd>
-<mover><mi>V</mi><mo>→</mo></mover><mo>=</mo>
-<mfenced close="]" open="[">
-<mtable>
-<mtr>
-<mtd><mfrac><mrow><mo>∂</mo><mi>x</mi></mrow><mrow><mo>∂</mo><mi>φ</mi></mrow></mfrac></mtd>
-</mtr>
-<mtr>
-<mtd><mfrac><mrow><mo>∂</mo><mi>y</mi></mrow><mrow><mo>∂</mo><mi>φ</mi></mrow></mfrac></mtd>
-</mtr>
-</mtable>
-</mfenced>
-</mtd>
-</mtr></mtable>
+</mtd>
+</mtr></mtable>
</math>
</td>
</tr></table>
@@ -2874,6 +2545,8 @@ But when a <code class="OGC">nilReason</
<li><a href="#GeoAPI-validators">Instance validations</a></li>
<li><a href="#GeoAPI-tests">Executing pre-defined tests</a></li></ul></li>
<li><a href="#DesignNote">Design notes</a><ul>
+<li><a href="#AffineTransform">Affine transform</a><ul>
+<li><a href="#AffineTransformAPI">Integration with graphical libraries</a></li></ul></li>
<li><a href="#MatrixLibrary">Specificities of a matrix library for GIS</a><ul>
<li><a href="#NonSquareMatrix">What to do with non-square matrices (and why)</a></li>
<li><a href="#MatrixLibrarySummary">Apache SIS matrix library</a></li></ul></li></ul></li></ul></nav>
@@ -3219,7 +2892,336 @@ However, this example adds a supplementa
<h2 id="DesignNote"><span class="section-number">7.3.</span> Design notes</h2>
<p>Following chapters explain the rational behind some implementation choices done in Apache <abbr title="Spatial Information System">SIS</abbr>.</p>
-<h3 id="MatrixLibrary"><span class="section-number">7.3.1.</span> Specificities of a matrix library for <abbr>GIS</abbr></h3>
+
+<h3 id="AffineTransform"><span class="section-number">7.3.1.</span> Affine transform</h3>
+<p>
+Among the many kinds of operations performed by <abbr>GIS</abbr> softwares on spatial coordinates,
+<cite>affine transforms</cite> are both relatively simple and very common.
+Affine transforms can represent any combination of scales, shears, flips, rotations and translations,
+which are <em>linear</em> operations.
+Affine transforms can not handle <em>non-linear</em> operations like map projections,
+but the affine transform capabilities nevertheless cover many other cases:
+</p>
+<ul>
+<li>Axis order changes, for example from (<var>latitude</var>, <var>longitude</var>) to (<var>longitude</var>, <var>latitude</var>).</li>
+<li>Axis direction changes, for example the <var>y</var> axis oriented toward down in images.</li>
+<li>Prime meridian rotations, for example from <cite>Paris</cite> to <cite>Greenwich</cite> prime meridian.</li>
+<li>Dimensionality changes, for example from 3-dimensional coordinates to 2-dimensional coordinates by dropping the height.</li>
+<li>Unit conversion, for example from feet to metres.</li>
+<li>Pixel to geodetic coordinate, for example the conversion represented in the <code>.tfw</code> files associated to some <abbr>TIFF</abbr> images.</li>
+<li>Part of map projections, for example the <cite>False Easting</cite>, <cite>False Northing</cite> and <cite>Scale factor</cite> parameters.</li>
+</ul>
+<p>
+Affine transforms can be concatenated efficiently.
+No matter how many affine transforms are chained, the result can be represented by a single affine transform.
+This property is more easily seen when affine transforms are represented by matrices:
+in order to concatenate those operations, we only need to multiply those matrices.
+The “pixel to geographic coordinate conversions” case below gives an example.
+</p>
+
+<div class="example">
+<p><b>Example:</b>
+given an image with pixel coordinates represented by (<var>x</var>,<var>y</var>) tuples
+and given the following assumptions:
+</p>
+<ul>
+<li>There is no shear, no rotation and no flip.</li>
+<li>All pixels have the same width in degrees of longitude.</li>
+<li>All pixels have the same height in degrees of latitude.</li>
+<li>Pixel indices are positive integers starting at (0,0) inclusive.</li>
+</ul>
+<p>Then conversions from pixel coordinates (<var>x</var>,<var>y</var>)
+to geographic coordinates (<var>λ</var>,<var>φ</var>) can be represented by the following equations,
+where <var>N</var><sub><var>x</var></sub> is the image width and
+<var>N</var><sub><var>y</var></sub> the image height in number of pixels:
+</p><p>
+
+
+<math xmlns="http://www.w3.org/1998/Math/MathML" alttext="MathML capable browser required" display="block">
+<mtable>
+<mtr>
+<mtd><mo>λ</mo></mtd>
+<mtd><mo>=</mo></mtd>
+<mtd><msub><mi>S</mi><mrow>λ</mrow></msub><mi>x</mi><mo>+</mo><msub><mi>T</mi><mrow>λ</mrow></msub></mtd>
+<mtd><mtext> where </mtext></mtd>
+<mtd><msub><mi>S</mi><mrow>λ</mrow></msub></mtd>
+<mtd><mo>=</mo></mtd>
+<mtd>
+<mfrac>
+<mrow>
+<msub><mi>λ</mi><mrow>max</mrow></msub><mo>-</mo>
+<msub><mi>λ</mi><mrow>min</mrow></msub>
+</mrow><mrow>
+<msub><mi>N</mi><mrow><mi>x</mi></mrow></msub>
+</mrow>
+</mfrac>
+</mtd>
+<mtd><mtext> and </mtext></mtd>
+<mtd><msub><mi>T</mi><mrow>λ</mrow></msub></mtd>
+<mtd><mo>=</mo></mtd>
+<mtd><msub><mi>λ</mi><mrow>min</mrow></msub></mtd>
+</mtr>
+<mtr>
+<mtd><mo>φ</mo></mtd>
+<mtd><mo>=</mo></mtd>
+<mtd><msub><mi>S</mi><mrow>φ</mrow></msub><mi>y</mi><mo>+</mo><msub><mi>T</mi><mrow>φ</mrow></msub></mtd>
+<mtd><mtext> where </mtext></mtd>
+<mtd><msub><mi>S</mi><mrow>φ</mrow></msub></mtd>
+<mtd><mo>=</mo></mtd>
+<mtd>
+<mfrac>
+<mrow>
+<msub><mi>φ</mi><mrow>max</mrow></msub><mo>-</mo>
+<msub><mi>φ</mi><mrow>min</mrow></msub>
+</mrow><mrow>
+<msub><mi>N</mi><mrow><mi>y</mi></mrow></msub>
+</mrow>
+</mfrac>
+</mtd>
+<mtd><mtext> and </mtext></mtd>
+<mtd><msub><mi>T</mi><mrow>φ</mrow></msub></mtd>
+<mtd><mo>=</mo></mtd>
+<mtd><msub><mi>φ</mi><mrow>min</mrow></msub></mtd>
+</mtr>
+</mtable>
+</math>
+</p><p>
+Above equations can be represented in matrix form as below:
+</p><p>
+
+
+<math xmlns="http://www.w3.org/1998/Math/MathML" alttext="MathML capable browser required" display="block">
+<mfenced close="]" open="[">
+<mtable>
+<mtr><mtd><mi>λ</mi></mtd></mtr>
+<mtr><mtd><mi>φ</mi></mtd></mtr>
+<mtr><mtd><mn>1</mn></mtd></mtr>
+</mtable>
+</mfenced>
+<mo>=</mo>
+<mfenced close="]" open="[">
+<mtable>
+<mtr>
+<mtd><msub><mi>S</mi><mrow>λ</mrow></msub></mtd>
+<mtd><mn>0</mn></mtd>
+<mtd><msub><mi>T</mi><mrow>λ</mrow></msub></mtd>
+</mtr>
+<mtr>
+<mtd><mn>0</mn></mtd>
+<mtd><msub><mi>S</mi><mrow>φ</mrow></msub></mtd>
+<mtd><msub><mi>T</mi><mrow>φ</mrow></msub></mtd>
+</mtr>
+<mtr>
+<mtd><mn>0</mn></mtd>
+<mtd><mn>0</mn></mtd>
+<mtd><mn>1</mn></mtd>
+</mtr>
+</mtable>
+</mfenced>
+<mo>×</mo>
+<mfenced close="]" open="[">
+<mtable>
+<mtr><mtd><mi>x</mi></mtd></mtr>
+<mtr><mtd><mi>y</mi></mtd></mtr>
+<mtr><mtd><mn>1</mn></mtd></mtr>
+</mtable>
+</mfenced>
+</math>
+</p><p>
+In this particular case, scale factors <var>S</var> are the pixel size in degrees
+and translation terms <var>T</var> are the geographic coordinate of an image corner
+(not necessarily the lower-left corner if some axes have been flipped).
+This straightforward interpretation holds because of above-cited assumptions, but
+matrix coefficients become more complex if the image has shear or rotation
+or if pixel coordinates do not start at (0,0).
+However it is not necessary to use more complex equations for supporting more generic cases.
+The following example starts with an “initial conversion” matrix
+where the <var>S</var> and <var>T</var> terms are set to the most straightforward values.
+Then the <var>y</var> axis direction is reversed for matching the most common convention in image coordinate systems (change 1),
+and axis are swapped resulting in latitude before longitude (change 2).
+Note that when affine transform concatenations are written as matrix multiplications, operations are ordered from right to left:
+<var>A</var>×<var>B</var>×<var>C</var> is equivalent to first applying operation <var>C</var>,
+then operation <var>B</var> and finally operation <var>A</var>.
+</p>
+<table class="hidden"><tr>
+<th>Change 2</th><th/>
+<th>Change 1</th><th/>
+<th>Initial conversion</th><th/>
+<th>Concatenated operation</th>
+</tr><tr>
+<td style="vertical-align: middle">
+<math xmlns="http://www.w3.org/1998/Math/MathML" alttext="MathML capable browser required" display="block">
+<mfenced close="]" open="[">
+<mtable>
+<mtr>
+<mtd><mn>0</mn></mtd>
+<mtd><mn>1</mn></mtd>
+<mtd><mn>0</mn></mtd>
+</mtr>
+<mtr>
+<mtd><mn>1</mn></mtd>
+<mtd><mn>0</mn></mtd>
+<mtd><mn>0</mn></mtd>
+</mtr>
+<mtr>
+<mtd><mn>0</mn></mtd>
+<mtd><mn>0</mn></mtd>
+<mtd><mn>1</mn></mtd>
+</mtr>
+</mtable>
+</mfenced>
+</math>
+</td>
+<td style="vertical-align: middle; padding-left: 15px; padding-right: 15px">×</td>
+<td style="vertical-align: middle">
+<math xmlns="http://www.w3.org/1998/Math/MathML" display="block">
+<mfenced close="]" open="[">
+<mtable>
+<mtr>
+<mtd><mn>1</mn></mtd>
+<mtd><mn>0</mn></mtd>
+<mtd><mn>0</mn></mtd>
+</mtr>
+<mtr>
+<mtd><mn>0</mn></mtd>
+<mtd><mn>-1</mn></mtd>
+<msub><mi>N</mi><mrow><mi>y</mi></mrow></msub>
+</mtr>
+<mtr>
+<mtd><mn>0</mn></mtd>
+<mtd><mn>0</mn></mtd>
+<mtd><mn>1</mn></mtd>
+</mtr>
+</mtable>
+</mfenced>
+</math>
+</td>
+<td style="vertical-align: middle; padding-left: 15px; padding-right: 15px">×</td>
+<td style="vertical-align: middle">
+<math xmlns="http://www.w3.org/1998/Math/MathML" display="block">
+<mfenced close="]" open="[">
+<mtable>
+<mtr>
+<mtd><mfrac>
+<mrow>
+<msub><mi>λ</mi><mrow>max</mrow></msub><mo>-</mo>
+<msub><mi>λ</mi><mrow>min</mrow></msub>
+</mrow><mrow>
+<msub><mi>N</mi><mrow><mi>x</mi></mrow></msub>
+</mrow>
+</mfrac></mtd>
+<mtd><mn>0</mn></mtd>
+<mtd><msub><mi>λ</mi><mrow>min</mrow></msub></mtd>
+</mtr>
+<mtr>
+<mtd><mn>0</mn></mtd>
+<mtd><mfrac>
+<mrow>
+<msub><mi>φ</mi><mrow>max</mrow></msub><mo>-</mo>
+<msub><mi>φ</mi><mrow>min</mrow></msub>
+</mrow><mrow>
+<msub><mi>N</mi><mrow><mi>y</mi></mrow></msub>
+</mrow>
+</mfrac></mtd>
+<mtd><msub><mi>φ</mi><mrow>min</mrow></msub></mtd>
+</mtr>
+<mtr>
+<mtd><mn>0</mn></mtd>
+<mtd><mn>0</mn></mtd>
+<mtd><mn>1</mn></mtd>
+</mtr>
+</mtable>
+</mfenced>
+</math>
+</td>
+<td style="vertical-align: middle; padding-left: 15px; padding-right: 15px">=</td>
+<td style="vertical-align: middle">
+<math xmlns="http://www.w3.org/1998/Math/MathML" display="block">
+<mfenced close="]" open="[">
+<mtable>
+<mtr>
+<mtd><mn>0</mn></mtd>
+<mtd><mo>-</mo><mfrac>
+<mrow>
+<msub><mi>φ</mi><mrow>max</mrow></msub><mo>-</mo>
+<msub><mi>φ</mi><mrow>min</mrow></msub>
+</mrow><mrow>
+<msub><mi>N</mi><mrow><mi>y</mi></mrow></msub>
+</mrow>
+</mfrac></mtd>
+<mtd><msub><mi>φ</mi><mrow>max</mrow></msub></mtd>
+</mtr>
+<mtr>
+<mtd><mfrac>
+<mrow>
+<msub><mi>λ</mi><mrow>max</mrow></msub><mo>-</mo>
+<msub><mi>λ</mi><mrow>min</mrow></msub>
+</mrow><mrow>
+<msub><mi>N</mi><mrow><mi>x</mi></mrow></msub>
+</mrow>
+</mfrac></mtd>
+<mtd><mn>0</mn></mtd>
+<mtd><msub><mi>λ</mi><mrow>min</mrow></msub></mtd>
+</mtr>
+<mtr>
+<mtd><mn>0</mn></mtd>
+<mtd><mn>0</mn></mtd>
+<mtd><mn>1</mn></mtd>
+</mtr>
+</mtable>
+</mfenced>
+</math>
+</td>
+</tr></table>
+<p>
+A key principle is that there is no need to write Java code dedicated to above kinds of axis changes.
+Those operations, and many other, can be handled by matrix algebra.
+This approach makes easier to write generic code and improves performance.
+Apache <abbr title="Spatial Information System">SIS</abbr> follows this principle by using affine transforms for every operations
+that can be performed by such transform.
+For instance there is no code dedicated to changing order of ordinate values in a coordinate.
+</p>
+</div>
+
+<h4 id="AffineTransformAPI"><span class="section-number">7.3.1.1.</span> Integration with graphical libraries</h4>
+<p>
+About all graphical libraries support some kind of coordinate operations, usually as <cite>affine transforms</cite>
+or a slight generalization like <cite>perspective transforms</cite>.
+Each library defines its own <abbr title="Application Programming Interface">API</abbr>. Some examples are listed below:
+</p>
+<table>
+<caption>Affine transform implementations in graphical libraries</caption>
+<tr><th>Library</th> <th>Transform implementation</th> <th>Dimensions</th></tr>
+<tr><td>Java2D</td> <td><code>java.awt.geom.AffineTransform</code></td> <td>2</td></tr>
+<tr><td>Java3D</td> <td><code>javax.media.j3d.Transform3D</code></td> <td>3</td></tr>
+<tr><td>JavaFX</td> <td><code>javafx.scene.transform.Affine</code></td> <td>2 or 3</td></tr>
+<tr><td>Java Advanced Imaging (<abbr>JAI</abbr>)</td> <td><code>javax.media.jai.PerspectiveTransform</code></td> <td>2</td></tr>
+<tr><td>Android</td> <td><code>android.graphics.Matrix</code></td> <td>2</td></tr>
+</table>
+<p>
+However in many cases, affine or perspective transforms are the only kind of coordinate operations supported by the graphical library.
+Apache <abbr title="Spatial Information System">SIS</abbr> needs to handle a wider range of operations, in which affine transforms are only special cases.
+In particular most map projections and datum shifts can not be represented by affine transforms.
+<abbr>SIS</abbr> also needs to support arbitrary number of dimensions,
+while above-cited <abbr>API</abbr> restrict the use to a fixed number of dimensions.
+For those reasons <abbr>SIS</abbr> can not use directly the above-cited <abbr>API</abbr>.
+Instead, <abbr>SIS</abbr> uses the more abstract <code class="GeoAPI">org.opengis.referencing.transform.MathTransform</code> interface.
+But in the special case where the transform is actually affine, <abbr>SIS</abbr> may try to use an existing implementation,
+in particular Java2D. The following Java code can be used in situations where the Java2D object is desired:
+</p>
+<pre><code class="GeoAPI">MathTransform</code> mt = ...; <code class="comment">// Any math transform created by Apache SIS.
+</code><b>if</b> (mt <b>instanceof</b> AffineTransform) {
+ AffineTransform at = (AffineTransform) mt;
+ <code class="comment">// Use Java2D API from here.
+</code>}</pre>
+<p>
+Apache <abbr>SIS</abbr> uses Java2D on a <em>best effort</em> basis only.
+The above cast is not guaranteed to succeed,
+even when the <code class="GeoAPI">MathTransform</code> meets the requirements allowing Java2D usage.
+</p>
+
+
+<h3 id="MatrixLibrary"><span class="section-number">7.3.2.</span> Specificities of a matrix library for <abbr>GIS</abbr></h3>
<p>
<abbr>GIS</abbr> make an extensive usage of matrices for displaying maps or for transforming coordinates.
There is many excellent open source or commercial matrix libraries available.
@@ -3264,7 +3266,7 @@ This implementation addresses the accura
at the cost of performance in a phase (transform <em>preparation</em>) where performance is not considered critical.
</p>
-<h4 id="NonSquareMatrix"><span class="section-number">7.3.1.1.</span> What to do with non-square matrices (and why)</h4>
+<h4 id="NonSquareMatrix"><span class="section-number">7.3.2.1.</span> What to do with non-square matrices (and why)</h4>
<p>
Apache <abbr title="Spatial Information System">SIS</abbr> often needs to inverse matrices, in order to perform a coordinate operation in reverse direction.
Matrix inversions are typically performed on square matrices, but <abbr>SIS</abbr> also needs to inverse non-square matrices.
@@ -3363,7 +3365,7 @@ Consequently in over-determined systems
but in case of success the resulting coordinate operation is guaranteed to be exact (ignoring rounding errors).
</p>
-<h4 id="MatrixLibrarySummary"><span class="section-number">7.3.1.2.</span> Apache <abbr title="Spatial Information System">SIS</abbr> matrix library</h4>
+<h4 id="MatrixLibrarySummary"><span class="section-number">7.3.2.2.</span> Apache <abbr title="Spatial Information System">SIS</abbr> matrix library</h4>
<p>
In summary, Apache <abbr>SIS</abbr> provides its own matrix library for the following reasons:
</p>