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 2022/05/19 22:19:31 UTC
[sis-site] branch asf-staging updated: Regenerate the developer guide.
This is an automated email from the ASF dual-hosted git repository.
desruisseaux pushed a commit to branch asf-staging
in repository https://gitbox.apache.org/repos/asf/sis-site.git
The following commit(s) were added to refs/heads/asf-staging by this push:
new 8f28edd1 Regenerate the developer guide.
8f28edd1 is described below
commit 8f28edd190d141812053d16b50ab1034489ce544
Author: Martin Desruisseaux <ma...@geomatys.com>
AuthorDate: Fri May 20 00:18:51 2022 +0200
Regenerate the developer guide.
---
book/book.css | 204 +--
book/en/developer-guide.html | 3797 +++++++++++++++++++++---------------------
book/fr/developer-guide.html | 125 +-
book/toc.js | 34 +
4 files changed, 2035 insertions(+), 2125 deletions(-)
diff --git a/book/book.css b/book/book.css
index a570fb1b..d2d61bfc 100644
--- a/book/book.css
+++ b/book/book.css
@@ -1,113 +1,89 @@
/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
+ * Licensed to the Apache Software Foundation (ASF)
+ * under one or more contributor license agreements.
*/
/*
* Table of content, to be shown on the left side.
- * main{left} should be at least equal to nav.toc{width}.
+ * main{left} should be at least equal to nav{width}.
* We use <p> element for the "Table of content" title instead than <h1>
* because we don't want those textes to be inserted in the auto-generated TOC.
*/
nav {
- font-family: sans-serif;
- line-height: 100%;
- color: #006699;
-}
-
-nav.toc {
- background-color: #f7f8f9;
- position: absolute;
- overflow: auto;
- top: 0;
- bottom: 0;
- left: 0;
- max-width: 80%;
- width: 20em;
+ position: absolute;
+ top: 0;
+ left: 0;
+ right: 0;
+ bottom: 0;
+ width: 450px;
+ white-space: nowrap;
+ overflow: auto;
+ font-family: sans-serif;
+ font-size: smaller;
+ color: #1a5276;
+ background-color: #f8f9f9;
+ border-right: #cacfd2 1px solid;
}
main {
- left: 20em;
- right: 0;
- top: 0;
- bottom: 0;
- position: fixed;
- overflow: auto;
+ position: fixed;
+ left: 450px;
+ top: 0;
+ right: 0;
+ bottom: 0;
+ overflow: auto;
+ padding-left: 42px;
+ padding-right: 30px;
+ font-size: 18px;
+ /*
+ * Firefox has a monospace font size different than the proportional font size.
+ * By setting a font size in the main block, we force the same size for both fonts.
+ *
+ * https://bugzilla.mozilla.org/show_bug.cgi?id=328621
+ */
}
nav a {
+ display: block;
text-decoration: none;
- font-family: sans-serif;
- font-size: small;
- color: #006699;
+ font-family: sans-serif;
+ color: #5d6d7e;
+ transition: all 50ms ease-in-out;
}
+nav a:focus,
nav a:hover {
+ color: #154360;
text-decoration: underline;
}
nav p {
- font-size: large;
- font-weight: bold;
- margin-top: 9px;
- margin-bottom: 6px;
- margin-left: 6px;
-}
-
-/*
- * Table of content items. Note that fragments of TOC are repeated at the beginning
- * of each chapter in the main body. Those fragments have a slightly different layout.
- */
-ul.toc {
- list-style-type: square;
- margin-bottom: 30px;
- padding-left: 21px;
+ font-size: large;
+ font-weight: bold;
+ padding-left: 15px;
+ padding-bottom: 4px;
+ margin-bottom: 6px;
+ border-bottom: #2471a3 1px solid;
}
-ul.toc ul {
- list-style-type: square;
- padding-left: 21px;
+nav ul {
+ list-style-type: none;
+ padding-left: 15px;
}
-nav.toc ul.toc li {
+nav ul li {
margin-top: 3px;
margin-bottom: 3px;
}
-/*
- * For the main body, we put a margin for almost everything except the elements to be centered.
- */
-section > header > h2,
-section > h3,
-section > h4,
-section > p,
-section > nav > p,
-section > pre,
-section > div.example,
-section > details {
- margin-left: 42px;
- margin-right: 30px;
-}
-
-li > p {
- margin-right: 30px;
+nav li.active > a {
+ color: #154360;
+ font-weight: bolder;
}
-section > div.example,
-section > article,
-section > aside {
+div.example,
+article,
+aside {
margin-left: 80px;
margin-right: 68px;
}
@@ -118,81 +94,52 @@ dd > div.example {
margin-right: 60px;
}
-main nav ul.toc,
section > ul,
+section > ol,
section > dl {
- margin-left: 42px;
+ margin-left: 30px;
}
/*
* Lists.
*/
ul.verbose li {
- margin-top: 4px;
- margin-bottom: 4px;
-}
-
-/*
- * Links to previous and next chapters.
- */
-div.chapter-links {
- width: 100%;
- background-color: #CCDFFF;
- border-bottom-color: #0077B3;
- border-bottom-style: solid;
- border-bottom-width: 1px;
- margin-top: 0px;
- padding-top: 6px;
- margin-bottom: 18px;
- padding-bottom: 24px;
- white-space: nowrap;
-}
-
-div.previous-chapter {
- width: 50%;
- float: left;
-}
-
-div.next-chapter {
- width: 50%;
- float: right;
- text-align: right;
+ margin-top: 9px;
+ margin-bottom: 9px;
}
/*
* Chapters and sections titles (excluding the book titles).
*/
+section > h1,
section > header > h1 {
font-family: sans-serif;
- margin-top: 160px;
- text-align: center;
- background-color: #99AAFF;
- border-top-color: #0000CC;
- border-bottom-color: #0000CC;
- border-top-style: solid;
+ margin-top: 200px;
border-bottom-style: solid;
- border-top-width: 3px;
border-bottom-width: 3px;
padding-top: 6px;
- padding-bottom: 0px;
+ padding-bottom: 6px;
margin-bottom: 0px;
}
+section > h2,
section > header > h2 {
font-family: sans-serif;
- margin-top: 60px;
+ margin-top: 160px;
border-bottom-style: solid;
border-bottom-width: 2px;
}
-section > h3 {
+section > h3,
+section > header > h3 {
font-family: sans-serif;
- margin-top: 50px;
+ margin-top: 100px;
}
-section > h4 {
+section > h4,
+section > header > h4 {
font-family: sans-serif;
- margin-top: 30px;
+ margin-top: 60px;
}
span.section-number {
@@ -290,6 +237,21 @@ table tr td.separator {
padding-bottom: 6px;
}
+/*
+ * Table with the first column in monospaced font, used for drawing trees.
+ * Because line-wrap is disabled, the table in HTML may need a `font-size`
+ * style element with a magic number using the `vw` unit.
+ */
+table.monospacedHeaderColumn {
+ white-space: nowrap;
+ line-height: 1;
+ border: none;
+}
+
+table.monospacedHeaderColumn tr > :nth-child(1) {
+ font-family: monospace;
+}
+
div.caption {
margin: 6px;
text-align: center;
diff --git a/book/en/developer-guide.html b/book/en/developer-guide.html
index c26b1b49..1c6debf3 100644
--- a/book/en/developer-guide.html
+++ b/book/en/developer-guide.html
@@ -11,58 +11,49 @@
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">
<head>
-<title>Introduction to Apache SIS</title>
+<title>Apache SIS developer guide</title>
<meta charset="UTF-8"/>
<link href="../book.css" rel="stylesheet" type="text/css"/>
+<script src="../toc.js">/* highlighter */</script>
</head>
<body>
-<nav class="toc">
+<nav>
<p>Table of content</p>
-<ul class="toc">
-<li><a href="#Standards">Standards and norms</a><ul>
-<li><a href="#ConceptualModels">Sources of conceptual models used by Apache SIS</a></li>
-<li><a href="#GeoAPI">From conceptual models to Java interfaces: GeoAPI</a><ul>
-<li><a href="#GeoAPI-implementation">Implementations provided by Apache SIS</a></li></ul></li>
-<li><a href="#AboutBook">Conventions used in this guide</a><ul>
-<li><a href="#ChosenTerms">Chosen terms</a></li></ul></li></ul></li>
-<li><a href="#DataAccess">Geospatial data access</a><ul>
-<li><a href="#GetMetadataElement">Navigating in metadata elements</a></li></ul></li>
-<li><a href="#Coverage">Data coverages</a></li>
+<ul>
+<li><a href="#Introduction">Introduction</a><ul>
+<li><a href="#Conventions">Typographic and naming conventions</a></li>
+<li><a href="#Installation">Installation</a></li>
+<li><a href="#DataAccess">Data access overview</a></li></ul></li>
+<li><a href="#Coverage">Data as coverage</a><ul>
+<li><a href="#GridGeometry">Grid coverage domain</a><ul>
+<li><a href="#AffineTransform">Affine transform</a></li></ul></li>
+<li><a href="#SampleDimension">Sample dimensions</a></li></ul></li>
<li><a href="#Geometry">Geometries</a><ul>
-<li><a href="#GeometryBase">Base classes</a><ul>
-<li><a href="#DirectPosition">Direct points and positions</a></li>
<li><a href="#Envelope">Envelopes</a><ul>
-<li><a href="#AntiMeridian">Envelopes that cross the antimeridian</a></li></ul></li></ul></li></ul></li>
+<li><a href="#AntiMeridian">Crossing the antimeridian</a></li>
+<li><a href="#EnvelopeTransform">Transforming to another reference system</a></li></ul></li></ul></li>
<li><a href="#Referencing">Spatial reference systems</a><ul>
-<li><a href="#ComponentsOfCRS">Components of a reference system by coordinates</a><ul>
-<li><a href="#Ellipsoid">Geoid et ellipsoid</a></li>
-<li><a href="#GeodeticDatum">Geodetic datum</a></li>
-<li><a href="#CoordinateSystem">Coordinate systems</a><ul>
-<li><a href="#AxisOrder">Axis order</a></li></ul></li>
-<li><a href="#GeographicCRS">Geographic reference systems</a><ul>
-<li><a href="#GeographicWKT">Well-Known Text format</a></li></ul></li>
-<li><a href="#ProjectedCRS">Map projections</a><ul>
-<li><a href="#ProjectedWKT">Well-Known Text format</a></li></ul></li>
-<li><a href="#CompoundCRS">Vertical and temporal dimensions</a><ul>
-<li><a href="#CompoundWKT">Well-Known Text format</a></li></ul></li></ul></li>
+<li><a href="#ComponentsOfCRS">Coordinate reference systems</a><ul>
+<li><a href="#ProjectedCRS">Map projections</a></li>
+<li><a href="#GeographicCRS">Geographic reference systems</a></li>
+<li><a href="#CompoundCRS">Vertical and temporal dimensions</a></li>
+<li><a href="#CoordinateSystem">Coordinate systems</a></li>
+<li><a href="#GeodeticDatum">Geodetic datum</a></li></ul></li>
<li><a href="#GetCRS">Fetching a spatial reference system</a><ul>
-<li><a href="#CRSAuthorityFactory">Looking CRS defined by authorities</a></li>
-<li><a href="#CRSParsing">Reading definitions in GML or WKT format</a></li>
-<li><a href="#CRSFactory">Constructing programmatically</a></li>
<li><a href="#CRS_UserCode">Adding new CRS definitions</a></li></ul></li>
+<li><a href="#AxisOrder">Axis order</a></li>
<li><a href="#CoordinateOperations">Coordinate operations</a><ul>
<li><a href="#CRS.findOperation">Getting a coordinate operation</a></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>
-<li><a href="#GetDerivative">Getting the derivative at a point</a></li></ul></li>
-<li><a href="#CoordinateOperationSteps">Conceptual versus real chain of coordinate operations</a></li></ul></li>
-<li><a href="#Formats">Data storage formats</a></li>
-<li><a href="#XML-ISO">Representing objects in XML</a><ul>
-<li><a href="#XML-ISO-19115">Representing metadata according to ISO 19115-3</a><ul>
-<li><a href="#gco-id">Identification of already-defined instances</a></li>
-<li><a href="#nilReason">Representing missing values</a></li></ul></li></ul></li></ul></li>
+<li><a href="#TransformDerivative">Partial derivatives of coordinate operations</a></li>
+<li><a href="#CoordinateOperationSteps">Chain of coordinate operation steps</a></li></ul></li></ul></li>
+<li><a href="#Metadata">Metadata</a><ul>
+<li><a href="#GetMetadataElement">Navigating in metadata elements</a><ul>
+<li><a href="#MetadataAsMap">View as key-value pairs</a></li></ul></li></ul></li>
+<li><a href="#XML-ISO">XML representation of ISO objects</a><ul>
+<li><a href="#XML-ISO-19115">ISO 19115-3 metadata</a><ul>
+<li><a href="#gco-id">Links to previously-defined instances</a></li>
+<li><a href="#nilReason">Placeholders for missing values</a></li></ul></li></ul></li>
<li><a href="#Utilities">Utility classes and methods</a><ul>
<li><a href="#ComparisonModes">Comparison modes of objects</a></li>
<li><a href="#ObjectConverters">Object converters</a></li>
@@ -70,33 +61,28 @@
<li><a href="#LocalizedString">Distinct character sequences for each locale</a></li>
<li><a href="#InternationalString">Single instance for all supported locales</a></li>
<li><a href="#Locale.ROOT">Locale.ROOT convention</a></li>
-<li><a href="#UnicodePoint">Treatment of characters</a><ul>
-<li><a href="#Whitespaces">Blank spaces interpretation</a></li></ul></li></ul></li></ul></li>
-<li><a href="#GeoAPI-details">GeoAPI relationship with standards</a><ul>
+<li><a href="#UnicodePoint">Treatment of characters</a></li></ul></li></ul></li>
+<li><a href="#Annexes">Annexes</a><ul>
+<li><a href="#Standards">Standards and norms</a><ul>
+<li><a href="#ConceptualModels">Sources of conceptual models used by Apache SIS</a></li>
+<li><a href="#GeoAPI">From conceptual models to Java interfaces: GeoAPI</a></li>
<li><a href="#GeoAPI-modules">GeoAPI modules</a></li>
-<li><a href="#SpecificationToInterfaces">From OGC specifications to Java interfaces</a><ul>
-<li><a href="#UML-annotation">Explicit mapping given by @UML annotations</a></li>
-<li><a href="#MappingToJDK">Implicit mapping to standard JDK</a></li></ul></li>
-<li><a href="#ReduceDependency">Reduce direct dependency to Apache SIS</a><ul>
-<li><a href="#UML-annotation-indep">Mapping given by @UML annotations</a></li>
-<li><a href="#ServiceLoader">Fetching implementations of GeoAPI interfaces</a><ul>
-<li><a href="#GeoAPI-simple">Defining custom implementations</a></li></ul></li></ul></li></ul></li>
+<li><a href="#SpecificationToInterfaces">From OGC specifications to Java interfaces</a></li>
+<li><a href="#ReduceDependency">Reduce direct dependency to Apache SIS</a></li></ul></li>
<li><a href="#Tests">Test suites</a><ul>
-<li><a href="#GeoAPI-conformance">GeoAPI conformance</a><ul>
-<li><a href="#GeoAPI-validators">Instance validations</a></li>
-<li><a href="#GeoAPI-tests">Executing pre-defined tests</a></li></ul></li></ul></li>
+<li><a href="#GeoAPI-conformance">GeoAPI conformance</a></li></ul></li>
<li><a href="#DesignNotes">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>
+<li><a href="#EarlyOrLateBinding">Early binding versus late binding</a></li>
+<li><a href="#MatrixLibrary">Specificities of a matrix library for GIS</a></li>
+<li><a href="#JacobianUsage">Usages of Jacobian matrix</a></li>
+<li><a href="#AffineTransformAPI">Integration with graphical libraries</a></li>
+<li><a href="#XMLTools">Tools for reading and writing XML documents</a></li></ul></li></ul></li>
</ul>
</nav>
<main>
<p style="margin-top:30pt; font-size:30pt; font-weight:900; text-align:center">
-Introduction to Apache SIS™
+Apache SIS™ developer guide
</p>
@@ -108,58 +94,34 @@ Introduction to Apache SIS™
-
-
<section>
<header>
-<h1 id="Standards"><span class="section-number">1.</span> Standards and norms</h1>
-<nav><div class="chapter-links"><div class="next-chapter"><a href="#DataAccess">Next chapter</a> ➡</div></div></nav>
+<h1 id="Introduction"><span class="section-number">1.</span> Introduction</h1>
</header>
-<nav><p>In this chapter:</p><ul class="toc">
-<li><a href="#ConceptualModels">Sources of conceptual models used by Apache SIS</a></li>
-<li><a href="#GeoAPI">From conceptual models to Java interfaces: GeoAPI</a><ul>
-<li><a href="#GeoAPI-implementation">Implementations provided by Apache SIS</a></li></ul></li>
-<li><a href="#AboutBook">Conventions used in this guide</a><ul>
-<li><a href="#ChosenTerms">Chosen terms</a></li></ul></li></ul></nav>
<p>
-A geospatial information community is a collection of systems or individuals capable of exchanging their geospatial data
-through the use of common standards, allowing them to communicate with one another.
-As there are many ways to represent geospatial information, each community tends to structure this information in light of its areas of interest.
-This diversity complicates the task of Spatial Information System (<abbr>SIS</abbr>) users
-by confronting them with an apparently chaotic variety of data formats and structures.
-The characteristics of these structures vary according to the observed phenomenon and measurement methods,
-as well as the habits of the organizations producing the data.
-Such a variety represents an obstacle in studies that require heterogeneous combinations of data,
-especially when they originate in communities that are traditionally distinct.
-For example, a researcher studying cholera might be interested in populations of shrimp as a propagation vector of the disease.
-But as doctors and oceanographers may not be used to share their work,
-the participants of such a study may be limited by the effort required to convert the data.
+Apache <abbr title="Spatial Information System">SIS</abbr> is a free software,
+Java language library for developing geospatial desktop or server applications.
+This library provides services for data discovery (metadata), reading and writing vector or raster data,
+filtering the data and applying operations such as map projections.
+Apache <abbr>SIS</abbr> data structures follow closely the geospatial models defined in the international standards published by
+the Open Geospatial Consortium (<abbr>OGC</abbr>) and the International Organization for Standardization (<abbr>ISO</abbr>).
+The <a href="#Annexes">annex</a> provides more context about international standards.
</p><p>
-We cannot impose a uniform format on all data collections, as the diversity of formats is tied to factors
-such as the constraints imposed by the measuring apparatus, and the statistical distribution of values.
-A more flexible solution is to ensure the interoperability of data across a common programming interface
-(<abbr title="Application Programming Interface">API</abbr>).
-This <abbr>API</abbr> is not necessarily defined in a programming language;
-the actual tendency is rather to define conventions that use existing web protocols, which we can translate into various programming languages.
-But in order for this approach to be viable, the <abbr>API</abbr> must be generally accepted by independent developers.
-In other words, the <abbr>API</abbr> must come as near as possible to industrial standards.
+The library is an implementation of <abbr title="Open Geospatial Consortium">OGC</abbr> <a href="http://www.geoapi.org">GeoAPI</a> interfaces.
+In a series of <code class="GeoAPI">org.opengis.*</code> packages, GeoAPI offers a set of implementation-neutral Java interfaces for geospatial applications.
+These interfaces closely follow the specifications of the <abbr>OGC</abbr>, while interpreting and adapting them
+to meet the needs of Java developers — for example, conforming with Java naming conventions.
+The conceptual model of GeoAPI will be explained in detail in the chapters describing Apache <abbr>SIS</abbr> implementation.
+However, we can get an overview of its content by consulting the page listing the mapping between
+<a href="http://www.geoapi.org/3.0/javadoc/content.html">GeoAPI methods and the standards where they come from</a>.
+The <a href="#GeoAPI">annex</a> provides more details about GeoAPI history and how to use it.
</p><p>
-For example, one task that benefit from a successful standardization is the accessing of relational databases.
-The industry has established a common language — the <abbr title="Structured Query Language">SQL</abbr> standard —
-that the creators of Java have embedded in standard <abbr title="Java DataBase Connectivity">JDBC</abbr> programming interfaces.
-Today, these interfaces are implemented by many software programs, both free and commercial.
-Like databases, methods of accessing geographic information have been standardized.
-In this case, however, the efforts have been more recent, and their integration in software — especially in older programs — is incomplete and not always coherent.
-At the time of writing, no product to our knowledge has implemented all of the specifications in their entirety.
-However, there are many implementations that cover a fairly large spectrum.
-One of these is the Apache <abbr>SIS</abbr>™ library that is described in this document.
+While Apache <abbr>SIS</abbr> is primarily a library for helping developers to create their own applications,
+<abbr>SIS</abbr> provides also an optional JavaFX application for testing its capability to read, transform and visualize data files.
+Screenshots of this application may be used in this document for illustrative purposes.
</p><p>
-Apache <abbr title="Spatial Information System">SIS</abbr> is characterized by a sustained effort to comply with standards.
-In general, complying with standards demands a greater effort than would be required for an isolated development,
-but rewards us with a double advantage: not only does it improve the interoperability of our data with that of external projects,
-it also points towards a robust way of elaborating the conceptual model reflected in the <abbr>API</abbr>.
-In effect, the groups of experts who conceived the standards anticipated difficulties that sometimes escape the engineer at the beginning of a project,
-but which risk to hit them before the end.
+<b>Note:</b> this document contains mathematical formulas expressed in MathML.
+For viewing those formulas, a MathML-capable browser (e.g. Firefox) is required.
</p>
@@ -169,165 +131,78 @@ but which risk to hit them before the end.
<section>
<header>
-<h2 id="ConceptualModels"><span class="section-number">1.1.</span> Sources of conceptual models used by Apache SIS</h2>
+<h2 id="Conventions"><span class="section-number">1.1.</span> Typographic and naming conventions</h2>
</header>
<p>
-Most standards used by Apache <abbr title="Spatial Information System">SIS</abbr> have been devised by the <a href="https://www.ogc.org/">Open Geospatial Consortium</a> (<abbr>OGC</abbr>),
-sometimes in collaboration with the <a href="https://www.iso.org/">International Organization for Standardization</a> (<abbr>ISO</abbr>).
-Some <abbr>ISO</abbr> standards themselves become European standards via the <a href="http://inspire.jrc.ec.europa.eu">INSPIRE Directive</a>.
-These standards offer two key features:
+The elements defined in a computer language, such as classes and methods in Java or elements in an <abbr>XML</abbr> document,
+appear in monospaced font in this document.
+In order to facilitate an understanding of the relationships between Apache <abbr title="Spatial Information System">SIS</abbr> and the standards,
+these elements are also represented using the following colour codes:
</p>
<ul>
<li>
-Allowing a community to make its information public in such a way that outside individuals or systems can discover it.
+Elements in blue are defined in an <abbr title="International Organization for Standardization">ISO</abbr>
+or <abbr title="Open Geospatial Consortium">OGC</abbr> standard other than GeoAPI.
</li>
<li>
-Transferring information from one community to another while preserving its semantics,
-even if the two communities use very different internal representations.
+Elements in green are Java element defined in GeoAPI.
+</li>
+<li>
+Elements in brown are defined in Apache <abbr title="Spatial Information System">SIS</abbr>.
+</li>
+<li>
+Elements left in black are either defined elsewhere (for example the standard Java library),
+or there is simply no emphasis on that element for the discussion.
</li>
</ul>
<p>
-These standards are made available to the international community for free,
-as <a href="https://www.ogc.org/standards/is">specifications (<abbr title="Portable Document Format">PDF</abbr> files)</a> or
-as <a href="http://schemas.opengis.net/gml/3.3/">schemas (<abbr title="XML Schema Definition">XSD</abbr> files)</a>.
-Standardization organizations do not create software; to obtain an implementation of these specifications,
-users must choose one of the compliant products available on the market, or develop their own solutions.
-Such voluntary compliance with these specifications allow independent communities to more easily exchange geographic information.
-</p>
-
-
-
-<details>
-<summary>More about standardization process</summary>
-<article id="OGC-process">
-<header>
-<h2><abbr>OGC</abbr> standardization process</h2>
-</header>
-<p>
-The work of the <abbr title="Open Geospatial Consortium">OGC</abbr> is done by email, teleconferences, and at <a href="https://www.ogc.org/event?category=ogctcpc">in-person meetings</a>.
-The <abbr>OGC</abbr> organizes four meetings per year, each lasting five days, and hosted by member organizations that sponsor the event (companies, universities, research centres, <i>etc</i>).
-The host continent alternates between Europe and North America, with a growing presence in Asia since 2011.
-These meetings are usually attended by between 50 and 100 participants from among the hundreds of members of the <abbr>OGC</abbr>.
-Some participants are present at almost all the meetings, forming the pillars of the organization.
-The meetings of the <abbr>OGC</abbr> offer opportunities for exchange among members from diverse backgrounds.
-</p><p>
-The creation of a <abbr>OGC</abbr> standard begins with a gathering of organizations or individuals with a common interest in an issue.
-A working group is proposed as a <i>Domain Working Group</i> (<abbr>DWG</abbr>) or as a <i>Standard Working Group</i> (<abbr>SWG</abbr>).
-<abbr>DWG</abbr>s are open to all members of the <abbr>OGC</abbr>,
-while <abbr>SWG</abbr>s require that their participants enter into an agreement not to hinder the distribution of the standard through intellectual property claims.
-</p>
-
-<h3 id="OGC-SWG">Standard Working Group (<abbr>SWG</abbr>) procedures</h3>
-<p>
-In order to be accepted, a standardization project must be supported by a minimum number of members belonging to distinct organizations.
-These founding members draft a charter defining the objectives of the <abbr>SWG</abbr>,
-which must be approved by the Technical Committee of the <abbr title="Open Geospatial Consortium">OGC</abbr>.
-Each founding member is endowed with the right to vote, with a limit of one voting member per organization.
-Each new member that wishes to join the <abbr>SWG</abbr> after its creation is granted the role of observer,
-and receives on request the right to vote after several months of observation.
-</p><p>
-A <abbr>SWG</abbr> may contain several dozen members, but the volunteers performing the bulk of the work are usually fewer.
-Their proposals are submitted to the entire membership of the group, who may accept them by unanimous consent.
-Any objections must be debated, and an alternative proposed.
-<abbr>SWG</abbr>s usually try to debate an issue until a consensus emerges rather than move ahead despite negative votes,
-even if those opposed are in a minority.
-The decisions of the group are then integrated into the specifications by a member who assumes the role of editor.
-</p><p>
-As far as possible, the working group must structure the specifications as a core around which various extensions might be built.
-A series of tests must accompany the standard, allowing implementations to be classified by the level of test passed.
-There must be at least one <i>reference implementation</i> that passes all the tests in order to demonstrate that the standard is usable.
-</p><p>
-When the standard is considered ready, the <abbr>SWG</abbr> votes on a motion proposing its submission to a vote by the higher authorities of the <abbr>OGC</abbr>.
-This process takes several months. There is a faster process for approving <i>de facto</i> standards, but it is applied sparingly.
-</p>
-
-<h3 id="OGC-OAB">The Architecture Board (<abbr>OAB</abbr>) and the Technical Committee (<abbr>TC</abbr>)</h3>
-<p>
-All proposals for standards are first examined by the <abbr title="Open Geospatial Consortium">OGC</abbr> Architecture Board (<abbr>OAB</abbr>).
-This board ensures that the standard conforms to the requirements of the <abbr>OGC</abbr> in form,
-modularization, and in terms of integration with other standards.
-If the <abbr>OAB</abbr> approves it, the standard is next submitted to a vote by the members of the Technical Committee (<abbr>TC</abbr>).
-This committee consists of the principal members of the <abbr>OGC</abbr>, and only they are capable of granting final approval.
-If approved, the standard is made publicly available for comments during a period of several months.
-At the end of this period, the <abbr title="Standard Working Group">SWG</abbr> must examine and respond to each comment.
-The eventual modifications of the standard are submitted to the <abbr>OAB</abbr>, then the standard is published in its final form.
-This distribution is announced in a press release by the <abbr>OGC</abbr>.
+For example to represent a projected coordinate reference system (Mercator, Lambert, <i>etc</i>),
+<code class="OGC">SC_ProjectedCRS</code> is an <abbr>UML</abbr> and <abbr>XML</abbr> element defined by the <abbr>ISO</abbr> 19111 standard.
+Then <code class="GeoAPI">org.opengis.referencing.crs.<b>ProjectedCRS</b></code> is the implementation-neutral GeoAPI interface derived from that standard,
+and <code class="SIS">org.apache.sis.referencing.crs.<b>DefaultProjectedCRS</b></code> is the implementation class provided by Apache SIS.
</p><p>
-Certain members of the <abbr title="Open Geospatial Consortium">OGC</abbr> and the <abbr title="Technical Committee">TC</abbr>
-also act as liaisons with the International Organization for Standardization (<abbr>ISO</abbr>).
-Cooperation between the two organizations goes two ways:
-the <abbr>OGC</abbr> adopts the <abbr>ISO</abbr> standards as a foundation on which to develop new standards,
-and certain <abbr>OGC</abbr> standards become <abbr>ISO</abbr> standards.
-</p>
-
-<h3 id="OGC-RFC">Procedure for the submission of proposals for modification</h3>
-<p>
-All users, whether or not they are members of the Open Geospatial Consortium, may propose modifications to <abbr title="Open Geospatial Consortium">OGC</abbr> standards.
-A list of current proposals for changes, along with a form for submitting new proposals, is <a href="https://www.ogc.org/standards/cr">available online</a>.
-Each proposal is reviewed by the <abbr title="Standard Working Group">SWG</abbr>.
+Apache SIS implements most GeoAPI interfaces by a classes of the same name than the interface
+but prefixed by <code>Abstract</code>, <code>Default</code> or <code>General</code> word.
+The <code>General</code> prefix is sometime used instead of <code>Default</code>
+to indicate that alternative implementations are available for some specific cases.
+For example the <code class="GeoAPI">Envelope</code> interface is implemented by at least two Apache SIS classes:
+<code class="SIS">GeneralEnvelope</code> and <code class="SIS">Envelope2D</code>.
+The first implementation can represent envelopes with any number of dimensions
+while the second implementation is specialized for two-dimensional envelopes.
</p><p>
-Some working groups use other parallel systems for submissions, for example GitHub merge requests, hosted outside of the structures of the <abbr>OGC</abbr>.
+Apache SIS classes prefixed by <code>Abstract</code> should not (in principle) be instantiated.
+Users should instantiate a non-abstract subclass instead.
+However many <abbr>SIS</abbr> classes are only conceptually abstract,
+without <code>abstract</code> Java keyword in class definition.
+Such classes can be instantiated by a <code>new AbstractXXX(…)</code> statement despite being conceptually abstract.
+Such instantiations should be avoided, but are nevertheless permitted in last resort when it is not possible to determine the exact subtype.
</p>
-</article>
-</details>
-
-
-
<p>
-Besides these formal standardization organizations, there are organizations that are not officially dedicated
-to the creation of standards, but whose work has largely been adopted as <i>de facto</i> standards.
-In particular, the <a href="https://epsg.org/">EPSG repository</a> offers numeric codes which allow the easy identification of a
-Coordinates Reference System (<abbr>CRS</abbr>) among <a href="../../tables/CoordinateReferenceSystems.html">several thousand</a>.
-This database is offered by petroleum companies that have an interest in ensuring their explorations are conducted in the correct place,
-even when using map produced by another party.
-Other examples of <i>de facto</i> standards include <a href="http://geotiff.osgeo.org">GeoTIFF</a> for data distributed on a grid (such as images),
-and <a href="http://en.wikipedia.org/wiki/Shapefile">Shapefile</a> for vector data (such as geometric shapes).
-</p><p>
-<abbr>OGC</abbr> standards are specified in several dozen documents.
-Each document outlines a service — for example, the transformation of coordinates.
-The function of each service is described by a collection of object classes and their interactions.
-These elements are illustrated by <abbr>UML</abbr> (Unified Modeling Language) diagrams in specifications called “abstracts”.
-<a href="https://www.ogc.org/standards/as">Abstract specifications</a> do not refer to any specific computer language.
-Their concepts may be applied more or less directly to a programming language, a database or an <abbr>XML</abbr> schema.
-There is always an element of arbitrariness in the method of applying an abstract specification,
-given that adjustments are often necessary to take into account the constraints or conventions of the target language.
-Certain data structures only exist in a few languages — for example, unions that exist in C/C++ but not in Java.
+Text in gray boxes, like below (click to expand), are for information purpose only and can be ignored.
</p>
-
-
-
<details>
-<summary>More about “implementation specifications”</summary>
-<article id="implementation-standard">
+<summary>Note about the definition of terms</summary>
+<article id="ChosenTerms">
<header>
-<h2>Historical note</h2>
+<h2>Source of term definitions</h2>
</header>
<p>
-At the turn of the millennium, the abstract specifications were explicitly concretized in <i>implementation specifications</i>.
-The term “implementation” is used here in the sense of all types of interfaces (Java or others) derived from
-<abbr title="Unified Modeling Language">UML</abbr> diagrams, and not implementations in the Java sense.
-Such specifications existed for <abbr title="Structured Query Language">SQL</abbr>,
-<abbr title="Common Object Request Broker Architecture">CORBA</abbr>, <abbr title="Component Object Model">COM</abbr>, and Java languages.
-As these languages are capable of executing procedures, the specifications of this period define not only data structures,
-but also operations that apply to these structures.
+Standards sometimes favour the application of certain generic terms to particular contexts,
+which may differ from the context in which other communities use these terms.
+For example, the terms <i>domain</i> and <i>range</i> may apply to arbitrary mathematical functions in order to designate
+a set of possible values of inputs and outputs respectively.
+The <abbr title="International Organization for Standardization">ISO</abbr> 19123 standard applies these terms to <code class="OGC">CV_Coverage</code> objects,
+seen as functions in which the <i>domain</i> is the set of spatio-temporal coordinates encompassed by the data,
+and the <i>range</i> is the set of values encompassed.
</p><p>
-Thereafter, enthusiasm for “Web 2.0” increased interest for <abbr>XML</abbr> over other languages.
-Older implementation specifications were deprecated,
-and <abbr title="XML Schema Definition">XSD</abbr> schemas became the main concretization of abstract specifications.
-Even the way abstract specifications are designed has evolved: they are less likely to define operations, and so what remains is closer to descriptions of database schemas.
-Some operations that were defined in older standards now appear, in another form, in web service specifications.
-Finally, the term “implementation specification” has been deprecated, to be subsumed under the term “<abbr title="Open Geospatial Consortium">OGC</abbr> standard.”
-But despite their depreciation, <a href="https://www.ogc.org/docs/retired">old implementation specifications</a> remain useful to programs in Java, because:
-</p>
-<ul>
-<li>Their simpler models, applied to the same concepts, are helpful in understanding new specifications.</li>
-<li>They sometimes define easy ways to perform common tasks, where the newer specifications limit themselves to general cases.</li>
-<li>As operations are more often omitted from the newer specifications, the old ones remain a useful supplement when defining <abbr title="Application Programming Interface">API</abbr>s.</li>
-</ul>
-<p>
-The Apache <abbr title="Spatial Information System">SIS</abbr> project is based on the most recent specifications,
-drawing from the archives of the <abbr>OGC</abbr> to complete certain abstract standards or make them more usable.
-Some old definitions are preserved as “convenience methods”, not always bringing new functionality, but facilitating the practical use of a library.
+However the functions to which above terms are applied by <abbr>ISO</abbr> standards are not the same as the functions to which they are applied by other libraries.
+For example <abbr title="University Corporation for Atmospheric Research">UCAR</abbr>’s <abbr title="Network Common Data Form">netCDF</abbr> library
+applies these terms instead to the function for converting pixel indices (its <i>domain</i>) to spatial-temporal coordinates (its <i>range</i>).
+Thus the <abbr>UCAR</abbr> library’s <i>range</i> may be the <i>domain</i> of <abbr>ISO</abbr> 19123.
+</p><p>
+The Apache <abbr title="Spatial Information System">SIS</abbr> library prefers as much as possible to use terms in the sense of <abbr title="Open Geospatial Consortium">OGC</abbr> and <abbr>ISO</abbr> norms.
+Particular care must be taken, however, with the interfaces between <abbr>SIS</abbr> and certain other external libraries,
+in order to reduce the risk of confusion.
</p>
</article>
</details>
@@ -336,206 +211,81 @@ Some old definitions are preserved as “convenience methods”, not always brin
<section>
<header>
-<h2 id="GeoAPI"><span class="section-number">1.2.</span> From conceptual models to Java interfaces: GeoAPI</h2>
+<h2 id="Installation"><span class="section-number">1.2.</span> Installation</h2>
</header>
<p>
-The <a href="http://www.geoapi.org">GeoAPI</a> project offers a set of Java interfaces for geospatial applications.
-In a series of <code class="GeoAPI">org.opengis.*</code> packages, GeoAPI defines structures representing metadata,
-coordinate reference systems and operations that perform cartographic projections.
-In a part that is not yet standardized — called <i>pending</i> — GeoAPI defines structures that represent geo-referenced images,
-geometries, filters that can be applied to queries, and other features.
-These interfaces closely follow the specifications of the <abbr title="Open Geospatial Consortium">OGC</abbr>, while interpreting and adapting them
-to meet the needs of Java developers — for example, conforming with naming conventions.
-These interfaces benefit both client applications and libraries:
+The easiest way to use Apache <abbr title="Spatial Information System">SIS</abbr> is to declare Maven dependencies in the application project.
+<abbr>SIS</abbr> is divided in about 20 modules, which allow applications to import a subset of the library.
+The <a href="../../downloads.html">Apache SIS downloads</a> page lists the main modules.
+The <code>pom.xml</code> fragment below gives all dependencies needed by the code snippets in this document
+(ignoring core modules such as <code class="SIS">sis-referencing</code> which are inherited by transitive dependencies).
+<em>Note that the <code class="SIS">sis-epsg</code> optional module is not under Apache license.</em>
+Inclusion of that module is subject to acceptation of <a href="https://epsg.org/terms-of-use.html">EPSG terms of use</a>.
+It is optional but recommended;
+see <a href="../../epsg.html">How to use EPSG geodetic dataset</a> page for more information.
+</p>
+<pre><properties>
+ <sis.version>1.2</sis.version>
+</properties>
+<dependencies>
+ <dependency>
+ <groupId>org.apache.sis.storage</groupId>
+ <artifactId>sis-geotiff</artifactId>
+ <version>${sis.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.sis.storage</groupId>
+ <artifactId>sis-netcdf</artifactId>
+ <version>${sis.version}</version>
+ </dependency>
+
+ <!-- Specialization of GeoTIFF reader for Landsat data. -->
+ <dependency>
+ <groupId>org.apache.sis.storage</groupId>
+ <artifactId>sis-earth-observation</artifactId>
+ <version>${sis.version}</version>
+ </dependency>
+
+ <!-- The following dependency can be omitted if XML support is not desired. -->
+ <dependency>
+ <groupId>org.glassfish.jaxb</groupId>
+ <artifactId>jaxb-runtime</artifactId>
+ <version>2.3.6</version>
+ <scope>runtime</scope>
+ </dependency>
+
+ <!-- <b>This optional dependency requires agreement with EPSG terms of use.</b> -->
+ <dependency>
+ <groupId>org.apache.sis.non-free</groupId>
+ <artifactId>sis-epsg</artifactId>
+ <version>${sis.version}</version>
+ <scope>runtime</scope>
+ </dependency>
+</dependencies></pre>
+
+<p>
+The <code class="SIS">sis-epsg</code> optional module needs a directory where it will install the geodetic database.
+That directory can be anywhere on the local machine, it shall exist (but should be initially empty),
+and its location should be specified by the <code>SIS_DATA</code> environment variable.
+For example on a Unix system
+(replace <code>user</code> by the actual user name and <code>some_directory</code> by anything):
+</p>
+<pre>export SIS_DATA=/home/user/some_directory
+mkdir $SIS_DATA</pre>
+<p>
+It is possible to avoid the need to setup <code>SIS_DATA</code> directory
+if the <code class="SIS">sis-epsg</code> dependency is replaced by <code class="SIS">sis-embedded-data</code>.
+However the latter is slower, and an <code>SIS_DATA</code> directory is still needed
+for other purposes such as the installation of datum shift grids.
</p>
-<ul>
-<li><p>
-Developers of client applications benefit from the greater knowledge base available on the Internet
-(due to the many publications related to <abbr>OGC</abbr> standards), as well as increased interoperability.
-Interoperability is facilitated by a better separation between applications that <em>call</em> GeoAPI functions,
-and libraries that <em>implement</em> GeoAPI.
-The separation is similar to that offered by the <a href="http://docs.oracle.com/javase/8/docs/technotes/guides/jdbc/"><abbr title="Java DataBase Connectivity">JDBC</abbr></a> (<i>Java Database Connectivity</i>) interfaces of standard Java.
-Using the interfaces’ <abbr title="Application Programming Interface">API</abbr>, developers can ignore the underlying implementation.
-For example, they can perform cartographic projections with the help of the <a href="http://www.geoapi.org/geoapi-proj4/index.html">Proj.4</a> library, or the Apache <abbr title="Spatial Information System">SIS</abbr> library,
-without having to change their programs when they change libraries.
-</p></li>
-<li><p>
-The developers of libraries inherit the expertise of the specifications’ authors, via the models that represent interfaces.
-GeoAPI also provides a framework within which developers can prioritize the implementation of the features they most need,
-while leaving the remaining features as extension points for future developments.
-For example, clients can call a GeoAPI function even if it is not yet supported by the library,
-and simply get a null value until a new version of the library returns a relevant value.
-</p></li>
-</ul>
+</section>
-<details>
-<summary>More about the GeoAPI project</summary>
-<article id="GeoAPI-history">
+<section>
<header>
-<h2>GeoAPI project history</h2>
+<h2 id="DataAccess"><span class="section-number">1.3.</span> Data access overview</h2>
</header>
<p>
-In 2001, the Open GIS Consortium (the former name of the Open Geospatial Consortium) published
-<a href="https://www.ogc.org/standards/ct"><abbr title="Open Geospatial Consortium">OGC</abbr> implementation specification 01-009:
-<cite>Coordinate Transformation Services</cite></a>.
-This specification, developed by the Computer Aided Development Corporation (Cadcorp),
-was accompanied by <abbr title="Component Object Model">COM</abbr>, <abbr title="Common Object Request Broker Architecture">CORBA</abbr>, and Java interfaces.
-At this time, the wave of web services had not yet eclipsed classical programming interfaces.
-The interfaces of the <abbr>OGC</abbr> did anticipate a networked world,
-but invested rather — in the case of Java — in <abbr>RMI</abbr> (<i>Remote Method Invocation</i>) technology.
-As the GeoAPI project did not yet exist, we retroactively designate these historical interfaces “<a href="http://www.geoapi.org/0.1/index.html">GeoAPI 0.1</a>”.
-These interfaces already used the package name <code class="GeoAPI">org.opengis</code>, which would be adopted by GeoAPI.
-</p><p>
-In 2002, developers of free projects launched a
-<a href="http://web.archive.org/web/20030509104308/http://digitalearth.org/story/2002/10/10/55046/206">call for the creation of a geospatial <abbr title="Application Programming Interface">API</abbr></a>.
-The initial proposal attracted the interest of at least five free projects.
-The project was created using <a href="http://sourceforge.net/projects/geoapi/">SourceForge</a>,
-which has since hosted the source code in a <a href="http://www.geoapi.org/source-repository.html">Subversion repository</a>.
-It was then that the project assumed the name “GeoAPI”, and used the interfaces of the <abbr>OGC</abbr> specification 01-009 as a starting point.
-</p><p>
-A few months later, the <abbr>OGC</abbr> launched the <a href="https://www.ogc.org/standards/go"><abbr>GO</abbr>-1: <i>Geographic Objects</i></a> project,
-which pursued goals similar to those of GeoAPI.
-In the meantime, the <abbr>OGC</abbr> abandonned some of their specifications in favor of <abbr>ISO</abbr> standards.
-GeoAPI and <abbr>GO-1</abbr> worked jointly to rework the GeoAPI interfaces and base them on the new <abbr>ISO</abbr> norms.
-Their first interation, <a href="http://www.geoapi.org/1.0/index.html">GeoAPI 1.0</a>,
-served as a starting point for the first draft of the <abbr>OGC</abbr> specification 03-064 by the <abbr>GO</abbr>-1 working group.
-The final version of this specification became an <abbr>OGC</abbr> standard in 2005,
-and <a href="http://www.geoapi.org/2.0/index.html">GeoAPI 2.0</a> was published at that time.
-</p><p>
-The <abbr>GO</abbr>-1 project was largely supported by a company called <i>Polexis</i>.
-Its acquisition by <i>Sys Technology</i>, and the change in priorities under the new owners,
-brought a halt to the <abbr>GO</abbr>-1 project, which in turn slowed development on GeoAPI.
-In order to resume development, a new working group entitled “GeoAPI 3.0” was created at the <abbr>OGC</abbr>.
-This group took a narrower focus compared to GeoAPI 2.0, concentrating on the most stable interfaces, and putting the others
-— such as geometries — in a module entitled “<a href="http://www.geoapi.org/geoapi-pending/index.html">pending</a>”, for future consideration.
-<a href="http://www.geoapi.org/3.0/index.html">GeoAPI 3.0</a> became an <a href="https://www.ogc.org/standards/geoapi"><abbr>OGC</abbr> standard</a> in 2011.
-This version was the first to be deployed in the <a href="http://search.maven.org/#search|ga|1|geoapi">Maven central repository</a>.
-</p>
-</article>
-</details>
-
-<p id="GeoAPI-core">
-GeoAPI is composed of many modules.
-The <code class="GeoAPI">geoapi</code> and <code class="GeoAPI">geoapi-pending</code> modules
-provide interfaces derived from <abbr title="Unified Modeling Language">UML</abbr> schemas of international standards.
-The conceptual model will be explained in detail in the chapters describing Apache <abbr title="Spatial Information System">SIS</abbr> implementation.
-However, we can get an overview of its content by consulting the page listing the mapping between
-<a href="http://www.geoapi.org/3.0/javadoc/content.html">GeoAPI methods and the standards where they come from</a>.
-Those modules and the mapping between GeoAPI and international standards are described in more details <a href="#SpecificationToInterfaces">in annex</a>.
-</p>
-
-
-
-<h3 id="GeoAPI-implementation"><span class="section-number">1.2.1.</span> Implementations provided by Apache SIS</h3>
-<p>
-Apache SIS implements most GeoAPI interfaces by a class of the same name than the interface
-but prefixed by “<code>Abstract</code>”, “<code>Default</code>” or “<code>General</code>”.
-Apache SIS classes prefixed by “<code>Default</code>” can be instantiated directly by a
-<code>new DefaultXXX(…)</code> statement or by a call to the <code>createXXX(…)</code> method in a factory.
-</p>
-<div class="example"><b>Example:</b> to represent a projected coordinate reference system (Mercator, Lambert, <i>etc</i>):
-<ul>
-<li><code class="GeoAPI">org.opengis.referencing.crs.ProjectedCRS</code> is the GeoAPI interface derived from ISO 19111 standard, and</li>
-<li><code class="SIS">org.apache.sis.referencing.crs.DefaultProjectedCRS</code> is the implementation provided by Apache SIS.</li>
-</ul>
-An instance can be created by:
-<ul>
-<li><code>ProjectedCRS crs = new DefaultProjectedCRS(…)</code>, ou</li>
-<li><code>ProjectedCRS crs = CRSFactory.createProjectedCRS(…)</code>.</li>
-</ul>
-Both approaches expect the same arguments (omitted in this example for brevity).
-</div>
-<p>
-In the default Apache SIS configuration, using <code>FooFactory.createXXX(…)</code> or <code>new DefaultXXX(…)</code>
-is almost the same except that <code>FooFactory</code> may return existing instances instead than creating new instances,
-and that exceptions thrown in case of invalid arguments are different types.
-In more advanced configurations, using <code class="GeoAPI">Factory</code> reduces the
-<a href="#ServiceLoader">direct dependencies toward Apache SIS</a>
-and allows inversion of control.
-</p><p>
-The “<code>General</code>” prefix is sometime used instead than “<code>Default</code>”
-to indicate that alternative implementations are available for some specific cases.
-For example the <code class="GeoAPI">Envelope</code> interface is implemented by at least two Apache SIS classes:
-<code class="SIS">GeneralEnvelope</code> and <code class="SIS">Envelope2D</code>.
-The first implementation can represent envelopes with any number of dimensions
-while the second implementation is specialized for two-dimensional envelopes.
-</p><p>
-Apache SIS classes prefixed by “<code>Abstract</code>” should not – in principle – be instantiated.
-Users should instantiate a non-abstract subclass instead.
-But many SIS classes are only conceptually abstract, without <code>abstract</code> Java keyword in class definition.
-Such classes can be instantiated by a <code>new AbstractXXX(…)</code> statement
-– but not by <code class="GeoAPI">Factory</code> – despite being conceptually abstract.
-However such instantiations should be done only in last resort, when it is not possible to determine the exact subtype.
-</p>
-</section>
-
-
-<section>
-<header>
-<h2 id="AboutBook"><span class="section-number">1.3.</span> Conventions used in this guide</h2>
-</header>
-<p>
-The elements defined in a computer language, such as classes and methods in Java or elements in an <abbr>XML</abbr> document,
-appear in monospaced font.
-In order to facilitate an understanding of the relationships between Apache <abbr title="Spatial Information System">SIS</abbr> and the standards,
-these elements are also represented using the following colour codes:
-</p>
-<ul>
-<li>
-Elements in blue are defined in an <abbr title="Open Geospatial Consortium">OGC</abbr> standard
-or an <abbr title="International Organization for Standardization">ISO</abbr> standard.
-Example: <code class="OGC">CD_Ellipsoid</code>.
-</li>
-<li>
-Elements in green are defined in GeoAPI.
-Example: <code class="GeoAPI">Ellipsoid</code>.
-</li>
-<li>
-Elements in brown are defined in Apache <abbr title="Spatial Information System">SIS</abbr>.
-Example: <code class="SIS">DefaultEllipsoid</code>.
-</li>
-<li>
-Elements left in black are either defined elsewhere (example: <code>String</code>),
-or there is simply no emphasis on that element for the discussion.
-</li>
-</ul>
-<p>
-Text in gray boxes are for information purpose only and can be ignored.
-</p>
-
-
-
-<h3 id="ChosenTerms"><span class="section-number">1.3.1.</span> Chosen terms</h3>
-<p>
-Standards sometimes favour the application of certain generic terms to particular contexts,
-which may differ from the context in which other communities use these terms.
-For example, the terms <i>domain</i> and <i>range</i> may apply to arbitrary functions in order to designate
-a set of possible values of inputs and outputs respectively.
-But the functions to which they are applied by certain <abbr title="International Organization for Standardization">ISO</abbr> standards are not the same as the functions to which they are applied by other libraries.
-For example, <abbr>ISO</abbr> 19123 applies these terms to <code class="OGC">CV_Coverage</code> objects,
-seen as functions in which the <i>domain</i> is the set of spatio-temporal coordinates encompassed by the data,
-and the <i>range</i> is the set of values encompassed.
-But <abbr title="University Corporation for Atmospheric Research">UCAR</abbr>’s <abbr title="Network Common Data Form">netCDF</abbr> library
-applies these terms instead to the function of converting pixel indices (its <i>domain</i>) to spatial-temporal coordinates (its <i>range</i>).
-Thus the <abbr>UCAR</abbr> library’s <i>range</i> may be the <i>domain</i> of <abbr>ISO</abbr> 19123.
-</p><p>
-The Apache <abbr title="Spatial Information System">SIS</abbr> library prefers as much as possible to use terms in the sense of <abbr title="Open Geospatial Consortium">OGC</abbr> and <abbr>ISO</abbr> norms.
-Particular care must be taken, however, with the interfaces between <abbr>SIS</abbr> and certain other external libraries,
-in order to reduce the risk of confusion.
-</p>
-</section>
-</section>
-
-
-<section>
-<header>
-<h1 id="DataAccess"><span class="section-number">2.</span> Geospatial data access</h1>
-<nav><div class="chapter-links"><div class="previous-chapter">⬅ <a href="#Standards">Previous chapter</a></div><div class="next-chapter"><a href="#Coverage">Next chapter</a> ➡</div></div></nav>
-</header>
-<nav><p>In this chapter:</p><ul class="toc">
-<li><a href="#GetMetadataElement">Navigating in metadata elements</a></li></ul></nav>
-<p>
It is possible to instantiate data structures programmatically in memory.
But more often, data are read from files or other kinds of data stores.
There is different ways to access those data, but an easy way is to use
@@ -547,10 +297,9 @@ a connection to a data base (<code>DataSource</code>, <code>Connection</code>)
or other kinds of object specific to the data source.
The <code class="SIS">DataStores.open(Object)</code> method detects data formats
and returns a <code class="SIS">DataStore</code> instance for that format.
-</p>
-<p>
+</p><p>
<code class="SIS">DataStore</code> functionalities depend on the kind of data (coverage, feature set, time series, <i>etc.</i>).
-But in any cases, there is always some metadata that can be obtained.
+But in all cases, there is always some metadata that can be obtained.
Metadata allows to identify the phenomenon or features described by the data
(temperature, land occupation, <i>etc.</i>),
the geographic area or temporal period covered by the data, together with their resolution.
@@ -559,33 +308,28 @@ contact information for the responsible person or organization,
legal or technical constraints on data usage,
the history of processing apply on the data,
expected updates schedule, <i>etc.</i>
-</p>
-<p>
+</p><p>
Various data formats have their own metadata model, but Apache <abbr title="Spatial Information System">SIS</abbr> translates all of them
in a unique metadata model in order to hide this heterogeneity.
-This approach — to select a single metadata model as the <em>pivot model</em> — is often used by other libraries.
-For example Apache Tika uses <cite>Dublin Core</cite> as the pivot metadata model,
-while Java Image I/O defines its own standard metadata model in its <code>javax.imageio.metadata</code> package.
-For Apache <abbr>SIS</abbr>, the chosen pivot model is the <abbr title="International Organization for Standardization">ISO</abbr> <cite>19115-1:2014 — Fundamentals</cite>
-international standard, completed by <abbr>ISO</abbr> 19115-2 — <cite>Extensions for imagery and gridded data</cite>.
+This <em>pivot model</em> approach is often used by various libraries,
+with <cite>Dublin Core</cite> as a popular choice.
+For Apache <abbr>SIS</abbr>, the chosen pivot model is the <abbr title="International Organization for Standardization">ISO</abbr> <cite>19115</cite> international standard.
This model organizes metadata in a tree structure where each information is accessible by a well-defined path,
regardless the origin of that information.
For example if a data format can provides a geographic bounding box encompassing all data,
then that information will always be accessible (regardless the data format) from the root <code class="GeoAPI">Metadata</code> object
-under the <code class="OGC">identificationInfo</code> node, <code class="OGC">extent</code> sub-node,
-<code class="OGC">geographicElement</code> sub-node.
+under the <code class="OGC">identificationInfo</code> node, <code class="OGC">extent</code> sub-node,
+<code class="OGC">geographicElement</code> sub-node.
</p>
<div class="example"><p><b>Example:</b>
following code read a metadata file from a Landsat-8 image and prints the declared geographic bounding box:
</p>
-<pre><code><b>try</b> (<code class="SIS">DataStore</code> ds = <code class="SIS">DataStores</code>.open(<b>new</b> File(<i>"LC81230522014071LGN00_MTL.txt"</i>))) {
- <code class="GeoAPI">Metadata</code> md = ds.<code class="SIS">getMetadata()</code>;
+<pre><code><b>try</b> (<code class="SIS">DataStore</code> store = <code class="SIS">DataStores</code>.open(<b>new</b> File(<i>"LC81230522014071LGN00_MTL.txt"</i>))) {
+ <code class="GeoAPI">Metadata</code> overview = store.<code class="SIS">getMetadata()</code>;
- <code class="comment">// In order to make this example simpler, null values and empty collection checks are omited.</code>
- <code class="GeoAPI">Identification</code> idInfo = md .<code class="GeoAPI">getIdentificationInfo()</code>.iterator().next();
- <code class="GeoAPI">Extent</code> extent = idInfo.<code class="GeoAPI">getExtents()</code> .iterator().next();
- <code class="GeoAPI">GeographicExtent</code> bbox = extent.<code class="GeoAPI">getGeographicElements()</code>.iterator().next();
+ <code class="comment">// Convenience method for fetching the geographic bounding box at the right location in metadata tree.</code>
+ <code class="GeoAPI">GeographicBoundingBox</code> bbox = <code class="SIS"><code class="SIS">Extents</code>.getGeographicBoundingBox</code>(overview);
System.out.println(<i>"The geographic bounding box is:"</i>);
System.out.println(bbox);
@@ -601,12 +345,6 @@ Geographic Bounding Box
├─East bound longitude…………………………… 110°26′39.66″E
├─South bound latitude…………………………… 10°29′59.604″N
└─North bound latitude…………………………… 12°37′25.716″N</samp></pre>
-
-<p>
-The Java code in this example extracts metadata elements by Java method invocations like <code class="GeoAPI">getExtents()</code>,
-but the next chapters will introduce another way using paths given as character strings.
-That later approach is more convenient when the methods to invoke are not known at compile-time.
-</p>
</div>
<p>
@@ -617,9 +355,9 @@ Most of the nodes accept an arbitrary amount of values.
For example the <code class="OGC">extent</code> node may contain many geographic areas.
</p>
-<table style="line-height:1">
+<table class="monospacedHeaderColumn" style="font-size:0.82vw">
<caption>Extract of a few metadata elements from ISO 19115</caption>
-<tr><th>Élément</th> <th>Description</th></tr>
+<tr><th>Element</th> <th>Description</th></tr>
<tr><td style="padding-top:9px">Metadata</td> <td style="padding-top:9px">Metadata about a dataset, service or other resources.</td></tr>
<tr><td> ├─Reference system info</td> <td>Description of the spatial and temporal reference systems used in the dataset.</td></tr>
<tr><td> ├─Identification info</td> <td>Basic information about the resource(s) to which the metadata applies.</td></tr>
@@ -656,65 +394,9 @@ For example the <code class="OGC">extent</code> node may contain many geographic
<tr><td> ├─Source</td> <td>Information about the source data used in creating the data specified by the scope.</td></tr>
<tr><td> └─Process step</td> <td>Information about events in the life of a resource specified by the scope.</td></tr>
</table>
-
-
-
-<section>
-<header>
-<h2 id="GetMetadataElement"><span class="section-number">2.1.</span> Navigating in metadata elements</h2>
-</header>
-<p>
-Methods like <code class="GeoAPI">getExtents()</code> are efficient when looking for a particular element known at compile-time.
-But those elements may be deep in the tree structure and may require traversal of many optional elements and collection members,
-which is sometime tedious. For a few frequently-used elements, some convenience methods are provided.
-Those conveniences are generally defined as static methods in classes having a name in plural form.
-For example the <code class="SIS">Extents</code> class defines static methods for fetching more easily some information from <code class="GeoAPI">Extent</code> metadata elements.
-For example the following method navigates through different branches where North, South, East and West data bounds may be found:
-</p>
-<pre><code><code class="GeoAPI">GeographicBoundingBox</code> bbox = <code class="SIS">Extents</code>.getGeographicBoundingBox(extent);</code></pre>
-<p>
-Those conveniences are defined as static methods in order to allow their use with different metadata implementations.
-Even in Apache <abbr title="Spatial Information System">SIS</abbr> library, the <code class="SIS">DefaultExtent</code> class is not the only implementation of <code class="GeoAPI">Extent</code> interface.
-There is also implementations fetching information on-demand in a database, or implementations for particular data formats.
-Some other classes providing static methods for specific interfaces are
-<code class="SIS">Citations</code>, <code class="SIS">Envelopes</code>, <code class="SIS">Matrices</code> and <code class="SIS">MathTransforms</code>.
-</p><p>
-Those static methods explore fragments of metadata tree in search for requested information,
-but the searches are still targeted to elements whose types and at least part of their paths are known at compile-time.
-Sometime the element to search is known only at runtime, or sometime there is a need to iterate over all elements.
-In such cases, one can view the metadata as a <code>java.util.Map</code> like below:
-</p>
-
-<pre><code>Map<String,Object> elements = <code class="SIS">MetadataStandard</code>.ISO_19115.<code class="SIS">asValueMap</code>(
- metadata, <code class="comment">// Any instance from the org.opengis.metadata package or a sub-package.</code>
- <b>null</b>, <code class="comment">// Used for resolving ambiguities. We can ignore for this example.</code>
- <code class="SIS">KeyNamePolicy</code>.<code class="SIS">JAVABEANS_PROPERTY</code>, <code class="comment">// Keys in the map will be getter method names without "get" prefix.</code>
- <code class="SIS">ValueExistencePolicy</code>.<code class="SIS">NON_EMPTY</code>); <code class="comment">// Entries with null or empty values will be omitted.</code>
-<code class="comment">/*
- * Print the names of all root metadata elements having a value.
- * This loop does not iterate recursively in children.
- */</code>
-<b>for</b> (String name : elements.keySet()) {
- System.out.println(name);
-}</code></pre>
-
<p>
-The <code>Map</code> object returned by <code class="SIS">asValueMap(…)</code> is live:
-any change in the <code>metadata</code> instance will be immediately reflected in the view.
-Actually, each <code>map.get("foo")</code> call is forwarded to the corresponding <code>metadata.getFoo()</code> method.
-Conversely, any <code>map.put("foo", …)</code> or <code>map.remove("foo")</code> operation applied on the view
-will be forwarded to the corresponding <code>metadata.setFoo(…)</code> method, if that method exists.
-The view is lenient regarding keys given in arguments to <code>Map</code> methods:
-keys may be property names (<code>"foo"</code>), method names (<code>"getFoo"</code>),
-or names used in <abbr title="International Organization for Standardization">ISO</abbr> 19115 standard <abbr title="Unified Modeling Language">UML</abbr> diagrams
-(similar to property names but not always identical).
-Differences in upper cases and lower cases are ignored when this tolerance does not introduce ambiguities.
-For more information on metadata views, see
-<a href="../../apidocs/org/apache/sis/metadata/package-summary.html#package.description"><code class="SIS">org.apache.sis.metadata</code></a>
-package javadoc.
-</p><p>
Among metadata elements introduced in this chapter, there is one which will be the topic of
-a <a href="#Referencing">dedicated chapter</a>: <code class="OGC">referenceSystemInfo</code>.
+a <a href="#Referencing">dedicated chapter</a>: <code class="OGC">referenceSystemInfo</code>.
Its content is essential for accurate data positioning;
without this element, even positions given by latitudes and longitudes are ambiguous.
Reference systems have many characteristics that make them apart from other metadata:
@@ -728,192 +410,495 @@ performing coordinate transformation from one reference system to an other.
<section>
<header>
-<h1 id="Coverage"><span class="section-number">3.</span> Data coverages</h1>
-<nav><div class="chapter-links"><div class="previous-chapter">⬅ <a href="#DataAccess">Previous chapter</a></div><div class="next-chapter"><a href="#Geometry">Next chapter</a> ➡</div></div></nav>
+<h1 id="Coverage"><span class="section-number">2.</span> Data as coverage</h1>
</header>
-<nav><p>In this chapter:</p><ul class="toc"/></nav>
-<p>
-Images, or <i>rasters</i>, are a particular case of a data structure called a <i>coverage</i>.
-We could think of this as a “coverage of data.”
-The title of the <abbr title="International Organization for Standardization">ISO</abbr> 19123 standard that describes them, “Coverage Geometry and Functions”,
-nicely summarizes the two essential elements of coverages:
-</p>
-<ul>
-<li>
<p>
-A coverage is a function which returns an attribute value from an entered coordinate.
-The set of values that may be entered is called the domain, while the set of values that may be returned is called the range.
+Images, or <dfn>rasters</dfn>, are a particular case of a data structure called a <dfn>coverage</dfn>.
+A coverage is a function which returns attribute values from an input coordinate.
+The set of valid input values is called the <dfn>domain</dfn>, while the set of possible output values is called the <dfn>range</dfn>.
The domain is often the spatio-temporal area covered by the data,
-but nothing in <abbr title="Spatial Information System">SIS</abbr> prevents coverages from extending to other dimensions.
+but <abbr title="Spatial Information System">SIS</abbr> does not prevents coverages from extending to other dimensions.
For example, thermodynamic studies often use an area where the dimensions are temperature and pressure.
</p>
<div class="example"><p><b>Example:</b>
-The pixel values of an image may contain measures for terrain elevation.
-If the function <var>h</var> = <var>f</var>(φ,λ) allows us to obtain (eventually, with the help of interpolations)
-the elevation <var>h</var> according the the geographic coordinate (φ,λ),
-then the geographic envelope of the image defined by the domain — the function <var>f</var> — is the <i>coverage</i>,
-and the set of values <var>h</var> that this function can return is the <i>range</i>.
+Digital Elevation Models (<abbr>DEM</abbr>) are often represented as images where pixel values are terrain elevation values.
+This image can be used as the basis of an <var>h</var> = <var>f</var>(φ,λ) function providing
+(eventually by interpolations between pixels) the elevation <var>h</var> at the geographic coordinate (φ,λ).
+In that case, the <var>f</var> function is the <dfn>coverage</dfn>,
+the geographic envelope of the image is the <dfn>domain</dfn>,
+and the set of pixel values <var>h</var> that this function can return is the <dfn>range</dfn>.
</p></div>
-</li>
-<li>
<p>
-Different types of coverages may be characterized by the geometry of their cells.
+Ranges may be finite or infinite, and are not necessarily numerical.
+For example, the values returned by a coverage may come from an enumeration (“this is a forest”, “this is a lake”, <i>etc.</i>).
+However in the enumeration case, interpolations are not allowed.
+A coverage without interpolation is called a <dfn>discrete coverage</dfn>
+while a coverage that allows interpolations is called a <dfn>continuous coverage</dfn>.
+</p><p>
+Different types of coverages may also be characterized by the geometry of their cells.
In particular, a coverage is not necessarily composed of quadrilateral cells.
However, given that quadrilateral cells are by far the most frequent (since this is the usual geometry of image pixels),
-we often use the term “grid coverage” to specify coverages composed of such cells.
-In <abbr>SIS</abbr>, the geometry of coverages is described by the <code class="SIS">GridGeometry</code> class.
-</p>
-</li>
-</ul>
-<p>
-The characteristics of the spatial domain are defined by <abbr>ISO</abbr> 19123 standard,
-while the characteristics of range are not included in the standard.
-The standard simply mentions that ranges may be finite or infinite,
-and are not necessarily numerical.
-For example, the values returned by a coverage may come from an enumeration (“this is a forest,” “this is a lake,” etc.).
-However, the standard defines two important types of coverage which have an impact on the types of authorized ranges:
-<i>discrete</i> coverages and <i>continuous</i> coverages.
-Stated simply, continuous coverages are functions that can use interpolation methods.
-Thus, since interpolations are only possible with numeric values, the ranges of non-numeric values may only be used with coverages of the
-<code class="OGC">CV_DiscreteCoverage</code> type.
+we use the <dfn>grid coverage</dfn> term to specify coverages composed of such cells.
</p>
-<aside>
-<h2>SIS’s <code class="SIS">Range</code> class and its relationship to the standards</h2>
-<p>
-The distinction between the ranges of all types of values and the ranges of numeric values is represented in
-<abbr title="Spatial Information System">SIS</abbr> by the <code class="SIS">Range</code> and <code class="SIS">NumberRange</code>
-classes respectively.
-The <code class="SIS">NumberRange</code> is used more often, and is also the one that most closely approaches the
-<a href="http://en.wikipedia.org/wiki/Interval_%28mathematics%29">the common mathematical concept of an interval</a>.
-This textual representation approaches the specifications of <abbr title="International Organization for Standardization">ISO</abbr> 31-11 standard,
-except that the comma is replaced by the character “…” as the separator of minimal and maximal values.
-For example, “[0 … 256)” represents the range of values from 0 inclusive to 256 exclusive.
-</p>
-<p>
-<code class="SIS">Range</code> objects are only indirectly associated with coverages.
-In <abbr>SIS</abbr>, the values that can return coverages are described by objects of the
-<code class="SIS">SampleDimension</code> type. It is these that contain instances of <code class="SIS">Range</code>,
-as well as other information such as <i>transfer function</i> (described later).
-</p>
-</aside>
-<div class="warning">
-This section is incomplete. See Javadoc for more details.
-</div>
-</section>
-
-<section>
-<header>
-<h1 id="Geometry"><span class="section-number">4.</span> Geometries</h1>
-<nav><div class="chapter-links"><div class="previous-chapter">⬅ <a href="#Coverage">Previous chapter</a></div><div class="next-chapter"><a href="#Referencing">Next chapter</a> ➡</div></div></nav>
-</header>
-<nav><p>In this chapter:</p><ul class="toc">
-<li><a href="#GeometryBase">Base classes</a><ul>
-<li><a href="#DirectPosition">Direct points and positions</a></li>
-<li><a href="#Envelope">Envelopes</a><ul>
-<li><a href="#AntiMeridian">Envelopes that cross the antimeridian</a></li></ul></li></ul></li></ul></nav>
-<p>
-This chapter introduces a few aspects of <abbr title="International Organization for Standardization">ISO</abbr> 19107 standard (<i>Spatial schema</i>)
-and the Apache <abbr title="Spatial Information System">SIS</abbr> classes that implement them.
-</p>
<section>
<header>
-<h2 id="GeometryBase"><span class="section-number">4.1.</span> Base classes</h2>
+<h2 id="GridGeometry"><span class="section-number">2.1.</span> Grid coverage domain</h2>
</header>
<p>
-Each geometric object is considered an infinite set of points.
-As a set, their most fundamental operations are of the same nature as the standard operations of Java collections.
-We may therefore see a geometry as a kind of <code>java.util.Set</code> in which the elements are points,
-except that the number of elements contained in the set is infinite (with the exception of geometries representing a simple point).
-To better represent this concept, the <abbr title="International Organization for Standardization">ISO</abbr> standard and GeoAPI define a <code class="OGC">TransfiniteSet</code> interface
-which we could see as a <code>Set</code> of infinite size.
-Although a parent relationship exists conceptually between these interfaces,
-GeoAPI does not define <code class="GeoAPI">TransfiniteSet</code> as a sub-interface of <code>java.util.Set</code>,
-as the definition of certain methods such as <code>size()</code> and <code>iterator()</code> would be problematic.
-However, we find very similar methods such as <code class="GeoAPI">contains(…)</code> and <code class="GeoAPI">intersects(…)</code>.
+The domain of a coverage is the set of valid input values.
+In Apache <abbr title="Spatial Information System">SIS</abbr>, the domain of grid coverages is described by the <code class="SIS">GridGeometry</code> class.
+This class contains the following information:
</p>
+<ul>
+<li>A grid extent (a.k.a. <dfn>grid envelope</dfn>), often inferred from the image size in pixels.</li>
+<li>A <dfn>grid to <abbr>CRS</abbr></dfn> conversion, typically as a scale followed by a translation.</li>
+<li>A georeferenced envelope, which can be inferred from the grid extent and the <dfn>grid to <abbr>CRS</abbr></dfn> conversion.</li>
+<li>A Coordinate Reference System (<abbr>CRS</abbr>) which is the target of the <dfn>grid to CRS</dfn> conversion.</li>
+<li>An <em>estimation</em> of grid resolution along each <abbr>CRS</abbr> axes.</li>
+<li>An indication of whether conversion for some axes is linear or not.</li>
+</ul>
<p>
-All geometries are specializations of <code class="GeoAPI">TransfiniteSet</code>.
-The parent class of those geometries is called <code class="OGC">GM_Object</code> in <abbr>ISO</abbr> 19107 standard.
-GeoAPI interfaces use the <code class="GeoAPI">Geometry</code> name instead, as the omission of the <code class="OGC">GM_</code>
-prefix (as prescribed in GeoAPI convention) would leave a name too similar to Java’s <code>Object</code> class.
+One of the most important property listed above is the <dfn>grid to <abbr>CRS</abbr></dfn> conversion,
+which defines how to map pixel coordinates to "real world" coordinates such as latitudes and longitudes.
+This relationship is often linear (an affine transform), but not necessarily;
+<code class="SIS">GridGeometry</code> accepts non-linear conversions as well.
</p>
-<h3 id="DirectPosition"><span class="section-number">4.1.1.</span> Direct points and positions</h3>
-<p>
-<abbr title="International Organization for Standardization">ISO</abbr> 19107 defines two types of structures to represent a point:
-<code class="OGC">GM_Point</code> and <code class="OGC">DirectPosition</code>.
-The first type is a true geometry and may therefore be relatively cumbersome, depending on the implementation.
-The second type is not formally considered to be a geometry;
-it extends neither <code class="OGC">GM_Object</code> nor <code class="OGC">TransfiniteSet</code>.
-It barely defines any operations besides the storing of a sequence of numbers representing a coordinate.
-It may therefore be a more lightweight object.
-</p>
-<p>
-In order to allow the <abbr title="Application Programming Interface">API</abbr> to work equally with these two types of positions,
-<abbr>ISO</abbr> 19107 defines <code class="OGC">Position</code> as a <cite>union</cite> of
-<code class="OGC">DirectPosition</code> and <code class="OGC">GM_Point</code>.
-It is a union in the sense of C/C++. For the Java language, GeoAPI obtains the same effect by defining
-<code class="GeoAPI">Position</code> as the parent interface of <code class="GeoAPI">DirectPosition</code> and <code class="GeoAPI">Point</code>.
-In practice, the great majority of Apache <abbr title="Spatial Information System">SIS</abbr>’s <abbr>API</abbr> works on <code class="GeoAPI">DirectPosition</code>s,
-or occasionally on <code class="GeoAPI">Position</code>s when it seems useful to also allow geometric points.
-</p>
-
-
-<h3 id="Envelope"><span class="section-number">4.1.2.</span> Envelopes</h3>
-<p>
-Envelopes store minimal and maximal coordinate values of a geometry.
-Envelopes are <em>not</em> geometries themselves; they are not infinite sets of points (<code class="OGC">TransfiniteSet</code>).
-There is no guarantee that all the positions contained within the limits of an envelope are geographically valid.
-Envelopes must be seen as information about extreme values that might take the coordinates of a geometry as if
-each dimension were independent of the others, nothing more.
-Nevertheless, we speak of envelopes as rectangles, cubes or hyper-cubes (depending on the number of dimensions)
-in order to facilitate discussion, while bearing in mind their non-geometric nature.
-</p>
-<div class="example"><p><b>Example:</b>
-We could test whether a position is within the limits of an envelope.
-A positive result does not guarantee that the position is within the geometry delimited by the envelope,
-but a negative result guarantees that it is outside the envelope.
-We can perform intersection tests in the same way.
-On the other hand, it makes little sense to apply a rotation to an envelope,
-as the result may be very different from that which we would obtain be performing a rotation on the original geometry,
-and then recalculating its envelope.
-</p></div>
+<section>
+<header>
+<h3 id="AffineTransform"><span class="section-number">2.1.1.</span> Affine transform</h3>
+</header>
<p>
-An envelope might be represented by two positions corresponding to two opposite corners of a rectangle,
-cube or hyper-cube.
-For the first corner, we often take the one whose ordinates all have the maximal value (<code class="OGC">upperCorner</code>).
-When displayed using a conventional system of coordinates (with <var>y</var> axis values running upwards),
-these two positions appear respectively in the lower left corner and the upper right corner of a rectangle.
-Care must be taken with different coordinate systems, however, which may vary the positions of these corners on the screen.
-The expressions <i>lower corner</i> and <i>upper corner</i> should thus be understood in the mathematical rather than the visual sense.
+Among the many kinds of operations performed by <abbr>GIS</abbr> software products on spatial coordinates,
+<dfn>affine transforms</dfn> 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>
-
-
-
-<h4 id="AntiMeridian"><span class="section-number">4.1.2.1.</span> Envelopes that cross the antimeridian</h4>
+<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>
-Minimums and maximums are the values most often assigned to <code class="OGC">lowerCorner</code>
-and <code class="OGC">upperCorner</code>.
-But the situation becomes complicated when an envelope crosses the antimeridian (-180° or 180° longitude).
-For example, an envelope 10° in size may begin at 175° longitude and end at -175°.
-In this case, the longitude value assigned to <code class="OGC">lowerCorner</code> is greater than that assigned to <code class="OGC">upperCorner</code>.
-Apache <abbr title="Spatial Information System">SIS</abbr> therefore uses a slightly different definition of these two corners:
+Affine transforms can be concatenated efficiently.
+No matter how many affine transforms are chained, the result can be represented by a single affine transform.
+Affine transforms are extensively used by Apache <abbr title="Spatial Information System">SIS</abbr> for “grid to <abbr>CRS</abbr>” conversions.
+Given an image with pixel coordinates represented by (<var>x</var>,<var>y</var>) tuples and given the following assumptions:
</p>
<ul>
-<li><b><code class="SIS">lowerCorner</code>:</b>
-the starting point, if we move along the inside of the envelope in the direction of ascending values.
-</li>
-<li><b><code class="SIS">upperCorner</code>:</b>
-the end-point, if we move along the inside of the envelope in the direction of ascending values.
-</li>
+<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">
+<mrow>
+<mo>[</mo>
+<mtable>
+<mtr><mtd><mi>λ</mi></mtd></mtr>
+<mtr><mtd><mi>φ</mi></mtd></mtr>
+<mtr><mtd><mn>1</mn></mtd></mtr>
+</mtable>
+<mo>]</mo>
+</mrow>
+<mo>=</mo>
+<mrow>
+<mo>[</mo>
+<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>
+<mo>]</mo>
+</mrow>
+<mo>×</mo>
+<mrow>
+<mo>[</mo>
+<mtable>
+<mtr><mtd><mi>x</mi></mtd></mtr>
+<mtr><mtd><mi>y</mi></mtd></mtr>
+<mtr><mtd><mn>1</mn></mtd></mtr>
+</mtable>
+<mo>]</mo>
+</mrow>
+</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>
+<div style="display:table; margin:auto">
+<div style="display:table-row">
+<div class="caption" style="display:table-cell">Change 2</div>
+<div class="caption" style="display:table-cell"> </div>
+<div class="caption" style="display:table-cell">Change 1</div>
+<div class="caption" style="display:table-cell"> </div>
+<div class="caption" style="display:table-cell">Initial conversion</div>
+<div class="caption" style="display:table-cell"> </div>
+<div class="caption" style="display:table-cell">Concatenated operation</div>
+</div>
+<div style="display:table-row">
+<div style="display:table-cell; vertical-align:middle">
+<math xmlns="http://www.w3.org/1998/Math/MathML" alttext="MathML capable browser required" display="block">
+<mrow>
+<mo>[</mo>
+<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>
+<mo>]</mo>
+</mrow>
+</math>
+</div>
+<div style="display:table-cell; vertical-align:middle; padding-left: 15px; padding-right: 15px">×</div>
+<div style="display:table-cell; vertical-align:middle">
+<math xmlns="http://www.w3.org/1998/Math/MathML" display="block">
+<mrow>
+<mo>[</mo>
+<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>
+<mo>]</mo>
+</mrow>
+</math>
+</div>
+<div style="display:table-cell; vertical-align:middle; padding-left: 15px; padding-right: 15px">×</div>
+<div style="display:table-cell; vertical-align:middle">
+<math xmlns="http://www.w3.org/1998/Math/MathML" display="block">
+<mrow>
+<mo>[</mo>
+<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>
+<mo>]</mo>
+</mrow>
+</math>
+</div>
+<div style="display:table-cell; vertical-align:middle; padding-left: 15px; padding-right: 15px">=</div>
+<div style="display:table-cell; vertical-align:middle">
+<math xmlns="http://www.w3.org/1998/Math/MathML" display="block">
+<mrow>
+<mo>[</mo>
+<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>
+<mo>]</mo>
+</mrow>
+</math>
+</div>
+</div>
+</div>
+<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 class="warning">
+This section is incomplete. See Javadoc for more details.
+</div>
+</section>
+</section>
+
+
+<section>
+<header>
+<h2 id="SampleDimension"><span class="section-number">2.2.</span> Sample dimensions</h2>
+</header>
+<p>
+The range of a coverage is the set of valid output values.
+In Apache <abbr title="Spatial Information System">SIS</abbr>, the distinction between ranges of numerical values and range of any types of values is represented by
+<code class="SIS">NumberRange</code> and <code class="SIS">Range</code> classes respectively.
+The <code class="SIS">NumberRange</code> is used more often, and is also the one that most closely approaches the
+<a href="http://en.wikipedia.org/wiki/Interval_%28mathematics%29">the common mathematical concept of an interval</a>.
+This textual representation approaches the specifications of <abbr title="International Organization for Standardization">ISO</abbr> 31-11 standard,
+except that the comma is replaced by the character “…” as the separator of minimal and maximal values.
+For example, “[0 … 256)” represents the range of values from 0 inclusive to 256 exclusive.
+</p><p>
+<code class="SIS">Range</code> objects are only indirectly associated with coverages.
+In <abbr>SIS</abbr>, the values that can return coverages are described by objects of the
+<code class="GeoAPI">SampleDimension</code> type.
+It is these that contain instances of <code class="SIS">Range</code>,
+as well as other information such as <i>transfer function</i> (described later).
+</p>
+<div class="warning">
+This section is incomplete. See Javadoc for more details.
+</div>
+
+<p>
+The <code class="SIS">SampleDimension.Builder</code> provides convenience methods for building the sample dimensions of a coverage.
+The usage pattern is to invoke the following methods:
+</p>
+<ul>
+<li><code>setName(…)</code> for giving a name to a band.</li>
+<li><code>addQuantitative(…)</code> for declaring a range of sample values to convert to units of measurement.</li>
+<li><code>addQualitative(…)</code> for declaring "no data" values.</li>
+<li><code>setBackground(…)</code> for declaring a "no data" value which can also be used for filling empty space.</li>
+</ul>
+</section>
+</section>
+
+
+<section>
+<header>
+<h1 id="Geometry"><span class="section-number">3.</span> Geometries</h1>
+</header>
+<p>
+Each geometric object is considered as an infinite set of points
+(except the <code class="GeoAPI">Point</code> object which contains only itself).
+To better represent this concept, the <code class="GeoAPI">TransfiniteSet</code> interface
+can be seen as a <code>Set</code> of potentially infinite size in which the elements are points.
+All geometries are specializations of <code class="GeoAPI">TransfiniteSet</code>.
+</p><p>
+There is two types of structures to represent a point: <code class="GeoAPI">Point</code> and <code class="GeoAPI">DirectPosition</code>.
+The first type is a true geometry and may therefore be relatively cumbersome, depending on the implementation.
+The second type is not formally considered to be a geometry;
+it extends neither <code class="GeoAPI">Geometry</code> nor <code class="GeoAPI">TransfiniteSet</code>.
+It barely defines any operations besides the storing of a sequence of numbers representing a coordinate.
+It may therefore be a more lightweight object.
+</p><p>
+In order to allow the <abbr>API</abbr> to work equally with these two types of positions,
+<code class="GeoAPI">Position</code> is defined as a common interface implemented by <code class="GeoAPI">DirectPosition</code> and <code class="GeoAPI">Point</code>.
+In practice, the great majority of Apache <abbr title="Spatial Information System">SIS</abbr>’s <abbr>API</abbr> works on <code class="GeoAPI">DirectPosition</code>s,
+and occasionally on <code class="GeoAPI">Position</code>s when it seems useful to also allow geometric points.
+</p>
+
+
+
+
+<section>
+<header>
+<h2 id="Envelope"><span class="section-number">3.1.</span> Envelopes</h2>
+</header>
+<p>
+Envelopes store minimal and maximal coordinate values of a geometry.
+Envelopes are <em>not</em> geometries themselves; they are not infinite sets of points (<code class="GeoAPI">TransfiniteSet</code>).
+There is no guarantee that all the positions contained within the limits of an envelope are geographically valid.
+Envelopes must be seen as information about extreme values that might take the coordinates of a geometry as if
+each dimension were independent of the others, nothing more.
+Nevertheless, we speak of envelopes as rectangles, cubes or hyper-cubes (depending on the number of dimensions)
+in order to facilitate discussion, while bearing in mind their non-geometric nature.
+</p>
+<div class="example"><p><b>Example:</b>
+We could test whether a position is within the limits of an envelope.
+A positive result does not guarantee that the position is within the geometry delimited by the envelope,
+but a negative result guarantees that it is outside the geometry.
+We can perform intersection tests in the same way.
+On the other hand, it makes little sense to apply a rotation to an envelope,
+as the result may be very different from that which we would obtain by performing a rotation on the original geometry,
+and then recalculating its envelope.
+</p></div>
+<p>
+An envelope might be represented by two positions corresponding to two opposite corners of a rectangle,
+cube or hyper-cube.
+For the first corner, we often take the one whose ordinates all have the maximal value (<code class="OGC">upperCorner</code>).
+When displayed using a conventional system of coordinates (with <var>y</var> axis values running upwards),
+these two positions appear respectively in the lower left corner and the upper right corner of a rectangle.
+Care must be taken with different coordinate systems, however, which may vary the positions of these corners on the screen.
+The expressions <i>lower corner</i> and <i>upper corner</i> should thus be understood in the mathematical rather than the visual sense.
+</p>
+
+
+
+<h3 id="AntiMeridian"><span class="section-number">3.1.1.</span> Crossing the antimeridian</h3>
+<p>
+Minimums and maximums are the values most often assigned to <code class="OGC">lowerCorner</code>
+and <code class="OGC">upperCorner</code>.
+But the situation becomes complicated when an envelope crosses the antimeridian (−180° or 180° longitude).
+For example, an envelope 10° in size may begin at 175° longitude and end at −175°.
+In this case, the longitude value assigned to <code class="OGC">lowerCorner</code> is greater than that assigned to <code class="OGC">upperCorner</code>.
+Apache <abbr title="Spatial Information System">SIS</abbr> therefore uses a slightly different definition of these two corners:
+</p>
+<ul>
+<li><b><code class="SIS">lowerCorner</code>:</b>
+the starting point, if we move along the inside of the envelope in the direction of ascending values.
+</li>
+<li><b><code class="SIS">upperCorner</code>:</b>
+the end-point, if we move along the inside of the envelope in the direction of ascending values.
+</li>
</ul>
<p>
If the envelope does not cross the antimeridian, these two definitions are equivalent to the selection of minimal and
@@ -928,18 +913,18 @@ This case is illustrated by the red rectangle in the figure below.
<img alt="Envelope example with and without anti-meridian spanning." src="../../apidocs/org/apache/sis/geometry/doc-files/AntiMeridian.png"/>
</p>
<p>
-The notions of inclusion and intersection, however, interpreted slightly differently in these two cases.
-In the usual case where we do not cross the antimeridian, the green rectangle covers a region of inclusion.
+The notions of inclusion and intersection, however, are interpreted slightly differently in these two cases.
+In the usual case where the envelope does not cross the antimeridian, the green rectangle covers a region of inclusion.
The regions excluded from this rectangle continue on to infinity in all directions.
In other words, the region of inclusion is not repeated every 360°.
But in the case of the red rectangle, the information provided by the envelope actually covers a region of exclusion
between the two edges of the rectangle. The region of inclusion extends to infinity to the left and right.
-We could stipulate that all longitudes below -180° or above 180° are considered excluded,
+We could stipulate that all longitudes below −180° or above 180° are considered excluded,
but this would be an arbitrary decision that would not be an exact counterpart to the usual case (green rectangle).
A developer may wish to use these values, for example, in a mosaic where the map of the world is repeated several times
horizontally and each repetition is considered distinct.
If developers wish to perform operations as though the regions of inclusion or exclusion were repeated every 360°,
-they themselves will have to bring the longitudinal values between -180° and 180° in advance.
+they themselves will have to bring the longitudinal values between −180° and 180° in advance.
All the <code class="SIS">add(…)</code>, <code class="SIS">contains(…)</code>,
<code class="SIS">intersect(…)</code>, etc. functions of all the envelopes defined in the
<code class="SIS">org.apache.sis.geometry</code> package perform their calculations according to this convention.
@@ -957,81 +942,94 @@ Thus, any axis associated with the code <code class="GeoAPI">RangeMeaning.WRAPAR
the same treatment as does longitude.
For example, this could be a time axis for climatological data (one “year” represents the average temperature in all the
months of January, followed by the average of all the months of February, etc.)
-This generalization also applies to longitude axes defined by a range of 0° to 360° rather than -180° to 180°.
+This generalization also applies to longitude axes defined by a range of 0° to 360° rather than −180° to 180°.
</p>
</aside>
<p>
In order for functions such as <code class="SIS">add(…)</code> to work correctly,
all objects involved must use the same coordinate reference system, including the same range of values.
-Thus an envelope that expresses longitudes in the range [-180 … +180]° is not compatible with an envelope that expresses
+Thus an envelope that expresses longitudes in the range [−180 … +180]° is not compatible with an envelope that expresses
longitudes in the range [0 … 360]°.
The conversions, if necessary, are up to the user
(the <code class="SIS">Envelopes</code> class provides convenience methods to do this).
Moreover, the envelope’s coordinates must be included within the system of coordinates,
-unless the developer explicitly decides to consider (for example) 300° longitude as a position distinct from -60°.
+unless the developer explicitly decides to consider (for example) 300° longitude as a position distinct from −60°.
The <code class="SIS">GeneralEnvelope</code> class provides a <code class="SIS">normalize()</code> method to bring
-coordinates within the desired limits, sometimes at the coast of <cite><i>lower</i></cite> values being higher than
-<cite><i>upper</i></cite> values.
+coordinates within the desired limits, sometimes at the cost of <var>lower</var> values being higher than
+<var>upper</var> values.
</p>
<aside>
-<h5>The special case of [+0 … -0] range</h5>
+<h5>The special case of [+0 … −0] range</h5>
<p>
-Java (or more generally, IEEE Standard 754) defines two values distinct from zero:
+Java (or more generally, IEEE Standard 754) defines two zero values:
a positive zero and a negative zero. These two values are considered equal when we compare them with the <code>==</code> operator in Java.
But in <abbr title="Spatial Information System">SIS</abbr> envelopes, they may actually return opposite results for axes using <code class="GeoAPI">RangeMeaning.WRAPAROUND</code>.
-An envelope whose range is [0 … 0], [-0 … -0] or [-0 … +0] would normally be considered an empty envelope,
-but the [+0 … -0] range would in fact be considered to include the entire set of values all around the world.
+An envelope whose range is [0 … 0], [−0 … −0] or [−0 … +0] would normally be considered an empty envelope,
+but the [+0 … −0] range would in fact be considered to include the entire set of values all around the world.
This behaviour conforms to the definition of <code class="SIS">lowerCorner</code> and <code class="SIS">upperCorner</code>,
-which considers +0 as the starting point, and -0 as the end-point after cycling through all possible values.
-Such behaviour only occurs for the pair of values +0 and -0, and only in that order.
+which considers +0 as the starting point, and −0 as the end-point after cycling through all possible values.
+Such behaviour only occurs for the pair of values +0 and −0, and only in that order.
For all other real values, if the condition <code>lower</code> <code>==</code> <code>upper</code> is true,
then it is guaranteed that the envelope is empty.
</p>
</aside>
+
+
+
+<h3 id="EnvelopeTransform"><span class="section-number">3.1.2.</span> Transforming to another reference system</h3>
+<p>
+Geographic information systems often need to transform an envelope
+from one Coordinate Reference System (<abbr>CRS</abbr>) to another.
+But a naive approach transforming the 4 corners is not sufficient.
+The figure below shows an envelope before a map projection and the geometric shape
+that we would get if all points (not only the corners) were projected.
+The resulting geometric shape is more complex than a rectangle because of the curvature caused by the map projection.
+Computing the envelope that contains the 4 corners of that shape is not enough,
+because the area in the bottom of the projected shape is lower than the two bottom corners.
+That surface would be outside the envelope.
+</p>
+<div class="row-of-boxes">
+<div>
+<div class="caption">Envelope before projection</div>
+<img alt="Envelope in a geographic CRS" src="../images/GeographicArea.png" style="border: solid 1px; margin-right: 15px"/>
+</div><div>
+<div class="caption">Geometric shape after projection</div>
+<img alt="Shape in a projected CRS" src="../images/ConicArea.png" style="border: solid 1px; margin-left: 15px"/>
+</div>
+</div>
+<p>
+Sampling a larger number of points reduces the problem but does not resolve it.
+<a href="#TransformDerivative">Map projection derivatives</a> offer a more efficient way to resolve this problem
+(see the <a href="#DerivativeAndEnvelope">annex</a> for more mathematical details).
+Another complication occurs if the envelope contains the North or South pole.
+For making a long story short, transforming an envelope is <em>a lot</em> more complicated than it looks like.
+Apache <abbr title="Spatial Information System">SIS</abbr> contains a few utility methods for making this task easier.
+For transforming an envelope to another <abbr>CRS</abbr> (<cite>WGS 84 / World Mercator</cite> in this example):
+</p>
+<pre><code><code class="GeoAPI">CoordinateReferenceSystem</code> targetCRS = CRS.forCode(<i>"EPSG:3395"</i>);
+<code class="GeoAPI">Envelope</code> transformed = <code class="SIS">Envelopes</code>.transform(envelope, targetCRS);</code></pre>
+<p>
+If envelopes are transformed in the goal of using a common <abbr>CRS</abbr> before to compute the union of many envelopes,
+an additional complication is that each envelope may use a <abbr>CRS</abbr> with a relatively small domain of validity.
+The union operation needs to find a <abbr>CRS</abbr> valid in a domain large enough for containing all envelopes.
+It may be a <abbr>CRS</abbr> different than all <abbr>CRS</abbr> used by the source envelopes.
+Apache <abbr>SIS</abbr> has an utility method for handling this additional complexity.
+This method accepts an arbitrary amount of envelopes that may be in different <abbr>CRS</abbr>:
+</p>
+<pre><code><code class="GeoAPI">Envelope</code> union = <code class="SIS">Envelopes</code>.union(envelope1, envelope2, envelope3);</code></pre>
</section>
</section>
<section>
<header>
-<h1 id="Referencing"><span class="section-number">5.</span> Spatial reference systems</h1>
-<nav><div class="chapter-links"><div class="previous-chapter">⬅ <a href="#Geometry">Previous chapter</a></div><div class="next-chapter"><a href="#Utilities">Next chapter</a> ➡</div></div></nav>
+<h1 id="Referencing"><span class="section-number">4.</span> Spatial reference systems</h1>
</header>
-<nav><p>In this chapter:</p><ul class="toc">
-<li><a href="#ComponentsOfCRS">Components of a reference system by coordinates</a><ul>
-<li><a href="#Ellipsoid">Geoid et ellipsoid</a></li>
-<li><a href="#GeodeticDatum">Geodetic datum</a></li>
-<li><a href="#CoordinateSystem">Coordinate systems</a><ul>
-<li><a href="#AxisOrder">Axis order</a></li></ul></li>
-<li><a href="#GeographicCRS">Geographic reference systems</a><ul>
-<li><a href="#GeographicWKT">Well-Known Text format</a></li></ul></li>
-<li><a href="#ProjectedCRS">Map projections</a><ul>
-<li><a href="#ProjectedWKT">Well-Known Text format</a></li></ul></li>
-<li><a href="#CompoundCRS">Vertical and temporal dimensions</a><ul>
-<li><a href="#CompoundWKT">Well-Known Text format</a></li></ul></li></ul></li>
-<li><a href="#GetCRS">Fetching a spatial reference system</a><ul>
-<li><a href="#CRSAuthorityFactory">Looking CRS defined by authorities</a></li>
-<li><a href="#CRSParsing">Reading definitions in GML or WKT format</a></li>
-<li><a href="#CRSFactory">Constructing programmatically</a></li>
-<li><a href="#CRS_UserCode">Adding new CRS definitions</a></li></ul></li>
-<li><a href="#CoordinateOperations">Coordinate operations</a><ul>
-<li><a href="#CRS.findOperation">Getting a coordinate operation</a></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>
-<li><a href="#GetDerivative">Getting the derivative at a point</a></li></ul></li>
-<li><a href="#CoordinateOperationSteps">Conceptual versus real chain of coordinate operations</a></li></ul></li>
-<li><a href="#Formats">Data storage formats</a></li>
-<li><a href="#XML-ISO">Representing objects in XML</a><ul>
-<li><a href="#XML-ISO-19115">Representing metadata according to ISO 19115-3</a><ul>
-<li><a href="#gco-id">Identification of already-defined instances</a></li>
-<li><a href="#nilReason">Representing missing values</a></li></ul></li></ul></li></ul></nav>
<p>
For locating a point on Earth one can use identifiers like city name or postal address
-— an approach known as <cite>spatial reference systems by identifiers</cite> —
+— an approach known as <dfn>spatial reference systems by identifiers</dfn> —
or use numerical values valid in a given coordinate system like latitudes and longitudes
-— an approach known as <cite>spatial reference systems by coordinates</cite>.
+— an approach known as <dfn>spatial reference systems by coordinates</dfn>.
Each reference system implies approximations like
the choice of a figure of the Earth (geoid, ellipsoid, <i>etc.</i>) used as an approximation of Earth shape,
the choice of geometric properties (angles, distances, <i>etc.</i>) to be preserved when a map is shown on plane surface, and
@@ -1045,7 +1043,7 @@ and the kind of calculations to be performed with the data.
Unless otherwise specified, Apache <abbr title="Spatial Information System">SIS</abbr> aims to represent coordinates on Earth with an accuracy of one centimetre or better.
But the accuracy can be altered by various situations:
</p>
-<ul>
+<ul class="verbose">
<li>Points should be inside the domain of validity as given by <code class="GeoAPI">ReferenceSystem.getDomainOfValidity()</code>.</li>
<li>Distance measurements in a given map projection are true only is some special locations,
named for instance “standards parallels”.</li>
@@ -1054,70 +1052,14 @@ The new accuracy is described by <code class="GeoAPI">CoordinateOperation.get
<li>Finding the most appropriate coordinate transformation parameters require the use of a geodetic dataset like <abbr>EPSG</abbr>.
Declaring those parameters within the <abbr>CRS</abbr> (for example with a <code class="OGC">TOWGS84</code> element) is often not sufficient.</li>
</ul>
-<article>
-<header>
-<h2>“Early binding” versus “late binding” implementations</h2>
-</header>
-<p>
-Because of the <abbr title="World Geodetic System 1984">WGS84</abbr> ubiquity, it is tempting to use that system as a hub or a pivot system
-for all coordinate transformations.
-The use of an “universal” system as a pivot simplifies the design of coordinate transformations libraries.
-For example transformations from datum <var>A</var> to datum <var>B</var> can be done by first transforming
-from <var>A</var> to <abbr>WGS84</abbr>, then from <abbr>WGS84</abbr> to <var>B</var>.
-With such approach, a coordinate transformations library would only need to associate each
-<code class="GeoAPI">GeodeticDatum</code> instance with the transformation parameters from that datum to <abbr>WGS84</abbr>.
-This approach was encouraged in version 1 of <abbr>WKT</abbr> format, since that format specified a
-<code class="OGC">TOWGS84[…]</code> element (removed in <abbr>WKT</abbr> version 2) precisely for that purpose.
-This approach is known in <abbr>EPSG</abbr> guidance notes as “early binding” implementations
-since information about coordinate transformations are associated early in geodetic object definitions,
-usually right at <code class="GeoAPI">GeographicCRS</code> creation time.
-While <abbr>EPSG</abbr> acknowledges that this approach is commonly used,
-this is not a recommended strategy for the following reasons:
-</p>
-<ul>
-<li>More than one transformation may exist from datum <var>A</var> to datum <var>B</var>,
-where each transformation is designed for a different geographic area.</li>
-<li>Some operations are designed specifically for transformations from <var>A</var> to <var>B</var>
-and do not have the same accuracy than an operation using <abbr>WGS84</abbr> as an intermediate step.</li>
-<li><abbr>WGS84</abbr> itself has been updated many times,
-which makes it a kind of moving target (admittedly slowly) for coordinate transformations libraries.</li>
-<li>Different systems could be used as the pivot system, for example the <cite>Galileo Reference Frame</cite>
-(<abbr>GTRF</abbr>) created for the European <abbr>GPS</abbr> competitor.</li>
-</ul>
-<div class="example"><p><b>Example:</b>
-the <abbr>EPSG</abbr> geodetic dataset defines about 50 transformations from <abbr>NAD27</abbr> to <abbr>NAD83</abbr>.
-In an early binding approach, the same geographic <abbr>CRS</abbr> (namely “<abbr>NAD27</abbr>”) in the <abbr>WKT</abbr> 1
-format would need to be defined with a <code>TOWGS84[-8, 160, 176]</code> element for coordinates in <abbr>USA</abbr>
-or with a <code>TOWGS84[-10, 158, 187]</code> element for coordinates in Canada.
-Different parameter values exist for other regions like Cuba, so it is not possible to represent such diversity
-with a single <code class="OGC">TOWGS84[…]</code> element associated to a <abbr>CRS</abbr>.
-But even when restricting <abbr>CRS</abbr> usage to the domain of validity of its single <code class="OGC">TOWGS84[…]</code> element,
-those transformations are still approximative with a 10 metres accuracy in the <abbr>USA</abbr> case.
-More accurate transformations exist in the form of <abbr>NADCON</abbr> grid shift files,
-but those transformations are from <abbr>NAD27</abbr> to <abbr>NAD83</abbr> (which move together on the same continental plate),
-not to <abbr>WGS84</abbr> (which move independently).
-The difference was often ignored when <abbr>NAD83</abbr> and <abbr>WGS84</abbr> were considered as practically equivalent,
-but that assumption is subject to more caution today.
-</p></div>
-<p>
-<abbr>EPSG</abbr> rather recommends the use of “late binding” approach,
-in which coordinate transformation methods and parameters are defined for
-“<var>A</var> to <var>B</var>” pairs of systems (eventually completed with domain of validity)
-rather than associated to standalone datums.
-Apache <abbr title="Spatial Information System">SIS</abbr> is a “late binding” implementation,
-while some reminiscences of “early binding” approach still exist in the form of the
-<code class="SIS">DefaultGeodeticDatum.getBursaWolfParameters()</code> property.
-The later is used only if <abbr>SIS</abbr> fails to apply the late binding approach for given reference systems.
-</p>
-</article>
<p>
The <code class="SIS">sis-referencing</code> module provides a set of classes implementing
different specializations of the <code class="GeoAPI">ReferenceSystem</code> interface, together with required components.
Those implementations store spatial reference system descriptions, together with metadata like their domain of validity.
However those objects do not perform any operation on coordinate values.
-Coordinates <cite>conversions</cite> or <cite>transformations</cite> are performed by another family of types,
+Coordinates <dfn>conversions</dfn> or <dfn>transformations</dfn> are performed by another family of types,
with <code class="GeoAPI">CoordinateOperation</code> as the root interface.
-Those types will be discussed in <a href="#CoordinateOperation">another section</a>.
+Those types will be discussed in <a href="#CoordinateOperations">another section</a>.
</p>
@@ -1125,9 +1067,10 @@ Those types will be discussed in <a href="#CoordinateOperation">another section<
+
<section>
<header>
-<h2 id="ComponentsOfCRS"><span class="section-number">5.1.</span> Components of a reference system by coordinates</h2>
+<h2 id="ComponentsOfCRS"><span class="section-number">4.1.</span> Coordinate reference systems</h2>
</header>
<p>
Spatial reference systems by coordinates provide necessary information for mapping numerical coordinate values
@@ -1149,7 +1092,105 @@ Those standards are completed by two other standards defining exchange formats:
and the <cite>Well-Known Text</cite> (<abbr>WKT</abbr>) — a text format easier to read by humans.
</p>
-<h3 id="Ellipsoid"><span class="section-number">5.1.1.</span> Geoid et ellipsoid</h3>
+<h3 id="ProjectedCRS"><span class="section-number">4.1.1.</span> Map projections</h3>
+<p>
+Map projections represent a curved surface (the Earth surface) on a plane surface (a map or a computer screen).
+Every rendering of geospatial data on a flat screen uses some kind of map projection, sometime implicitly.
+Well-designed map projections provide some control over deformations:
+one can preserve the angles, another projection can preserve the areas,
+but none can preserve both in same time.
+The geometric properties to preserve depend on the feature to represent and the work to do on that feature.
+For example countries elongated along the East-West axis often use a Lambert projection,
+while countries elongated along the North-South axis prefer a Transverse Mercator projection.
+</p><p>
+There is thousands of projected <abbr>CRS</abbr> in use around the world.
+Many of them are published in the <a href="../../epsg.html"><abbr>EPSG</abbr> geodetic database</a>.
+The easiest way to get a projected <abbr>CRS</abbr> with Apache <abbr title="Spatial Information System">SIS</abbr> is to use its <abbr>EPSG</abbr> code.
+For example the following code gets the definition of the <cite>JGD2000 / UTM zone 54N</cite> <abbr>CRS</abbr>
+(for Japan from 138°E to 144°E):
+</p>
+<pre><code><code class="GeoAPI">CoordinateReferenceSystem</code> crs = CRS.forCode(<i>"EPSG:3100"</i>);</code></pre>
+<p>
+Other ways to get a coordinate reference system will be given in a <a href="#GetCRS">next section</a>.
+</p>
+
+<h3 id="GeographicCRS"><span class="section-number">4.1.2.</span> Geographic reference systems</h3>
+<p>
+All map projections are based on a geodetic (usually geographic) <abbr>CRS</abbr>.
+A geodetic <abbr>CRS</abbr> is a coordinate reference system with latitude, longitude and sometime height axes.
+There is many kinds of latitudes and longitudes,
+but two common kinds supported by Apache <abbr title="Spatial Information System">SIS</abbr> are <dfn>geodetic</dfn> and <dfn>geocentric</dfn> latitudes.
+Those two angles differ slightly in the way they intersect the ellipsoid surface.
+On Earth surface, the difference between those two kinds of latitude varies between 0 and about 20 km.
+</p><p>
+When peoples talk about latitudes and longitudes, they usually mean <em>geodetic</em> latitudes and longitudes.
+A coordinate reference system using such latitudes and longitudes is said <dfn>geographic</dfn>
+and is represented by the <code class="GeoAPI">GeographicCRS</code> interface.
+Systems using the other kinds of latitude are represented by other <abbr>CRS</abbr> interfaces.
+</p><p>
+Theoretically, data expressed in a geographic <abbr>CRS</abbr> can never be rendered directly on a flat screen
+(they could be rendered directly on a planetarium dome however).
+In practice we allow data rendering in a geographic <abbr>CRS</abbr>,
+but this process implicitly uses a <cite>Plate Carrée</cite> projection.
+</p>
+
+<h3 id="CompoundCRS"><span class="section-number">4.1.3.</span> Vertical and temporal dimensions</h3>
+<p style="color: red">TODO</p>
+
+<h3 id="CoordinateSystem"><span class="section-number">4.1.4.</span> Coordinate systems</h3>
+<p>
+A Coordinate System (<abbr>CS</abbr>) defines the set of axes that spans a given coordinate space.
+Each axis defines an approximative direction (north, south, east, west, up, down, port, starboard, past, future, <i>etc.</i>),
+units of measurement, minimal and maximal values, and what happen after reaching those extremum.
+For example in longitude case, after +180° the coordinate values continue at −180°.
+Axes having such behavior are flagged by the <code class="GeoAPI">RangeMeaning.WRAPAROUND</code> code.
+</p>
+<aside>
+<h4>Generalizing to other types of axes</h4>
+<p>
+Wraparound can also exist in time axis. For example in climatological data defining normal temperatures,
+after December the data sequence restarts to January; those months are associated to no particular year.
+Apache <abbr title="Spatial Information System">SIS</abbr> allows wraparound to happen on any axis, as long as it is flagged by <code class="GeoAPI">RangeMeaning</code> code.
+It is possible to have many wraparound axes in the same coordinate system.
+</p>
+</aside>
+<p>
+Each Coordinate Reference System (<abbr>CRS</abbr>)
+is associated with exactly one Coordinate System (<abbr>CS</abbr>).
+Some properties that we can get from a coordinate system and its axes are shown below.
+Axes are numbered from 0 to <code>cs.getDimension()-1</code> inclusive.
+</p>
+
+<pre><code><code class="GeoAPI">CoordinateSystem</code> cs = crs.getCoordinateSystem();
+<code class="GeoAPI">CoordinateSystemAxis</code> secondAxis = cs.getAxis(1); <code class="comment">// For a geographic CRS, this is usually geodetic longitude.</code>
+String abbreviation = secondAxis.getAbbreviation(); <code class="comment">// For a longitude axis, this is usually "λ", "L" or "lon".</code>
+<code class="GeoAPI">AxisDirection</code> direction = secondAxis.getDirection(); <code class="comment">// For a longitude axis, this is usually EAST. Another occasional value is WEST.</code>
+Unit<?> units = secondAxis.getUnit(); <code class="comment">// For a longitude axis, this is usually Units.DEGREE.</code>
+<b>double</b> minimum = secondAxis.getMinimumValue(); <code class="comment">// For a longitude axis, this is usually −180°. Another common value is 0°.</code>
+<b>double</b> maximum = secondAxis.getMaximumValue(); <code class="comment">// For a longitude axis, this is usually +180°. Another common value is 360°.</code>
+<code class="GeoAPI">RangeMeaning</code> atEnds = secondAxis.getRangeMeaning(); <code class="comment">// For a longitude axis, this is WRAPAROUND.</code>
+</code></pre>
+<p>
+
+In addition to axis definitions, another important coordinate system characteristic is their type
+(<code class="GeoAPI">CartesianCS</code>, <code class="GeoAPI">SphericalCS</code>, <i>etc.</i>).
+The <abbr>CS</abbr> type implies the set of mathematical rules for calculating geometric quantities like angles, distances and surfaces.
+Usually the various <abbr>CS</abbr> subtypes do not define any new Java methods compared to the parent type,
+but are nevertheless important for type safety.
+For example many calculations or associations are legal only when all axes are perpendicular to each other.
+In such case the coordinate system type is restricted to <code class="GeoAPI">CartesianCS</code> in method signatures.
+</p><p>
+Coordinate systems are mathematical concepts; they do <strong>not</strong> contain any information
+about where on Earth is located the system origin.
+Consequently coordinate systems alone are not sufficient for describing a location;
+they must be combined with a <dfn>datum</dfn> (or <dfn>reference frame</dfn>).
+Those combinations form the <dfn>coordinate reference systems</dfn> described in previous sections.
+</p>
+
+
+
+
+<h3 id="GeodeticDatum"><span class="section-number">4.1.5.</span> Geodetic datum</h3>
<p>
Since the real topographic surface is difficult to represent mathematically, it is not used directly.
A slightly more convenient surface is the geoid,
@@ -1162,7 +1203,7 @@ While much smoother than topographic surface, the geoid surface still have hollo
caused by the uneven distribution of mass inside Earth.
For more convenient mathematical operations, the geoid surface is approximated by an ellipsoid.
This “figure of Earth” is represented in GeoAPI by the <code class="GeoAPI">Ellipsoid</code> interface,
-a fundamental component in coordinate reference systems of kind <code class="GeoAPI">GeographicCRS</code> and <code class="GeoAPI">ProjectedCRS</code>.
+which is a fundamental component in coordinate reference systems of type <code class="GeoAPI">GeographicCRS</code> and <code class="GeoAPI">ProjectedCRS</code>.
Tenth of ellipsoids are commonly used for datum definitions.
Some of them provide a very good approximation for a particular geographic area
at the expense of the rest of the world for which the datum was not designed.
@@ -1192,8 +1233,6 @@ but many ellipsoid definitions provide this factor instead of semi-minor axis le
<b>double</b> ivf = ellipsoid.<code class="GeoAPI">getInverseFlattening()</code>; <code class="comment">// = semiMajor / (semiMajor - semiMinor).</code>
</code></pre>
-
-<h3 id="GeodeticDatum"><span class="section-number">5.1.2.</span> Geodetic datum</h3>
<p>
For defining a geodetic system in a country, a national authority selects an ellipsoid matching closely the country surface.
Differences between that ellipsoid and the geoid’s hollows and bumps are usually less than 100 metres.
@@ -1233,58 +1272,40 @@ Today, at least six <abbr>WGS84</abbr> versions exist.
Furthermore many borders were legally defined in legacy datums, for example <abbr>NAD27</abbr> in <abbr>USA</abbr>.
Updating data to the new datum would imply transforming some straight lines or simple geometric shapes
into more irregular shapes, if the shapes are large enough.
-</p><p>
-Contrarily to other kinds of objects introduced in this section,
-there is not many useful information that we can get from a <code class="GeoAPI">Datum</code> instance except its name.
-It is difficult to translate in programming language how a datum is related to the Earth.
-Often, the most we can do is to consider that having two datums with different names implies that the same location on Earth
-has different coordinate values when using those different datums, even if the ellipsoid is identical in both cases.
-Coordinate transformations between datums require some kind of database.
-</p>
-
-<h3 id="CoordinateSystem"><span class="section-number">5.1.3.</span> Coordinate systems</h3>
-<p>
-A Coordinate System (<abbr>CS</abbr>) defines the set of axes that spans a given coordinate space.
-Each axis defines an approximative direction (north, south, east, west, up, down, port, starboard, past, future, <i>etc.</i>),
-units of measurement, minimal and maximal values, and what happen after reaching those extremum.
-For example in longitude case, after +180° the coordinate values continue at −180°.
-But such loops may also exist in time axis. For example in climatological data defining normal temperatures,
-after December the data sequence restarts to January; those months are associated to no particular year.
-Axes having such behavior are associated to the <code class="GeoAPI">RangeMeaning.WRAPAROUND</code> code.
-</p><p>
-Some properties that we can get from a coordinate system and its axes are shown below.
-Axes are numbered from 0 to <code>cs.getDimension()-1</code> inclusive.
+</p><p>
+Contrarily to other kinds of objects introduced in this section,
+there is not many useful information that we can get from a <code class="GeoAPI">Datum</code> instance except its name.
+It is difficult to translate in programming language how a datum is related to the Earth.
+Often, the most we can do is to consider that having two datums with different names implies that the same location on Earth
+has different coordinate values when using those different datums, even if the ellipsoid is identical in both cases.
+Coordinate transformations between datums require some kind of database.
</p>
+</section>
-<pre><code><code class="GeoAPI">CoordinateSystem</code> cs = crs.getCoordinateSystem();
-<code class="GeoAPI">CoordinateSystemAxis</code> secondAxis = cs.getAxis(1); <code class="comment">// For a geographic CRS, this is usually geodetic longitude.</code>
-String abbreviation = secondAxis.getAbbreviation(); <code class="comment">// For a longitude axis, this is usually "λ", "L" or "lon".</code>
-<code class="GeoAPI">AxisDirection</code> direction = secondAxis.getDirection(); <code class="comment">// For a longitude axis, this is usually EAST. Another occasional value is WEST.</code>
-Unit<?> units = secondAxis.getUnit(); <code class="comment">// For a longitude axis, this is usually Units.DEGREE.</code>
-<b>double</b> minimum = secondAxis.getMinimumValue(); <code class="comment">// For a longitude axis, this is usually −180°. Another common value is 0°.</code>
-<b>double</b> maximum = secondAxis.getMaximumValue(); <code class="comment">// For a longitude axis, this is usually +180°. Another common value is 360°.</code>
-<code class="GeoAPI">RangeMeaning</code> atEnds = secondAxis.getRangeMeaning(); <code class="comment">// For a longitude axis, this is WRAPAROUND.</code>
-</code></pre>
-<p>
-In addition to axis definitions, another important coordinate system characteristic is their type
-(<code class="GeoAPI">CartesianCS</code>, <code class="GeoAPI">SphericalCS</code>, <i>etc.</i>).
-The <abbr>CS</abbr> type implies the set of mathematical rules for calculating geometric quantities like angles, distances and surfaces.
-Usually the various <abbr>CS</abbr> subtypes do not define any new Java methods compared to the parent type,
-but are nevertheless important for type safety.
-For example many calculations or associations are legal only when all axes are perpendicular to each other.
-In such case the coordinate system type is restricted to <code class="GeoAPI">CartesianCS</code> in method signatures.
-</p><p>
-Coordinate systems are mathematical concepts; they do <strong>not</strong> contain any information
-about where on Earth is located the system origin.
-Consequently coordinate systems alone are not sufficient for describing a location;
-they must be combined with a <cite>datum</cite> (or <cite>reference frame</cite>).
-Those combinations form the <cite>coordinate reference systems</cite> described in next sections.
-</p>
+<section>
+<header>
+<h2 id="GetCRS"><span class="section-number">4.2.</span> Fetching a spatial reference system</h2>
+</header>
+<p style="color: red">TODO:</p>
+<ul style="color: red">
+<li>Using <code class="SIS">CommonCRS</code></li>
+<li>Looking <abbr>CRS</abbr> defined by authorities with <code>CRSAuthorityFactory</code></li>
+<li>Reading definitions in GML or WKT format</li>
+<li>Constructing programmatically using <code class="GeoAPI">CRSFactory</code></li>
+</ul>
+
+<h3 id="CRS_UserCode"><span class="section-number">4.2.1.</span> Adding new <abbr>CRS</abbr> definitions</h3>
+<p style="color: red">TODO</p>
+</section>
+
-<h4 id="AxisOrder"><span class="section-number">5.1.3.1.</span> Axis order</h4>
+<section>
+<header>
+<h2 id="AxisOrder"><span class="section-number">4.3.</span> Axis order</h2>
+</header>
<p>
-The axis order is specified by the authority (typically a national agency) defining the <cite>Coordinate Reference System</cite> (<abbr>CRS</abbr>).
+The axis order is specified by the authority (typically a national agency) defining the <dfn>Coordinate Reference System</dfn> (<abbr>CRS</abbr>).
The order depends on the <abbr>CRS</abbr> type and the country defining the <abbr>CRS</abbr>.
In the case of geographic <abbr>CRS</abbr>, the (<var>latitude</var>, <var>longitude</var>) axis order is widely used by geographers and pilots for centuries.
However software developers tend to consistently use the (<var>x</var>, <var>y</var>) order for every kind of <abbr>CRS</abbr>.
@@ -1300,7 +1321,7 @@ by default, <abbr>SIS</abbr> creates <abbr>CRS</abbr> with axis order <em>as def
Those <abbr>CRS</abbr> are created by calls to the <code>CRS.forCode(String)</code> method
and the actual axis order can be verified after the <abbr>CRS</abbr> creation with <code>System.out.println(crs)</code>.
But if (<var>x</var>, <var>y</var>) axis order is wanted for compatibility with older <abbr>OGC</abbr> specifications or other software products,
-then <abbr>CRS</abbr> forced to <cite>longitude first</cite> axis order can be created by a call to the following method:
+then <abbr>CRS</abbr> forced to <em>longitude first</em> axis order can be created by a call to the following method:
</p>
<pre><code><code class="GeoAPI">CoordinateReferenceSystem</code> crs = …; <code class="comment">// CRS obtained by any means.</code>
@@ -1324,69 +1345,13 @@ but this is <abbr>SIS</abbr>-specific as <abbr title="International Organization
</ul>
<p>
To avoid ambiguities, users are encouraged to always provide explicit <code class="OGC">AXIS[…]</code> elements in their <abbr>WKT</abbr>.
-The <abbr>WKT</abbr> format will be presented in more details in the next sections.
-</p>
-
-<h3 id="GeographicCRS"><span class="section-number">5.1.4.</span> Geographic reference systems</h3>
-<p>
-There is many kinds of latitudes and longitudes. Two common kinds supported by Apache <abbr title="Spatial Information System">SIS</abbr>
-are <cite>geodetic</cite> and <cite>geocentric</cite> latitudes.
-Those two angles differ slightly in the way they intersect the ellipsoid surface.
-On Earth surface, the difference between those two kinds of latitude varies between 0 and about 20 km.
-</p><p>
-When peoples talk about latitudes and longitudes, they usually mean <em>geodetic</em> latitudes and longitudes.
-A coordinate reference systems using such latitudes and longitudes is said <cite>geographic</cite>
-and is represented by the <code class="GeoAPI">GeographicCRS</code> interface.
-Systems using the other kinds of latitude are represented by other <abbr>CRS</abbr> interfaces.
-</p>
-
-<h4 id="GeographicWKT"><span class="section-number">5.1.4.1.</span> <i>Well-Known Text</i> format</h4>
-<p style="color: red">TODO</p>
-
-<h3 id="ProjectedCRS"><span class="section-number">5.1.5.</span> Map projections</h3>
-<p>
-Map projections represent a curved surface (the Earth) on a plane surface (a map or a computer screen)
-with some control over deformations: one can preserve either the angles or the areas, but not both in same time.
-The geometric properties to preserve depend on the feature to represent and the work to do on that feature.
-For example countries elongated along the East-West axis often use a Lambert projection,
-while countries elongated along the North-South axis prefer a Transverse Mercator projection.
</p>
-<p style="color: red">TODO</p>
-
-<h4 id="ProjectedWKT"><span class="section-number">5.1.5.1.</span> <i>Well-Known Text</i> format</h4>
-<p style="color: red">TODO</p>
-
-<h3 id="CompoundCRS"><span class="section-number">5.1.6.</span> Vertical and temporal dimensions</h3>
-<p style="color: red">TODO</p>
-
-<h4 id="CompoundWKT"><span class="section-number">5.1.6.1.</span> <i>Well-Known Text</i> format</h4>
-<p style="color: red">TODO</p>
-</section>
-
-
-<section>
-<header>
-<h2 id="GetCRS"><span class="section-number">5.2.</span> Fetching a spatial reference system</h2>
-</header>
-<p style="color: red">TODO</p>
-
-<h3 id="CRSAuthorityFactory"><span class="section-number">5.2.1.</span> Looking <abbr>CRS</abbr> defined by authorities</h3>
-<p style="color: red">TODO</p>
-
-<h3 id="CRSParsing"><span class="section-number">5.2.2.</span> Reading definitions in GML or WKT format</h3>
-<p style="color: red">TODO</p>
-
-<h3 id="CRSFactory"><span class="section-number">5.2.3.</span> Constructing programmatically</h3>
-<p style="color: red">TODO</p>
-
-<h3 id="CRS_UserCode"><span class="section-number">5.2.4.</span> Adding new <abbr>CRS</abbr> definitions</h3>
-<p style="color: red">TODO</p>
</section>
<section>
<header>
-<h2 id="CoordinateOperations"><span class="section-number">5.3.</span> Coordinate operations</h2>
+<h2 id="CoordinateOperations"><span class="section-number">4.4.</span> Coordinate operations</h2>
</header>
<p>
Given a <em>source</em> coordinate reference system (<abbr>CRS</abbr>) in which existing coordinate values are expressed,
@@ -1414,7 +1379,7 @@ not <abbr>USA</abbr>.</p>
</div>
-<h3 id="CRS.findOperation"><span class="section-number">5.3.1.</span> Getting a coordinate operation</h3>
+<h3 id="CRS.findOperation"><span class="section-number">4.4.1.</span> Getting a coordinate operation</h3>
<p>
The easiest way to obtain a coordinate operation from above-cited information
is to use the <code class="SIS">org.apache.sis.referencing.CRS</code> convenience class:
@@ -1425,10 +1390,10 @@ is to use the <code class="SIS">org.apache.sis.referencing.CRS</code> convenienc
<p>
Among the information provided by <code class="GeoAPI">CoordinateOperation</code> object, the following are of special interest:
</p>
-<ul>
-<li>The <cite>domain of validity</cite>, either as a textual description (e.g. “Canada – onshore and offshore”)
+<ul class="verbose">
+<li>The <dfn>domain of validity</dfn>, either as a textual description (e.g. “Canada – onshore and offshore”)
or with the coordinates of a geographic bounding box.</li>
-<li>The <cite>positional accuracy</cite>, which may be anything from 1 centimetre to a few kilometres.</li>
+<li>The <dfn>positional accuracy</dfn>, which may be anything from 1 centimetre to a few kilometres.</li>
<li>The coordinate operation subtype. Among them, two sub-types provide the same functionalities but with a significant conceptual difference:
<ul class="verbose">
<li>
@@ -1449,11 +1414,11 @@ are in this category.
<p>
If the coordinate operation is an instance of <code class="GeoAPI">Transformation</code>,
then the instance selected by <abbr title="Spatial Information System">SIS</abbr> may be one among many possibilities depending on the area of interest.
-Furthermore its accuracy is certainly less than the centimetric accuracy that we can expect from a <code class="GeoAPI">Conversion</code>.
+Furthermore its accuracy is usually less than the centimetric accuracy that we can expect from a <code class="GeoAPI">Conversion</code>.
Consequently verifying the domain of validity and the positional accuracy declared in the transformation metadata is of particular importance.
</p>
-<h3 id="MathTransform"><span class="section-number">5.3.2.</span> Executing an operation on coordinate values</h3>
+<h3 id="MathTransform"><span class="section-number">4.4.2.</span> Executing an operation on coordinate values</h3>
<p>
The <code class="GeoAPI">CoordinateOperation</code> object introduced in above section provides high-level informations
(source and target <abbr>CRS</abbr>, domain of validity, positional accuracy, operation parameters, <i>etc</i>).
@@ -1504,13 +1469,11 @@ Note that all geographic coordinates below express latitude before longitude.
}</code></pre>
-<h3 id="TransformDerivative"><span class="section-number">5.3.3.</span> Partial derivatives of coordinate operations</h3>
+<h3 id="TransformDerivative"><span class="section-number">4.4.3.</span> Partial derivatives of coordinate operations</h3>
<p>
Previous section shows how to project a coordinate from one reference system to another one.
There is another, less known, operation which does not compute the projected coordinates of a given point,
but instead the derivative of the projection function at that point.
-This operation was defined in an older Open Geospatial specification,
-<a href="https://www.ogc.org/standards/ct">OGC 01-009</a>, now considered obsolete but still useful.
Let <var>P</var> be a map projection converting degrees of latitude and longitude (<var>φ</var>, <var>λ</var>)
into projected coordinates (<var>x</var>, <var>y</var>) in metres.
The formula below represents the map projection result as a column matrix
@@ -1560,294 +1523,95 @@ The formula below represents the map projection result as a column matrix
<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>
-<mo>]</mo>
-</mrow>
-</math>
-</div>
-<div style="min-width:500px; padding-left:60px">
-<div class="caption">Java code</div>
-<pre style="margin:0"><code><code class="GeoAPI">DirectPosition</code> geographic = <b>new</b> <code class="SIS">DirectPosition2D</code>(<var>φ</var>, <var>λ</var>);
-<code class="GeoAPI">Matrix</code> jacobian = <var><b>P</b></var>.derivative(geographic);
-<b>double</b> dx_dλ = jacobian.getElement(0,1);
-<b>double</b> dy_dφ = jacobian.getElement(1,0);</code></pre>
-</div>
-</div>
-
-<p>
-Remaining equations in this section will abridge
-∂<var>x</var>(<var>λ</var>, <var>φ</var>) as ∂<var>x</var> and
-∂<var>y</var>(<var>λ</var>, <var>φ</var>) as ∂<var>y</var>,
-but reader should keep in mind that each of those derivative values depends on the (<var>λ</var>, <var>φ</var>) coordinate given at Jacobian matrix calculation time.
-The first matrix column tells us that if we apply a small displacement of ∂<var>φ</var> degrees of latitude from the (<var>φ</var>, <var>λ</var>) position,
-— in other words if we move at the (<var>φ</var> + ∂<var>φ</var>, <var>λ</var>) geographic position —
-then the projected coordinate will be displaced by (∂<var>x</var>, ∂<var>λ</var>) metres
-— in other words it will become (<var>x</var> + ∂<var>x</var>, <var>y</var> + ∂<var>λ</var>).
-Similarly the last matrix column gives us the displacement that happen on the projected coordinate
-if we apply a small displacement of ∂<var>λ</var> degrees of longitude on the source geographic coordinate.
-We can visualize such displacements in a figure like below.
-This figure shows the derivative at two points, <var>P</var><sub>1</sub> and <var>P</var><sub>2</sub>,
-for emphasing that the result change for every points.
-In that figure, vectors <var>U</var> et <var>V</var> stand for the first and second column respectively
-in the Jacobian matrices.
-</p>
-
-<div class="row-of-boxes">
-<div>
-<img alt="Example of a map projection derivative" src="../images/Derivatives.png" style="border: solid 1px"/>
-</div><div>
-<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>
-<mrow>
-<mo>[</mo>
-<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>
-<mo>]</mo>
-</mrow>
-</mtd>
-<mtd><mtext>et</mtext></mtd>
-<mtd>
-<mover><mi>V</mi><mo>→</mo></mover><mo>=</mo>
-<mrow>
-<mo>[</mo>
-<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>
-<mo>]</mo>
-</mrow>
-</mtd>
-</mtr></mtable>
-</math>
-</div>
-</div>
-
-<p>
-Above figure shows one usage of map projection derivatives:
-they provide the direction of parallels and meridians at a given location in a map projection.
-One can use that information for determining if axes have been swapped or their direction reversed.
-But the usefulness of map projection derivatives goes further.
-</p>
-
-<h4 id="DerivativeAndEnvelope"><span class="section-number">5.3.3.1.</span> Transform derivatives applied to envelopes</h4>
-<p>
-Geographic information systems often need to transform an envelope from one <abbr>CRS</abbr> to another.
-But a naive approach transforming the 4 corners is not sufficient.
-The figure below shows an envelope before a map projection and the geometric shape
-that we would get if all points (not only the corners) were projected.
-The resulting geometric shape is more complex than a rectangle because of the curvature caused by the map projection.
-Computing the envelope that contains the 4 corners of that shape is not enough,
-because the area in the bottom of the projected shape is lower than the two bottom corners.
-That surface would be outside the envelope.
-</p>
-<div class="row-of-boxes">
-<div>
-<div class="caption">Envelope before projection</div>
-<img alt="Envelope in a geographic CRS" src="../images/GeographicArea.png" style="border: solid 1px; margin-right: 15px"/>
-</div><div>
-<div class="caption">Geometric shape after projection</div>
-<img alt="Shape in a projected CRS" src="../images/ConicArea.png" style="border: solid 1px; margin-left: 15px"/>
-</div>
-</div>
-<p>
-A simple way to reduce the problem could be to sample a large number of points on each envelope border.
-For example we could sample 40 points on each border, transform them to the target <abbr>CRS</abbr>
-and compute an envelope containing all the transformed points.
-But even with 40 points, the point which is closest to the minimum in above figure can still be above that minimum.
-Consequently we still miss a small portion of the projected shape.
-It may be tempting to declare this error is negligible, but a single missing pixel can be enough for
-causing artifacts such as thin black lines in a mosaic or missing “piece of pie” in a projection over a pole.
-A workaround could be to arbitrarily increase the envelope size by some percentage,
-but a percentage too high will cause a larger amount of unnecessary data processing (e.g. more data to load from a file)
-while a percentage too low will leave some artifacts.
-</p><p>
-Map projection derivatives offer a more efficient way to resolve this problem.
-The figure below reproduces the same projected shape than above figure but with exaggerated deformations.
-The Apache <abbr title="Spatial Information System">SIS</abbr> algorithm projects the 4 corners as in the naive approach,
-but opportunistically computes also their derivatives (the Jacobian matrices).
-Between two corners and using derivative information, there is only one possible cubic curve.
-We can describe that curve by the
-
-<i>f(<var>x</var>)</i> = <var>C</var>₀ + <var>C</var>₁<var>x</var> + <var>C</var>₂<var>x</var>² + <var>C</var>₃<var>x</var>³ equation
-
-with <var>C</var> coefficients computed from corner positions and derivatives.
-This approximation (shown by the red curve in above figure) does not match exactly the desired curve
-(shown by the blue shape in above figure) but is close.
-We do not use directly the cubic curve minimum,
-but instead we take the longitude λ (for above example) where this minimum is located.
-This is shown by the green dashed line in above figure.
-This position is easy to compute when the <var>C</var> coefficients are known.
-Assuming that the λ coordinate of the cubic curve minimum is close to the λ coordinates of the projected shape minimum,
-we can project the point on the envelope border at that location instead of projecting blindly 40 points on that border.
-</p>
-<div class="row-of-boxes">
-<div>
-<img alt="Cubic approximation of an envelope bounds" src="../images/Approximation.png"/>
-</div><div>
-Legend:
-<ul>
-<li><b>Blue:</b> the geometric shape of the envelope after projection.
-This is the shape from which to get a new envelope.</li>
-<li><b>Red</b> (with hash): The
-<var>y</var> = <var>C</var>₀ + <var>C</var>₁λ + <var>C</var>₂λ² + <var>C</var>₃λ³ approximation.</li>
-<li><b>Green</b> (dashed line): Position λ<sub>m</sub> of approximation minimum, obtained by resolving
-0 = <var>C</var>₁ + 2<var>C</var>₂λ<sub>m</sub> + 3<var>C</var>₃λ<sub>m</sub>².
-The same cubic line can have two minimums.</li>
-</ul>
-</div>
-</div>
-<p>
-In practice Apache <abbr>SIS</abbr> uses 8 points:
-the 4 corners plus one point at the center of each border of the envelope to project.
-The center points are added as a safety for map projections having symmetric deformations above and below equator.
-According our tests, using only those 8 points together with derivatives as described above
-gives more accurate results than “brute force” approach with 160 points on the 4 envelope borders.
-Saving 150 points seems small compared to computer performances.
-But above discussion used a two-dimensional envelope as an example.
-The same discussion applies to <var>n</var>-dimensional envelopes as well.
-Apache <abbr>SIS</abbr> can apply this algorithm on envelopes with any number of dimensions up to 64.
-The performance gain offered by this algorithm compared to “brute force” approach
-increases exponentially with the number of dimensions.
-</p><p>
-Apache <abbr>SIS</abbr> implements the algorithm described in this section
-by the static <code class="SIS">Envelopes.transform(CoordinateOperation, Envelope)</code> method.
-An alternative <code class="SIS">Envelopes.transform(MathTransform, Envelope)</code> method is also available,
-but should be used only when the <code class="GeoAPI">CoordinateOperation</code> is unknown.
-The reason is because <code class="GeoAPI">MathTransform</code> objects does not contain any information about coordinate system axes,
-which prevent the <code class="SIS">Envelopes.transform(…)</code> method to handle special cases such as envelopes containing a pole.
-</p>
-
-
-<h4 id="DerivativeAndRaster"><span class="section-number">5.3.3.2.</span> Transform derivatives applied to rasters</h4>
-<p>
-A raster can be projected by preparing an initially empty raster which will contain the resampled pixel values.
-Then for each pixel in the <em>destination</em> raster, we use the <em>inverse</em> of the map projection
-(<var>T</var>⁻¹) for computing the coordinates of the corresponding pixel in source raster.
-The transformed coordinates may not fall at the center of a source raster pixel,
-so source pixel values usually need to be interpolated.
-</p>
-<div style="display:flex; flex-direction:column; align-items:center">
-<div style="display:flex; justify-content:space-between; width:564px">
-<div class="caption">Source image</div>
-<div class="caption">Destination image</div>
+<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>
+<mo>]</mo>
+</mrow>
+</math>
</div>
-<img alt="Raster reprojection" src="../images/RasterProjection.png"/>
+<div style="min-width:500px; padding-left:60px">
+<div class="caption">Java code</div>
+<pre style="margin:0"><code><code class="GeoAPI">DirectPosition</code> geographic = <b>new</b> <code class="SIS">DirectPosition2D</code>(<var>φ</var>, <var>λ</var>);
+<code class="GeoAPI">Matrix</code> jacobian = <var><b>P</b></var>.derivative(geographic);
+<b>double</b> dx_dλ = jacobian.getElement(0,1);
+<b>double</b> dy_dφ = jacobian.getElement(1,0);</code></pre>
</div>
+</div>
+
<p>
-However applying the inverse transform on all pixel coordinates can be relatively slow.
-We can accelerate raster reprojections by pre-computing an <cite>interpolation grid</cite>.
-This grid contains the coordinate values of inverse transform <var>T</var>⁻¹ for only a few points.
-The coordinate values of other points are obtained by bilinear interpolations between interpolation grid points.
-Historically, this algorithm was implemented in the <code>WarpGrid</code> object of <cite>Java Advanced Imaging</cite> library.
-The performance gain is yet better if the same interpolation grid is reused for many rasters having their pixels at the same coordinates.
-</p><p>
-A difficulty in using interpolation grids is to determine how many points we need for keeping errors
-(defined as the difference between interpolated positions and actual positions computed by <var>T</var>⁻¹)
-below some threshold value (for example ¼ of pixel size).
-A “brute force” approach is to begin with a grid of size 3×3, then increase the number of points iteratively:
+The first matrix column tells us that if we apply a displacement of 1° of latitude from the (<var>φ</var>, <var>λ</var>) position,
+— in other words if we move at the (<var>φ</var> + 1, <var>λ</var>) geographic position —
+then the projected coordinates would be displaced by (∂<var>x</var>, ∂<var>λ</var>) metres
+— in other words they would become (<var>x</var> + ∂<var>x</var>, <var>y</var> + ∂<var>y</var>) —
+if the map projection is approximated by an affine transform valid at the (<var>φ</var>, <var>λ</var>) position.
+Similarly the last matrix column gives us the displacement that happen on the projected coordinate
+if we apply a displacement of 1° of longitude on the source geographic coordinate under the same assumption.
+We can visualize such displacements in a figure like below.
+This figure shows the derivative at two points, <var>P</var><sub>1</sub> and <var>P</var><sub>2</sub>,
+for emphasing that the result change for every points.
+In that figure, vectors <var>U</var> et <var>V</var> stand for the first and second column respectively
+in the Jacobian matrices.
</p>
+
<div class="row-of-boxes">
<div>
-<img alt="Warp grid" src="../images/WarpGrid.png"/>
+<img alt="Example of a map projection derivative" src="../images/Derivatives.png" style="border: solid 1px"/>
</div><div>
-Legend:
-<ul>
-<li><b>Blue dots:</b> first iteration (9 points).</li>
-<li><b>Green dots:</b> second iteration (25 points, including 16 news).</li>
-<li><b>Red dots:</b> third iteration (81 points, including 56 news).</li>
-</ul>
-Continuing…
-<ul>
-<li>Forth iteration: 289 points, including 208 news.</li>
-<li>Fifth iteration: 1089 points, including 800 news.</li>
-<li>Sixth iteration: 4225 points, including 3136 news.</li>
-<li>…</li>
-</ul>
+<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>
+<mrow>
+<mo>[</mo>
+<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>
+<mo>]</mo>
+</mrow>
+</mtd>
+<mtd><mtext>et</mtext></mtd>
+<mtd>
+<mover><mi>V</mi><mo>→</mo></mover><mo>=</mo>
+<mrow>
+<mo>[</mo>
+<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>
+<mo>]</mo>
+</mrow>
+</mtd>
+</mtr></mtable>
+</math>
</div>
</div>
-<p>
-We could stop dividing the grid when, after having computed new points,
-we verified that the differences between coordinates computed by <var>T</var>⁻¹ during last iteration
-and coordinates computed by bilinear interpolations for the same points are lower than the threshold value.
-Unfortunately this approach can only tell us <strong>after</strong> computing new points… that those new points were unnecessary.
-This is unfortunate considering that each iteration adds an amount of points approximately equal to
-3 times the <em>sum</em> of the number of points of all previous iterations.
-</p><p>
-Map projection derivatives help to improve the speed of interpolation grid computations.
-Using the derivatives, we can estimate whether another iteration is necessary <strong>before</strong> to execute it.
-The basic idea is to check if the derivatives at two neighbor points define two tangent lines that are almost parallel.
-In such case, we assume that the transform between those two points is almost linear.
-In order to define numerically the meaning of “almost linear”,
-we compute the intersection of the two tangent lines as illustrated below (the blue arrows).
-Then we compute the distance between that intersection and the straight line connecting the two points
-(the dashed line in the figure below).
-</p>
-<p style="text-align:center"><img alt="Intersection of derivatives" src="../images/IntersectionOfDerivatives.png" style="border: solid 1px"/></p>
-<p>
-In “brute force” algorithm without derivatives, iteration stops when the distance between interpolated positions (blue dashed line)
-and actual projected positions (red curve) is less than the threshold value.
-This criteria requires to compute the projected positions before the decision can be made.
-But with an algorithm using derivatives, the projected positions (red curve) are replaced by the tangents intersection point.
-If the actual projected curve does not have too much deformations
-(which should be the case for pairs of neighbor points close enough),
-then the red curve stay between the blue dashed line and the tangents intersection point.
-By using that intersection point, we reduce greatly the number of points to transform
-(3× the sum of all previous iterations).
-</p>
-<h4 id="GetDerivative"><span class="section-number">5.3.3.3.</span> Getting the derivative at a point</h4>
<p>
-The algorithms discussed in previous section would be irrelevant if map projection derivatives were costly to compute.
-But analytic derivations of their formulas show that map projection and derivative formulas have many terms in common.
-Furthermore map projection formulas are simplified by Apache <abbr title="Spatial Information System">SIS</abbr> implementation strategy,
-which takes out linear terms (delegated to affine transforms)
-so that <code>NormalizedProjection</code> subclasses can focus on the non-linear terms only.
-Map projection implementations in Apache <abbr>SIS</abbr> exploit those characteristics
-for computing Jacobian matrices (if required) together with projected points in a single operation,
-reusing many common terms between the two set of formulas.
-Example:</p>
+Above figure shows one usage of map projection derivatives:
+they provide the direction of parallels and meridians at a given location in a map projection.
+One can use that information for determining if axes have been swapped or their direction reversed.
+But the usefulness of map projection derivatives goes further.
+The <a href="#JacobianUsage">annex</a> explains how derivatives are used by the Apache <abbr title="Spatial Information System">SIS</abbr>
+implementation of envelope and raster reprojections.
+</p>
-<pre><code><code class="SIS">AbstractMathTransform</code> projection = ...; <code class="comment">// An Apache SIS map projection.</code>
-<b>double</b>[] sourcePoint = {longitude, latitude}; <code class="comment">// The geographic coordinate to project.</code>
-<b>double</b>[] targetPoint = <b>new</b> <b>double</b>[2]; <code class="comment">// Where to store the projection result.</code>
-<code class="GeoAPI">Matrix</code> derivative = projection.<code class="SIS">transform</code>(sourcePoint, 0, targetPoint, 0, <b>true</b>);</code></pre>
-<p>
-If only the Jacobian matrix is desired (without the projected point),
-then the <code class="GeoAPI">MathTransform.derivative(DirectPosition)</code> method offers a more readable alternative.
-</p><p>
-Many operations on coordinate transforms can also be applied on transform derivatives:
-concatenation of a chain of transforms, inversion, taking a subset of the dimensions, <i>etc.</i>
-Inverse projection formulas are usually more complicated than forward projections formulas,
-but thankfully their derivatives do not need to be computed:
-the Jacobian matrix of an inverse transform is the inverse of the Jacobian matrix of the forward transform.
-Calculation of inverse projections can be implemented as below:
-</p>
-<pre><code>@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> <code class="SIS">Matrices</code>.inverse(jac);
-}</code></pre>
-<h3 id="CoordinateOperationSteps"><span class="section-number">5.3.4.</span> Conceptual versus real chain of coordinate operations</h3>
+<h3 id="CoordinateOperationSteps"><span class="section-number">4.4.4.</span> Chain of coordinate operation steps</h3>
<p>
Coordinate operations may include many steps, each with their own set of parameters.
For example transformations from one datum (e.g. <abbr title="North American Datum 1927">NAD27</abbr>) to another datum (e.g. <abbr title="World Geodetic System 1984">WGS84</abbr>)
@@ -1859,7 +1623,7 @@ However because that operation chain is very common, the <abbr>EPSG</abbr> geode
named “Geocentric translation <em>in geographic domain</em>”.
Using this operation, the conversion steps between geographic and geocentric <abbr>CRS</abbr> are implicit.
Consequently the datum shifts as specified by <abbr>EPSG</abbr> appears as if it was a single operation,
-but this is not the real operation executed by Apache <abbr title="Spatial Information System">SIS</abbr>.
+but the real operation executed by Apache <abbr title="Spatial Information System">SIS</abbr> is divided in more steps.
</p>
<div class="example"><p><b>Example:</b>
@@ -1874,12 +1638,15 @@ For all columns, input coordinates of the first step and output coordinates of t
are (<var>latitude</var>, <var>longitude</var>) coordinates in degrees.
</p>
<div style="display:flex; padding-left:24px">
+<style>
+ol, ul {padding-left:20px}
+</style>
<div style="width:30%; padding-right:15px; border-right:1px solid">
<b>Operation specified by <abbr>EPSG</abbr>:</b>
<ol>
<li><b>Geocentric translation</b> in <em>geographic</em> domain
<ul>
-<li>X-axis translation = -10 m</li>
+<li>X-axis translation = −10 m</li>
<li>Y-axis translation = 158 m</li>
<li>Z-axis translation = 187 m</li>
</ul>
@@ -1892,18 +1659,18 @@ are inferred from the source and target datum.
<div style="width:30%; padding-left:30px; padding-right:15px; border-right:1px solid">
<b>Conceptual chain of operations:</b>
<ol>
-<li><b>Geographic to geocentric</b> conversion
+<li><b>Geographic to geocentric</b>
<ul>
<li>Source semi-major = 6378206.4 m</li>
<li>Source semi-minor = 6356583.8 m</li>
</ul>
</li><li><b>Geocentric translation</b>
<ul>
-<li>X-axis translation = -10 m</li>
+<li>X-axis translation = −10 m</li>
<li>Y-axis translation = 158 m</li>
<li>Z-axis translation = 187 m</li>
</ul>
-</li><li><b>Geocentric to geographic</b> conversion
+</li><li><b>Geocentric to geographic</b>
<ul>
<li>Target semi-major = 6378137.0 m</li>
<li>Target semi-minor ≈ 6356752.3 m</li>
@@ -1916,27 +1683,27 @@ It is implementation responsibility to perform any needed unit conversions and/o
<div style="width:30%; padding-left:30px">
<b>Operations actually performed by Apache <abbr>SIS</abbr>:</b>
<ol>
-<li><b>Affine parametric</b> conversion
+<li><b>Affine parametric conversion</b>
<ul>
<li>Scale factors (λ and φ) = 0</li>
<li>Shear factors (λ and φ) = π/180</li>
</ul>
-</li><li>Ellipsoid (radians domain) to centric conversion
+</li><li><b>Ellipsoid (radians) to centric</b>
<ul>
<li>Eccentricity ≈ 0.08227</li>
</ul>
</li><li><b>Affine parametric transformation</b>
<ul>
-<li>Scale factors (X, Y and Z) ≈ 1.00001088</li>
-<li>X-axis translation ≈ -1.568 E-6</li>
+<li>Scale factors ≈ 1.00001088</li>
+<li>X-axis translation ≈ −1.568 E-6</li>
<li>Y-axis translation ≈ 24.772 E-6</li>
<li>Z-axis translation ≈ 29.319 E-6</li>
</ul>
-</li><li>Centric to ellipsoid (radians domain) conversion
+</li><li><b>Centric to ellipsoid (radians)</b>
<ul>
<li>Eccentricity ≈ 0.08182</li>
</ul>
-</li><li><b>Affine parametric</b> conversion
+</li><li><b>Affine parametric conversion</b>
<ul>
<li>Scale factors (λ and φ) = 0</li>
<li>Shear factors (λ and φ) = 180/π</li>
@@ -1950,8 +1717,8 @@ The operation chain actually performed by Apache <abbr>SIS</abbr> is very differ
because the coordinate systems are not the same.
Except for the first and last ones, all Apache <abbr>SIS</abbr> steps work on right-handed coordinate systems
(as opposed to the left-handed coordinate system when <var>latitude</var> is before <var>longitude</var>),
-with angular units in radians (instead than degrees) and
-linear units relative to an ellipsoid of semi-major axis length of 1 (instead than Earth’s size).
+with angular units in radians (instead of degrees) and
+linear units relative to an ellipsoid of semi-major axis length of 1 (instead of Earth’s size).
Working in those coordinate systems requires additional steps for unit conversions and axes swapping
at the beginning and at the end of the chain.
Apache <abbr>SIS</abbr> uses <cite>affine parametric conversions</cite> for this purpose,
@@ -1977,8 +1744,8 @@ together with some metadata like the accuracy and domain of validity.
Some operation steps and parameters may be omitted if they can be inferred from the context.
</p>
<div class="example">
-<div style="display:flex; padding-left:24px; padding-right:24px">
-<div>
+<div style="display:flex">
+<div style="padding-right:24px">
<p><b>Example:</b>
the <abbr>WKT</abbr> 2 representation on the right is for the same coordinate operation than the one used in previous example.
This representation can be obtained by a call to <code>System.out.println(cop)</code>
@@ -1996,19 +1763,17 @@ This kind of metadata could hardly be guessed from the mathematical function alo
</ul>
</div>
<div>
-
-<pre><samp><code class="GeoAPI">CoordinateOperation</code>[<i>"NAD27 to WGS 84 (3)"</i>,
- SourceCRS[<span style="font-family:serif"><i>full CRS definition required here but omitted <b>for</b> brevity</i></span>],
- TargetCRS[<span style="font-family:serif"><i>full CRS definition required here but omitted <b>for</b> brevity</i></span>],
- Method[<i>"Geocentric translations (geog2D domain)"</i>],
- Parameter[<i>"X-axis translation"</i>, -10.0, Unit[<i>"metre"</i>, 1]],
- Parameter[<i>"Y-axis translation"</i>, 158.0, Unit[<i>"metre"</i>, 1]],
- Parameter[<i>"Z-axis translation"</i>, 187.0, Unit[<i>"metre"</i>, 1]],
+<pre><samp class="wkt">CoordinateOperation["NAD27 to WGS 84 (3)",
+ SourceCRS[<span style="font-family:serif"><i>full CRS definition required here but omitted for brevity</i></span>],
+ TargetCRS[<span style="font-family:serif"><i>full CRS definition required here but omitted for brevity</i></span>],
+ Method["Geocentric translations (geog2D domain)"],
+ Parameter["X-axis translation", -10.0, Unit["metre", 1]],
+ Parameter["Y-axis translation", 158.0, Unit["metre", 1]],
+ Parameter["Z-axis translation", 187.0, Unit["metre", 1]],
OperationAccuracy[20.0],
- Area[<i>"Canada - onshore and offshore"</i>],
+ Area["Canada - onshore and offshore"],
BBox[40.04, -141.01, 86.46, -47.74],
- Id[<i>"EPSG"</i>, 1172, <i>"8.9"</i>]]</samp></pre>
-
+ Id["EPSG", 1172, "8.9"]]</samp></pre>
</div>
</div>
</div>
@@ -2023,8 +1788,8 @@ Apache <abbr>SIS</abbr> constructs this representation from the data structure i
but convert them in a more convenient form for human, for example by converting radians to degrees.
</p>
<div class="example">
-<div style="display:flex; padding-left:24px; padding-right:24px">
-<div>
+<div style="display:flex">
+<div style="padding-right:24px">
<p><b>Example:</b>
the <abbr>WKT</abbr> 1 representation on the right is for the same coordinate operation than the one used in previous example.
This representation can be obtained by a call to <code>System.out.println(cop.getMathTransform())</code>
@@ -2045,33 +1810,32 @@ By default the ellipsoidal height before conversion is set to zero.</p></li>
</ul>
</div>
<div>
-
-<pre><samp>Concat_MT[
- Param_MT[<i>"Affine parametric transformation"</i>,
- Parameter[<span style="font-family:serif"><i>parameters performing axis swapping omitted <b>for</b> brevity</i></span>]],
- Inverse_MT[Param_MT[<i>"Geographic3D to 2D conversion"</i>]],
- Param_MT[<i>"Geographic/geocentric conversions"</i>,
- Parameter[<i>"semi_major"</i>, 6378206.4],
- Parameter[<i>"semi_minor"</i>, 6356583.8]],
- Param_MT[<i>"Geocentric translations (geocentric domain)"</i>,
- Parameter[<i>"X-axis translation"</i>, -10.0],
- Parameter[<i>"Y-axis translation"</i>, 158.0],
- Parameter[<i>"Z-axis translation"</i>, 187.0]],
- Param_MT[<i>"Geocentric_To_Ellipsoid"</i>,
- Parameter[<i>"semi_major"</i>, 6378137.0],
- Parameter[<i>"semi_minor"</i>, 6356752.314245179]],
- Param_MT[<i>"Geographic3D to 2D conversion"</i>],
- Param_MT[<i>"Affine parametric transformation"</i>,
- Parameter[<span style="font-family:serif"><i>parameters performing axis swapping omitted <b>for</b> brevity</i></span>]]]</samp></pre>
-
+<pre><samp class="wkt">Concat_MT[
+ Param_MT["Affine parametric transformation",
+ Parameter[<span style="font-family:serif"><i>parameters performing axis swapping omitted for brevity</i></span>]],
+ Inverse_MT[Param_MT["Geographic3D to 2D conversion"]],
+ Param_MT["Geographic/geocentric conversions",
+ Parameter["semi_major", 6378206.4],
+ Parameter["semi_minor", 6356583.8]],
+ Param_MT["Geocentric translations (geocentric domain)",
+ Parameter["X-axis translation", -10.0],
+ Parameter["Y-axis translation", 158.0],
+ Parameter["Z-axis translation", 187.0]],
+ Param_MT["Geocentric_To_Ellipsoid",
+ Parameter["semi_major", 6378137.0],
+ Parameter["semi_minor", 6356752.314245179]],
+ Param_MT["Geographic3D to 2D conversion"],
+ Param_MT["Affine parametric transformation",
+ Parameter[<span style="font-family:serif"><i>parameters performing axis swapping omitted for brevity</i></span>]]]</samp></pre>
</div>
</div>
</div>
<p>
-Finally, the raw operation chain can be view by a call to <code class="SIS">AbstractMathTransform.toString(Convention.INTERNAL)</code>.
-This pseudo-<abbr>WKT</abbr> representation shows exactly what Apache <abbr>SIS</abbr> does,
-but is rarely used because difficult to read.
-It may occasionally be useful for advanced debugging.
+The latter form is often useful for debugging.
+If a coordinate operation seems to produce wrong results,
+inspecting the Well Known Text like above should be the first thing to do.
+The <a href="../../faq.html#transforms">Frequently Asked Questions page</a> gives more tips
+about common causes of coordinate transformation errors.
</p>
</section>
</section>
@@ -2079,35 +1843,81 @@ It may occasionally be useful for advanced debugging.
<section>
<header>
-<h2 id="Formats"><span class="section-number">5.4.</span> Data storage formats</h2>
+<h1 id="Metadata"><span class="section-number">5.</span> Metadata</h1>
</header>
-<p>
-Apache SIS can read and write spatial data and associated metadata in different formats.
-</p>
<section>
<header>
-<h2 id="XML-ISO"><span class="section-number">5.5.</span> Representing objects in <abbr>XML</abbr></h2>
+<h2 id="GetMetadataElement"><span class="section-number">5.1.</span> Navigating in metadata elements</h2>
</header>
<p>
-Objects defined by <abbr title="Open Geospatial Consortium">OGC</abbr>/<abbr title="International Organization for Standardization">ISO</abbr> standards must be able to communicate with remote machines via the Internet,
-using different software written in different languages.
-Some of the better known formats include <abbr>WKT</abbr> (<i>Well-Known Text</i>) and <abbr>WKB</abbr> (<i>Well-Known Binary</i>).
-But the most exhaustive and often referred format is <abbr>XML</abbr>,
-to the point where the representation of <abbr>ISO</abbr> objects in this format is itself sometimes
-the entire focus of an international standard.
-Thus are metadata classes described in <abbr>ISO</abbr> 19115-1 standard (an abstract specification),
-while the representation of these classes in <abbr>XML</abbr> is described in <abbr>ISO</abbr> 19115-3 and 19139 standards.
+Methods like <code class="GeoAPI">getExtents()</code> are efficient when looking for a particular element known at compile-time.
+But those elements may be deep in the tree structure and may require traversal of many optional elements and collection members,
+which is sometime tedious. For a few frequently-used elements, some convenience methods are provided.
+Those conveniences are generally defined as static methods in classes having a name in plural form.
+For example the <code class="SIS">Extents</code> class defines static methods for fetching more easily some information from <code class="GeoAPI">Extent</code> metadata elements.
+For example the following method navigates through different branches where North, South, East and West data bounds may be found:
+</p>
+<pre><code><code class="GeoAPI">GeographicBoundingBox</code> bbox = <code class="SIS">Extents</code>.getGeographicBoundingBox(extent);</code></pre>
+<p>
+Those conveniences are defined as static methods in order to allow their use with different metadata implementations.
+Some other classes providing static methods for specific interfaces are
+<code class="SIS">Citations</code>, <code class="SIS">Envelopes</code>, <code class="SIS">Matrices</code> and <code class="SIS">MathTransforms</code>.
+</p>
+
+<h3 id="MetadataAsMap"><span class="section-number">5.1.1.</span> View as key-value pairs</h3>
+<p>
+Above static methods explore fragments of metadata tree in search for requested information,
+but the searches are still targeted to elements whose types and at least part of their paths are known at compile-time.
+Sometime the element to search is known only at runtime, or sometime there is a need to iterate over all elements.
+In such cases, one can view the metadata as a <code>java.util.Map</code> like below:
+</p>
+
+<pre><code>Map<String,Object> elements = <code class="SIS">MetadataStandard</code>.ISO_19115.<code class="SIS">asValueMap</code>(
+ metadata, <code class="comment">// Any instance from the org.opengis.metadata package or a sub-package.</code>
+ <b>null</b>, <code class="comment">// Used for resolving ambiguities. We can ignore for this example.</code>
+ <code class="SIS">KeyNamePolicy</code>.<code class="SIS">JAVABEANS_PROPERTY</code>, <code class="comment">// Keys in the map will be getter method names without "get" prefix.</code>
+ <code class="SIS">ValueExistencePolicy</code>.<code class="SIS">NON_EMPTY</code>); <code class="comment">// Entries with null or empty values will be omitted.</code>
+<code class="comment">/*
+ * Print the names of all root metadata elements having a value.
+ * This loop does not iterate recursively in children.
+ */</code>
+<b>for</b> (String name : elements.keySet()) {
+ System.out.println(name);
+}</code></pre>
+
+<p>
+The <code>Map</code> object returned by <code class="SIS">asValueMap(…)</code> is live:
+any change in the <code>metadata</code> instance will be immediately reflected in the view.
+Actually, each <code>map.get("foo")</code> call is forwarded to the corresponding <code>metadata.getFoo()</code> method.
+Conversely, any <code>map.put("foo", …)</code> or <code>map.remove("foo")</code> operation applied on the view
+will be forwarded to the corresponding <code>metadata.setFoo(…)</code> method, if that method exists.
+The view is lenient regarding keys given in arguments to <code>Map</code> methods:
+keys may be property names (<code>"foo"</code>), method names (<code>"getFoo"</code>),
+or names used in <abbr title="International Organization for Standardization">ISO</abbr> 19115 standard <abbr>UML</abbr> diagrams
+(similar to property names but not always identical).
+Differences in upper cases and lower cases are ignored when this tolerance does not introduce ambiguities.
+For more information on metadata views, see
+<a href="../../apidocs/org/apache/sis/metadata/package-summary.html#package.description"><code class="SIS">org.apache.sis.metadata</code></a>
+package javadoc.
</p>
+</section>
+</section>
+
+
+<section>
+<header>
+<h1 id="XML-ISO"><span class="section-number">6.</span> <abbr>XML</abbr> representation of <abbr title="International Organization for Standardization">ISO</abbr> objects</h1>
+</header>
<p>
-Different <abbr>OGC</abbr>/<abbr>ISO</abbr> standards do not always use the same strategy to express objects in <abbr>XML</abbr>.
+Different <abbr title="Open Geospatial Consortium">OGC</abbr>/<abbr>ISO</abbr> standards do not always use the same strategy to express objects in <abbr>XML</abbr>.
<abbr>ISO</abbr> 19115-3 standard in particular uses a more verbose approach than other standards,
and will be the subject of its <a href="#XML-ISO-19115">own section</a>.
But most <abbr>XML</abbr> formats define supplementary types and attributes that are not part of the original abstract specifications.
-These supplementary attributes are usually specific to <abbr>XML</abbr> and may not appear in the <abbr title="Application Programming Interface">API</abbr> of Apache <abbr title="Spatial Information System">SIS</abbr>.
+These supplementary attributes are usually specific to <abbr>XML</abbr> and may not appear in the <abbr>API</abbr> of Apache <abbr title="Spatial Information System">SIS</abbr>.
However, some of these attributes, such as <code class="OGC">id</code>, <code class="OGC">uuid</code> and
<code>xlink:href</code>, remain accessible in the form of key-value pairs.
</p>
@@ -2131,61 +1941,33 @@ These prefixes are defined in the <code class="SIS">org.apache.sis.xml.Namespace
<td><code class="OGC">gfc</code></td>
<td><code>http://www.isotc211.org/2005/gfc</code></td>
</tr>
-<tr>
-<td><code class="OGC">gmd</code></td>
-<td><code>http://www.isotc211.org/2005/gmd</code></td>
-</tr>
-<tr>
-<td><code class="OGC">gmi</code></td>
-<td><code>http://www.isotc211.org/2005/gmi</code></td>
-</tr>
-<tr>
-<td><code class="OGC">gmx</code></td>
-<td><code>http://www.isotc211.org/2005/gmx</code></td>
-</tr>
-<tr>
-<td><code class="OGC">gml</code></td>
-<td><code>http://www.opengis.net/gml/3.2</code></td>
-</tr>
-<tr>
-<td><code>xlink</code></td>
-<td><code>http://www.w3.org/1999/xlink</code></td>
-</tr>
-</table>
-
-<aside>
-<h2>Tools for reading and writing <abbr>XML</abbr> documents</h2>
-<p>
-Apache <abbr title="Spatial Information System">SIS</abbr> uses different libraries to read and write different types of objects.
-The library used depends on the complexity of the object and on performance constraints.
-For example, <abbr title="Java Architecture for XML Binding">JAXB</abbr> annotations have the advantage of being close to code,
-which makes it easier to maintain mapping between Java and <abbr>XML</abbr>.
-On the other hand, <abbr title="Simple API for XML">SAX</abbr> is more efficient.
-In general, Apache <abbr>SIS</abbr> uses:
-</p>
-<ul>
-<li>
-<abbr>JAXB</abbr> for objects that do not occur very often in <abbr>XML</abbr> documents, but with complex structures and deep hierarchies.
-The metadata set in <abbr title="International Organization for Standardization">ISO</abbr> 19115-3 standard is a typical example
-</li>
-<li>
-<abbr>SAX</abbr> for objects that are relatively simple, but which may exist in very large numbers.
-The set of points in a geometry is a typical example.
-</li>
-<li>
-<abbr title="Document Object Model">DOM</abbr> as an alternative to <abbr>JAXB</abbr>
-when the <abbr>XML</abbr> elements do not correspond exactly to Java attributes.
-<i>Features</i> are an example, as their structure is dynamic.
-</li>
-</ul>
-</aside>
-
+<tr>
+<td><code class="OGC">gmd</code></td>
+<td><code>http://www.isotc211.org/2005/gmd</code></td>
+</tr>
+<tr>
+<td><code class="OGC">gmi</code></td>
+<td><code>http://www.isotc211.org/2005/gmi</code></td>
+</tr>
+<tr>
+<td><code class="OGC">gmx</code></td>
+<td><code>http://www.isotc211.org/2005/gmx</code></td>
+</tr>
+<tr>
+<td><code class="OGC">gml</code></td>
+<td><code>http://www.opengis.net/gml/3.2</code></td>
+</tr>
+<tr>
+<td><code>xlink</code></td>
+<td><code>http://www.w3.org/1999/xlink</code></td>
+</tr>
+</table>
<section>
<header>
-<h3 id="XML-ISO-19115"><span class="section-number">5.5.1.</span> Representing metadata according to <abbr title="International Organization for Standardization">ISO</abbr> 19115-3</h3>
+<h2 id="XML-ISO-19115"><span class="section-number">6.1.</span> <abbr title="International Organization for Standardization">ISO</abbr> 19115-3 metadata</h2>
</header>
<p>
For each metadata class, there is an <abbr>XML</abbr> type with the same name than in the abstract specification
@@ -2242,7 +2024,7 @@ consists of a systematic alternation of two types of <abbr>XML</abbr> elements:
<ol>
<li><p>
It begins with the name of the property, which always begins with a lower-case letter (ignoring prefixes).
-In Java <abbr title="Application Programming Interface">API</abbr>s, each property corresponds to a method in its enclosing class.
+In Java <abbr>API</abbr>s, each property corresponds to a method in its enclosing class.
In the example above, <code class="OGC">mdb:identificationInfo</code> (a property of <code class="OGC">MD_Metadata</code> class)
corresponds to the <code class="GeoAPI">Metadata.getIdentificationInfo()</code> method.
</p></li>
@@ -2261,34 +2043,10 @@ It is this <abbr>XML</abbr> element that contains the child properties.
In order to reduce the complexity of the libraries, GeoAPI and Apache <abbr title="Spatial Information System">SIS</abbr>
only expose publicly a single unified view of these two types of elements.
The public <abbr>API</abbr> basically corresponds to the second group.
-However, when writing an <abbr>XML</abbr> document, elements of the first group must be temporarily recreated.
-The corresponding classes are defined in internal <abbr>SIS</abbr> packages.
-These classes may be ignored, unless the developer wishes to implement his or her own classes whose instances must be written in <abbr title="Java Architecture for XML Binding">JAXB</abbr>.
-</p>
-
-<aside id="XML-SIS">
-<h3>Implementation strategy in Apache <abbr title="Spatial Information System">SIS</abbr></h3>
-<p>
-<code class="SIS">org.apache.sis.internal.jaxb.*</code> packages (non-public) define <abbr title="Java Architecture for XML Binding">JAXB</abbr> adaptors for all types of <abbr title="International Organization for Standardization">ISO</abbr> objects.
-These adaptors are required anyway to allow <abbr>JAXB</abbr> to get <abbr>SIS</abbr> classes while implementing GeoAPI interfaces.
-Conveniently, <abbr>SIS</abbr> made both <abbr>JAXB</abbr> adaptors and objects wrapping the “real” object to be read or written.
-This double usage avoids having to double the number of classes (already quite high) present in the internal packages.
-</p>
-<h4>Naming conventions in <abbr title="XML Schema Definition">XSD</abbr> schemas</h4>
-<p>
-For each element of the first group listed above, the <abbr>XSD</abbr> schemas of the <abbr title="Open Geospatial Consortium">OGC</abbr>
-define a type whose name ends with “<code class="OGC">_PropertyType</code>”.
-For the second group, each element has a type whose name ends with “<code class="OGC">_Type</code>”.
-The “<code class="OGC">_PropertyType</code>” elements may have a group of attributes
-(such as <code class="OGC">gco:uuidref</code> and <code>xlink:href</code>)
-which the <abbr>XSD</abbr> schemas collectively name <code class="OGC">gco:ObjectIdentification</code>.
-These attributes do not have dedicated Java methods, but are accessible indirectly via the
-<code class="SIS">IdentifiedObject</code> interface described in the following subsection.
</p>
-</aside>
-<h4 id="gco-id"><span class="section-number">5.5.1.1.</span> Identification of already-defined instances</h4>
+<h3 id="gco-id"><span class="section-number">6.1.1.</span> Links to previously-defined instances</h3>
<p>
The parent element may contain an <code class="OGC">id</code> or <code class="OGC">uuid</code> attribute.
If one of these attributes is present, the parent attribute may be completely omitted;
@@ -2367,7 +2125,7 @@ where all types of identifiers (not only <abbr>XML</abbr>) associated with an ob
-<h4 id="nilReason"><span class="section-number">5.5.1.2.</span> Representing missing values</h4>
+<h3 id="nilReason"><span class="section-number">6.1.2.</span> Placeholders for missing values</h3>
<p>
When a property is not defined, the corresponding GeoAPI method usually returns <code>null</code>.
However, things become complicated when the missing property is a value considered mandatory by <abbr title="International Organization for Standardization">ISO</abbr> 19115 standard.
@@ -2415,23 +2173,12 @@ But when a <code class="OGC">nilReason</code> is present, the <abbr>SIS</abbr> i
</div>
</section>
</section>
-</section>
<section>
<header>
-<h1 id="Utilities"><span class="section-number">6.</span> Utility classes and methods</h1>
-<nav><div class="chapter-links"><div class="previous-chapter">⬅ <a href="#Referencing">Previous chapter</a></div><div class="next-chapter"><a href="#GeoAPI-details">Next chapter</a> ➡</div></div></nav>
+<h1 id="Utilities"><span class="section-number">7.</span> Utility classes and methods</h1>
</header>
-<nav><p>In this chapter:</p><ul class="toc">
-<li><a href="#ComparisonModes">Comparison modes of objects</a></li>
-<li><a href="#ObjectConverters">Object converters</a></li>
-<li><a href="#Internationalization">Internationalization</a><ul>
-<li><a href="#LocalizedString">Distinct character sequences for each locale</a></li>
-<li><a href="#InternationalString">Single instance for all supported locales</a></li>
-<li><a href="#Locale.ROOT">Locale.ROOT convention</a></li>
-<li><a href="#UnicodePoint">Treatment of characters</a><ul>
-<li><a href="#Whitespaces">Blank spaces interpretation</a></li></ul></li></ul></li></ul></nav>
<p>
This chapter describes aspects of Apache <abbr title="Spatial Information System">SIS</abbr> that apply to the entire library.
Most of these utilities are not specific to spatial information systems.
@@ -2444,7 +2191,7 @@ Most of these utilities are not specific to spatial information systems.
<section>
<header>
-<h2 id="ComparisonModes"><span class="section-number">6.1.</span> Comparison modes of objects</h2>
+<h2 id="ComparisonModes"><span class="section-number">7.1.</span> Comparison modes of objects</h2>
</header>
<p>
There are various opinions on how to implement Java standard’s <code>Object.equals(Object)</code> method.
@@ -2520,7 +2267,7 @@ regardless of whether <code>B</code> knows more.
<section>
<header>
-<h2 id="ObjectConverters"><span class="section-number">6.2.</span> Object converters</h2>
+<h2 id="ObjectConverters"><span class="section-number">7.2.</span> Object converters</h2>
</header>
<p>
There is sometime a need to convert instances from a <var>source</var> Java type to a <var>target</var> Java type
@@ -2545,7 +2292,7 @@ An Apache <abbr>SIS</abbr> converter can have zero, one or many of the following
<dd>A function is injective if no pair of <var>S</var> values can produce the same <var>T</var> value.
<div class="example"><p><b>Example:</b>
the <code>Integer</code> → <code>String</code> conversion performed by <code>Integer.toString()</code>
-is an <cite>injective</cite> function because if two <code>Integer</code> values are not equal,
+is an <dfn>injective</dfn> function because if two <code>Integer</code> values are not equal,
then it is guaranteed that their conversions will result in different <code>String</code> values.
However the <code>String</code> → <code>Integer</code> conversion performed by <code>Integer.valueOf(String)</code>
is <strong>not</strong> an injective function
@@ -2558,7 +2305,7 @@ For example converting the "42", "+42" and "0042" character strings all result i
<dd>A function is surjective if each values of <var>T</var> can be created from at least one value of <var>S</var>.
<div class="example"><p><b>Example:</b>
the <code>String</code> → <code>Integer</code> conversion performed by <code>Integer.valueOf(String)</code>
-is a <cite>surjective</cite> function because every <code>Integer</code> value can be created from at least one <code>String</code> value.
+is a <dfn>surjective</dfn> function because every <code>Integer</code> value can be created from at least one <code>String</code> value.
However the <code>Integer</code> → <code>String</code> conversion performed by <code>Integer.toString()</code>
is <strong>not</strong> a surjective function because it can not produce all possible <code>String</code> values.
For example there is no way to produce the "ABC" value with the <code>Integer.toString()</code> method.
@@ -2568,9 +2315,9 @@ For example there is no way to produce the "ABC" value with the <code>Integer
<dt><dfn>Bijective</dfn></dt>
<dd>A function is bijective if there is a one-to-one relationship between <var>S</var> and <var>T</var> values.
<div class="example"><p><b>Note:</b>
-the <cite>bijective</cite> property is defined here for clarity, but actually does not have an explicit item
+the <dfn>bijective</dfn> property is defined here for clarity, but actually does not have an explicit item
in Apache <abbr>SIS</abbr> <code>FunctionProperty</code> enumeration.
-It is not necessary since a function that is both <cite>injective</cite> and <cite>surjective</cite> is necessarily bijective.
+It is not necessary since a function that is both <dfn>injective</dfn> and <dfn>surjective</dfn> is necessarily bijective.
</p></div>
</dd>
@@ -2594,8 +2341,8 @@ a conversion that reverses the sign of numbers.
<p>
Above information may seem unnecessary when values are converted without taking in account the context in which the values appear.
But when the value to convert is part of a bigger object, then above information can affect the way the converted value will be used.
-For example conversion of a [<var>min</var> … <var>max</var>] range is straightforward when the converter is <cite>order preserving</cite>.
-But if the converter is <cite>order reversing</cite>, then the minimum and maximum values need to be interchanged.
+For example conversion of a [<var>min</var> … <var>max</var>] range is straightforward when the converter is <dfn>order preserving</dfn>.
+But if the converter is <dfn>order reversing</dfn>, then the minimum and maximum values need to be interchanged.
For example if the converter reverses the sign of values, then the converted range is [-<var>max</var> … -<var>min</var>].
If the converter is neither order preserving or order reversing, then range conversion is not allowed at all
(because it does not contain the same set of values) even if the minimum and maximum values could be converted individually.
@@ -2605,7 +2352,7 @@ If the converter is neither order preserving or order reversing, then range conv
<section>
<header>
-<h2 id="Internationalization"><span class="section-number">6.3.</span> Internationalization</h2>
+<h2 id="Internationalization"><span class="section-number">7.3.</span> Internationalization</h2>
</header>
<p>
In an architecture where a program executed on a server provides its data to multiple clients,
@@ -2618,7 +2365,7 @@ or at the level of the objects that create the messages.
The approach used also determines whether it is possible to share the same instance of an object for all languages.
</p>
-<h3 id="LocalizedString"><span class="section-number">6.3.1.</span> Distinct character sequences for each locale</h3>
+<h3 id="LocalizedString"><span class="section-number">7.3.1.</span> Distinct character sequences for each locale</h3>
<p>
Some classes are only designed to function according to one locale convention at a time.
This is of course true for the standard implementations of <code>java.text.Format</code>,
@@ -2631,7 +2378,7 @@ by which the instance produces its message.
</p>
<p>
Another class that provides different methods for different locales is <code>java.lang.Throwable</code>.
-The standard Java <abbr title="Application Programming Interface">API</abbr> defines two methods for getting the error message:
+The standard Java <abbr>API</abbr> defines two methods for getting the error message:
<code>getMessage()</code> and <code>getLocalizedMessage()</code>.
Usually those two methods return the same character sequences,
but some exceptions thrown by Apache <abbr>SIS</abbr> may use different locales.
@@ -2660,9 +2407,9 @@ according to the conventions of a given locale, when this information is availab
-<h3 id="InternationalString"><span class="section-number">6.3.2.</span> Single instance for all supported locales</h3>
+<h3 id="InternationalString"><span class="section-number">7.3.2.</span> Single instance for all supported locales</h3>
<p>
-The <abbr title="Application Programming Interface">API</abbr> conventions defined by <abbr title="Spatial Information System">SIS</abbr> or inherited by GeoAPI favour the use of the
+The <abbr>API</abbr> conventions defined by <abbr title="Spatial Information System">SIS</abbr> or inherited by GeoAPI favour the use of the
<code class="GeoAPI">InternationalString</code> type when the value of a <code>String</code> type would likely be localized.
This approach allows us to defer the internationalization process to the time when a character sequence is requested,
rather than the time when the object that contains them is created.
@@ -2686,18 +2433,18 @@ so sharing a single instance becomes even more preferable in order to reduce mem
-<h3 id="Locale.ROOT"><span class="section-number">6.3.3.</span> <code>Locale.ROOT</code> convention</h3>
+<h3 id="Locale.ROOT"><span class="section-number">7.3.3.</span> <code>Locale.ROOT</code> convention</h3>
<p>
All <abbr title="Spatial Information System">SIS</abbr> methods receiving or returning the value of a <code>Locale</code> type accept the <code>Locale.ROOT</code> value.
This value is interpreted as specifying not to localize the text.
-The notion of a <cite>non-localized text</cite> is a little false, as it is always necessary to chose a formatting convention.
+The notion of a <dfn>non-localized text</dfn> is a little false, as it is always necessary to chose a formatting convention.
This convention however, though very close to English, is usually slightly different.
For example:
</p>
<ul>
<li>
-Identifiers are written as they appear in <abbr title="Unified Modeling Language">UML</abbr> diagrams,
-such as <cite>blurredImage</cite> instead of <cite>Blurred image</cite>.
+Identifiers are written as they appear in <abbr>UML</abbr> diagrams,
+such as <var>blurredImage</var> instead of <var>Blurred image</var>.
</li>
<li>
Dates are written according to the <abbr title="International Organization for Standardization">ISO</abbr> 8601 format,
@@ -2712,119 +2459,412 @@ use of exponential notation and the absence of thousands separators.
-<h3 id="UnicodePoint"><span class="section-number">6.3.4.</span> Treatment of characters</h3>
+<h3 id="UnicodePoint"><span class="section-number">7.3.4.</span> Treatment of characters</h3>
+<p>
+In Java, sequences of characters use UTF-16 encoding.
+There is a direct correspondence between the values of the <code>char</code> type and the great majority of characters,
+which facilitates the use of sequences so long as these characters are sufficient.
+However, certain Unicode characters cannot be represented by a single <code>char</code>.
+These <i>supplementary characters</i> include certain ideograms,
+but also road and geographical symbols in the 1F680 to 1F700 range.
+Support for these supplementary characters requires slightly more complex interactions than the classic case,
+where we may assume a direct correspondence.
+Thus, instead of the loop on the left below, international applications must generally use the loop on the right:
+</p>
+
+<div class="row-of-boxes">
+<div>
+<div class="caption">Loop to Avoid</div>
+<pre style="margin-top: 6pt"><code><b>for</b> (<b>int</b> i=0; i<string.length(); i++) {
+ <b>char</b> c = string.charAt(i);
+ <b>if</b> (Character.isWhitespace(c)) {
+ <code class="comment">// A blank space was found.</code>
+ }
+}</code></pre>
+</div>
+<div>
+<div class="caption">Recommended loop</div>
+<pre style="margin-top: 6pt"><code><b>for</b> (<b>int</b> i=0; i<string.length();) {
+ <b>int</b> c = string.codePointAt(i);
+ <b>if</b> (Character.isWhitespace(c)) {
+ <code class="comment">// A blank space was found.</code>
+ }
+ i += Character.charCount(c);
+}</code></pre>
+</div>
+<div>
+<div class="caption">Supplementary character examples</div>
+<center>(rendering depends on browser capabilities)</center>
+<p style="font-size: 40px">🚉 🚥 🚧 🚫
+🚯 🚸 🚺 🚹 🛄 🚭</p>
+</div>
+</div>
+
+<p>
+<abbr title="Spatial Information System">SIS</abbr> supports supplementary characters by using the loop on the right where necessary,
+but the loop on the left is occasionally used when it is known that the characters searched for are not supplementary characters,
+even if some may be present in the sequence in which we are searching.
+</p>
+
+
+
+<h4 id="Whitespaces"><span class="section-number">7.3.4.1.</span> Blank spaces interpretation</h4>
+<p>
+Standard Java provides two methods for determining whether a character is a blank space:
+<code>Character.isWhitespace(…)</code> and <code>Character.isSpaceChar(…)</code>.
+These two methods differ in their interpretations of non-breaking spaces, tabs and line breaks.
+The first method conforms to the interpretation currently used in languages such as Java, C/C++ and <abbr>XML</abbr>,
+which considers tabs and line breaks to be blank spaces, while non-breaking spaces are read as not blank.
+The second method — which conforms strictly to the Unicode definition — makes the opposite interpretation.
+</p>
+<p>
+<abbr title="Spatial Information System">SIS</abbr> uses each of these methods in different contexts.
+<code>isWhitespace(…)</code> is used to <em>separate</em> the elements of a list (numbers, dates, words, etc.),
+while <code>isSpaceChar(…)</code> is used to ignore blank spaces <em>inside</em> a single element.
+</p>
+<div class="example"><p><b>Example:</b>
+Take a list of numbers represented according to French conventions.
+Each number may contain <em>non-breaking spaces</em> as thousands separators,
+while the different numbers in the list may be separated by ordinary spaces, tabs or line breaks.
+When analyzing a number, we want to consider the non-breaking spaces as being part of the number,
+whereas a tab or a line break most likely indicates a separation between this number and the next.
+We would thus use <code>isSpaceChar(…)</code>.
+Conversely, when separating the numbers in the list, we want to consider tabs and line breaks as separators,
+but not non-breaking spaces.
+We would thus use <code>isWhitespace(…)</code>.
+The role of ordinary spaces, to which either case might apply, should be decided beforehand.
+</p></div>
+<p>
+In practice, this distinction is reflected in the use of <code>isSpaceChar(…)</code> in the implementations of <code>java.text.Format</code>,
+or the use of <code>isWhitespace(…)</code> in nearly all the rest of the <abbr>SIS</abbr> library.
+</p>
+</section>
+</section>
+
+
+<section>
+<header>
+<h1 id="Annexes"><span class="section-number">8.</span> Annexes</h1>
+</header>
+<p>
+The rest of this document provides historical contexts, rational behind some design choices
+and guidance for reducing the dependency of an application to Apache SIS.
+Those annexes can be safely ignored by most Apache SIS users,
+but may be useful for developers wanting to create their own geospatial libraries.
+</p>
+
+
+
+
+
+
+<section>
+<header>
+<h2 id="Standards"><span class="section-number">8.1.</span> Standards and norms</h2>
+</header>
+
+<p>
+A geospatial information community is a collection of systems or individuals capable of exchanging their geospatial data
+through the use of common standards, allowing them to communicate with one another.
+As there are many ways to represent geospatial information, each community tends to structure this information in light of its areas of interest.
+This diversity complicates the task of Spatial Information System (<abbr title="Spatial Information System">SIS</abbr>) users
+by confronting them with an apparently chaotic variety of data formats and structures.
+The characteristics of these structures vary according to the observed phenomenon and measurement methods,
+as well as the habits of the organizations producing the data.
+Such a variety represents an obstacle in studies that require heterogeneous combinations of data,
+especially when they originate in communities that are traditionally distinct.
+For example, a researcher studying cholera might be interested in populations of shrimp as a propagation vector of the disease.
+But as doctors and oceanographers may not be used to share their work,
+the participants of such a study may be limited by the effort required to convert the data.
+</p><p>
+We cannot impose a uniform format on all data collections, as the diversity of formats is tied to factors
+such as the constraints imposed by the measuring apparatus, and the statistical distribution of values.
+A more flexible solution is to ensure the interoperability of data across a common programming interface
+(<abbr title="Application Programming Interface">API</abbr>).
+This <abbr>API</abbr> is not necessarily defined in a programming language;
+the actual tendency is rather to define conventions that use existing web protocols, which we can translate into various programming languages.
+But in order for this approach to be viable, the <abbr>API</abbr> must be generally accepted by independent developers.
+In other words, the <abbr>API</abbr> must come as near as possible to industrial standards.
+</p><p>
+For example, one task that benefit from a successful standardization is the accessing of relational databases.
+The industry has established a common language — the <abbr title="Structured Query Language">SQL</abbr> standard —
+that the creators of Java have embedded in standard <abbr title="Java DataBase Connectivity">JDBC</abbr> programming interfaces.
+Today, these interfaces are implemented by many software programs, both free and commercial.
+Like databases, methods of accessing geographic information have been standardized.
+In this case, however, the efforts have been more recent, and their integration in software — especially in older programs — is incomplete and not always coherent.
+At the time of writing, no product to our knowledge has implemented all of the specifications in their entirety.
+However, there are many implementations that cover a fairly large spectrum.
+One of these is the Apache <abbr>SIS</abbr>™ library that is described in this document.
+</p><p>
+Apache <abbr title="Spatial Information System">SIS</abbr> is characterized by a sustained effort to comply with standards.
+In general, complying with standards demands a greater effort than would be required for an isolated development,
+but rewards us with a double advantage: not only does it improve the interoperability of our data with that of external projects,
+it also points towards a robust way of elaborating the conceptual model reflected in the <abbr>API</abbr>.
+In effect, the groups of experts who conceived the standards anticipated difficulties that sometimes escape the engineer at the beginning of a project,
+but which risk to hit them before the end.
+</p>
+
+
+
+
+
+
+
+
+<section>
+<header>
+<h3 id="ConceptualModels"><span class="section-number">8.1.1.</span> Sources of conceptual models used by Apache SIS</h3>
+</header>
+<p>
+Most standards used by Apache <abbr title="Spatial Information System">SIS</abbr> have been devised by the <a href="https://www.ogc.org/">Open Geospatial Consortium</a> (<abbr title="Open Geospatial Consortium">OGC</abbr>),
+sometimes in collaboration with the <a href="https://www.iso.org/">International Organization for Standardization</a> (<abbr title="International Organization for Standardization">ISO</abbr>).
+Some <abbr>ISO</abbr> standards themselves become European standards via the <a href="http://inspire.jrc.ec.europa.eu">INSPIRE Directive</a>.
+These standards offer two key features:
+</p>
+<ul>
+<li>
+Allowing a community to make its information public in such a way that outside individuals or systems can discover it.
+</li>
+<li>
+Transferring information from one community to another while preserving its semantics,
+even if the two communities use very different internal representations.
+</li>
+</ul>
+<p>
+These standards are made available to the international community for free,
+as <a href="https://www.ogc.org/standards/is">specifications (<abbr title="Portable Document Format">PDF</abbr> files)</a> or
+as <a href="http://schemas.opengis.net/gml/3.3/">schemas (<abbr title="XML Schema Definition">XSD</abbr> files)</a>.
+Standardization organizations do not create software; to obtain an implementation of these specifications,
+users must choose one of the compliant products available on the market, or develop their own solutions.
+Such voluntary compliance with these specifications allow independent communities to more easily exchange geographic information.
+</p>
+
+
+
+<details>
+<summary>More about standardization process</summary>
+<article id="OGC-process">
+<header>
+<h2><abbr title="Open Geospatial Consortium">OGC</abbr> standardization process</h2>
+</header>
+<p>
+The work of the <abbr title="Open Geospatial Consortium">OGC</abbr> is done by email, teleconferences, and at <a href="https://www.ogc.org/event?category=ogctcpc">in-person meetings</a>.
+The <abbr>OGC</abbr> organizes four meetings per year, each lasting five days, and hosted by member organizations that sponsor the event (companies, universities, research centres, <i>etc</i>).
+The host continent alternates between Europe and North America, with a growing presence in Asia since 2011.
+These meetings are usually attended by between 50 and 100 participants from among the hundreds of members of the <abbr>OGC</abbr>.
+Some participants are present at almost all the meetings, forming the pillars of the organization.
+The meetings of the <abbr>OGC</abbr> offer opportunities for exchange among members from diverse backgrounds.
+</p><p>
+The creation of a <abbr>OGC</abbr> standard begins with a gathering of organizations or individuals with a common interest in an issue.
+A working group is proposed as a <i>Domain Working Group</i> (<abbr>DWG</abbr>) or as a <i>Standard Working Group</i> (<abbr>SWG</abbr>).
+<abbr>DWG</abbr>s are open to all members of the <abbr>OGC</abbr>,
+while <abbr>SWG</abbr>s require that their participants enter into an agreement not to hinder the distribution of the standard through intellectual property claims.
+</p>
+
+<h3 id="OGC-SWG">Standard Working Group (<abbr>SWG</abbr>) procedures</h3>
+<p>
+In order to be accepted, a standardization project must be supported by a minimum number of members belonging to distinct organizations.
+These founding members draft a charter defining the objectives of the <abbr>SWG</abbr>,
+which must be approved by the Technical Committee of the <abbr title="Open Geospatial Consortium">OGC</abbr>.
+Each founding member is endowed with the right to vote, with a limit of one voting member per organization.
+Each new member that wishes to join the <abbr>SWG</abbr> after its creation is granted the role of observer,
+and receives on request the right to vote after several months of observation.
+</p><p>
+A <abbr>SWG</abbr> may contain several dozen members, but the volunteers performing the bulk of the work are usually fewer.
+Their proposals are submitted to the entire membership of the group, who may accept them by unanimous consent.
+Any objections must be debated, and an alternative proposed.
+<abbr>SWG</abbr>s usually try to debate an issue until a consensus emerges rather than move ahead despite negative votes,
+even if those opposed are in a minority.
+The decisions of the group are then integrated into the specifications by a member who assumes the role of editor.
+</p><p>
+As far as possible, the working group must structure the specifications as a core around which various extensions might be built.
+A series of tests must accompany the standard, allowing implementations to be classified by the level of test passed.
+There must be at least one <i>reference implementation</i> that passes all the tests in order to demonstrate that the standard is usable.
+</p><p>
+When the standard is considered ready, the <abbr>SWG</abbr> votes on a motion proposing its submission to a vote by the higher authorities of the <abbr>OGC</abbr>.
+This process takes several months. There is a faster process for approving <i>de facto</i> standards, but it is applied sparingly.
+</p>
+
+<h3 id="OGC-OAB">The Architecture Board (<abbr>OAB</abbr>) and the Technical Committee (<abbr>TC</abbr>)</h3>
<p>
-In Java, sequences of characters use UTF-16 encoding.
-There is a direct correspondence between the values of the <code>char</code> type and the great majority of characters,
-which facilitates the use of sequences so long as these characters are sufficient.
-However, certain Unicode characters cannot be represented by a single <code>char</code>.
-These <i>supplementary characters</i> include certain ideograms,
-but also road and geographical symbols in the 1F680 to 1F700 range.
-Support for these supplementary characters requires slightly more complex interactions than the classic case,
-where we may assume a direct correspondence.
-Thus, instead of the loop on the left below, international applications must generally use the loop on the right:
+All proposals for standards are first examined by the <abbr title="Open Geospatial Consortium">OGC</abbr> Architecture Board (<abbr>OAB</abbr>).
+This board ensures that the standard conforms to the requirements of the <abbr>OGC</abbr> in form,
+modularization, and in terms of integration with other standards.
+If the <abbr>OAB</abbr> approves it, the standard is next submitted to a vote by the members of the Technical Committee (<abbr>TC</abbr>).
+This committee consists of the principal members of the <abbr>OGC</abbr>, and only they are capable of granting final approval.
+If approved, the standard is made publicly available for comments during a period of several months.
+At the end of this period, the <abbr title="Standard Working Group">SWG</abbr> must examine and respond to each comment.
+The eventual modifications of the standard are submitted to the <abbr>OAB</abbr>, then the standard is published in its final form.
+This distribution is announced in a press release by the <abbr>OGC</abbr>.
+</p><p>
+Certain members of the <abbr title="Open Geospatial Consortium">OGC</abbr> and the <abbr title="Technical Committee">TC</abbr>
+also act as liaisons with the International Organization for Standardization (<abbr title="International Organization for Standardization">ISO</abbr>).
+Cooperation between the two organizations goes two ways:
+the <abbr>OGC</abbr> adopts the <abbr>ISO</abbr> standards as a foundation on which to develop new standards,
+and certain <abbr>OGC</abbr> standards become <abbr>ISO</abbr> standards.
</p>
-<div class="row-of-boxes">
-<div>
-<div class="caption">Loop to Avoid</div>
-<pre style="margin-top: 6pt"><code><b>for</b> (<b>int</b> i=0; i<string.length(); i++) {
- <b>char</b> c = string.charAt(i);
- <b>if</b> (Character.isWhitespace(c)) {
- <code class="comment">// A blank space was found.</code>
- }
-}</code></pre>
-</div>
-<div>
-<div class="caption">Recommended loop</div>
-<pre style="margin-top: 6pt"><code><b>for</b> (<b>int</b> i=0; i<string.length();) {
- <b>int</b> c = string.codePointAt(i);
- <b>if</b> (Character.isWhitespace(c)) {
- <code class="comment">// A blank space was found.</code>
- }
- i += Character.charCount(c);
-}</code></pre>
-</div>
-<div>
-<div class="caption">Supplementary character examples</div>
-<center>(rendering depends on browser capabilities)</center>
-<p style="font-size: 40px">🚉 🚥 🚧 🚫
-🚯 🚸 🚺 🚹 🛄 🚭</p>
-</div>
-</div>
-
+<h3 id="OGC-RFC">Procedure for the submission of proposals for modification</h3>
<p>
-<abbr title="Spatial Information System">SIS</abbr> supports supplementary characters by using the loop on the right where necessary,
-but the loop on the left is occasionally used when it is known that the characters searched for are not supplementary characters,
-even if some may be present in the sequence in which we are searching.
+All users, whether or not they are members of the Open Geospatial Consortium, may propose modifications to <abbr title="Open Geospatial Consortium">OGC</abbr> standards.
+A list of current proposals for changes, along with a form for submitting new proposals, is <a href="https://www.ogc.org/standards/cr">available online</a>.
+Each proposal is reviewed by the <abbr title="Standard Working Group">SWG</abbr>.
+</p><p>
+Some working groups use other parallel systems for submissions, for example GitHub merge requests, hosted outside of the structures of the <abbr>OGC</abbr>.
</p>
+</article>
+</details>
-<h4 id="Whitespaces"><span class="section-number">6.3.4.1.</span> Blank spaces interpretation</h4>
<p>
-Standard Java provides two methods for determining whether a character is a blank space:
-<code>Character.isWhitespace(…)</code> and <code>Character.isSpaceChar(…)</code>.
-These two methods differ in their interpretations of non-breaking spaces, tabs and line breaks.
-The first method conforms to the interpretation currently used in languages such as Java, C/C++ and <abbr>XML</abbr>,
-which considers tabs and line breaks to be blank spaces, while non-breaking spaces are read as not blank.
-The second method — which conforms strictly to the Unicode definition — makes the opposite interpretation.
+Besides these formal standardization organizations, there are organizations that are not officially dedicated
+to the creation of standards, but whose work has largely been adopted as <i>de facto</i> standards.
+In particular, the <a href="https://epsg.org/">EPSG repository</a> offers numeric codes which allow the easy identification of a
+Coordinates Reference System (<abbr>CRS</abbr>) among <a href="../../tables/CoordinateReferenceSystems.html">several thousand</a>.
+This database is offered by petroleum companies that have an interest in ensuring their explorations are conducted in the correct place,
+even when using map produced by another party.
+Other examples of <i>de facto</i> standards include <a href="http://geotiff.osgeo.org">GeoTIFF</a> for data distributed on a grid (such as images),
+and <a href="http://en.wikipedia.org/wiki/Shapefile">Shapefile</a> for vector data (such as geometric shapes).
+</p><p>
+<abbr>OGC</abbr> standards are specified in several dozen documents.
+Each document outlines a service — for example, the transformation of coordinates.
+The function of each service is described by a collection of object classes and their interactions.
+These elements are illustrated by <abbr>UML</abbr> (Unified Modeling Language) diagrams in specifications called “abstracts”.
+<a href="https://www.ogc.org/standards/as">Abstract specifications</a> do not refer to any specific computer language.
+Their concepts may be applied more or less directly to a programming language, a database or an <abbr>XML</abbr> schema.
+There is always an element of arbitrariness in the method of applying an abstract specification,
+given that adjustments are often necessary to take into account the constraints or conventions of the target language.
+Certain data structures only exist in a few languages — for example, unions that exist in C/C++ but not in Java.
</p>
+
+
+
+<details>
+<summary>More about “implementation specifications”</summary>
+<article id="implementation-standard">
+<header>
+<h2>Historical note</h2>
+</header>
<p>
-<abbr title="Spatial Information System">SIS</abbr> uses each of these methods in different contexts.
-<code>isWhitespace(…)</code> is used to <em>separate</em> the elements of a list (numbers, dates, words, etc.),
-while <code>isSpaceChar(…)</code> is used to ignore blank spaces <em>inside</em> a single element.
+At the turn of the millennium, the abstract specifications were explicitly concretized in <i>implementation specifications</i>.
+The term “implementation” is used here in the sense of all types of interfaces (Java or others) derived from
+<abbr title="Unified Modeling Language">UML</abbr> diagrams, and not implementations in the Java sense.
+Such specifications existed for <abbr title="Structured Query Language">SQL</abbr>,
+<abbr title="Common Object Request Broker Architecture">CORBA</abbr>, <abbr title="Component Object Model">COM</abbr>, and Java languages.
+As these languages are capable of executing procedures, the specifications of this period define not only data structures,
+but also operations that apply to these structures.
+</p><p>
+Thereafter, enthusiasm for “Web 2.0” increased interest for <abbr>XML</abbr> over other languages.
+Older implementation specifications were deprecated,
+and <abbr title="XML Schema Definition">XSD</abbr> schemas became the main concretization of abstract specifications.
+Even the way abstract specifications are designed has evolved: they are less likely to define operations, and so what remains is closer to descriptions of database schemas.
+Some operations that were defined in older standards now appear, in another form, in web service specifications.
+Finally, the term “implementation specification” has been deprecated, to be subsumed under the term “<abbr title="Open Geospatial Consortium">OGC</abbr> standard.”
+But despite their depreciation, <a href="https://www.ogc.org/docs/retired">old implementation specifications</a> remain useful to programs in Java, because:
</p>
-<div class="example"><p><b>Example:</b>
-Take a list of numbers represented according to French conventions.
-Each number may contain <em>non-breaking spaces</em> as thousands separators,
-while the different numbers in the list may be separated by ordinary spaces, tabs or line breaks.
-When analyzing a number, we want to consider the non-breaking spaces as being part of the number,
-whereas a tab or a line break most likely indicates a separation between this number and the next.
-We would thus use <code>isSpaceChar(…)</code>.
-Conversely, when separating the numbers in the list, we want to consider tabs and line breaks as separators,
-but not non-breaking spaces.
-We would thus use <code>isWhitespace(…)</code>.
-The role of ordinary spaces, to which either case might apply, should be decided beforehand.
-</p></div>
+<ul>
+<li>Their simpler models, applied to the same concepts, are helpful in understanding new specifications.</li>
+<li>They sometimes define easy ways to perform common tasks, where the newer specifications limit themselves to general cases.</li>
+<li>As operations are more often omitted from the newer specifications, the old ones remain a useful supplement when defining <abbr title="Application Programming Interface">API</abbr>s.</li>
+</ul>
<p>
-In practice, this distinction is reflected in the use of <code>isSpaceChar(…)</code> in the implementations of <code>java.text.Format</code>,
-or the use of <code>isWhitespace(…)</code> in nearly all the rest of the <abbr>SIS</abbr> library.
+The Apache <abbr title="Spatial Information System">SIS</abbr> project is based on the most recent specifications,
+drawing from the archives of the <abbr>OGC</abbr> to complete certain abstract standards or make them more usable.
+Some old definitions are preserved as “convenience methods”, not always bringing new functionality, but facilitating the practical use of a library.
</p>
-</section>
+</article>
+</details>
</section>
<section>
<header>
-<h1 id="GeoAPI-details"><span class="section-number">7.</span> GeoAPI relationship with standards</h1>
-<nav><div class="chapter-links"><div class="previous-chapter">⬅ <a href="#Utilities">Previous chapter</a></div><div class="next-chapter"><a href="#Tests">Next chapter</a> ➡</div></div></nav>
+<h3 id="GeoAPI"><span class="section-number">8.1.2.</span> From conceptual models to Java interfaces: GeoAPI</h3>
</header>
-
-<nav><p>In this chapter:</p><ul class="toc">
-<li><a href="#GeoAPI-modules">GeoAPI modules</a></li>
-<li><a href="#SpecificationToInterfaces">From OGC specifications to Java interfaces</a><ul>
-<li><a href="#UML-annotation">Explicit mapping given by @UML annotations</a></li>
-<li><a href="#MappingToJDK">Implicit mapping to standard JDK</a></li></ul></li>
-<li><a href="#ReduceDependency">Reduce direct dependency to Apache SIS</a><ul>
-<li><a href="#UML-annotation-indep">Mapping given by @UML annotations</a></li>
-<li><a href="#ServiceLoader">Fetching implementations of GeoAPI interfaces</a><ul>
-<li><a href="#GeoAPI-simple">Defining custom implementations</a></li></ul></li></ul></li></ul></nav>
<p>
-The GeoAPI project has been briefly presented <a href="#GeoAPI">in introduction</a> to this document.
-This annex explains in more details how GeoAPI relates to international standards.
-The goal is to allow developers to reduce their dependency toward GeoAPI or Apache SIS specificities.
+The <a href="http://www.geoapi.org">GeoAPI</a> project offers a set of Java interfaces for geospatial applications.
+In a series of <code class="GeoAPI">org.opengis.*</code> packages, GeoAPI defines structures representing metadata,
+coordinate reference systems and operations that perform cartographic projections.
+In a part that is not yet standardized — called <i>pending</i> — GeoAPI defines structures that represent geo-referenced images,
+geometries, filters that can be applied to queries, and other features.
+These interfaces closely follow the specifications of the <abbr title="Open Geospatial Consortium">OGC</abbr>, while interpreting and adapting them
+to meet the needs of Java developers — for example, conforming with naming conventions.
+These interfaces benefit both client applications and libraries:
</p>
+<ul>
+<li><p>
+Developers of client applications benefit from the greater knowledge base available on the Internet
+(due to the many publications related to <abbr>OGC</abbr> standards), as well as increased interoperability.
+Interoperability is facilitated by a better separation between applications that <em>call</em> GeoAPI functions,
+and libraries that <em>implement</em> GeoAPI.
+The separation is similar to that offered by the <a href="http://docs.oracle.com/javase/8/docs/technotes/guides/jdbc/"><abbr title="Java DataBase Connectivity">JDBC</abbr></a> (<i>Java Database Connectivity</i>) interfaces of standard Java.
+Using the interfaces’ <abbr title="Application Programming Interface">API</abbr>, developers can ignore the underlying implementation.
+For example, they can perform cartographic projections with the help of the <a href="http://www.geoapi.org/geoapi-proj4/index.html">Proj.4</a> library, or the Apache <abbr title="Spatial Information System">SIS</abbr> library,
+without having to change their programs when they change libraries.
+</p></li>
+<li><p>
+The developers of libraries inherit the expertise of the specifications’ authors, via the models that represent interfaces.
+GeoAPI also provides a framework within which developers can prioritize the implementation of the features they most need,
+while leaving the remaining features as extension points for future developments.
+For example, clients can call a GeoAPI function even if it is not yet supported by the library,
+and simply get a null value until a new version of the library returns a relevant value.
+</p></li>
+</ul>
-
-
+<details>
+<summary>More about the GeoAPI project</summary>
+<article id="GeoAPI-history">
+<header>
+<h2>GeoAPI project history</h2>
+</header>
+<p>
+In 2001, the Open GIS Consortium (the former name of the Open Geospatial Consortium) published
+<a href="https://www.ogc.org/standards/ct"><abbr title="Open Geospatial Consortium">OGC</abbr> implementation specification 01-009:
+<cite>Coordinate Transformation Services</cite></a>.
+This specification, developed by the Computer Aided Development Corporation (Cadcorp),
+was accompanied by <abbr title="Component Object Model">COM</abbr>, <abbr title="Common Object Request Broker Architecture">CORBA</abbr>, and Java interfaces.
+At this time, the wave of web services had not yet eclipsed classical programming interfaces.
+The interfaces of the <abbr>OGC</abbr> did anticipate a networked world,
+but invested rather — in the case of Java — in <abbr>RMI</abbr> (<i>Remote Method Invocation</i>) technology.
+As the GeoAPI project did not yet exist, we retroactively designate these historical interfaces “<a href="http://www.geoapi.org/0.1/index.html">GeoAPI 0.1</a>”.
+These interfaces already used the package name <code class="GeoAPI">org.opengis</code>, which would be adopted by GeoAPI.
+</p><p>
+In 2002, developers of free projects launched a
+<a href="http://web.archive.org/web/20030509104308/http://digitalearth.org/story/2002/10/10/55046/206">call for the creation of a geospatial <abbr title="Application Programming Interface">API</abbr></a>.
+The initial proposal attracted the interest of at least five free projects.
+The project was created using <a href="http://sourceforge.net/projects/geoapi/">SourceForge</a>,
+which has since hosted the source code in a <a href="http://www.geoapi.org/source-repository.html">Subversion repository</a>.
+It was then that the project assumed the name “GeoAPI”, and used the interfaces of the <abbr>OGC</abbr> specification 01-009 as a starting point.
+</p><p>
+A few months later, the <abbr>OGC</abbr> launched the <a href="https://www.ogc.org/standards/go"><abbr>GO</abbr>-1: <i>Geographic Objects</i></a> project,
+which pursued goals similar to those of GeoAPI.
+In the meantime, the <abbr>OGC</abbr> abandonned some of their specifications in favor of <abbr title="International Organization for Standardization">ISO</abbr> standards.
+GeoAPI and <abbr>GO-1</abbr> worked jointly to rework the GeoAPI interfaces and base them on the new <abbr>ISO</abbr> norms.
+Their first interation, <a href="http://www.geoapi.org/1.0/index.html">GeoAPI 1.0</a>,
+served as a starting point for the first draft of the <abbr>OGC</abbr> specification 03-064 by the <abbr>GO</abbr>-1 working group.
+The final version of this specification became an <abbr>OGC</abbr> standard in 2005,
+and <a href="http://www.geoapi.org/2.0/index.html">GeoAPI 2.0</a> was published at that time.
+</p><p>
+The <abbr>GO</abbr>-1 project was largely supported by a company called <i>Polexis</i>.
+Its acquisition by <i>Sys Technology</i>, and the change in priorities under the new owners,
+brought a halt to the <abbr>GO</abbr>-1 project, which in turn slowed development on GeoAPI.
+In order to resume development, a new working group entitled “GeoAPI 3.0” was created at the <abbr>OGC</abbr>.
+This group took a narrower focus compared to GeoAPI 2.0, concentrating on the most stable interfaces, and putting the others
+— such as geometries — in a module entitled “<a href="http://www.geoapi.org/geoapi-pending/index.html">pending</a>”, for future consideration.
+<a href="http://www.geoapi.org/3.0/index.html">GeoAPI 3.0</a> became an <a href="https://www.ogc.org/standards/geoapi"><abbr>OGC</abbr> standard</a> in 2011.
+This version was the first to be deployed in the <a href="http://search.maven.org/#search|ga|1|geoapi">Maven central repository</a>.
+</p>
+</article>
+</details>
+</section>
<section>
<header>
-<h2 id="GeoAPI-modules"><span class="section-number">7.1.</span> GeoAPI modules</h2>
+<h3 id="GeoAPI-modules"><span class="section-number">8.1.3.</span> GeoAPI modules</h3>
</header>
<p>
The GeoAPI project consists of a standardized part (<code class="GeoAPI">geoapi</code>)
@@ -2849,8 +2889,9 @@ The final versions of Apache <abbr>SIS</abbr> depend on this module.
<em>copy</em> of all interfaces in the <code class="GeoAPI">geoapi</code> module
(not a dependence) with additions that have not yet been approved as an <abbr>OGC</abbr> standard.
Some additions appear in interfaces normally defined by the <code class="GeoAPI">geoapi</code> module, hence the need to copy them.
-Apache <abbr>SIS</abbr>’s development branches <code>JDK8</code> and <code>JDK9</code> depend on this module,
-but this dependence becomes a dependence on the <code class="GeoAPI">geoapi</code> standard module when the branches are merged to the trunk.
+Apache <abbr>SIS</abbr>’s development branches depend on this module,
+but this dependence becomes a dependence on the <code class="GeoAPI">geoapi</code> standard module
+when the development branches are merged to the main branch.
</p></li>
<li><p>
<b><code class="GeoAPI">geoapi-conformance</code></b> — includes a JUnit test suite that developers may use to test their implementations.
@@ -2860,21 +2901,6 @@ but this dependence becomes a dependence on the <code class="GeoAPI">geoapi</cod
These examples are placed in the public domain in order to encourage users to copy and adapt them to their needs if
Apache <abbr>SIS</abbr> services are unsuitable.
</p></li>
-<li><p>
-<b><code class="GeoAPI">geoapi-proj4</code></b> — contains a partial implementation of <code class="GeoAPI">org.opengis.referencing</code>
-packages as adaptors based on the C/C++ Proj.4 library.
-This module may be used as an alternative to the <code class="SIS">sis-referencing</code> module for certain functions.
-</p></li>
-<li><p>
-<b><code class="GeoAPI">geoapi-netcdf</code></b> — contains a partial implementation of <code class="GeoAPI">org.opengis.referencing</code>
-and <code class="GeoAPI">org.opengis.coverage</code> packages as adaptors based on the <abbr title="University Corporation for Atmospheric Research">UCAR</abbr> <abbr title="Network Common Data Form">netCDF</abbr> library.
-The series of tests in this module was developed in such a way as to be reusable for other projects.
-Apache <abbr>SIS</abbr> uses them to test its own <code class="SIS">sis-netcdf</code> module.
-</p></li>
-<li><p>
-<b><code class="GeoAPI">geoapi-openoffice</code></b> — contains an add-in for the OpenOffice.org office suite.
-Note: Apache <abbr>SIS</abbr> provides its own <i>add-in</i> in the <code class="SIS">sis-openoffice</code> module.
-</p></li>
</ul>
</section>
@@ -2882,7 +2908,7 @@ Note: Apache <abbr>SIS</abbr> provides its own <i>add-in</i> in the <code class=
<section>
<header>
-<h2 id="SpecificationToInterfaces"><span class="section-number">7.2.</span> From <abbr title="Open Geospatial Consortium">OGC</abbr> specifications to Java interfaces</h2>
+<h3 id="SpecificationToInterfaces"><span class="section-number">8.1.4.</span> From <abbr title="Open Geospatial Consortium">OGC</abbr> specifications to Java interfaces</h3>
</header>
<p>
GeoAPI interfaces are sometime generated from other files provided by <abbr>OGC</abbr>, like <abbr title="XML Schema Definition">XSD</abbr> files.
@@ -2890,7 +2916,7 @@ But there is always a manual revision, and often modifications compared to autom
It would have been possible to automatically generate Java interfaces from <abbr>OGC</abbr> standards using existing tools.
For example one of the most commonly-used approaches is to transform <a href="http://schemas.opengis.net/gml/3.3/"><abbr>XSD</abbr> schemas</a>
into Java interfaces using command line utility <code>xjc</code>.
-As this utility is included in most Java distributions (it is one of the <a href="http://jaxb.java.net"><abbr title="Java Architecture for XML Binding">JAXB</abbr></a> tools),
+As this utility is included in most Java distributions (it is one of the <a href="http://jaxb.java.net"><abbr>JAXB</abbr></a> tools),
this approach is favoured by many projects found on the Internet.
Other approaches use tools integrated into the Eclipse Development Environment,
which is based on <abbr title="Unified Modeling Language">UML</abbr> schemas rather than <abbr>XSD</abbr> ones.
@@ -2996,7 +3022,7 @@ the correspondence between these languages is explained by <code class="GeoAPI">
-<h3 id="UML-annotation"><span class="section-number">7.2.1.</span> Explicit mapping given by <code class="GeoAPI">@UML</code> annotations</h3>
+<h4 id="UML-annotation"><span class="section-number">8.1.4.1.</span> Explicit mapping given by <code class="GeoAPI">@UML</code> annotations</h4>
<p>
For each class, method and constant defined by an <abbr title="Open Geospatial Consortium">OGC</abbr> or <abbr title="International Organization for Standardization">ISO</abbr> standard,
GeoAPI indicates its provenance using annotations defined in the <code class="GeoAPI">org.opengis.annotation</code> package.
@@ -3044,7 +3070,7 @@ provided in a <a href="#UML-annotation-geoapi">separated chapter</a>.
-<h3 id="MappingToJDK"><span class="section-number">7.2.2.</span> Implicit mapping to standard <abbr>JDK</abbr></h3>
+<h4 id="MappingToJDK"><span class="section-number">8.1.4.2.</span> Implicit mapping to standard <abbr>JDK</abbr></h4>
<p>
Some classes and methods have neither an <code class="GeoAPI">@UML</code> annotation, nor an entry in the <code class="GeoAPI">class-index.properties</code> file.
They are either extensions of GeoAPI, or else types defined in other libraries, such as standard <abbr title="Java Development Kit">JDK</abbr>.
@@ -3231,7 +3257,7 @@ MediumName usbKey = MediumName.<code class="GeoAPI">valueOf</code>(<i>"<code cla
<section>
<header>
-<h2 id="ReduceDependency"><span class="section-number">7.3.</span> Reduce direct dependency to Apache SIS</h2>
+<h3 id="ReduceDependency"><span class="section-number">8.1.5.</span> Reduce direct dependency to Apache SIS</h3>
</header>
<p>
Previous chapters used Apache SIS static methods for convenience.
@@ -3242,7 +3268,7 @@ However this may require that applications write their own convenience methods.
The following sections provide some tip for easing this task.
</p>
-<h3 id="UML-annotation-indep"><span class="section-number">7.3.1.</span> Mapping given by <code class="GeoAPI">@UML</code> annotations</h3>
+<h4 id="UML-annotation-indep"><span class="section-number">8.1.5.1.</span> Mapping given by <code class="GeoAPI">@UML</code> annotations</h4>
<p>
For each class, method and constant defined by an <abbr title="Open Geospatial Consortium">OGC</abbr> or <abbr title="International Organization for Standardization">ISO</abbr> standard,
GeoAPI indicates its provenance using annotations defined in the <code class="GeoAPI">org.opengis.annotation</code> package.
@@ -3282,7 +3308,7 @@ The <code class="SIS">org.apache.sis.util.iso.Types</code> convenience method fo
-<h3 id="ServiceLoader"><span class="section-number">7.3.2.</span> Fetching implementations of GeoAPI interfaces</h3>
+<h4 id="ServiceLoader"><span class="section-number">8.1.5.2.</span> Fetching implementations of GeoAPI interfaces</h4>
<p>
GeoAPI defines factories (<code class="GeoAPI">Factory</code>) that can create implementations of interfaces.
For example, <code class="GeoAPI">DatumFactory</code> provides methods that can create instances which implement interfaces of the
@@ -3317,7 +3343,7 @@ for example when multiple libraries coexist — then the choice is left to the u
-<h4 id="GeoAPI-simple"><span class="section-number">7.3.2.1.</span> Defining custom implementations</h4>
+<h5 id="GeoAPI-simple"><span class="section-number">8.1.5.2.1.</span> Defining custom implementations</h5>
<p>
Implementing GeoAPI oneself in order to meet very specific needs is not difficult.
A developer might concentrate on a handful of interfaces among the hundreds available,
@@ -3325,8 +3351,8 @@ while keeping other interfaces as extension points to eventually implement as ne
</p>
<p>
The conceptual model that the interfaces represent is complex. But this complexity may be reduced by combining certain interfaces.
-For example, many libraries, even well-known ones, do not distinguish between a <cite>Coordinate System</cite> (<abbr>CS</abbr>)
-and a <cite>Coordinate <u>Reference</u> System</cite> (<abbr title="Coordinate Reference System">CRS</abbr>).
+For example, many libraries, even well-known ones, do not distinguish between a <dfn>Coordinate System</dfn> (<abbr>CS</abbr>)
+and a <dfn>Coordinate <u>Reference</u> System</dfn> (<abbr title="Coordinate Reference System">CRS</abbr>).
A developer that also wishes not to make this distinction may implement these two interfaces with the same class.
The resulting implementation may have a simpler class hierarchy than that of GeoAPI interfaces.
The <code class="GeoAPI">geoapi-examples</code> module, discussed later, provides such combinations.
@@ -3408,13 +3434,8 @@ while retaining the ability to switch easily to another library if desired.
<section>
<header>
-<h1 id="Tests"><span class="section-number">8.</span> Test suites</h1>
-<nav><div class="chapter-links"><div class="previous-chapter">⬅ <a href="#GeoAPI-details">Previous chapter</a></div><div class="next-chapter"><a href="#DesignNotes">Next chapter</a> ➡</div></div></nav>
+<h2 id="Tests"><span class="section-number">8.2.</span> Test suites</h2>
</header>
-<nav><p>In this chapter:</p><ul class="toc">
-<li><a href="#GeoAPI-conformance">GeoAPI conformance</a><ul>
-<li><a href="#GeoAPI-validators">Instance validations</a></li>
-<li><a href="#GeoAPI-tests">Executing pre-defined tests</a></li></ul></li></ul></nav>
<p>
In addition to its own tests, Apache SIS uses tests defined by GeoAPI.
One advantages is that those tests provide an external source for the definition of expected results
@@ -3429,7 +3450,7 @@ Those tests can also be used by projects other than Apache SIS.
<section>
<header>
-<h2 id="GeoAPI-conformance"><span class="section-number">8.1.</span> GeoAPI conformance</h2>
+<h3 id="GeoAPI-conformance"><span class="section-number">8.2.1.</span> GeoAPI conformance</h3>
</header>
<p>
The <code class="GeoAPI">geoapi-conformance</code> module provides <i>validators</i>, a JUnit <i>test suite</i>, and <i>report generators</i>
@@ -3446,7 +3467,7 @@ since <code class="GeoAPI">geoapi-conformance</code> has its own test suite and
-<h3 id="GeoAPI-validators"><span class="section-number">8.1.1.</span> Instance validations</h3>
+<h4 id="GeoAPI-validators"><span class="section-number">8.2.1.1.</span> Instance validations</h4>
<p>
GeoAPI can validate an instance of its interfaces by checking that certain constraints are observed.
Many constraints can not be expressed in the method signature. Those constraints
@@ -3532,7 +3553,7 @@ This approach requires the creation of a new instance of the validator that we w
-<h3 id="GeoAPI-tests"><span class="section-number">8.1.2.</span> Executing pre-defined tests</h3>
+<h4 id="GeoAPI-tests"><span class="section-number">8.2.1.2.</span> Executing pre-defined tests</h4>
<p>
JUnit tests are defined in the <code class="GeoAPI">org.opengis.test</code> sub-packages.
All test classes bear a name ending in "<code>Test</code>".
@@ -3591,219 +3612,153 @@ However, this example adds a supplemental verification, annotated with <code>@Af
<section>
<header>
-<h1 id="DesignNotes"><span class="section-number">9.</span> Design notes</h1>
-<nav><div class="chapter-links"><div class="previous-chapter">⬅ <a href="#Tests">Previous chapter</a></div></div></nav>
-</header>
-<nav><p>In this chapter:</p><ul class="toc">
-<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></nav>
-<p>Following sections explain the rational behind some implementation choices done in Apache <abbr title="Spatial Information System">SIS</abbr>.</p>
-
-
-
-
-
-<section>
-<header>
-<h2 id="AffineTransform"><span class="section-number">9.1.</span> Affine transform</h2>
+<h2 id="DesignNotes"><span class="section-number">8.3.</span> Design notes</h2>
+</header>
+<p>Following sections explain the rational behind some implementation choices done in Apache <abbr title="Spatial Information System">SIS</abbr>.</p>
+
+
+
+
+
+
+
+
+<section>
+<header>
+<h3 id="EarlyOrLateBinding"><span class="section-number">8.3.1.</span> Early binding versus late binding</h3>
+</header>
+<p>
+Because of the <abbr title="World Geodetic System 1984">WGS84</abbr> ubiquity, it is tempting to use that system as a hub or a pivot system
+for all coordinate transformations.
+The use of an “universal” system as a pivot simplifies the design of coordinate transformations libraries.
+For example transformations from datum <var>A</var> to datum <var>B</var> can be done by first transforming
+from <var>A</var> to <abbr>WGS84</abbr>, then from <abbr>WGS84</abbr> to <var>B</var>.
+With such approach, a coordinate transformations library would only need to associate each
+<code class="GeoAPI">GeodeticDatum</code> instance with the transformation parameters from that datum to <abbr>WGS84</abbr>.
+This approach was encouraged in version 1 of <abbr>WKT</abbr> format, since that format specified a
+<code class="OGC">TOWGS84[…]</code> element (removed in <abbr>WKT</abbr> version 2) precisely for that purpose.
+This approach is known in <abbr>EPSG</abbr> guidance notes as “early binding” implementations
+since information about coordinate transformations are associated early in geodetic object definitions,
+usually right at <code class="GeoAPI">GeographicCRS</code> creation time.
+While <abbr>EPSG</abbr> acknowledges that this approach is commonly used,
+this is not a recommended strategy for the following reasons:
+</p>
+<ul class="verbose">
+<li>More than one transformation may exist from datum <var>A</var> to datum <var>B</var>,
+where each transformation is designed for a different geographic area.</li>
+<li>Some operations are designed specifically for transformations from <var>A</var> to <var>B</var>
+and do not have the same accuracy than an operation using <abbr>WGS84</abbr> as an intermediate step.</li>
+<li><abbr>WGS84</abbr> itself has been updated many times,
+which makes it a kind of moving target (admittedly slowly) for coordinate transformations libraries.</li>
+<li>Different systems could be used as the pivot system, for example the <cite>Galileo Reference Frame</cite>
+(<abbr>GTRF</abbr>) created for the European <abbr title="Global Positioning System">GPS</abbr> competitor.</li>
+</ul>
+<div class="example"><p><b>Example:</b>
+the <abbr>EPSG</abbr> geodetic dataset defines about 50 transformations from <abbr title="North American Datum 1927">NAD27</abbr> to <abbr title="North American Datum 1983">NAD83</abbr>.
+In an early binding approach, the same geographic <abbr title="Coordinate Reference System">CRS</abbr> (namely “<abbr>NAD27</abbr>”) in the <abbr>WKT</abbr> 1
+format would need to be defined with a <code>TOWGS84[-8, 160, 176]</code> element for coordinates in <abbr>USA</abbr>
+or with a <code>TOWGS84[-10, 158, 187]</code> element for coordinates in Canada.
+Different parameter values exist for other regions like Cuba, so it is not possible to represent such diversity
+with a single <code class="OGC">TOWGS84[…]</code> element associated to a <abbr>CRS</abbr>.
+But even when restricting <abbr>CRS</abbr> usage to the domain of validity of its single <code class="OGC">TOWGS84[…]</code> element,
+those transformations are still approximative with a 10 metres accuracy in the <abbr>USA</abbr> case.
+More accurate transformations exist in the form of <abbr>NADCON</abbr> grid shift files,
+but those transformations are from <abbr>NAD27</abbr> to <abbr>NAD83</abbr> (which move together on the same continental plate),
+not to <abbr>WGS84</abbr> (which move independently).
+The difference was often ignored when <abbr>NAD83</abbr> and <abbr>WGS84</abbr> were considered as practically equivalent,
+but that assumption is subject to more caution today.
+</p></div>
+<p>
+<abbr>EPSG</abbr> rather recommends the use of “late binding” approach,
+in which coordinate transformation methods and parameters are defined for
+“<var>A</var> to <var>B</var>” pairs of systems (eventually completed with domain of validity)
+rather than associated to standalone datums.
+Apache <abbr title="Spatial Information System">SIS</abbr> is a “late binding” implementation,
+while some reminiscences of “early binding” approach still exist in the form of the
+<code class="SIS">DefaultGeodeticDatum.getBursaWolfParameters()</code> property.
+The later is used only if <abbr>SIS</abbr> fails to apply the late binding approach for given reference systems.
+</p>
+</section>
+
+
+<section>
+<header>
+<h3 id="MatrixLibrary"><span class="section-number">8.3.2.</span> Specificities of a matrix library for <abbr>GIS</abbr></h3>
</header>
<p>
-Among the many kinds of operations performed by <abbr>GIS</abbr> software products 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:
+<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.
+However, <abbr>GIS</abbr> have some specific needs that differ a little bit from the goals of many existent libraries.
+Matrix operations like those described in the <a href="#AffineTransform">affine transform chapter</a>
+appear in almost all coordinate operations applied by Apache <abbr title="Spatial Information System">SIS</abbr>.
+But the analysis of those operations reveal some patterns:
</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>
+<li><p>Those matrices are almost always of small size, rarely more than 5 rows and 5 columns.</p></li>
+<li><p>“Heavy” matrix operations (matrix inversions or multiplications) do not happen in performance-critical code.
+In almost every cases, those heavy operations are executed only once, for example when a data file is read
+or in preparation steps before to transform coordinates.
+Those heavy operations rarely happen in the loop that apply the coordinate operation
+after we finished to prepare it.</p></li>
+<li><p>In a sequence of matrix multiplications or inversions, rounding errors accumulate and grow fast.
+If the sequence of matrix operations is long enough,
+rounding errors can become indistinguishable from real operations like datum shifts.
+This ambiguity can happen because the matrix representation of some datum shifts has small values,
+with scale factors of a few parts per million and rotation terms of a few arc-seconds.</p></li>
+<li><p>It is quite common that two affine transforms cancel each other when they are concatenated, i.e.
+that matrix multiplications result in some or all scale factors equal to 1 and some or all translation terms equal to 0.
+However because of rounding errors the results are rarely exact, but are rather some values like 0,9999…97 instead of 1.
+The usual workaround is to compare floating point numbers with some tolerance threshold.
+Unfortunately it is difficult to choose a threshold that catch a wide range of rounding errors
+without wrongly considering legitimate datum shifts as rounding errors (see previous point).</p></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.
+As a consequence of above points, accuracy of a matrix library is more important than performance for a <abbr>GIS</abbr> like Apache <abbr>SIS</abbr>.
+Paradoxically, a good way to improve performance is to invest more CPU time for more accurate matrix operations
+when <em>preparing</em> (not <em>executing</em>) the coordinate operation,
+because it increases the chances to correctly detect which operations cancel each other.
+This investment can save execution time at the place where it matters most:
+in the code looping over millions of coordinates to transform.
+</p><p>
+However matrix libraries are often designed for high performances with large matrices, sometime containing thousands of rows and columns.
+Those libraries can efficiently resolve systems of linear equations with hundreds of unknown variables.
+Those libraries resolve difficult problems, but not of the same kind than the problems that Apache <abbr>SIS</abbr> needs to solve.
+For that reason, and also for another reason described in next paragraphs, Apache <abbr>SIS</abbr> uses its own matrix implementation.
+This implementation addresses the accuracy issue by using “double-double” arithmetic
+(a technic for simulating the accuracy of approximatively 120 bits wide floating point numbers)
+at the cost of performance in a phase (transform <em>preparation</em>) where performance is not considered critical.
</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:
+<h4 id="NonSquareMatrix"><span class="section-number">8.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.
+Depending on whether we have more lines than columns:
</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>
+<li>From Apache <abbr>SIS</abbr> library perspective, a non-square matrix is a coordinate operation that adds or removes a dimension.</li>
+<li>From linear algebra libraries perspective, a non-square matrix is an under-determined or over-determined system of equations.</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>
+To illustrate the issues caused by direct use of libraries designed for linear algebra,
+consider a (<var>φ₁</var>, <var>λ₁</var>, <var>h</var>) → (<var>φ₂</var>, <var>λ₂</var>) conversion
+from three-dimensional points to two-dimensional points on a surface.
+The <var>φ</var> terms are latitudes, the <var>λ</var> terms are longitudes and
+(<var>φ₂</var>, <var>λ₂</var>) may be different than (<var>φ₁</var>, <var>λ₁</var>) if <var>h</var> axis is not perpendicular to the surface.
</p><p>
<math xmlns="http://www.w3.org/1998/Math/MathML" alttext="MathML capable browser required" display="block">
<mrow>
<mo>[</mo>
-<mtable>
-<mtr><mtd><mi>λ</mi></mtd></mtr>
-<mtr><mtd><mi>φ</mi></mtd></mtr>
-<mtr><mtd><mn>1</mn></mtd></mtr>
-</mtable>
-<mo>]</mo>
-</mrow>
-<mo>=</mo>
-<mrow>
-<mo>[</mo>
-<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>
-<mo>]</mo>
-</mrow>
-<mo>×</mo>
-<mrow>
-<mo>[</mo>
-<mtable>
-<mtr><mtd><mi>x</mi></mtd></mtr>
-<mtr><mtd><mi>y</mi></mtd></mtr>
-<mtr><mtd><mn>1</mn></mtd></mtr>
-</mtable>
-<mo>]</mo>
-</mrow>
-</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>
-<div style="display:table; margin:auto">
-<div style="display:table-row">
-<div class="caption" style="display:table-cell">Change 2</div>
-<div class="caption" style="display:table-cell"> </div>
-<div class="caption" style="display:table-cell">Change 1</div>
-<div class="caption" style="display:table-cell"> </div>
-<div class="caption" style="display:table-cell">Initial conversion</div>
-<div class="caption" style="display:table-cell"> </div>
-<div class="caption" style="display:table-cell">Concatenated operation</div>
-</div>
-<div style="display:table-row">
-<div style="display:table-cell; vertical-align:middle">
-<math xmlns="http://www.w3.org/1998/Math/MathML" alttext="MathML capable browser required" display="block">
-<mrow>
-<mo>[</mo>
-<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>
+<mtr><mtd><msub><mi>φ</mi><mrow><mn>2</mn></mrow></msub></mtd></mtr>
+<mtr><mtd><msub><mi>λ</mi><mrow><mn>2</mn></mrow></msub></mtd></mtr>
+<mtr><mtd><mn>1</mn></mtd></mtr>
</mtable>
<mo>]</mo>
</mrow>
-</math>
-</div>
-<div style="display:table-cell; vertical-align:middle; padding-left: 15px; padding-right: 15px">×</div>
-<div style="display:table-cell; vertical-align:middle">
-<math xmlns="http://www.w3.org/1998/Math/MathML" display="block">
+<mo>=</mo>
<mrow>
<mo>[</mo>
<mtable>
@@ -3811,118 +3766,294 @@ then operation <var>B</var> and finally operation <var>A</var>.
<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>
-<mo>]</mo>
-</mrow>
-</math>
-</div>
-<div style="display:table-cell; vertical-align:middle; padding-left: 15px; padding-right: 15px">×</div>
-<div style="display:table-cell; vertical-align:middle">
-<math xmlns="http://www.w3.org/1998/Math/MathML" display="block">
-<mrow>
-<mo>[</mo>
-<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>0</mn></mtd>
<mtd><mn>1</mn></mtd>
</mtr>
</mtable>
<mo>]</mo>
</mrow>
-</math>
-</div>
-<div style="display:table-cell; vertical-align:middle; padding-left: 15px; padding-right: 15px">=</div>
-<div style="display:table-cell; vertical-align:middle">
-<math xmlns="http://www.w3.org/1998/Math/MathML" display="block">
+<mo>×</mo>
<mrow>
<mo>[</mo>
<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>
+<mtr><mtd><msub><mi>φ</mi><mrow><mn>1</mn></mrow></msub></mtd></mtr>
+<mtr><mtd><msub><mi>λ</mi><mrow><mn>1</mn></mrow></msub></mtd></mtr>
+<mtr><mtd><mi>h</mi></mtd></mtr>
+<mtr><mtd><mn>1</mn></mtd></mtr>
</mtable>
<mo>]</mo>
</mrow>
</math>
+</p><p>
+For linear algebra libraries, the above non-square matrix represents an under-determined system of equations and may be considered unresolvable.
+Indeed the above coordinate operation can not be inverted as a (<var>φ₂</var>, <var>λ₂</var>) → (<var>φ₁</var>, <var>λ₁</var>, <var>h</var>)
+operation because we do not know which value to assign to <var>h</var>.
+Ignoring <var>h</var> implies that we can not assign values to (<var>φ₁</var>, <var>λ₁</var>) neither since those values may depend on <var>h</var>.
+However in <abbr>GIS</abbr> case, the ellipsoidal <var>h</var> axis is perpendicular to the ellipsoid surface
+on which the <em>geodetic</em> latitudes and longitudes (<var>φ</var>, <var>λ</var>) are represented
+(note that this statement is not true for <em>geocentric</em> latitudes and longitudes).
+This perpendicularity makes <var>φ₁</var> and <var>λ₁</var> independent of <var>h</var>.
+In such cases, we can can still do some processing.
+</p><p>
+Apache <abbr>SIS</abbr> proceeds by checking if <var>h</var> values are independent of <var>φ</var> and <var>λ</var> values.
+We identify such cases by checking which matrix coefficients are zero.
+If <abbr>SIS</abbr> can identify independent dimensions, it can temporarily exclude those dimensions
+and invert the matrix using only the remaining dimensions.
+If <abbr>SIS</abbr> does not found a sufficient amount of independent dimensions, an exception is thrown.
+But if a matrix inversion has been possible, then we need to decide which value to assign to the dimensions that <abbr>SIS</abbr> temporarily excluded.
+By default, <abbr>SIS</abbr> assigns the <code>NaN</code> (<dfn>Not-a-Number</dfn>) value to those dimensions.
+However in the particular case of ellipsoidal height <var>h</var> in a (<var>φ₂</var>, <var>λ₂</var>) → (<var>φ₁</var>, <var>λ₁</var>, <var>h</var>) operation,
+the zero value may also be appropriate on the assumption that the coordinates are usually close to the ellipsoid surface.
+In any case, the coefficients that Apache <abbr>SIS</abbr> sets to zero or <code>NaN</code> is based on the assumption
+that the matrix represents a coordinate operation; this is not something that can be done with arbitrary matrices.
+</p><p>
+The above-described approach allows Apache <abbr>SIS</abbr> to resolve some under-determined equation systems commonly found in <abbr>GIS</abbr>.
+In our example using <code>NaN</code> as the default value, the <var>h</var> ordinate stay unknown – we do not create information from nothing –
+but at least the (<var>φ</var>, <var>λ</var>) coordinates are preserved.
+The opposite problem, those of over-determined equation systems, is more subtile.
+An approach commonly applied by linear algebra libraries is to resolve over-determined systems by the least squares method.
+Such method applied to our example would compute a (<var>φ₂</var>, <var>λ₂</var>, <var>h</var>) → (<var>φ₁</var>, <var>λ₁</var>) operation
+that seems the best compromise for various <var>φ₂</var>, <var>λ₂</var> and <var>h</var> values,
+while being (except special cases) an exact solution for no-one.
+Furthermore linear combinations between those three variables may be an issue because of heterogenous units of measurement,
+for instance with <var>h</var> in metres and (<var>φ</var>, <var>λ</var>) in degrees.
+Apache <abbr>SIS</abbr> rather proceeds in the same way than for under-determined systems:
+by requiring that some dimensions are independent from other dimensions, otherwise the matrix is considered non-invertible.
+Consequently in over-determined systems case, <abbr>SIS</abbr> may refuse to perform some matrix inversions that linear algebra libraries can do,
+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">8.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>
+<ul>
+<li>Lightweight objects for small matrices, especially the 3×3 ones.</li>
+<li>Improved accuracy with “double-double” arithmetic, accepting performance cost in codes where performance is not critical.</li>
+<li>Special handling of non-square matrices on the assumption that those matrices represent coordinate operations.</li>
+</ul>
+<p>
+This library is provided in the <code class="SIS">org.apache.sis.matrix</code> package of the <code class="SIS">sis-referencing</code> module.
+</p>
+</section>
+
+
+<section>
+<header>
+<h3 id="JacobianUsage"><span class="section-number">8.3.3.</span> Usages of Jacobian matrix</h3>
+</header>
+<p>
+The Jacobian matrix (or transform derivative) was introduced in the
+<a href="#TransformDerivative">section about coordinate operations</a>.
+This section explains how derivatives are used by the Apache <abbr title="Spatial Information System">SIS</abbr>
+implementation of some high-level operations.
+</p>
+
+<h4 id="DerivativeAndEnvelope"><span class="section-number">8.3.3.1.</span> Transform derivatives applied to envelopes</h4>
+<p>
+Geographic information systems often need to transform an envelope from one <abbr title="Coordinate Reference System">CRS</abbr> to another.
+A <a href="#EnvelopeTransform">previous section</a> has shown why a naive approach transforming the 4 corners is not sufficient.
+A simple way to reduce the problem could be to sample a large number of points on each envelope border.
+For example we could sample 40 points on each border, transform them to the target <abbr>CRS</abbr>
+and compute an envelope containing all the transformed points.
+But even with 40 points, the point which is closest to the minimum in above figure can still be above that minimum.
+Consequently we still miss a small portion of the projected shape.
+It may be tempting to declare this error is negligible, but a single missing pixel can be enough for
+causing artifacts such as thin black lines in a mosaic or missing “piece of pie” in a projection over a pole.
+A workaround could be to arbitrarily increase the envelope size by some percentage,
+but a percentage too high will cause a larger amount of unnecessary data processing (e.g. more data to load from a file)
+while a percentage too low will leave some artifacts.
+</p><p>
+Map projection derivatives offer a more efficient way to resolve this problem.
+The figure below reproduces the same projected shape than above figure but with exaggerated deformations.
+The Apache <abbr title="Spatial Information System">SIS</abbr> algorithm projects the 4 corners as in the naive approach,
+but opportunistically computes also their derivatives (the Jacobian matrices).
+Between two corners and using derivative information, there is only one possible cubic curve.
+We can describe that curve by the
+
+<i>f(<var>x</var>)</i> = <var>C</var>₀ + <var>C</var>₁<var>x</var> + <var>C</var>₂<var>x</var>² + <var>C</var>₃<var>x</var>³ equation
+
+with <var>C</var> coefficients computed from corner positions and derivatives.
+This approximation (shown by the red curve in above figure) does not match exactly the desired curve
+(shown by the blue shape in above figure) but is close.
+We do not use directly the cubic curve minimum,
+but instead we take the longitude λ (for above example) where this minimum is located.
+This is shown by the green dashed line in above figure.
+This position is easy to compute when the <var>C</var> coefficients are known.
+Assuming that the λ coordinate of the cubic curve minimum is close to the λ coordinates of the projected shape minimum,
+we can project the point on the envelope border at that location instead of projecting blindly 40 points on that border.
+</p>
+<div class="row-of-boxes">
+<div>
+<img alt="Cubic approximation of an envelope bounds" src="../images/Approximation.png"/>
+</div><div>
+Legend:
+<ul>
+<li><b>Blue:</b> the geometric shape of the envelope after projection.
+This is the shape from which to get a new envelope.</li>
+<li><b>Red</b> (with hash): The
+<var>y</var> = <var>C</var>₀ + <var>C</var>₁λ + <var>C</var>₂λ² + <var>C</var>₃λ³ approximation.</li>
+<li><b>Green</b> (dashed line): Position λ<sub>m</sub> of approximation minimum, obtained by resolving
+0 = <var>C</var>₁ + 2<var>C</var>₂λ<sub>m</sub> + 3<var>C</var>₃λ<sub>m</sub>².
+The same cubic line can have two minimums.</li>
+</ul>
+</div>
</div>
+<p>
+In practice Apache <abbr>SIS</abbr> uses 8 points:
+the 4 corners plus one point at the center of each border of the envelope to project.
+The center points are added as a safety for map projections having symmetric deformations above and below equator.
+According our tests, using only those 8 points together with derivatives as described above
+gives more accurate results than “brute force” approach with 160 points on the 4 envelope borders.
+Saving 150 points seems small compared to computer performances.
+But above discussion used a two-dimensional envelope as an example.
+The same discussion applies to <var>n</var>-dimensional envelopes as well.
+Apache <abbr>SIS</abbr> can apply this algorithm on envelopes with any number of dimensions up to 64.
+The performance gain offered by this algorithm compared to “brute force” approach
+increases exponentially with the number of dimensions.
+</p><p>
+Apache <abbr>SIS</abbr> implements the algorithm described in this section
+by the static <code class="SIS">Envelopes.transform(CoordinateOperation, Envelope)</code> method.
+An alternative <code class="SIS">Envelopes.transform(MathTransform, Envelope)</code> method is also available,
+but should be used only when the <code class="GeoAPI">CoordinateOperation</code> is unknown.
+The reason is because <code class="GeoAPI">MathTransform</code> objects does not contain any information about coordinate system axes,
+which prevent the <code class="SIS">Envelopes.transform(…)</code> method to handle special cases such as envelopes containing a pole.
+</p>
+
+
+<h4 id="DerivativeAndRaster"><span class="section-number">8.3.3.2.</span> Transform derivatives applied to rasters</h4>
+<p>
+A raster can be projected by preparing an initially empty raster which will contain the resampled pixel values.
+Then for each pixel in the <em>destination</em> raster, we use the <em>inverse</em> of the map projection
+(<var>T</var>⁻¹) for computing the coordinates of the corresponding pixel in source raster.
+The transformed coordinates may not fall at the center of a source raster pixel,
+so source pixel values usually need to be interpolated.
+</p>
+<div style="display:flex; flex-direction:column; align-items:center">
+<div style="display:flex; justify-content:space-between; width:564px">
+<div class="caption">Source image</div>
+<div class="caption">Destination image</div>
+</div>
+<img alt="Raster reprojection" src="../images/RasterProjection.png"/>
+</div>
+<p>
+However applying the inverse transform on all pixel coordinates can be relatively slow.
+We can accelerate raster reprojections by pre-computing an <dfn>interpolation grid</dfn>.
+This grid contains the coordinate values of inverse transform <var>T</var>⁻¹ for only a few points.
+The coordinate values of other points are obtained by bilinear interpolations between interpolation grid points.
+Historically, this algorithm was implemented in the <code>WarpGrid</code> object of <cite>Java Advanced Imaging</cite> library.
+The performance gain is yet better if the same interpolation grid is reused for many rasters having their pixels at the same coordinates.
+</p><p>
+A difficulty in using interpolation grids is to determine how many points we need for keeping errors
+(defined as the difference between interpolated positions and actual positions computed by <var>T</var>⁻¹)
+below some threshold value (for example ¼ of pixel size).
+A “brute force” approach is to begin with a grid of size 3×3, then increase the number of points iteratively:
+</p>
+<div class="row-of-boxes">
+<div>
+<img alt="Warp grid" src="../images/WarpGrid.png"/>
+</div><div>
+Legend:
+<ul>
+<li><b>Blue dots:</b> first iteration (9 points).</li>
+<li><b>Green dots:</b> second iteration (25 points, including 16 news).</li>
+<li><b>Red dots:</b> third iteration (81 points, including 56 news).</li>
+</ul>
+Continuing…
+<ul>
+<li>Forth iteration: 289 points, including 208 news.</li>
+<li>Fifth iteration: 1089 points, including 800 news.</li>
+<li>Sixth iteration: 4225 points, including 3136 news.</li>
+<li>…</li>
+</ul>
</div>
</div>
<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.
+We could stop dividing the grid when, after having computed new points,
+we verified that the differences between coordinates computed by <var>T</var>⁻¹ during last iteration
+and coordinates computed by bilinear interpolations for the same points are lower than the threshold value.
+Unfortunately this approach can only tell us <strong>after</strong> computing new points… that those new points were unnecessary.
+This is unfortunate considering that each iteration adds an amount of points approximately equal to
+3 times the <em>sum</em> of the number of points of all previous iterations.
+</p><p>
+Map projection derivatives help to improve the speed of interpolation grid computations.
+Using the derivatives, we can estimate whether another iteration is necessary <strong>before</strong> to execute it.
+The basic idea is to check if the derivatives at two neighbor points define two tangent lines that are almost parallel.
+In such case, we assume that the transform between those two points is almost linear.
+In order to define numerically the meaning of “almost linear”,
+we compute the intersection of the two tangent lines as illustrated below (the blue arrows).
+Then we compute the distance between that intersection and the straight line connecting the two points
+(the dashed line in the figure below).
</p>
-</div>
+<p style="text-align:center"><img alt="Intersection of derivatives" src="../images/IntersectionOfDerivatives.png" style="border: solid 1px"/></p>
+<p>
+In “brute force” algorithm without derivatives, iteration stops when the distance between interpolated positions (blue dashed line)
+and actual projected positions (red curve) is less than the threshold value.
+This criteria requires to compute the projected positions before the decision can be made.
+But with an algorithm using derivatives, the projected positions (red curve) are replaced by the tangents intersection point.
+If the actual projected curve does not have too much deformations
+(which should be the case for pairs of neighbor points close enough),
+then the red curve stay between the blue dashed line and the tangents intersection point.
+By using that intersection point, we reduce greatly the number of points to transform
+(3× the sum of all previous iterations).
+</p>
+
+<h4 id="GetDerivative"><span class="section-number">8.3.3.3.</span> Getting the derivative at a point</h4>
+<p>
+The algorithms discussed in previous section would be irrelevant if map projection derivatives were costly to compute.
+But analytic derivations of their formulas show that map projection and derivative formulas have many terms in common.
+Furthermore map projection formulas are simplified by Apache <abbr title="Spatial Information System">SIS</abbr> implementation strategy,
+which takes out linear terms (delegated to affine transforms)
+so that <code>NormalizedProjection</code> subclasses can focus on the non-linear terms only.
+Map projection implementations in Apache <abbr>SIS</abbr> exploit those characteristics
+for computing Jacobian matrices (if required) together with projected points in a single operation,
+reusing many common terms between the two set of formulas.
+Example:</p>
+
+<pre><code><code class="SIS">AbstractMathTransform</code> projection = ...; <code class="comment">// An Apache SIS map projection.</code>
+<b>double</b>[] sourcePoint = {longitude, latitude}; <code class="comment">// The geographic coordinate to project.</code>
+<b>double</b>[] targetPoint = <b>new</b> <b>double</b>[2]; <code class="comment">// Where to store the projection result.</code>
+<code class="GeoAPI">Matrix</code> derivative = projection.<code class="SIS">transform</code>(sourcePoint, 0, targetPoint, 0, <b>true</b>);</code></pre>
+
+<p>
+If only the Jacobian matrix is desired (without the projected point),
+then the <code class="GeoAPI">MathTransform.derivative(DirectPosition)</code> method offers a more readable alternative.
+</p><p>
+Many operations on coordinate transforms can also be applied on transform derivatives:
+concatenation of a chain of transforms, inversion, taking a subset of the dimensions, <i>etc.</i>
+Inverse projection formulas are usually more complicated than forward projections formulas,
+but thankfully their derivatives do not need to be computed:
+the Jacobian matrix of an inverse transform is the inverse of the Jacobian matrix of the forward transform.
+Calculation of inverse projections can be implemented as below:
+</p>
+
+<pre><code>@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> <code class="SIS">Matrices</code>.inverse(jac);
+}</code></pre>
+</section>
+
-<h3 id="AffineTransformAPI"><span class="section-number">9.1.1.</span> Integration with graphical libraries</h3>
+<section>
+<header>
+<h3 id="AffineTransformAPI"><span class="section-number">8.3.4.</span> Integration with graphical libraries</h3>
+</header>
<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>.
+Affine transforms, introduced <a href="#AffineTransform">earlier</a>, are extensively used by Apache <abbr title="Spatial Information System">SIS</abbr>.
+About all graphical libraries support some kind of coordinate operations, usually as <dfn>affine transforms</dfn>
+or a slight generalization like <dfn>perspective transforms</dfn>.
Each library defines its own <abbr title="Application Programming Interface">API</abbr>. Some examples are listed below:
</p>
<table>
@@ -3936,7 +4067,7 @@ Each library defines its own <abbr title="Application Programming Interface">API
</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.
+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.
@@ -3962,171 +4093,53 @@ even when the <code class="GeoAPI">MathTransform</code> meets the requirements a
<section>
<header>
-<h2 id="MatrixLibrary"><span class="section-number">9.2.</span> Specificities of a matrix library for <abbr>GIS</abbr></h2>
+<h3 id="XMLTools"><span class="section-number">8.3.5.</span> Tools for reading and writing <abbr>XML</abbr> documents</h3>
</header>
<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.
-However, <abbr>GIS</abbr> have some specific needs that differ a little bit from the goals of many existent libraries.
-Matrix operations like those described in the <a href="#AffineTransform">affine transform chapter</a>
-appear in almost all coordinate operations applied by Apache <abbr title="Spatial Information System">SIS</abbr>.
-But the analysis of those operations reveal some patterns:
-</p>
-<ul>
-<li><p>Those matrices are almost always of small size, rarely more than 5 rows and 5 columns.</p></li>
-<li><p>“Heavy” matrix operations (matrix inversions or multiplications) do not happen in performance-critical code.
-In almost every cases, those heavy operations are executed only once, for example when a data file is read
-or in preparation steps before to transform coordinates.
-Those heavy operations rarely happen in the loop that apply the coordinate operation
-after we finished to prepare it.</p></li>
-<li><p>In a sequence of matrix multiplications or inversions, rounding errors accumulate and grow fast.
-If the sequence of matrix operations is long enough,
-rounding errors can become indistinguishable from real operations like datum shifts.
-This ambiguity can happen because the matrix representation of some datum shifts has small values,
-with scale factors of a few parts per million and rotation terms of a few arc-seconds.</p></li>
-<li><p>It is quite common that two affine transforms cancel each other when they are concatenated, i.e.
-that matrix multiplications result in some or all scale factors equal to 1 and some or all translation terms equal to 0.
-However because of rounding errors the results are rarely exact, but are rather some values like 0,9999…97 instead of 1.
-The usual workaround is to compare floating point numbers with some tolerance threshold.
-Unfortunately it is difficult to choose a threshold that catch a wide range of rounding errors
-without wrongly considering legitimate datum shifts as rounding errors (see previous point).</p></li>
-</ul>
-<p>
-As a consequence of above points, accuracy of a matrix library is more important than performance for a <abbr>GIS</abbr> like Apache <abbr>SIS</abbr>.
-Paradoxically, a good way to improve performance is to invest more CPU time for more accurate matrix operations
-when <em>preparing</em> (not <em>executing</em>) the coordinate operation,
-because it increases the chances to correctly detect which operations cancel each other.
-This investment can save execution time at the place where it matters most:
-in the code looping over millions of coordinates to transform.
-</p><p>
-However matrix libraries are often designed for high performances with large matrices, sometime containing thousands of rows and columns.
-Those libraries can efficiently resolve systems of linear equations with hundreds of unknown variables.
-Those libraries resolve difficult problems, but not of the same kind than the problems that Apache <abbr>SIS</abbr> needs to solve.
-For that reason, and also for another reason described in next paragraphs, Apache <abbr>SIS</abbr> uses its own matrix implementation.
-This implementation addresses the accuracy issue by using “double-double” arithmetic
-(a technic for simulating the accuracy of approximatively 120 bits wide floating point numbers)
-at the cost of performance in a phase (transform <em>preparation</em>) where performance is not considered critical.
-</p>
-
-<h3 id="NonSquareMatrix"><span class="section-number">9.2.1.</span> What to do with non-square matrices (and why)</h3>
-<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.
-Depending on whether we have more lines than columns:
+Apache <abbr title="Spatial Information System">SIS</abbr> uses different libraries to read and write different types of objects.
+The library used depends on the complexity of the object and on performance constraints.
+For example, <abbr title="Java Architecture for XML Binding">JAXB</abbr> annotations have the advantage of being close to code,
+which makes it easier to maintain mapping between Java and <abbr>XML</abbr>.
+On the other hand, <abbr title="Simple API for XML">SAX</abbr> is more efficient.
+In general, Apache <abbr>SIS</abbr> uses:
</p>
-<ul>
-<li>From Apache <abbr>SIS</abbr> library perspective, a non-square matrix is a coordinate operation that adds or removes a dimension.</li>
-<li>From linear algebra libraries perspective, a non-square matrix is an under-determined or over-determined system of equations.</li>
+<ul class="verbose">
+<li>
+<abbr>JAXB</abbr> for objects that do not occur very often in <abbr>XML</abbr> documents, but with complex structures and deep hierarchies.
+The metadata set in <abbr title="International Organization for Standardization">ISO</abbr> 19115-3 standard is a typical example
+</li>
+<li>
+<abbr>SAX</abbr> for objects that are relatively simple, but which may exist in very large numbers.
+The set of points in a geometry is a typical example.
+</li>
+<li>
+<abbr title="Document Object Model">DOM</abbr> as an alternative to <abbr>JAXB</abbr>
+when the <abbr>XML</abbr> elements do not correspond exactly to Java attributes.
+<i>Features</i> are an example, as their structure is dynamic.
+</li>
</ul>
-<p>
-To illustrate the issues caused by direct use of libraries designed for linear algebra,
-consider a (<var>φ₁</var>, <var>λ₁</var>, <var>h</var>) → (<var>φ₂</var>, <var>λ₂</var>) conversion
-from three-dimensional points to two-dimensional points on a surface.
-The <var>φ</var> terms are latitudes, the <var>λ</var> terms are longitudes and
-(<var>φ₂</var>, <var>λ₂</var>) may be different than (<var>φ₁</var>, <var>λ₁</var>) if <var>h</var> axis is not perpendicular to the surface.
-</p><p>
-
-
-<math xmlns="http://www.w3.org/1998/Math/MathML" alttext="MathML capable browser required" display="block">
-<mrow>
-<mo>[</mo>
-<mtable>
-<mtr><mtd><msub><mi>φ</mi><mrow><mn>2</mn></mrow></msub></mtd></mtr>
-<mtr><mtd><msub><mi>λ</mi><mrow><mn>2</mn></mrow></msub></mtd></mtr>
-<mtr><mtd><mn>1</mn></mtd></mtr>
-</mtable>
-<mo>]</mo>
-</mrow>
-<mo>=</mo>
-<mrow>
-<mo>[</mo>
-<mtable>
-<mtr>
-<mtd><mn>1</mn></mtd>
-<mtd><mn>0</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><mn>0</mn></mtd>
-<mtd><mn>0</mn></mtd>
-</mtr>
-<mtr>
-<mtd><mn>0</mn></mtd>
-<mtd><mn>0</mn></mtd>
-<mtd><mn>0</mn></mtd>
-<mtd><mn>1</mn></mtd>
-</mtr>
-</mtable>
-<mo>]</mo>
-</mrow>
-<mo>×</mo>
-<mrow>
-<mo>[</mo>
-<mtable>
-<mtr><mtd><msub><mi>φ</mi><mrow><mn>1</mn></mrow></msub></mtd></mtr>
-<mtr><mtd><msub><mi>λ</mi><mrow><mn>1</mn></mrow></msub></mtd></mtr>
-<mtr><mtd><mi>h</mi></mtd></mtr>
-<mtr><mtd><mn>1</mn></mtd></mtr>
-</mtable>
-<mo>]</mo>
-</mrow>
-</math>
-</p><p>
-For linear algebra libraries, the above non-square matrix represents an under-determined system of equations and may be considered unresolvable.
-Indeed the above coordinate operation can not be inverted as a (<var>φ₂</var>, <var>λ₂</var>) → (<var>φ₁</var>, <var>λ₁</var>, <var>h</var>)
-operation because we do not know which value to assign to <var>h</var>.
-Ignoring <var>h</var> implies that we can not assign values to (<var>φ₁</var>, <var>λ₁</var>) neither since those values may depend on <var>h</var>.
-However in <abbr>GIS</abbr> case, the ellipsoidal <var>h</var> axis is perpendicular to the ellipsoid surface
-on which the <em>geodetic</em> latitudes and longitudes (<var>φ</var>, <var>λ</var>) are represented
-(note that this statement is not true for <em>geocentric</em> latitudes and longitudes).
-This perpendicularity makes <var>φ₁</var> and <var>λ₁</var> independent of <var>h</var>.
-In such cases, we can can still do some processing.
-</p><p>
-Apache <abbr>SIS</abbr> proceeds by checking if <var>h</var> values are independent of <var>φ</var> and <var>λ</var> values.
-We identify such cases by checking which matrix coefficients are zero.
-If <abbr>SIS</abbr> can identify independent dimensions, it can temporarily exclude those dimensions
-and invert the matrix using only the remaining dimensions.
-If <abbr>SIS</abbr> does not found a sufficient amount of independent dimensions, an exception is thrown.
-But if a matrix inversion has been possible, then we need to decide which value to assign to the dimensions that <abbr>SIS</abbr> temporarily excluded.
-By default, <abbr>SIS</abbr> assigns the <code>NaN</code> (<cite>Not-a-Number</cite>) value to those dimensions.
-However in the particular case of ellipsoidal height <var>h</var> in a (<var>φ₂</var>, <var>λ₂</var>) → (<var>φ₁</var>, <var>λ₁</var>, <var>h</var>) operation,
-the zero value may also be appropriate on the assumption that the coordinates are usually close to the ellipsoid surface.
-In any case, the coefficients that Apache <abbr>SIS</abbr> sets to zero or <code>NaN</code> is based on the assumption
-that the matrix represents a coordinate operation; this is not something that can be done with arbitrary matrices.
-</p><p>
-The above-described approach allows Apache <abbr>SIS</abbr> to resolve some under-determined equation systems commonly found in <abbr>GIS</abbr>.
-In our example using <code>NaN</code> as the default value, the <var>h</var> ordinate stay unknown – we do not create information from nothing –
-but at least the (<var>φ</var>, <var>λ</var>) coordinates are preserved.
-The opposite problem, those of over-determined equation systems, is more subtile.
-An approach commonly applied by linear algebra libraries is to resolve over-determined systems by the least squares method.
-Such method applied to our example would compute a (<var>φ₂</var>, <var>λ₂</var>, <var>h</var>) → (<var>φ₁</var>, <var>λ₁</var>) operation
-that seems the best compromise for various <var>φ₂</var>, <var>λ₂</var> and <var>h</var> values,
-while being (except special cases) an exact solution for no-one.
-Furthermore linear combinations between those three variables may be an issue because of heterogenous units of measurement,
-for instance with <var>h</var> in metres and (<var>φ</var>, <var>λ</var>) in degrees.
-Apache <abbr>SIS</abbr> rather proceeds in the same way than for under-determined systems:
-by requiring that some dimensions are independent from other dimensions, otherwise the matrix is considered non-invertible.
-Consequently in over-determined systems case, <abbr>SIS</abbr> may refuse to perform some matrix inversions that linear algebra libraries can do,
-but in case of success the resulting coordinate operation is guaranteed to be exact (ignoring rounding errors).
-</p>
-<h3 id="MatrixLibrarySummary"><span class="section-number">9.2.2.</span> Apache <abbr title="Spatial Information System">SIS</abbr> matrix library</h3>
+<h4 id="XML-SIS"><span class="section-number">8.3.5.1.</span> Implementation strategy in Apache <abbr title="Spatial Information System">SIS</abbr></h4>
<p>
-In summary, Apache <abbr>SIS</abbr> provides its own matrix library for the following reasons:
+<code class="SIS">org.apache.sis.internal.jaxb.*</code> packages (non-public) define <abbr title="Java Architecture for XML Binding">JAXB</abbr> adaptors for all types of <abbr title="International Organization for Standardization">ISO</abbr> objects.
+These adaptors are required anyway to allow <abbr>JAXB</abbr> to get <abbr>SIS</abbr> classes while implementing GeoAPI interfaces.
+Conveniently, <abbr>SIS</abbr> made both <abbr>JAXB</abbr> adaptors and objects wrapping the “real” object to be read or written.
+This double usage avoids having to double the number of classes (already quite high) present in the internal packages.
</p>
-<ul>
-<li>Lightweight objects for small matrices, especially the 3×3 ones.</li>
-<li>Improved accuracy with “double-double” arithmetic, accepting performance cost in codes where performance is not critical.</li>
-<li>Special handling of non-square matrices on the assumption that those matrices represent coordinate operations.</li>
-</ul>
+<h4><span class="section-number">8.3.5.2.</span> Naming conventions in <abbr title="XML Schema Definition">XSD</abbr> schemas</h4>
<p>
-This library is provided in the <code class="SIS">org.apache.sis.matrix</code> package of the <code class="SIS">sis-referencing</code> module.
+For each element of the first group listed above, the <abbr>XSD</abbr> schemas of the <abbr title="Open Geospatial Consortium">OGC</abbr>
+define a type whose name ends with “<code class="OGC">_PropertyType</code>”.
+For the second group, each element has a type whose name ends with “<code class="OGC">_Type</code>”.
+The “<code class="OGC">_PropertyType</code>” elements may have a group of attributes
+(such as <code class="OGC">gco:uuidref</code> and <code>xlink:href</code>)
+which the <abbr>XSD</abbr> schemas collectively name <code class="OGC">gco:ObjectIdentification</code>.
+These attributes do not have dedicated Java methods, but are accessible indirectly via the
+<code class="SIS">IdentifiedObject</code> interface described in the following subsection.
</p>
</section>
</section>
+</section>
</main>
</body>
</html>
\ No newline at end of file
diff --git a/book/fr/developer-guide.html b/book/fr/developer-guide.html
index c66c5b9a..845c1584 100644
--- a/book/fr/developer-guide.html
+++ b/book/fr/developer-guide.html
@@ -14,11 +14,12 @@
<title>Introduction à Apache SIS</title>
<meta charset="UTF-8"/>
<link href="../book.css" rel="stylesheet" type="text/css"/>
+<script src="../toc.js">/* highlighter */</script>
</head>
<body>
-<nav class="toc">
+<nav>
<p>Table des matières</p>
-<ul class="toc">
+<ul>
<li><a href="#Standards">Standards et normes</a><ul>
<li><a href="#ConceptualModels">Sources des modèles conceptuels de Apache SIS</a></li>
<li><a href="#GeoAPI">Des modèles conceptuels vers des interfaces Java: GeoAPI</a><ul>
@@ -31,28 +32,21 @@
<li><a href="#Geometry">Géométries</a><ul>
<li><a href="#GeometryBase">Classes de base</a><ul>
<li><a href="#DirectPosition">Points et positions directes</a></li>
-<li><a href="#Envelope">Enveloppes</a><ul>
-<li><a href="#AntiMeridian">Enveloppes traversant l’antiméridien</a></li></ul></li></ul></li></ul></li>
+<li><a href="#Envelope">Enveloppes</a></li></ul></li></ul></li>
<li><a href="#Referencing">Systèmes de références spatiales</a><ul>
<li><a href="#ComponentsOfCRS">Composantes d’un système de références par coordonnées</a><ul>
<li><a href="#Ellipsoid">Géoïde et ellipsoïde</a></li>
<li><a href="#GeodeticDatum">Référentiel géodésique</a></li>
-<li><a href="#CoordinateSystem">Systèmes de coordonnées</a><ul>
-<li><a href="#AxisOrder">Ordre des axes</a></li></ul></li>
+<li><a href="#CoordinateSystem">Systèmes de coordonnées</a></li>
<li><a href="#GeographicCRS">Systèmes géographiques</a></li>
<li><a href="#ProjectedCRS">Projections cartographiques</a></li></ul></li>
<li><a href="#CoordinateOperations">Opérations sur les coordonnées</a><ul>
<li><a href="#CRS.findOperation">Obtention d’une opération sur les coordonnées</a></li>
<li><a href="#MathTransform">Exécution de opérations</a></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 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>
+<li><a href="#TransformDerivative">Dérivées partielles des opérations</a></li></ul></li>
<li><a href="#Formats">Formats de stockage des données</a></li>
<li><a href="#XML-ISO">Représentation des objets en XML</a><ul>
-<li><a href="#XML-ISO-19115">Représentation des méta-données selon ISO 19115-3</a><ul>
-<li><a href="#gco-id">Identification d’instances déjà définies</a></li>
-<li><a href="#nilReason">Représentation de valeurs manquantes</a></li></ul></li></ul></li></ul></li>
+<li><a href="#XML-ISO-19115">Représentation des méta-données selon ISO 19115-3</a></li></ul></li></ul></li>
<li><a href="#Utilities">Classes et méthodes utilitaires</a><ul>
<li><a href="#ComparisonModes">Modes de comparaisons des objets</a></li>
<li><a href="#ObjectConverters">Convertisseurs d’objets</a></li>
@@ -60,8 +54,7 @@
<li><a href="#LocalizedString">Chaînes de caractères distinctes pour chaque conventions locales</a></li>
<li><a href="#InternationalString">Instance unique pour toutes les conventions locales</a></li>
<li><a href="#Locale.ROOT">Convention Locale.ROOT</a></li>
-<li><a href="#UnicodePoint">Traitement des caractères</a><ul>
-<li><a href="#Whitespaces">Interprétation des espaces blancs</a></li></ul></li></ul></li></ul></li>
+<li><a href="#UnicodePoint">Traitement des caractères</a></li></ul></li></ul></li>
<li><a href="#GeoAPI-details">Relation entre GeoAPI et les standards</a><ul>
<li><a href="#GeoAPI-modules">Les modules de GeoAPI</a></li>
<li><a href="#SpecificationToInterfaces">Des spécifications de l’OGC aux interfaces Java</a><ul>
@@ -69,8 +62,7 @@
<li><a href="#MappingToJDK">Correspondances implicites avec le JDK standard</a></li></ul></li>
<li><a href="#ReduceDependency">Réduire la dépendance directe envers Apache SIS</a><ul>
<li><a href="#UML-annotation-indep">Correspondances entre GeoAPI et les spécifications abstraites</a></li>
-<li><a href="#ServiceLoader">Obtenir une implémentation des interfaces de GeoAPI</a><ul>
-<li><a href="#GeoAPI-simple">Fournir sa propre implémentation</a></li></ul></li></ul></li></ul></li>
+<li><a href="#ServiceLoader">Obtenir une implémentation des interfaces de GeoAPI</a></li></ul></li></ul></li>
<li><a href="#Tests">Les suites de tests</a><ul>
<li><a href="#GeoAPI-conformance">Conformance avec GeoAPI</a><ul>
<li><a href="#GeoAPI-validators">Validations des instances</a></li>
@@ -88,10 +80,10 @@
<p style="margin-top:30pt; font-size:30pt; font-weight:900; text-align:center">
Introduction à Apache SIS™
</p>
-<div class="warning">
+<div class="warning" style="position:sticky; top:0; font-size:18px; padding:32px; border-width:3px">
Cette page est une traduction de la version anglaise du guide.
Cette traduction n’est pas maintenue et peut être obsolète.
-Pour des informations plus à jour, voir la version anglaise.
+Pour des informations plus à jour, voir la <a href="../en/developer-guide.html">version anglaise</a>.
</div>
@@ -108,14 +100,7 @@ Pour des informations plus à jour, voir la version anglaise.
<section>
<header>
<h1 id="Standards"><span class="section-number">1.</span> Standards et normes</h1>
-<nav><div class="chapter-links"><div class="next-chapter"><a href="#DataAccess">Chapitre suivant</a> ➡</div></div></nav>
</header>
-<nav><p>Dans ce chapitre:</p><ul class="toc">
-<li><a href="#ConceptualModels">Sources des modèles conceptuels de Apache SIS</a></li>
-<li><a href="#GeoAPI">Des modèles conceptuels vers des interfaces Java: GeoAPI</a><ul>
-<li><a href="#GeoAPI-implementation">Implémentations fournies par Apache SIS</a></li></ul></li>
-<li><a href="#AboutBook">Conventions utilisées dans ce guide</a><ul>
-<li><a href="#ChosenTerms">Choix des termes</a></li></ul></li></ul></nav>
<p>
Une communauté d’informations géospatiales est un ensemble de systèmes ou d’individus capables d’échanger
leurs données géospatiales grâce à des définitions et des standards communs ainsi qu’une reconnaissance réciproque.
@@ -562,10 +547,7 @@ Mais un soin particulier doit être apporté aux interfaces entre <abbr>SIS</abb
<section>
<header>
<h1 id="DataAccess"><span class="section-number">2.</span> Accès aux données géospatiales</h1>
-<nav><div class="chapter-links"><div class="previous-chapter">⬅ <a href="#Standards">Chapitre précédent</a></div><div class="next-chapter"><a href="#Coverage">Chapitre suivant</a> ➡</div></div></nav>
</header>
-<nav><p>Dans ce chapitre:</p><ul class="toc">
-<li><a href="#GetMetadataElement">Parcourir les méta-données</a></li></ul></nav>
<p>
Bien qu’il soit possible de créer des structures de données programmatiquement en mémoire,
le plus souvent les données sont lues à partir de fichiers ou autres types d’entrepôts.
@@ -767,9 +749,7 @@ et sont associés à un mécanisme permettant de transformer des coordonnées d
<section>
<header>
<h1 id="Coverage"><span class="section-number">3.</span> Couvertures de données (<i>Coverages</i>)</h1>
-<nav><div class="chapter-links"><div class="previous-chapter">⬅ <a href="#DataAccess">Chapitre précédent</a></div><div class="next-chapter"><a href="#Geometry">Chapitre suivant</a> ➡</div></div></nav>
</header>
-<nav><p>Dans ce chapitre:</p><ul class="toc"/></nav>
<p>
Les images, souvent nommées <i>rasters</i> en anglais, sont des cas particuliers
d’une structure de données appelée <i>coverages</i>.
@@ -849,13 +829,7 @@ Cette section est incomplète. Voyez la version anglaise pour une version évent
<section>
<header>
<h1 id="Geometry"><span class="section-number">4.</span> Géométries</h1>
-<nav><div class="chapter-links"><div class="previous-chapter">⬅ <a href="#Coverage">Chapitre précédent</a></div><div class="next-chapter"><a href="#Referencing">Chapitre suivant</a> ➡</div></div></nav>
</header>
-<nav><p>Dans ce chapitre:</p><ul class="toc">
-<li><a href="#GeometryBase">Classes de base</a><ul>
-<li><a href="#DirectPosition">Points et positions directes</a></li>
-<li><a href="#Envelope">Enveloppes</a><ul>
-<li><a href="#AntiMeridian">Enveloppes traversant l’antiméridien</a></li></ul></li></ul></li></ul></nav>
<p>
Ce chapitre introduit quelques aspects de la norme <abbr title="International Organization for Standardization">ISO</abbr> 19107 (<i>Spatial schema</i>)
et les classes de Apache <abbr title="Spatial Information System">SIS</abbr> qui les implémentent.
@@ -1040,28 +1014,7 @@ est vrai, alors il est garanti que l’enveloppe est vide.
<section>
<header>
<h1 id="Referencing"><span class="section-number">5.</span> Systèmes de références spatiales</h1>
-<nav><div class="chapter-links"><div class="previous-chapter">⬅ <a href="#Geometry">Chapitre précédent</a></div><div class="next-chapter"><a href="#Utilities">Chapitre suivant</a> ➡</div></div></nav>
</header>
-<nav><p>Dans ce chapitre:</p><ul class="toc">
-<li><a href="#ComponentsOfCRS">Composantes d’un système de références par coordonnées</a><ul>
-<li><a href="#Ellipsoid">Géoïde et ellipsoïde</a></li>
-<li><a href="#GeodeticDatum">Référentiel géodésique</a></li>
-<li><a href="#CoordinateSystem">Systèmes de coordonnées</a><ul>
-<li><a href="#AxisOrder">Ordre des axes</a></li></ul></li>
-<li><a href="#GeographicCRS">Systèmes géographiques</a></li>
-<li><a href="#ProjectedCRS">Projections cartographiques</a></li></ul></li>
-<li><a href="#CoordinateOperations">Opérations sur les coordonnées</a><ul>
-<li><a href="#CRS.findOperation">Obtention d’une opération sur les coordonnées</a></li>
-<li><a href="#MathTransform">Exécution de opérations</a></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 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>
-<li><a href="#Formats">Formats de stockage des données</a></li>
-<li><a href="#XML-ISO">Représentation des objets en XML</a><ul>
-<li><a href="#XML-ISO-19115">Représentation des méta-données selon ISO 19115-3</a><ul>
-<li><a href="#gco-id">Identification d’instances déjà définies</a></li>
-<li><a href="#nilReason">Représentation de valeurs manquantes</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
— on parle alors de références spatiales par <cite>identifiants</cite> —
@@ -2212,17 +2165,7 @@ et dont la méthode <code class="SIS">getNilReason()</code> retournera la consta
<section>
<header>
<h1 id="Utilities"><span class="section-number">6.</span> Classes et méthodes utilitaires</h1>
-<nav><div class="chapter-links"><div class="previous-chapter">⬅ <a href="#Referencing">Chapitre précédent</a></div><div class="next-chapter"><a href="#GeoAPI-details">Chapitre suivant</a> ➡</div></div></nav>
</header>
-<nav><p>Dans ce chapitre:</p><ul class="toc">
-<li><a href="#ComparisonModes">Modes de comparaisons des objets</a></li>
-<li><a href="#ObjectConverters">Convertisseurs d’objets</a></li>
-<li><a href="#Internationalization">Internationalisation</a><ul>
-<li><a href="#LocalizedString">Chaînes de caractères distinctes pour chaque conventions locales</a></li>
-<li><a href="#InternationalString">Instance unique pour toutes les conventions locales</a></li>
-<li><a href="#Locale.ROOT">Convention Locale.ROOT</a></li>
-<li><a href="#UnicodePoint">Traitement des caractères</a><ul>
-<li><a href="#Whitespaces">Interprétation des espaces blancs</a></li></ul></li></ul></li></ul></nav>
<p>
Ce chapitre décrit des aspects de Apache <abbr title="Spatial Information System">SIS</abbr> qui s’appliquent à l’ensemble de la bibliothèque.
La plupart de ces utilitaires ne sont pas spécifiques aux systèmes d’information spatiales.
@@ -2597,18 +2540,8 @@ de la bibliothèque <abbr>SIS</abbr>.
<section>
<header>
<h1 id="GeoAPI-details"><span class="section-number">7.</span> Relation entre GeoAPI et les standards</h1>
-<nav><div class="chapter-links"><div class="previous-chapter">⬅ <a href="#Utilities">Chapitre précédent</a></div><div class="next-chapter"><a href="#Tests">Chapitre suivant</a> ➡</div></div></nav>
</header>
-<nav><p>Dans ce chapitre:</p><ul class="toc">
-<li><a href="#GeoAPI-modules">Les modules de GeoAPI</a></li>
-<li><a href="#SpecificationToInterfaces">Des spécifications de l’OGC aux interfaces Java</a><ul>
-<li><a href="#UML-annotation">Correspondances explicites entre GeoAPI et les spécifications abstraites</a></li>
-<li><a href="#MappingToJDK">Correspondances implicites avec le JDK standard</a></li></ul></li>
-<li><a href="#ReduceDependency">Réduire la dépendance directe envers Apache SIS</a><ul>
-<li><a href="#UML-annotation-indep">Correspondances entre GeoAPI et les spécifications abstraites</a></li>
-<li><a href="#ServiceLoader">Obtenir une implémentation des interfaces de GeoAPI</a><ul>
-<li><a href="#GeoAPI-simple">Fournir sa propre implémentation</a></li></ul></li></ul></li></ul></nav>
<p>
Le projet GeoAPI a été brièvement présenté <a href="#GeoAPI">en introduction</a> de ce document.
Cet annexe donne plus de détails à propos de la relation entre GeoAPI et les standards internationaux.
@@ -2648,10 +2581,9 @@ Les versions finales de Apache <abbr>SIS</abbr> dépendent de ce module.
(non pas une dépendance) avec des ajouts qui n’ont pas encore été approuvés comme un standard <abbr>OGC</abbr>.
Certains ajouts apparaissent dans des interfaces normalement définies par le module <code class="GeoAPI">geoapi</code>,
d’où la nécessité de les copier.
-Les branches de développement
-<code>JDK8</code> et <code>JDK9</code> de Apache <abbr>SIS</abbr> dépendent de ce module,
+Les branches de développement de Apache <abbr>SIS</abbr> dépendent de ce module,
mais cette dépendance est transformée en une dépendance vers le module <code class="GeoAPI">geoapi</code>
-standard au moment de fusionner les branches avec le tronc.
+standard au moment de fusionner les branches avec la branche principale.
</p></li>
<li><p>
<b><code class="GeoAPI">geoapi-conformance</code></b> — contient
@@ -2663,25 +2595,6 @@ exemples d’implémentations relativement simples. Ces exemples sont placés da
afin d’encourager les utilisateurs à les copier et les adapter à leurs besoins si les services
de Apache <abbr>SIS</abbr> ne conviennent pas.
</p></li>
-<li><p>
-<b><code class="GeoAPI">geoapi-proj4</code></b> — contient une
-implémentation partielle des paquets <code class="GeoAPI">org.opengis.referencing</code>
-sous forme d’adaptateurs basés sur la bibliothèque C/C++ Proj.4.
-Ce module peut être utilisé comme alternative au module <code class="SIS">sis-referencing</code>
-pour certaines fonctions.
-</p></li>
-<li><p>
-<b><code class="GeoAPI">geoapi-netcdf</code></b> — contient une implémentation partielle des paquets
-<code class="GeoAPI">org.opengis.referencing</code> et <code class="GeoAPI">org.opengis.coverage</code>
-sous forme d’adaptateurs basés sur la bibliothèque <abbr title="Network Common Data Form">netCDF</abbr> de l’<abbr title="University Corporation for Atmospheric Research">UCAR</abbr>.
-La suite de tests de ce module a été conçue de manière à être réutilisable par d’autres projets.
-Apache <abbr>SIS</abbr> l’utilise pour tester son propre module <code class="SIS">sis-netcdf</code>.
-</p></li>
-<li><p>
-<b><code class="GeoAPI">geoapi-openoffice</code></b> — contient
-un <i>add-in</i> pour les suites bureautiques Libre/OpenOffice.org.
-Note: Apache <abbr>SIS</abbr> offre son propre <i>add-in</i> dans le module <code class="SIS">sis-openoffice</code>.
-</p></li>
</ul>
</section>
@@ -3226,12 +3139,7 @@ tout en se gardant la possibilité de basculer plus facilement à une autre bibl
<section>
<header>
<h1 id="Tests"><span class="section-number">8.</span> Les suites de tests</h1>
-<nav><div class="chapter-links"><div class="previous-chapter">⬅ <a href="#GeoAPI-details">Chapitre précédent</a></div><div class="next-chapter"><a href="#DesignNotes">Chapitre suivant</a> ➡</div></div></nav>
</header>
-<nav><p>Dans ce chapitre:</p><ul class="toc">
-<li><a href="#GeoAPI-conformance">Conformance avec GeoAPI</a><ul>
-<li><a href="#GeoAPI-validators">Validations des instances</a></li>
-<li><a href="#GeoAPI-tests">Exécution des tests pré-définis</a></li></ul></li></ul></nav>
<p>
En plus des tests propres au projet, Apache SIS utilise aussi des tests définis par GeoAPI.
Ces tests ont l’avantage d’utiliser une source externe définissant ce que doivent être les résultats
@@ -3413,14 +3321,7 @@ qui sera exécutée après chacun des tests.
<section>
<header>
<h1 id="DesignNotes"><span class="section-number">9.</span> Notes de design</h1>
-<nav><div class="chapter-links"><div class="previous-chapter">⬅ <a href="#Tests">Chapitre précédent</a></div></div></nav>
</header>
-<nav><p>Dans ce chapitre:</p><ul class="toc">
-<li><a href="#AffineTransform">Utilisation des transformations affines</a><ul>
-<li><a href="#AffineTransformAPI">Intégration avec les bibliothèques graphiques</a></li></ul></li>
-<li><a href="#MatrixLibrary">Particularités d’une bibliothèque de calculs matriciels pour un SIG</a><ul>
-<li><a href="#NonSquareMatrix">Que faire des matrices qui ne sont pas carrées (et pourquoi)</a></li>
-<li><a href="#MatrixLibrarySummary">La bibliothèque matricielle de Apache SIS</a></li></ul></li></ul></nav>
<p>Les chapitres suivants expliquent les raisons derrières certains choix d’implémentation de Apache <abbr title="Spatial Information System">SIS</abbr>.</p>
diff --git a/book/toc.js b/book/toc.js
new file mode 100644
index 00000000..069dfbfe
--- /dev/null
+++ b/book/toc.js
@@ -0,0 +1,34 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF)
+ * under one or more contributor license agreements.
+ */
+window.addEventListener('DOMContentLoaded', () => {
+
+ var lastVisibleId = null;
+
+ const observer = new IntersectionObserver(entries => {
+ entries.forEach(entry => {
+ const id = entry.target.getAttribute('id');
+ var line = document.querySelector(`nav li a[href="#${id}"]`);
+ if (line !== null) {
+ if (entry.intersectionRatio > 0) {
+ if (lastVisibleId !== null) {
+ document.querySelector(`nav li a[href="#${lastVisibleId}"]`).parentElement.classList.remove('active');
+ }
+ lastVisibleId = id;
+ var item = line.parentElement;
+ item.classList.add('active');
+ const bounds = item.getBoundingClientRect();
+ if (bounds.top < 0 || bounds.bottom > window.innerHeight - 2) {
+ item.scrollIntoView();
+ }
+ }
+ }
+ });
+ });
+
+ // Track headers that have an `id` applied.
+ document.querySelectorAll(':is(h1,h2,h3,h4)[id]').forEach((section) => {
+ observer.observe(section);
+ });
+});