Author: desruisseaux
Date: Mon Nov 9 12:17:16 2015
New Revision: 1713408
URL: http://svn.apache.org/viewvc?rev=1713408&view=rev
Log:
Ported a text about the specificities of matrix in Apache SIS.
Modified:
sis/site/trunk/book/fr/referencing.html
sis/site/trunk/content/book/fr/developer-guide.html
Modified: sis/site/trunk/book/fr/referencing.html
URL:
http://svn.apache.org/viewvc/sis/site/trunk/book/fr/referencing.html?rev=1713408&r1=1713407&r2=1713408&view=diff
==============================================================================
--- sis/site/trunk/book/fr/referencing.html (original)
+++ sis/site/trunk/book/fr/referencing.html Mon Nov 9 12:17:16 2015
@@ -48,7 +48,7 @@
<ul>
<li>Rester dans la zone de validité du système, telle que donnée par
<code>ReferenceSystem.getDomainOfValidity()</code>.</li>
<li>Savoir que les mesures de distances dans une projection
cartographique donnée ne sont vraies quâà certains endroits,
- appelés par exemple « parallèles standards ».</li>
+ appelés par exemple « parallèles standards ».</li>
<li>Vérifier la précision des transformations de coordonnées, telle
que donnée par
<code>CoordinateOperation.getCoordinateOperationAccuracy()</code>.</li>
</ul>
@@ -116,14 +116,14 @@
Tout en étant nettement plus lisse que la surface topographique,
le géoïde présente des creux et des bosses liés à lâinégale
distribution des masses de la Terre.
Pour une utilisation mathématiquement plus aisée, le géoïde est
donc approximé par un ellipsoïde.
- Cette « figure de la Terre » est représentée dans GeoAPI par
lâinterface <code>Ellipsoid</code>,
+ Cette « figure de la Terre » est représentée dans GeoAPI par
lâinterface <code>Ellipsoid</code>,
qui constitue un élément fondamental des systèmes de références de
type <code>GeographicCRS</code> et <code>ProjectedCRS</code>.
Plusieurs dizaines dâellipsoïdes sont couramment employés, certains
offrant une excellente approximation pour une région précise
au détriment des régions pour lesquelles lâellipsoïde nâa pas
été conçu, et dâautres offrant un compromis pour lâensemble de la
planète.
</p>
<div class="example"><p><b>Exemple:</b>
au début du XX<sup>e</sup> siècle aux Ãtats-Unis, lâétat du
Michigan utilisait pour ses cartes un ellipsoïde basé
- sur lâellipsoïde « Clarke 1866 » mais auquel la longueur des axes a
été allongée de 800 pieds.
+ sur lâellipsoïde « Clarke 1866 » mais auquel la longueur des axes
a été allongée de 800 pieds.
Cette modification visait à tenir compte du niveau moyen de lâétat
au dessus du niveau de la mer.</p>
</div>
@@ -133,12 +133,13 @@
qui épouse au mieux sur lâensemble du pays la forme locale du
géoïde.
Lâécart entre cet ellipsoïde de référence et les creux et les
bosses du géoïde reste généralement inférieur à 100 mètres.
Les paramètres qui permettent de lier un <code>Ellipsoid</code> à la
surface de la Terre (par exemple la position de son centre)
- sont encapsulés dans un objet de type <code>GeodeticDatum</code>, que
lâon traduit en français par « référentiel géodésique ».
+ sont encapsulés dans un objet de type <code>GeodeticDatum</code>, que
lâon traduit en français par « référentiel géodésique ».
Plusieurs <code>GeodeticDatum</code> peuvent utiliser le même
<code>Ellipsoid</code>, mais centré ou orienté différemment.
</p><p>
Avant lâavènement des satellites, les mesures géodésiques se
déroulaient exclusivement à la surface de la terre.
En conséquence, deux îles ou continents qui ne sont pas à portée
visuelle lâun de lâautre nâétaient pas rattachés géodésiquement entre
eux.
- Ainsi les référentiels <cite>North American Datum 1983</cite>
(<abbr>NAD83</abbr>) et <cite>European Datum 1950</cite> (<abbr>ED50</abbr>)
sont indépendants lâun de lâautre:
+ Ainsi les référentiels <cite>North American Datum 1983</cite>
(<abbr>NAD83</abbr>) et
+ <cite>European Datum 1950</cite> (<abbr>ED50</abbr>) sont indépendants
lâun de lâautre:
leurs ellipsoïdes de référence ont des centres distincts et des
dimensions différentes.
Une même coordonnée géographique correspondra à des positions
différentes dans le monde réel
selon que la coordonnée se réfère à lâun ou lâautre de ces
référentiels.
@@ -164,7 +165,7 @@
</p>
<article>
<header>
- <h1>Bibliothèques de type « early binding » versus « late binding
»</h1>
+ <h1>Bibliothèques de type « early binding » versus « late
binding »</h1>
</header>
<p>
Le caractère universel du système <abbr>WGS84</abbr> rend tentante
lâidée de lâutiliser comme système pivot,
@@ -174,7 +175,7 @@
Il suffirait ainsi de stocker dans chaque objet
<code>GeodeticDatum</code> les informations nécessaires à la transformation
vers <abbr>WGS84</abbr>.
Cette approche était encouragée dans la version 1 du format
<abbr>WKT</abbr>, qui définissait un élément <code>TOWGS84</code>
remplissant ce rôle.
</p><p>
- Cette approche est désignée par <abbr>EPSG</abbr> sous le nom de «
early binding »,
+ Cette approche est désignée par <abbr>EPSG</abbr> sous le nom de «Â
early binding »,
car elle associe des informations sur la transformations de
coordonnées très tôt dans la définition des objets géodésiques.
Bien que <abbr>EPSG</abbr> reconnaisse que cette approche soit
couramment employée, elle nâest pas recommandée pour plusieurs raisons:
</p>
@@ -188,23 +189,23 @@
mis en place par le concurrent européen du <abbr>GPS</abbr>. Et
<abbr>WGS84</abbr> lui-même subit parfois des révisions.</li>
</ul>
<p>
- <abbr>EPSG</abbr> recommande plutôt dâutiliser une approche dite «
late binding »,
+ <abbr>EPSG</abbr> recommande plutôt dâutiliser une approche dite
« late binding »,
selon laquelle les paramètres nécessaires aux transformations de
coordonnées sont définis pour des paires de
- référentiels « <var>A</var> vers <var>B</var> » plutôt
quâassociés à des référentiels pris isolément.
- Apache <abbr>SIS</abbr> est une implémentation de type « late
binding »,
- bien quâune réminiscence de lâapproche « early binding » existe
toujours
+ référentiels « <var>A</var> vers <var>B</var> » plutôt
quâassociés à des référentiels pris isolément.
+ Apache <abbr>SIS</abbr> est une implémentation de type « late
binding »,
+ bien quâune réminiscence de lâapproche « early binding »
existe toujours
sous la forme de la propriété
<code>DefaultGeodeticDatum.getBursaWolfParameters()</code>.
</p>
</article>
<h3 id="CoordinateSystem">Systèmes de coordonnées</h3>
- <p>TODO</p>
+ <p style="color: red">TODO</p>
<h3 id="GeographicCRS">Systèmes géographiques</h3>
- <p>TODO</p>
+ <p style="color: red">TODO</p>
<h4 id="GeographicWKT">Format <i>Well-Known Text</i></h4>
- <p>TODO</p>
+ <p style="color: red">TODO</p>
<h3 id="ProjectedCRS">Projections cartographiques</h3>
<p>
@@ -214,43 +215,388 @@
Les propriétés géométriques à conserver dépendent de lâobjet
dâétude et du travail à effectuer.
Par exemple les pays plutôt allongés dans le sens Est-Ouest utilisent
souvent une projection de Lambert,
alors que les pays plutôt allongés dans le sens Nord-Sud préfèrent
une projection de Mercator Transverse.
- </p><p>
- TODO
</p>
+ <p style="color: red">TODO</p>
<h4 id="ProjectedWKT">Format <i>Well-Known Text</i></h4>
- <p>TODO</p>
+ <p style="color: red">TODO</p>
<h3 id="CompoundCRS">Dimensions verticales et temporelles</h3>
- <p>TODO</p>
+ <p style="color: red">TODO</p>
<h4 id="CompoundWKT">Format <i>Well-Known Text</i></h4>
- <p>TODO</p>
+ <p style="color: red">TODO</p>
<h2 id="GetCRS">Obtention dâun système de référence spatial</h2>
- <p>TODO</p>
+ <p style="color: red">TODO</p>
<h3 id="CRSAuthorityFactory">Systèmes prédéfinis par des autorités</h3>
- <p>TODO</p>
+ <p style="color: red">TODO</p>
<h3 id="CRSParsing">Lecture dâune définition au format GML ou WKT</h3>
- <p>TODO</p>
+ <p style="color: red">TODO</p>
<h3 id="CRSFactory">Construction programmatique explicite</h3>
- <p>TODO</p>
+ <p style="color: red">TODO</p>
<h3 id="CRS_UserCode">Ajout de définitions</h3>
- <p>TODO</p>
+ <p style="color: red">TODO</p>
<h2 id="CoordinateOperation">Opérations sur les coordonnées</h2>
- <p>TODO</p>
+ <p style="color: red">TODO</p>
<h3 id="MathTransform">Exécution de opérations</h3>
- <p>TODO</p>
+ <p style="color: red">TODO</p>
+
+ <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, il en est une à la fois simple et très
fréquente.
+ Ce sont les opérations linéaires, constituées uniquement dâune
combinaison dâadditions et de certaines multiplications.
+ Ces opérations nâeffectuent pas de projections cartographiques, plus
complexes, mais couvrent 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>
des images pointe souvent vers le bas).</li>
+ <li>Changer de méridien dâorigine (par exemple de <cite>Paris</cite>
vers <cite>Greenwich</cite>).</li>
+ <li>Changer le nombre de dimensions (par exemple passer des coordonnées
3D vers 2D).</li>
+ <li>Convertir des unités de mesures (par exemple convertir des pieds en
mètres).</li>
+ <li>Convertir les coordonnées pixels dâune image 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>
+ <li>Appliquer des rotations, translations, échelles ou cisaillements
(des transformations dites <cite>affines</cite>).</li>
+ </ul>
+ <p>
+ Les opérations linéaires ont la propriété de toujours se combiner:
+ peu importe le nombre dâopérations linéaires que lâon enchaîne,
le résultat sera toujours exprimable par une seule opération linéaire.
+ Cette propriété est plus facilement visible lorsque les opérations
linéaires sont exprimées sous forme de matrices:
+ pour les combiner, il suffit de multiplier les matrices.
+ </p>
+ <div class="example"><p><b>Example:</b>
+ supposons que nous disposons dâune image dont les coordonnées des
pixels sont représentées par (<var>i</var>,<var>j</var>).
+ Supposons que la taille de chaque pixel correspond à un nombre fixe de
degrées de longitude et de latitude
+ dans un système géographique donné et quâil nây a pas de rotation.
+ La conversion des coordonnées pixels (<var>i</var>,<var>j</var>) vers
les coordonnées géographiques (<var>λ</var>,<var>Ï</var>)
+ est alors linéaire et peut être représentée par la matrice
suivante:</p>
+
+ <table class="hidden"><tr><td>
+ <math xmlns="http://www.w3.org/1998/Math/MathML" display="block"
alttext="MathML capable browser required">
+ <mfenced open="[" close="]">
+ <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 open="[" close="]">
+ <mtable>
+ <mtr>
+ <mtd><msub><mi>S</mi><mrow>λ</mrow></msub></mtd>
+ <mtd><msub><mi>H</mi><mrow>λ</mrow></msub></mtd>
+ <mtd><msub><mi>T</mi><mrow>λ</mrow></msub></mtd>
+ </mtr>
+ <mtr>
+ <mtd><msub><mi>H</mi><mrow>Ï</mrow></msub></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 open="[" close="]">
+ <mtable>
+ <mtr><mtd><mi>i</mi></mtd></mtr>
+ <mtr><mtd><mi>j</mi></mtd></mtr>
+ <mtr><mtd><mn>1</mn></mtd></mtr>
+ </mtable>
+ </mfenced>
+ </math>
+ </td><td style="vertical-align: middle; padding-left: 30px">
+ où
+ </td><td style="vertical-align: middle">
+ <ul>
+ <li><var>S</var> est un facteur dâéchelle (<cite>Scale</cite>)
correspondant dans cet exemple à la taille des pixels.</li>
+ <li><var>H</var> est un terme de cisaillement (<cite>Shear</cite>),
habituellement zéro sauf si lâimage a une rotation.</li>
+ <li><var>T</var> est une translation (<cite>Translation</cite>)
correspondant dans cet exemple à la coordonnée dâun coin de lâimage.</li>
+ </ul>
+ </td></tr></table>
+ <p>
+ Concentrons notre attention sur la matrice du milieu dans
lâéquation ci-dessus.
+ Si nous nâinterchangeons ni nâinversons la direction dâaucun
axe, alors une conversion des coordonnées pixels vers les coordonnées
géographiques
+ pourrait sâexprimer par la matrice « conversion originale »
ci-dessous.
+ Mais si lâon veut en outre inverser la direction de lâaxe des
<var>j</var> pour se conformer à la convention la plus courante appliquée aux
images
+ (« changement 1 ») et interchanger lâordre des axes pour
exprimer la latitude avant la longitude (« changement 2 »),
+ alors on peut exprimer ces modifications par des multiplications
matricielles comme suit
+ (lâordre dans laquelle les opérations sont effectuées sur les
coordonnées se lit de droite à gauche):
+ </p>
+ <table class="hidden"><tr>
+ <th>Changement 2</th><th></th>
+ <th>Changement 1</th><th></th>
+ <th>Conversion originale</th><th></th>
+ <th>Conversion modifiée</th>
+ </tr><tr>
+ <td style="vertical-align: middle">
+ <math xmlns="http://www.w3.org/1998/Math/MathML" display="block"
alttext="MathML capable browser required">
+ <mfenced open="[" close="]">
+ <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 open="[" close="]">
+ <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>
+
<mtd><mo>(</mo><msub><mi>j</mi><mrow>max</mrow></msub><mo>-</mo>
+
<msub><mi>j</mi><mrow>min</mrow></msub><mo>)</mo></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 open="[" close="]">
+ <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>i</mi><mrow>max</mrow></msub><mo>-</mo>
+ <msub><mi>i</mi><mrow>min</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>j</mi><mrow>max</mrow></msub><mo>-</mo>
+ <msub><mi>j</mi><mrow>min</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 open="[" close="]">
+ <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>j</mi><mrow>max</mrow></msub><mo>-</mo>
+ <msub><mi>j</mi><mrow>min</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>i</mi><mrow>max</mrow></msub><mo>-</mo>
+ <msub><mi>i</mi><mrow>min</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>
+ Lâélément clé est quâil nây a pas besoin dâécrire un code
dédié à lâinversion des axes.
+ Cette opération, et bien dâautres, est prise en compte
naturellement par lâalgèbre matricielle.
+ On y gagne en généricité du code et en performance.
+ </p>
+ </div>
+
+ <p style="color: red">TODO</p>
+
+ <article>
+ <header>
+ <h1>Particularités dâune bibliothèque de calculs matriciels pour
un <abbr>SIG</abbr></h1>
+ </header>
+ <p>
+ Les <abbr>SIG</abbr> font un usage intensif de matrices afin
dâafficher leurs cartes ou transformer des coordonnées.
+ On pourrait croire que le marché est suffisamment bien pourvu en
excellentes bibliothèques de calculs matriciels, libres ou commerciales.
+ Pourtant, les <abbr>SIG</abbr> ont des besoins spécifiques qui
divergent un peu des objectifs de plusieurs bibliothèques existantes.
+ Des manipulations de matrices comme lâexemple précédent
interviennent dans quasiment toutes les opérations
+ appliquées par Apache <abbr>SIS</abbr> sur des coordonnées.
+ Mais lâanalyse de ces opérations révèle quelques patterns:
+ </p>
+ <ul>
+ <li><p>Ces matrices sont presque toujours de petites tailles,
dépassant rarement 5 lignes par 5 colonnes.</p></li>
+ <li><p>Les opérations matricielles « lourdes » (multiplications
ou inversions de matrices) ne surviennent pas dans des endroits où la
performance est importante.
+ Dans la quasi-totalité des cas, elles ne sont effectuées
quâune fois pour toute, Ã la lecture dâun fichier,
+ ou lors des étapes de préparation avant de convertir des
coordonnées.
+ Elles ne surviennent quasiment jamais dans la boucle convertissant
chacune des coordonnées.</p></li>
+ <li><p>Dans une succession de multiplications et dâinversions de
matrices, les erreurs dâarrondissement sâaccumulent et grandissent
rapidement
+ au point de se confondre avec certaines opérations légitimes,
notamment les changements de référentiel.
+ Ces dernières sâexpriment souvent par un changement de la
taille, position et orientation de lâellipsoïde
+ choisi comme approximation de la forme de la Terre. Les
changements de la taille sâexpriment en parties par million et
+ les rotations en arc-secondes. Retranscrites dans une matrice, ces
valeurs sont donc assez petites.</p></li>
+ <li><p>Il arrive fréquemment que des matrices sâannulent en tout ou
en partie,
+ câest-à -dire que leurs multiplications ramènent des facteurs
dâéchelles à 1 et des translations à 0.
+ Toutefois les erreurs dâarrondissements font que les valeurs
obtenues sont rarement exactes,
+ mais plutôt des valeurs sâen rapprochant telles que 0,9999â¦97
à la place de 1.
+ Malheureusement, les erreurs dâarrondissement sont parfois
telles quâil est difficile de savoir
+ si certains coefficients de la matrices sont des artefacts ou
proviennent dâun réel changement de référentiel.</p></li>
+ </ul>
+ <p>
+ Ces points font que, pour un <abbr>SIG</abbr>, la précision dâune
bibliothèque de calculs matriciels
+ est plus importante que la performance. Paradoxalement, un bon moyen
de gagner en performance est justement dâinvestir davantage de temps de CPU
+ pour effectuer des opérations matricielles plus précises, car on
augmente ainsi les chances de détecter correctement quelles opérations
sâannulent.
+ Lâeffort investit dans cette détection permet de sauver du temps lÃ
où ça compte: quand viendra le moment de boucler sur des millions de
coordonnées à transformer.
+ </p><p>
+ Mais les bibliothèques dédiées aux calculs matriciels sont souvent
conçues pour opérer de manière très performante
+ sur des matrices de grandes tailles, ayant par exemple des milliers de
lignes et colonnes.
+ Elles sont ainsi conçues pour être capable de résoudre efficacement
des systèmes dâéquations linéaires comportant des centaines dâinconnues.
+ Les problèmes quâelles résolvent sont certes difficiles, mais
assez différents de ceux qui intéressent Apache <abbr>SIS</abbr>.
+ Pour cette raison, et aussi à cause dâun autre besoin spécifique
détaillé dans la section suivante,
+ Apache <abbr>SIS</abbr> utilise ses propres fonctions de calculs
matriciels.
+ Ces fonctions tentent de résoudre le problème de précision en
utilisant lâarithmétique « double-double »
+ (une technique permettant de simuler une précision dâenviron 120
bits)
+ au prix de la performance dans une partie du code où elle nâest pas
jugée critique.
+ </p>
+ <h2>Que faire des matrices qui ne sont pas carrées (et pourquoi)</h2>
+ <p>
+ Apache <abbr>SIS</abbr> a très souvent besoin dâinverser des
matrices,
+ afin dâobtenir une conversion de coordonnées qui fasse le contraire
de la conversion originale.
+ Mais on nâinverse habituellement que des matrices carrées.
+ Or, Apache <abbr>SIS</abbr> a besoin dâeffectuer des inversions de
matrices non-carrées.
+ Selon que lâon ait plus de lignes ou plus de colonnes:
+ </p>
+ <ul>
+ <li>Pour <abbr>SIS</abbr>, une matrice non-carrée est une conversion
qui ajoute ou supprime une dimension aux coordonnées.</li>
+ <li>Pour les bibliothèques dâalgèbre linéaire, une matrice
non-carrée est un système dâéquations sous-déterminé ou
surdéterminé.</li>
+ </ul>
+ <p>
+ Pour mieux comprendre les difficultés que causerait une transposition
trop directe des bibliothèques dâalgèbre linéaire aux <abbr>SIG</abbr>,
+ imaginons une conversion qui projetterait les points dâun espace 3D
vers une surface 2D:
+ </p>
+ <table class="hidden">
+ <tr>
+ <td>(λâ, Ïâ, <var>h</var>) â (λâ, Ïâ)</td>
+ <td style="padding-left: 30px">où</td>
+ <td><ul style="margin-top: 0">
+ <li>λ est la longitude.</li>
+ <li>Ï est la latitude.</li>
+ <li>(λâ, Ïâ) nâégale pas forcement (λâ, Ïâ) si la
hauteur <var>h</var> nâest pas perpendiculaire à la surface.</li>
+ </ul></td>
+ </tr>
+ </table>
+ <p>
+ Pour des bibliothèques dâalgèbre linéaire, la matrice
représentant cette conversion serait un système dâéquations
sous-déterminé, et donc insoluble.
+ Câest-Ã -dire quâon ne peut pas inverser cette conversion pour
obtenir (λâ, Ïâ) â (λâ, Ïâ, <var>h</var>) puisquâon ne sait pas
quelle valeur donner à <var>h</var>,
+ ce qui implique quâon ne peut pas trouver (λâ, Ïâ) non-plus
car ces valeurs dépendent peut-être de <var>h</var>.
+ Toutefois, dans le cas des <abbr>SIG</abbr>, lâaxe des <var>h</var>
est très souvent perpendiculaire à la surface sur laquelle sont exprimées
les coordonnées (λ, Ï).
+ Cette perpendicularité rend λâ et Ïâ indépendants de
<var>h</var>. Dans ce cas particulier, et ce cas seulement, on peut encore
sauver les meubles.
+ </p><p>
+ Apache <abbr>SIS</abbr> procède en vérifiant si les coordonnées
<var>h</var> sont indépendantes des coordonnées λ et Ï.
+ Nous reconnaissons ce cas en vérifiant quels coefficients de la
matrice ont la valeur zéro.
+ Si <abbr>SIS</abbr> arrive à identifier des dimensions indépendantes,
+ il peut les exclure temporairement de manière à inverser sans
ambiguïté la conversion dans les dimensions restantes.
+ Sâil ne trouve pas de dimension indépendante, alors une exception
est levée.
+ </p><p>
+ Si une inversion a été possible, alors il reste à décider du sort
des dimensions que <abbr>SIS</abbr> avait temporairement exclues.
+ Dans notre exemple, <abbr>SIS</abbr> assignera la valeur
<code>NaN</code> (<cite>Not-a-Number</cite>) aux valeurs de <var>h</var> dans
la conversion (λâ, Ïâ) â (λâ, Ïâ, <var>h</var>).
+ Là encore, le choix du coefficient à mettre à <code>NaN</code> dans
la matrice est basé sur la présomption quâelle représente une conversion
de coordonnées.
+ </p><p>
+ Le traitement particulier fait par <abbr>SIS</abbr> permet donc
dâinverser des matrices que lâon rencontre couramment dans les
<abbr>SIG</abbr>,
+ même si en principe le système est sous-déterminé.
+ Dans notre exemple la coordonnée <var>h</var> reste inconnue âÂ
nous ne faisons pas surgir de lâinformation du néant â mais au moins les
coordonnées (λ, Ï) ont pu être récupérées.
+ </p><p>
+ Le problème inverse, celui des systèmes surdéterminés, est plus
subtil.
+ Une approche classique des bibliothèques dâalgèbre linéaire est
de résoudre les systèmes surdéterminés par la méthode des moindres
carrées.
+ Transposée à notre exemple, cette approche proposerait une
conversion (λâ, Ïâ, <var>h</var>) â (λâ, Ïâ)
+ qui semble le meilleur compromis pour diverses valeurs de λâ, Ïâ
et <var>h</var>, tout en nâétant (sauf cas particuliers) une solution exacte
pour personne.
+ De plus, les éventuelles combinaisons linéaires entre ces trois
variables sont délicates compte tenu de lâhétérogénéité des unités de
mesures,
+ où les <var>h</var> sont en mètres et (λ, Ï) en degrés.
+ Apache <abbr>SIS</abbr> procède plutôt comme pour les systèmes
sous-déterminés: en exigeant que certaines dimensions soient indépendantes
des autres,
+ faute de quoi la matrice sera considérée non-inversible.
+ Dans le cas des systèmes surdéterminés <abbr>SIS</abbr> refusera
donc dâeffectuer certaines opérations que les bibliothèques dâalgèbre
linéaire auraient faite,
+ mais garantira que les conversions obtenues sont exactes (aux erreurs
dâarrondissement prêts).
+ </p>
+ <p>
+ En résumé, les besoins qui ont amené Apache <abbr>SIS</abbr> Ã
fournir ses propres fonctions de calculs matriciels sont:
+ </p>
+ <ul>
+ <li>Structure légère pour les petites matrices, particulièrement
celles de taille 3Ã3.</li>
+ <li>Précision accrue avec lâarithmétique « double-double »,
quitte à sacrifier un peu de performance dans des endroits où elle nâest
pas critique.</li>
+ <li>Traitement particulier de lâinversion des matrices non-carrées
pour des conversions de coordonnées.</li>
+ </ul>
+ </article>
<h3 id="TransformDerivative">Dérivées partielles des opérations</h3>
<p>
@@ -262,13 +608,13 @@
</p>
<p>
- Appelons <var>P</var> une projection cartographique qui convertit une
longitude et latitude (λ,Ï) en degrés
+ Appelons <var>P</var> une projection cartographique qui convertit une
longitude et latitude (λ, Ï) en degrés
vers une coordonnée projetée (<var>x</var>,<var>y</var>) en mètres.
Dans lâexpression ci-dessous, nous représentons le résultat de la
projection cartographique
sous forme dâune matrice colonne (la raison sera plus claire bientôt):
</p>
- <math display="block" alttext="MathML capable browser required">
+ <math xmlns="http://www.w3.org/1998/Math/MathML" display="block"
alttext="MathML capable browser required">
<mi>P</mi><mo>(</mo><mi>λ</mi><mo>,</mo><mi>Ï</mi><mo>)</mo>
<mo>=</mo>
<mfenced open="[" close="]">
@@ -281,7 +627,7 @@
<p>La dérivée de la projection cartographique en ce même point peut se
représenter par la matrice Jacobienne définie tel que:</p>
- <math display="block" alttext="MathML capable browser required">
+ <math xmlns="http://www.w3.org/1998/Math/MathML" display="block"
alttext="MathML capable browser required">
<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>
@@ -301,13 +647,14 @@
</math>
<p>
+ Dans la suite de ce texte, nous abrégerons â<var>x</var>(λ,Ï) par
â<var>x</var> et de même pour â<var>y</var>.
Le premier élément de la matrice (â<var>x</var>/âλ) nous indique
à quel déplacement vers lâ<em>Est</em>
(<var>x</var> en mètres) correspond un déplacement de un degré de
<em>longitude</em> (λ).
De même, le dernier élément de la matrice (â<var>y</var>/âÏ)
nous indique à quel déplacement vers le <em>Nord</em>
(<var>y</var> en mètres) correspond un déplacement de un degré de
<em>latitude</em> (Ï).
Les autres éléments (â<var>x</var>/âÏ et â<var>y</var>/âλ)
sont des termes croisés (par exemple à quel déplacement
en mètres vers le <strong>Nord</strong> correspond un déplacement de
un degré de <strong>longitude</strong>).
- Ces valeurs ne sont généralement valides quâà la position
géographique (λ,Ï) donnée.
+ Ces valeurs ne sont généralement valides quâà la position
géographique (λ, Ï) donnée.
Si on se déplace un peu, ces valeurs changent légèrement.
</p>
@@ -323,7 +670,7 @@
<td><img style="border: solid 1px" src="../images/Derivatives.png"
alt="Exemple de dérivées dâune projection cartographique"/></td>
<td style="padding-left: 30px; vertical-align: middle">
<p>où les vecteurs sont reliés à la matrice par:</p>
- <math display="block" alttext="MathML capable browser required">
+ <math xmlns="http://www.w3.org/1998/Math/MathML" display="block"
alttext="MathML capable browser required">
<mtable><mtr>
<mtd>
<mover><mi>U</mi><mo>â</mo></mover><mo>=</mo>
@@ -364,7 +711,7 @@
ou si la direction dâun axe est renversée. Mais lâintérêt des
dérivées ne sâarrête pas là .
</p>
- <h4 id="DerivativeAndEnvelope">Utilité des dérivées pour la projection
dâenveloppes</h4>
+ <h4 id="DerivativeAndEnvelope">Utilité des dérivées pour la
reprojection dâenveloppes</h4>
<p>
Les systèmes dâinformation géographiques ont très fréquemment
besoin de projeter une enveloppe.
Mais lâapproche naïve, qui consisterait à projeter chacun des 4
coins du rectangle, ne suffit pas.
@@ -440,10 +787,17 @@
alors que lâalgorithme est applicable dans un espace à <var>n</var>
dimensions.
Et de fait, lâimplémentation de Apache SIS fonctionne pour un nombre
arbitraire de dimensions.
Les économies apportées par cet algorithme par rapport à la force
brute augmentent de manière exponentielle avec le nombre de dimensions.
+ </p><p>
+ Lâapproche décrite dans cette section est implémentée dans Apache
<abbr>SIS</abbr>
+ par la méthode statique <code>Envelopes.transform(CoordinateOperation,
Envelope)</code>.
+ Une méthode <code>Envelopes.transform(MathTransform, Envelope)</code>
existe aussi comme alternative,
+ mais cette dernière ne devrait être utilisée que si on ne connaît
pas lâobjet <code>CoordinateOperation</code> utilisé.
+ La raison est que les objets de type <code>MathTransform</code> ne
contiennent pas dâinformation sur le système de coordonnées sous-jasent,
+ ce qui empêche la méthode <code>Envelopes.transform(â¦)</code> de
savoir comment gérer les points aux pôles.
</p>
- <h4 id="DerivativeAndRaster">Utilité des dérivées pour la projection
dâimages</h4>
+ <h4 id="DerivativeAndRaster">Utilité des dérivées pour la reprojection
dâimages</h4>
<p>
La projection cartographique dâune image sâeffectue en préparant
une image initialement vide qui contiendra le résultat de lâopération,
puis à remplir cette image en itérant sur tous les pixels. Pour chaque
pixel de lâimage <em>destination</em>, on obtient la coordonnées
@@ -502,7 +856,7 @@
si câest la peine dâeffectuer une nouvelle itération
<strong>avant</strong> de la faire.
Lâidée de base est de vérifier si les dérivées de deux points
voisins sont presque pareilles,
auquel cas on présumera que la transformation entre ces deux points est
pratiquement linéaire.
- Pour quantifier « presque pareil », on procède en calculant
lâintersection entre les tangentes aux deux points
+ Pour quantifier « presque pareil », on procède en calculant
lâintersection entre les tangentes aux deux points
(une information fournie par les dérivées), et en calculant la
distance entre cette intersection et la droite
qui relie les deux points (la ligne pointillée dans la figure
ci-dessous).
</p>
@@ -522,26 +876,35 @@
Cette discussion nâaurait pas un grand intérêt si le coût du calcul
des dérivées des projections cartographiques
était élevé par rapport aux coût de la projection des points. Mais
lorsque lâon dérive analytiquement les équations
des projections, on constate que les calculs des positions et de leurs
dérivées ont souvent plusieurs termes en commun.
- En outre le calcul des dérivées est simplifié lorsque le code Java
effectuant les projections ne se concentre que sur le « noyau » non-linéaire,
+ En outre le calcul des dérivées est simplifié lorsque le code Java
effectuant les projections ne se concentre que sur le « noyau »
non-linéaire,
après sâêtre déchargé des parties linéaires en les déléguant
aux transformations affines comme le fait <abbr>SIS</abbr>.
- Les implémentations des projections cartographiques dans Apache
<abbr>SIS</abbr> tirent parti de ces propriétés en ne calculant les
dérivées que si elles sont demandées,
- et en offrant une méthode qui permet de projeter un point et obtenir sa
dérivée en une seule opération afin de permettre à <abbr>SIS</abbr> de
réutiliser un maximum de termes communs.
+ Les implémentations des projections cartographiques dans Apache
<abbr>SIS</abbr> tirent parti de ces propriétés
+ en ne calculant les dérivées que si elles sont demandées,
+ et en offrant une méthode qui permet de projeter un point et obtenir sa
dérivée en une seule opération
+ afin de permettre à <abbr>SIS</abbr> de réutiliser un maximum de
termes communs.
Exemple:</p>
<pre>AbstractMathTransform projection = ...; // Une projection
cartographique de Apache SIS.
double[] sourcePoint = {longitude, latitude}; // La coordonnée
géographique que lâon veut projeter.
double[] targetPoint = new double[2]; // Là où on mémorisera le
résultat de la projection.
-Matrix derivative = projection.transform(sourcePoint, 0, targetPoint, 0,
true);</pre>
-
- <p>
- Apache <abbr>SIS</abbr> est capable combiner les dérivées des
projections cartographiques de la même façon que pour les
- projections de coordonnées: concaténation dâune chaîne de
transformations, inversion, opérer sur un sous-ensemble des
- dimensions, <i>etc.</i>
- </p>
+Matrix derivative = projection.<span
class="SIS">transform</span>(sourcePoint, 0, targetPoint, 0, true);</pre>
<p>
- Lâapproche décrite dans la section sur les <a
href="#DerivativeAndEnvelope">projection dâenveloppes</a>
- est implémentée par la méthode statique
<code>Envelopes.transform(CoordinateOperation, Envelope)</code> de
<abbr>SIS</abbr>.
- </p>
+ Si seule la matrice Jacobienne est désirée (sans la projection du
point), alors la méthode
+ <code>MathTransform.derivative(DirectPosition)</code> offre une
alternative plus lisible.
+ </p><p>
+ Apache <abbr>SIS</abbr> est capable combiner les dérivées des
projections cartographiques de la même façon que pour les projections de
coordonnées:
+ concaténation dâune chaîne de transformations, inversion, opérer
sur un sous-ensemble des dimensions, <i>etc.</i>
+ Les opérations inverses (des systèmes projetés vers géographiques)
+ sont souvent beaucoup plus compliquées à implémenter que les
opérations originales (des systèmes géographiques vers projetés),
+ mais par chance la matrice Jacobienne dâune fonction inverse est
simplement lâinverse de la matrice Jacobienne de la fonction originale.
+ Une fonction inverse peut donc implémenter le calcul de sa dérivée
comme suit:
+ </p>
+<pre>@Override
+public Matrix derivative(DirectPosition p) throws TransformException {
+ Matrix jac = inverse().derivative(transform(p));
+ return Matrices.inverse(jac);
+}
+</pre>
</body>
</html>
Modified: sis/site/trunk/content/book/fr/developer-guide.html
URL:
http://svn.apache.org/viewvc/sis/site/trunk/content/book/fr/developer-guide.html?rev=1713408&r1=1713407&r2=1713408&view=diff
==============================================================================
--- sis/site/trunk/content/book/fr/developer-guide.html [UTF-8] (original)
+++ sis/site/trunk/content/book/fr/developer-guide.html [UTF-8] Mon Nov 9
12:17:16 2015
@@ -72,10 +72,11 @@
<li><a href="#CRSFactory">Construction programmatique explicite</a></li>
<li><a href="#CRS_UserCode">Ajout de définitions</a></li></ul></li>
<li><a href="#CoordinateOperation">Opérations sur les coordonnées</a><ul>
-<li><a href="#MathTransform">Exécution de opérations</a></li>
+<li><a href="#MathTransform">Exécution de opérations</a><ul>
+<li><a href="#AffineTransform">Les transformations affines</a></li></ul></li>
<li><a href="#TransformDerivative">Dérivées partielles des opérations</a><ul>
-<li><a href="#DerivativeAndEnvelope">Utilité des dérivées pour la projection
d’enveloppes</a></li>
-<li><a href="#DerivativeAndRaster">Utilité des dérivées pour la projection
d’images</a></li>
+<li><a href="#DerivativeAndEnvelope">Utilité des dérivées pour la reprojection
d’enveloppes</a></li>
+<li><a href="#DerivativeAndRaster">Utilité des dérivées pour la reprojection
d’images</a></li>
<li><a href="#GetDerivative">Obtention de la dérivée en un
point</a></li></ul></li></ul></li></ul></li>
<li><a href="#Geometry">Géométries</a><ul>
<li><a href="#Geometry-root">Classes de base</a><ul>
@@ -2043,10 +2044,11 @@ de la bibliothèque <abbr>SIS</abbr>.
<li><a href="#CRSFactory">Construction programmatique explicite</a></li>
<li><a href="#CRS_UserCode">Ajout de définitions</a></li></ul></li>
<li><a href="#CoordinateOperation">Opérations sur les coordonnées</a><ul>
-<li><a href="#MathTransform">Exécution de opérations</a></li>
+<li><a href="#MathTransform">Exécution de opérations</a><ul>
+<li><a href="#AffineTransform">Les transformations affines</a></li></ul></li>
<li><a href="#TransformDerivative">Dérivées partielles des opérations</a><ul>
-<li><a href="#DerivativeAndEnvelope">Utilité des dérivées pour la projection
d’enveloppes</a></li>
-<li><a href="#DerivativeAndRaster">Utilité des dérivées pour la projection
d’images</a></li>
+<li><a href="#DerivativeAndEnvelope">Utilité des dérivées pour la reprojection
d’enveloppes</a></li>
+<li><a href="#DerivativeAndRaster">Utilité des dérivées pour la reprojection
d’images</a></li>
<li><a href="#GetDerivative">Obtention de la dérivée en un
point</a></li></ul></li></ul></li></ul></nav>
<p>
Pour donner une position sur la Terre on peut utiliser des noms tels que celui
d’une ville ou une adresse postale
@@ -2067,7 +2069,7 @@ Mais la maîtrise de cette précision n�
<ul>
<li>Rester dans la zone de validité du système, telle que donnée par <code
class="GeoAPI">ReferenceSystem.getDomainOfValidity()</code>.</li>
<li>Savoir que les mesures de distances dans une projection cartographique
donnée ne sont vraies qu’à certains endroits,
-appelés par exemple « parallèles standards ».</li>
+appelés par exemple « parallèles standards ».</li>
<li>Vérifier la précision des transformations de coordonnées, telle que donnée
par
<code
class="GeoAPI">CoordinateOperation.getCoordinateOperationAccuracy()</code>.</li>
</ul>
@@ -2135,14 +2137,14 @@ Le géoïde coïnciderait avec le niveau
Tout en étant nettement plus lisse que la surface topographique,
le géoïde présente des creux et des bosses liés à l’inégale distribution des
masses de la Terre.
Pour une utilisation mathématiquement plus aisée, le géoïde est donc approximé
par un ellipsoïde.
-Cette « figure de la Terre » est représentée dans GeoAPI par l’interface <code
class="GeoAPI">Ellipsoid</code>,
+Cette « figure de la Terre » est représentée dans GeoAPI par l’interface <code
class="GeoAPI">Ellipsoid</code>,
qui constitue un élément fondamental des systèmes de références de type <code
class="GeoAPI">GeographicCRS</code> et <code class="GeoAPI">ProjectedCRS</code>.
Plusieurs dizaines d’ellipsoïdes sont couramment employés, certains offrant
une excellente approximation pour une région précise
au détriment des régions pour lesquelles l’ellipsoïde n’a pas été conçu, et
d’autres offrant un compromis pour l’ensemble de la planète.
</p>
<div class="example"><p><b>Exemple:</b>
au début du XX<sup>e</sup> siècle aux États-Unis, l’état du Michigan utilisait
pour ses cartes un ellipsoïde basé
-sur l’ellipsoïde « Clarke 1866 » mais auquel la longueur des axes a été
allongée de 800 pieds.
+sur l’ellipsoïde « Clarke 1866 » mais auquel la longueur des axes a été
allongée de 800 pieds.
Cette modification visait à tenir compte du niveau moyen de l’état au dessus
du niveau de la mer.</p>
</div>
@@ -2152,12 +2154,13 @@ Pour définir un système géodésique d
qui épouse au mieux sur l’ensemble du pays la forme locale du géoïde.
L’écart entre cet ellipsoïde de référence et les creux et les bosses du géoïde
reste généralement inférieur à 100 mètres.
Les paramètres qui permettent de lier un <code class="GeoAPI">Ellipsoid</code>
à la surface de la Terre (par exemple la position de son centre)
-sont encapsulés dans un objet de type <code
class="GeoAPI">GeodeticDatum</code>, que l’on traduit en français par «
référentiel géodésique ».
+sont encapsulés dans un objet de type <code
class="GeoAPI">GeodeticDatum</code>, que l’on traduit en français par «
référentiel géodésique ».
Plusieurs <code class="GeoAPI">GeodeticDatum</code> peuvent utiliser le même
<code class="GeoAPI">Ellipsoid</code>, mais centré ou orienté différemment.
</p><p>
Avant l’avènement des satellites, les mesures géodésiques se déroulaient
exclusivement à la surface de la terre.
En conséquence, deux îles ou continents qui ne sont pas à portée visuelle l’un
de l’autre n’étaient pas rattachés géodésiquement entre eux.
-Ainsi les référentiels <cite>North American Datum 1983</cite>
(<abbr>NAD83</abbr>) et <cite>European Datum 1950</cite> (<abbr>ED50</abbr>)
sont indépendants l’un de l’autre:
+Ainsi les référentiels <cite>North American Datum 1983</cite>
(<abbr>NAD83</abbr>) et
+<cite>European Datum 1950</cite> (<abbr>ED50</abbr>) sont indépendants l’un de
l’autre:
leurs ellipsoïdes de référence ont des centres distincts et des dimensions
différentes.
Une même coordonnée géographique correspondra à des positions différentes dans
le monde réel
selon que la coordonnée se réfère à l’un ou l’autre de ces référentiels.
@@ -2183,7 +2186,7 @@ Ainsi il existe aujourd’hui au moins s
</p>
<article>
<header>
-<h1>Bibliothèques de type « early binding » versus « late binding »</h1>
+<h1>Bibliothèques de type « early binding » versus « late binding »</h1>
</header>
<p>
Le caractère universel du système <abbr title="World Geodetic System
1984">WGS84</abbr> rend tentante l’idée de l’utiliser comme système pivot,
@@ -2191,9 +2194,9 @@ afin de simplifier l’implémentation d
La transformation d’une coordonnées d’un référentiel <var>A</var> vers un
référentiel <var>B</var>
pourrait se faire en transformant d’abord de <var>A</var> vers
<abbr>WGS84</abbr>, puis de <abbr>WGS84</abbr> vers <var>B</var>.
Il suffirait ainsi de stocker dans chaque objet <code
class="GeoAPI">GeodeticDatum</code> les informations nécessaires à la
transformation vers <abbr>WGS84</abbr>.
-Cette approche était encouragée dans la version 1 du format <abbr>WKT</abbr>,
qui définissait un élément <code>TOWGS84</code> remplissant ce rôle.
+Cette approche était encouragée dans la version 1 du format <abbr>WKT</abbr>,
qui définissait un élément <code class="OGC">TOWGS84</code> remplissant ce rôle.
</p><p>
-Cette approche est désignée par <abbr>EPSG</abbr> sous le nom de « early
binding »,
+Cette approche est désignée par <abbr>EPSG</abbr> sous le nom de « early
binding »,
car elle associe des informations sur la transformations de coordonnées très
tôt dans la définition des objets géodésiques.
Bien que <abbr>EPSG</abbr> reconnaisse que cette approche soit couramment
employée, elle n’est pas recommandée pour plusieurs raisons:
</p>
@@ -2207,23 +2210,23 @@ et n’ont pas la même précision qu’
mis en place par le concurrent européen du <abbr title="Global Positioning
System">GPS</abbr>. Et <abbr>WGS84</abbr> lui-même subit parfois des
révisions.</li>
</ul>
<p>
-<abbr>EPSG</abbr> recommande plutôt d’utiliser une approche dite « late
binding »,
+<abbr>EPSG</abbr> recommande plutôt d’utiliser une approche dite « late
binding »,
selon laquelle les paramètres nécessaires aux transformations de coordonnées
sont définis pour des paires de
-référentiels « <var>A</var> vers <var>B</var> » plutôt qu’associés à des
référentiels pris isolément.
-Apache <abbr title="Spatial Information System">SIS</abbr> est une
implémentation de type « late binding »,
-bien qu’une réminiscence de l’approche « early binding » existe toujours
-sous la forme de la propriété
<code>DefaultGeodeticDatum.getBursaWolfParameters()</code>.
+référentiels « <var>A</var> vers <var>B</var> » plutôt qu’associés à des
référentiels pris isolément.
+Apache <abbr title="Spatial Information System">SIS</abbr> est une
implémentation de type « late binding »,
+bien qu’une réminiscence de l’approche « early binding » existe toujours
+sous la forme de la propriété <code
class="SIS">DefaultGeodeticDatum.getBursaWolfParameters()</code>.
</p>
</article>
<h3 id="CoordinateSystem"><span class="section-number">5.1.3.</span> Systèmes
de coordonnées</h3>
-<p>TODO</p>
+<p style="color: red">TODO</p>
<h3 id="GeographicCRS"><span class="section-number">5.1.4.</span> Systèmes
géographiques</h3>
-<p>TODO</p>
+<p style="color: red">TODO</p>
<h4 id="GeographicWKT"><span class="section-number">5.1.4.1.</span> Format
<i>Well-Known Text</i></h4>
-<p>TODO</p>
+<p style="color: red">TODO</p>
<h3 id="ProjectedCRS"><span class="section-number">5.1.5.</span> Projections
cartographiques</h3>
<p>
@@ -2233,43 +2236,388 @@ en contrôlant les déformations: on peu
Les propriétés géométriques à conserver dépendent de l’objet d’étude et du
travail à effectuer.
Par exemple les pays plutôt allongés dans le sens Est-Ouest utilisent souvent
une projection de Lambert,
alors que les pays plutôt allongés dans le sens Nord-Sud préfèrent une
projection de Mercator Transverse.
-</p><p>
-TODO
</p>
+<p style="color: red">TODO</p>
<h4 id="ProjectedWKT"><span class="section-number">5.1.5.1.</span> Format
<i>Well-Known Text</i></h4>
-<p>TODO</p>
+<p style="color: red">TODO</p>
<h3 id="CompoundCRS"><span class="section-number">5.1.6.</span> Dimensions
verticales et temporelles</h3>
-<p>TODO</p>
+<p style="color: red">TODO</p>
<h4 id="CompoundWKT"><span class="section-number">5.1.6.1.</span> Format
<i>Well-Known Text</i></h4>
-<p>TODO</p>
+<p style="color: red">TODO</p>
<h2 id="GetCRS"><span class="section-number">5.2.</span> Obtention d’un
système de référence spatial</h2>
-<p>TODO</p>
+<p style="color: red">TODO</p>
<h3 id="CRSAuthorityFactory"><span class="section-number">5.2.1.</span>
Systèmes prédéfinis par des autorités</h3>
-<p>TODO</p>
+<p style="color: red">TODO</p>
<h3 id="CRSParsing"><span class="section-number">5.2.2.</span> Lecture d’une
définition au format GML ou WKT</h3>
-<p>TODO</p>
+<p style="color: red">TODO</p>
<h3 id="CRSFactory"><span class="section-number">5.2.3.</span> Construction
programmatique explicite</h3>
-<p>TODO</p>
+<p style="color: red">TODO</p>
<h3 id="CRS_UserCode"><span class="section-number">5.2.4.</span> Ajout de
définitions</h3>
-<p>TODO</p>
+<p style="color: red">TODO</p>
<h2 id="CoordinateOperation"><span class="section-number">5.3.</span>
Opérations sur les coordonnées</h2>
-<p>TODO</p>
+<p style="color: red">TODO</p>
<h3 id="MathTransform"><span class="section-number">5.3.1.</span> Exécution de
opérations</h3>
-<p>TODO</p>
+<p style="color: red">TODO</p>
+
+<h4 id="AffineTransform"><span class="section-number">5.3.1.1.</span> Les
transformations affines</h4>
+<p>
+Parmi les sortes d’opérations qu’un <abbr>SIG</abbr> doit effectuer sur les
coordonnées spatiales, il en est une à la fois simple et très fréquente.
+Ce sont les opérations linéaires, constituées uniquement d’une combinaison
d’additions et de certaines multiplications.
+Ces opérations n’effectuent pas de projections cartographiques, plus
complexes, mais couvrent 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> des
images pointe souvent vers le bas).</li>
+<li>Changer de méridien d’origine (par exemple de <cite>Paris</cite> vers
<cite>Greenwich</cite>).</li>
+<li>Changer le nombre de dimensions (par exemple passer des coordonnées 3D
vers 2D).</li>
+<li>Convertir des unités de mesures (par exemple convertir des pieds en
mètres).</li>
+<li>Convertir les coordonnées pixels d’une image 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>
+<li>Appliquer des rotations, translations, échelles ou cisaillements (des
transformations dites <cite>affines</cite>).</li>
+</ul>
+<p>
+Les opérations linéaires ont la propriété de toujours se combiner:
+peu importe le nombre d’opérations linéaires que l’on enchaîne, le résultat
sera toujours exprimable par une seule opération linéaire.
+Cette propriété est plus facilement visible lorsque les opérations linéaires
sont exprimées sous forme de matrices:
+pour les combiner, il suffit de multiplier les matrices.
+</p>
+<div class="example"><p><b>Example:</b>
+supposons que nous disposons d’une image dont les coordonnées des pixels sont
représentées par (<var>i</var>,<var>j</var>).
+Supposons que la taille de chaque pixel correspond à un nombre fixe de degrées
de longitude et de latitude
+dans un système géographique donné et qu’il n’y a pas de rotation.
+La conversion des coordonnées pixels (<var>i</var>,<var>j</var>) vers les
coordonnées géographiques (<var>λ</var>,<var>φ</var>)
+est alors linéaire et peut être représentée par la matrice suivante:</p>
+
+<table class="hidden"><tr><td>
+<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><msub><mi>H</mi><mrow>λ</mrow></msub></mtd>
+<mtd><msub><mi>T</mi><mrow>λ</mrow></msub></mtd>
+</mtr>
+<mtr>
+<mtd><msub><mi>H</mi><mrow>φ</mrow></msub></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>i</mi></mtd></mtr>
+<mtr><mtd><mi>j</mi></mtd></mtr>
+<mtr><mtd><mn>1</mn></mtd></mtr>
+</mtable>
+</mfenced>
+</math>
+</td><td style="vertical-align: middle; padding-left: 30px">
+où
+</td><td style="vertical-align: middle">
+<ul>
+<li><var>S</var> est un facteur d’échelle (<cite>Scale</cite>) correspondant
dans cet exemple à la taille des pixels.</li>
+<li><var>H</var> est un terme de cisaillement (<cite>Shear</cite>),
habituellement zéro sauf si l’image a une rotation.</li>
+<li><var>T</var> est une translation (<cite>Translation</cite>) correspondant
dans cet exemple à la coordonnée d’un coin de l’image.</li>
+</ul>
+</td></tr></table>
+<p>
+Concentrons notre attention sur la matrice du milieu dans l’équation ci-dessus.
+Si nous n’interchangeons ni n’inversons la direction d’aucun axe, alors une
conversion des coordonnées pixels vers les coordonnées géographiques
+pourrait s’exprimer par la matrice « conversion originale » ci-dessous.
+Mais si l’on veut en outre inverser la direction de l’axe des <var>j</var>
pour se conformer à la convention la plus courante appliquée aux images
+(« changement 1 ») et interchanger l’ordre des axes pour exprimer la latitude
avant la longitude (« changement 2 »),
+alors on peut exprimer ces modifications par des multiplications matricielles
comme suit
+(l’ordre dans laquelle les opérations sont effectuées sur les coordonnées se
lit de droite à gauche):
+</p>
+<table class="hidden"><tr>
+<th>Changement 2</th><th/>
+<th>Changement 1</th><th/>
+<th>Conversion originale</th><th/>
+<th>Conversion modifiée</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>
+<mtd><mo>(</mo><msub><mi>j</mi><mrow>max</mrow></msub><mo>-</mo>
+<msub><mi>j</mi><mrow>min</mrow></msub><mo>)</mo></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><mfrac>
+<mrow>
+<msub><mi>λ</mi><mrow>max</mrow></msub><mo>-</mo>
+<msub><mi>λ</mi><mrow>min</mrow></msub>
+</mrow><mrow>
+<msub><mi>i</mi><mrow>max</mrow></msub><mo>-</mo>
+<msub><mi>i</mi><mrow>min</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>j</mi><mrow>max</mrow></msub><mo>-</mo>
+<msub><mi>j</mi><mrow>min</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>j</mi><mrow>max</mrow></msub><mo>-</mo>
+<msub><mi>j</mi><mrow>min</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>i</mi><mrow>max</mrow></msub><mo>-</mo>
+<msub><mi>i</mi><mrow>min</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>
+L’élément clé est qu’il n’y a pas besoin d’écrire un code dédié à l’inversion
des axes.
+Cette opération, et bien d’autres, est prise en compte naturellement par
l’algèbre matricielle.
+On y gagne en généricité du code et en performance.
+</p>
+</div>
+
+<p style="color: red">TODO</p>
+
+<article>
+<header>
+<h1>Particularités d’une bibliothèque de calculs matriciels pour un
<abbr>SIG</abbr></h1>
+</header>
+<p>
+Les <abbr>SIG</abbr> font un usage intensif de matrices afin d’afficher leurs
cartes ou transformer des coordonnées.
+On pourrait croire que le marché est suffisamment bien pourvu en excellentes
bibliothèques de calculs matriciels, libres ou commerciales.
+Pourtant, les <abbr>SIG</abbr> ont des besoins spécifiques qui divergent un
peu des objectifs de plusieurs bibliothèques existantes.
+Des manipulations de matrices comme l’exemple précédent interviennent dans
quasiment toutes les opérations
+appliquées par Apache <abbr title="Spatial Information System">SIS</abbr> sur
des coordonnées.
+Mais l’analyse de ces opérations révèle quelques patterns:
+</p>
+<ul>
+<li><p>Ces matrices sont presque toujours de petites tailles, dépassant
rarement 5 lignes par 5 colonnes.</p></li>
+<li><p>Les opérations matricielles « lourdes » (multiplications ou inversions
de matrices) ne surviennent pas dans des endroits où la performance est
importante.
+Dans la quasi-totalité des cas, elles ne sont effectuées qu’une fois pour
toute, à la lecture d’un fichier,
+ou lors des étapes de préparation avant de convertir des coordonnées.
+Elles ne surviennent quasiment jamais dans la boucle convertissant chacune des
coordonnées.</p></li>
+<li><p>Dans une succession de multiplications et d’inversions de matrices, les
erreurs d’arrondissement s’accumulent et grandissent rapidement
+au point de se confondre avec certaines opérations légitimes, notamment les
changements de référentiel.
+Ces dernières s’expriment souvent par un changement de la taille, position et
orientation de l’ellipsoïde
+choisi comme approximation de la forme de la Terre. Les changements de la
taille s’expriment en parties par million et
+les rotations en arc-secondes. Retranscrites dans une matrice, ces valeurs
sont donc assez petites.</p></li>
+<li><p>Il arrive fréquemment que des matrices s’annulent en tout ou en partie,
+c’est-à-dire que leurs multiplications ramènent des facteurs d’échelles à 1 et
des translations à 0.
+Toutefois les erreurs d’arrondissements font que les valeurs obtenues sont
rarement exactes,
+mais plutôt des valeurs s’en rapprochant telles que 0,9999…97 à la place de 1.
+Malheureusement, les erreurs d’arrondissement sont parfois telles qu’il est
difficile de savoir
+si certains coefficients de la matrices sont des artefacts ou proviennent d’un
réel changement de référentiel.</p></li>
+</ul>
+<p>
+Ces points font que, pour un <abbr>SIG</abbr>, la précision d’une bibliothèque
de calculs matriciels
+est plus importante que la performance. Paradoxalement, un bon moyen de gagner
en performance est justement d’investir davantage de temps de CPU
+pour effectuer des opérations matricielles plus précises, car on augmente
ainsi les chances de détecter correctement quelles opérations s’annulent.
+L’effort investit dans cette détection permet de sauver du temps là où ça
compte: quand viendra le moment de boucler sur des millions de coordonnées à
transformer.
+</p><p>
+Mais les bibliothèques dédiées aux calculs matriciels sont souvent conçues
pour opérer de manière très performante
+sur des matrices de grandes tailles, ayant par exemple des milliers de lignes
et colonnes.
+Elles sont ainsi conçues pour être capable de résoudre efficacement des
systèmes d’équations linéaires comportant des centaines d’inconnues.
+Les problèmes qu’elles résolvent sont certes difficiles, mais assez différents
de ceux qui intéressent Apache <abbr>SIS</abbr>.
+Pour cette raison, et aussi à cause d’un autre besoin spécifique détaillé dans
la section suivante,
+Apache <abbr>SIS</abbr> utilise ses propres fonctions de calculs matriciels.
+Ces fonctions tentent de résoudre le problème de précision en utilisant
l’arithmétique « double-double »
+(une technique permettant de simuler une précision d’environ 120 bits)
+au prix de la performance dans une partie du code où elle n’est pas jugée
critique.
+</p>
+<h2>Que faire des matrices qui ne sont pas carrées (et pourquoi)</h2>
+<p>
+Apache <abbr title="Spatial Information System">SIS</abbr> a très souvent
besoin d’inverser des matrices,
+afin d’obtenir une conversion de coordonnées qui fasse le contraire de la
conversion originale.
+Mais on n’inverse habituellement que des matrices carrées.
+Or, Apache <abbr>SIS</abbr> a besoin d’effectuer des inversions de matrices
non-carrées.
+Selon que l’on ait plus de lignes ou plus de colonnes:
+</p>
+<ul>
+<li>Pour <abbr>SIS</abbr>, une matrice non-carrée est une conversion qui
ajoute ou supprime une dimension aux coordonnées.</li>
+<li>Pour les bibliothèques d’algèbre linéaire, une matrice non-carrée est un
système d’équations sous-déterminé ou surdéterminé.</li>
+</ul>
+<p>
+Pour mieux comprendre les difficultés que causerait une transposition trop
directe des bibliothèques d’algèbre linéaire aux <abbr>SIG</abbr>,
+imaginons une conversion qui projetterait les points d’un espace 3D vers une
surface 2D:
+</p>
+<table class="hidden">
+<tr>
+<td>(λ₁, φ₁, <var>h</var>) → (λ₂, φ₂)</td>
+<td style="padding-left: 30px">où</td>
+<td><ul style="margin-top: 0">
+<li>λ est la longitude.</li>
+<li>φ est la latitude.</li>
+<li>(λ₂, φ₂) n’égale pas forcement (λ₁, φ₁) si la hauteur <var>h</var> n’est
pas perpendiculaire à la surface.</li>
+</ul></td>
+</tr>
+</table>
+<p>
+Pour des bibliothèques d’algèbre linéaire, la matrice représentant cette
conversion serait un système d’équations sous-déterminé, et donc insoluble.
+C’est-à-dire qu’on ne peut pas inverser cette conversion pour obtenir (λ₂, φ₂)
→ (λ₁, φ₁, <var>h</var>) puisqu’on ne sait pas quelle valeur donner à
<var>h</var>,
+ce qui implique qu’on ne peut pas trouver (λ₁, φ₁) non-plus car ces valeurs
dépendent peut-être de <var>h</var>.
+Toutefois, dans le cas des <abbr>SIG</abbr>, l’axe des <var>h</var> est très
souvent perpendiculaire à la surface sur laquelle sont exprimées les
coordonnées (λ, φ).
+Cette perpendicularité rend λ₁ et φ₁ indépendants de <var>h</var>. Dans ce cas
particulier, et ce cas seulement, on peut encore sauver les meubles.
+</p><p>
+Apache <abbr>SIS</abbr> procède en vérifiant si les coordonnées <var>h</var>
sont indépendantes des coordonnées λ et φ.
+Nous reconnaissons ce cas en vérifiant quels coefficients de la matrice ont la
valeur zéro.
+Si <abbr>SIS</abbr> arrive à identifier des dimensions indépendantes,
+il peut les exclure temporairement de manière à inverser sans ambiguïté la
conversion dans les dimensions restantes.
+S’il ne trouve pas de dimension indépendante, alors une exception est levée.
+</p><p>
+Si une inversion a été possible, alors il reste à décider du sort des
dimensions que <abbr>SIS</abbr> avait temporairement exclues.
+Dans notre exemple, <abbr>SIS</abbr> assignera la valeur <code>NaN</code>
(<cite>Not-a-Number</cite>) aux valeurs de <var>h</var> dans la conversion (λ₂,
φ₂) → (λ₁, φ₁, <var>h</var>).
+Là encore, le choix du coefficient à mettre à <code>NaN</code> dans la matrice
est basé sur la présomption qu’elle représente une conversion de coordonnées.
+</p><p>
+Le traitement particulier fait par <abbr>SIS</abbr> permet donc d’inverser des
matrices que l’on rencontre couramment dans les <abbr>SIG</abbr>,
+même si en principe le système est sous-déterminé.
+Dans notre exemple la coordonnée <var>h</var> reste inconnue – nous ne faisons
pas surgir de l’information du néant – mais au moins les coordonnées (λ, φ) ont
pu être récupérées.
+</p><p>
+Le problème inverse, celui des systèmes surdéterminés, est plus subtil.
+Une approche classique des bibliothèques d’algèbre linéaire est de résoudre
les systèmes surdéterminés par la méthode des moindres carrées.
+Transposée à notre exemple, cette approche proposerait une conversion (λ₂, φ₂,
<var>h</var>) → (λ₁, φ₁)
+qui semble le meilleur compromis pour diverses valeurs de λ₂, φ₂ et
<var>h</var>, tout en n’étant (sauf cas particuliers) une solution exacte pour
personne.
+De plus, les éventuelles combinaisons linéaires entre ces trois variables sont
délicates compte tenu de l’hétérogénéité des unités de mesures,
+où les <var>h</var> sont en mètres et (λ, φ) en degrés.
+Apache <abbr>SIS</abbr> procède plutôt comme pour les systèmes
sous-déterminés: en exigeant que certaines dimensions soient indépendantes des
autres,
+faute de quoi la matrice sera considérée non-inversible.
+Dans le cas des systèmes surdéterminés <abbr>SIS</abbr> refusera donc
d’effectuer certaines opérations que les bibliothèques d’algèbre linéaire
auraient faite,
+mais garantira que les conversions obtenues sont exactes (aux erreurs
d’arrondissement prêts).
+</p>
+<p>
+En résumé, les besoins qui ont amené Apache <abbr>SIS</abbr> à fournir ses
propres fonctions de calculs matriciels sont:
+</p>
+<ul>
+<li>Structure légère pour les petites matrices, particulièrement celles de
taille 3×3.</li>
+<li>Précision accrue avec l’arithmétique « double-double », quitte à sacrifier
un peu de performance dans des endroits où elle n’est pas critique.</li>
+<li>Traitement particulier de l’inversion des matrices non-carrées pour des
conversions de coordonnées.</li>
+</ul>
+</article>
<h3 id="TransformDerivative"><span class="section-number">5.3.2.</span>
Dérivées partielles des opérations</h3>
<p>
@@ -2281,13 +2629,13 @@ Cette opération était définie dans un
</p>
<p>
-Appelons <var>P</var> une projection cartographique qui convertit une
longitude et latitude (λ,φ) en degrés
+Appelons <var>P</var> une projection cartographique qui convertit une
longitude et latitude (λ, φ) en degrés
vers une coordonnée projetée (<var>x</var>,<var>y</var>) en mètres.
Dans l’expression ci-dessous, nous représentons le résultat de la projection
cartographique
sous forme d’une matrice colonne (la raison sera plus claire bientôt):
</p>
-<math alttext="MathML capable browser required" display="block">
+<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="[">
@@ -2300,7 +2648,7 @@ sous forme d’une matrice colonne (la r
<p>La dérivée de la projection cartographique en ce même point peut se
représenter par la matrice Jacobienne définie tel que:</p>
-<math alttext="MathML capable browser required" display="block">
+<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>
@@ -2320,13 +2668,14 @@ sous forme d’une matrice colonne (la r
</math>
<p>
+Dans la suite de ce texte, nous abrégerons ∂<var>x</var>(λ,φ) par
∂<var>x</var> et de même pour ∂<var>y</var>.
Le premier élément de la matrice (∂<var>x</var>/∂λ) nous indique à quel
déplacement vers l’<em>Est</em>
(<var>x</var> en mètres) correspond un déplacement de un degré de
<em>longitude</em> (λ).
De même, le dernier élément de la matrice (∂<var>y</var>/∂φ) nous indique à
quel déplacement vers le <em>Nord</em>
(<var>y</var> en mètres) correspond un déplacement de un degré de
<em>latitude</em> (φ).
Les autres éléments (∂<var>x</var>/∂φ et ∂<var>y</var>/∂λ) sont des termes
croisés (par exemple à quel déplacement
en mètres vers le <strong>Nord</strong> correspond un déplacement de un degré
de <strong>longitude</strong>).
-Ces valeurs ne sont généralement valides qu’à la position géographique (λ,φ)
donnée.
+Ces valeurs ne sont généralement valides qu’à la position géographique (λ, φ)
donnée.
Si on se déplace un peu, ces valeurs changent légèrement.
</p>
@@ -2342,7 +2691,7 @@ la première et deuxième colonne des ma
<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>où les vecteurs sont reliés à la matrice par:</p>
-<math alttext="MathML capable browser required" display="block">
+<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>
@@ -2383,7 +2732,7 @@ Par extension, on peut aussi s’en serv
ou si la direction d’un axe est renversée. Mais l’intérêt des dérivées ne
s’arrête pas là.
</p>
-<h4 id="DerivativeAndEnvelope"><span class="section-number">5.3.2.1.</span>
Utilité des dérivées pour la projection d’enveloppes</h4>
+<h4 id="DerivativeAndEnvelope"><span class="section-number">5.3.2.1.</span>
Utilité des dérivées pour la reprojection d’enveloppes</h4>
<p>
Les systèmes d’information géographiques ont très fréquemment besoin de
projeter une enveloppe.
Mais l’approche naïve, qui consisterait à projeter chacun des 4 coins du
rectangle, ne suffit pas.
@@ -2459,10 +2808,17 @@ Mais toute la discussion précédente ut
alors que l’algorithme est applicable dans un espace à <var>n</var> dimensions.
Et de fait, l’implémentation de Apache SIS fonctionne pour un nombre
arbitraire de dimensions.
Les économies apportées par cet algorithme par rapport à la force brute
augmentent de manière exponentielle avec le nombre de dimensions.
+</p><p>
+L’approche décrite dans cette section est implémentée dans Apache
<abbr>SIS</abbr>
+par la méthode statique <code
class="SIS">Envelopes.transform(CoordinateOperation, Envelope)</code>.
+Une méthode <code class="SIS">Envelopes.transform(MathTransform,
Envelope)</code> existe aussi comme alternative,
+mais cette dernière ne devrait être utilisée que si on ne connaît pas l’objet
<code class="GeoAPI">CoordinateOperation</code> utilisé.
+La raison est que les objets de type <code class="GeoAPI">MathTransform</code>
ne contiennent pas d’information sur le système de coordonnées sous-jasent,
+ce qui empêche la méthode <code class="SIS">Envelopes.transform(…)</code> de
savoir comment gérer les points aux pôles.
</p>
-<h4 id="DerivativeAndRaster"><span class="section-number">5.3.2.2.</span>
Utilité des dérivées pour la projection d’images</h4>
+<h4 id="DerivativeAndRaster"><span class="section-number">5.3.2.2.</span>
Utilité des dérivées pour la reprojection d’images</h4>
<p>
La projection cartographique d’une image s’effectue en préparant une image
initialement vide qui contiendra le résultat de l’opération,
puis à remplir cette image en itérant sur tous les pixels. Pour chaque pixel
de l’image <em>destination</em>, on obtient la coordonnées
@@ -2521,7 +2877,7 @@ Les dérivées des projections cartograp
si c’est la peine d’effectuer une nouvelle itération <strong>avant</strong> de
la faire.
L’idée de base est de vérifier si les dérivées de deux points voisins sont
presque pareilles,
auquel cas on présumera que la transformation entre ces deux points est
pratiquement linéaire.
-Pour quantifier « presque pareil », on procède en calculant l’intersection
entre les tangentes aux deux points
+Pour quantifier « presque pareil », on procède en calculant l’intersection
entre les tangentes aux deux points
(une information fournie par les dérivées), et en calculant la distance entre
cette intersection et la droite
qui relie les deux points (la ligne pointillée dans la figure ci-dessous).
</p>
@@ -2541,27 +2897,36 @@ mais en fait beaucoup plus dans une gril
Cette discussion n’aurait pas un grand intérêt si le coût du calcul des
dérivées des projections cartographiques
était élevé par rapport aux coût de la projection des points. Mais lorsque
l’on dérive analytiquement les équations
des projections, on constate que les calculs des positions et de leurs
dérivées ont souvent plusieurs termes en commun.
-En outre le calcul des dérivées est simplifié lorsque le code Java effectuant
les projections ne se concentre que sur le « noyau » non-linéaire,
+En outre le calcul des dérivées est simplifié lorsque le code Java effectuant
les projections ne se concentre que sur le « noyau » non-linéaire,
après s’être déchargé des parties linéaires en les déléguant aux
transformations affines comme le fait <abbr title="Spatial Information
System">SIS</abbr>.
-Les implémentations des projections cartographiques dans Apache
<abbr>SIS</abbr> tirent parti de ces propriétés en ne calculant les dérivées
que si elles sont demandées,
-et en offrant une méthode qui permet de projeter un point et obtenir sa
dérivée en une seule opération afin de permettre à <abbr>SIS</abbr> de
réutiliser un maximum de termes communs.
+Les implémentations des projections cartographiques dans Apache
<abbr>SIS</abbr> tirent parti de ces propriétés
+en ne calculant les dérivées que si elles sont demandées,
+et en offrant une méthode qui permet de projeter un point et obtenir sa
dérivée en une seule opération
+afin de permettre à <abbr>SIS</abbr> de réutiliser un maximum de termes
communs.
Exemple:</p>
-<pre>AbstractMathTransform projection = ...; <code class="comment">//
Une projection cartographique de Apache SIS.
+<pre><code class="SIS">AbstractMathTransform</code> projection = ...;
<code class="comment">// Une projection cartographique de Apache SIS.
</code><b>double</b>[] sourcePoint = {longitude, latitude}; <code
class="comment">// La coordonnée géographique que l’on veut projeter.
</code><b>double</b>[] targetPoint = <b>new</b> <b>double</b>[2];
<code class="comment">// Là où on mémorisera le résultat de la projection.
-</code>Matrix derivative = projection.transform(sourcePoint, 0,
targetPoint, 0, <b>true</b>);</pre>
+</code><code class="GeoAPI">Matrix</code> derivative = projection.<span
class="SIS">transform</span>(sourcePoint, 0, targetPoint, 0, <b>true</b>);</pre>
<p>
-Apache <abbr>SIS</abbr> est capable combiner les dérivées des projections
cartographiques de la même façon que pour les
-projections de coordonnées: concaténation d’une chaîne de transformations,
inversion, opérer sur un sous-ensemble des
-dimensions, <i>etc.</i>
-</p>
-
-<p>
-L’approche décrite dans la section sur les <a
href="#DerivativeAndEnvelope">projection d’enveloppes</a>
-est implémentée par la méthode statique <code
class="SIS">Envelopes.transform(CoordinateOperation, Envelope)</code> de
<abbr>SIS</abbr>.
-</p>
+Si seule la matrice Jacobienne est désirée (sans la projection du point),
alors la méthode
+<code class="GeoAPI">MathTransform.derivative(DirectPosition)</code> offre
une alternative plus lisible.
+</p><p>
+Apache <abbr>SIS</abbr> est capable combiner les dérivées des projections
cartographiques de la même façon que pour les projections de coordonnées:
+concaténation d’une chaîne de transformations, inversion, opérer sur un
sous-ensemble des dimensions, <i>etc.</i>
+Les opérations inverses (des systèmes projetés vers géographiques)
+sont souvent beaucoup plus compliquées à implémenter que les opérations
originales (des systèmes géographiques vers projetés),
+mais par chance la matrice Jacobienne d’une fonction inverse est simplement
l’inverse de la matrice Jacobienne de la fonction originale.
+Une fonction inverse peut donc implémenter le calcul de sa dérivée comme suit:
+</p>
+<pre>@Override
+<b>public</b> <code class="GeoAPI">Matrix</code> derivative(<code
class="GeoAPI">DirectPosition</code> p) <b>throws</b> <code
class="GeoAPI">TransformException</code> {
+ <code class="GeoAPI">Matrix</code> jac =
inverse().derivative(transform(p));
+ <b>return</b> Matrices.inverse(jac);
+}
+</pre>
</section>
<section>
<header>