Copied: sis/site/trunk/book/en/annex/ReduceDependency.html (from r1794573, sis/site/trunk/book/en/annexes.html) URL: http://svn.apache.org/viewvc/sis/site/trunk/book/en/annex/ReduceDependency.html?p2=sis/site/trunk/book/en/annex/ReduceDependency.html&p1=sis/site/trunk/book/en/annexes.html&r1=1794573&r2=1794656&rev=1794656&view=diff ============================================================================== --- sis/site/trunk/book/en/annexes.html [UTF-8] (original) +++ sis/site/trunk/book/en/annex/ReduceDependency.html [UTF-8] Tue May 9 23:04:35 2017 @@ -20,23 +20,21 @@ under the License. --> - + - Annexes + ReduceDependency - +
-

Annexes

+

Reduce direct dependency to Apache SIS

-

Reduce direct dependency to Apache SIS

Previous chapters used Apache SIS static methods for convenience. In some cases, usage of those convenience methods can be replaced by Java code using only GeoAPI methods. @@ -206,420 +204,6 @@ public class MyApplication { The advantage of using these interfaces is to provide a unified model to operate two very different APIs, while retaining the ability to switch easily to another library if desired.

- - - -

Test suites

-

- 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 - (for example the numerical values of coordinates obtained after a map projection). - Such external source reduce the risk that some tests are actually anti-regression tests - instead of correctness tests. - Those tests can also be used by projects other than Apache SIS. -

-

- The geoapi-conformance module provides validators, a JUnit test suite, and report generators - in the form of HTML pages. - This module may be used with any GeoAPI implementation. - For developers of a geospatial library, it offers the following advantages: -

- - - - -

Instance validations

-

- 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 - are usually described textually in the abstract specifications or in the javadoc. -

-

Example: - A coordinate conversion or transformation (CC_CoordinateOperation) may require a sequence of several steps. - In such a sequence of operations (CC_ConcatenatedOperation), for each step (CC_SingleOperation) - the number of output dimensions must equal the number of input dimensions in the next operation. - Expressed in Java, this constraint stipulates that for the entire index 0 < i < n where n - is the number of operations, we have coordOperation[i].targetDimensions == coordOperation[i-1].sourceDimensions. -

- -

- The easiest way to perform these verifications is to call the static methods validate(…) - of the org.opengis.test.Validators class. - As all of Validators methods bear the same name, it is enough to write “validate(value)” - and then let the compiler choose the most appropriate method for the type of object given in argument. - If the object type is not known at the time of compilation, - the dispatch(Object) method can be invoked for redirecting the work to the most appropriate validate(…) method. -

-

- All validate(…) functions follow a chain of dependencies, - meaning that they will also validate each component of the object to be validated. - For example, the validation of a GeographicCRS implies the validation of its component - GeodeticDatum, which itself implies the validation of its component Ellipsoid, and so on. - Thus it is unnecessary to validate the components explicitely, unless the developer wishes to isolate the test for a particular item known to cause problems. -

-

- By default, validations are as strict as possible. It is always possible to relax certain rules. - The most common is to tolerate the absence of attributes that would normally be mandatory. - This rule and a few others may be modified globally for all tests executed by the currently running JVM, - as in the following example: -

- -
import org.opengis.metadata.Metadata;
-import org.opengis.test.Validators;
-import org.junit.Test;
-
-public class MyTest {
-    /*
-     * Tolerate the absence of mandatory attributes in metadata and citation packages.
-     * This modification applies to all tests executed by the currently running JVM.
-     * If there are multiple test classes, this initialization may be performed
-     * in a parent class to all test classes.
-     */
-    static {
-        Validators.DEFAULT.metadata.requireMandatoryAttributes = false;
-        Validators.DEFAULT.citation.requireMandatoryAttributes = false;
-    }
-
-    @Test
-    public void testMyMetadata() {
-        Metadata myObject = …; // Create an object here.
-        Validators.validate(myObject);
-    }
-}
- -

- Rules may also be modified for a particular test suite without affecting the default configuration of the standard JVM. - This approach requires the creation of a new instance of the validator that we wish to modify the configuration. -

- -
import org.opengis.metadata.Metadata;
-import org.opengis.test.ValidatorContainer;
-import org.junit.Test;
-
-public class MyTest {
-    private final ValidatorContainer validators;
-
-    public MyTest() {
-        validators = new ValidatorContainer();
-        validators.metadata.requireMandatoryAttributes = false;
-        validators.citation.requireMandatoryAttributes = false;
-    }
-
-    @Test
-    public void testMyMetadata() {
-        Metadata myObject = …; // Create an object here.
-        validators.validate(myObject);
-    }
-}
- - - -

Executing pre-defined tests

-

- JUnit tests are defined in the org.opengis.test sub-packages. - All test classes bear a name ending in "Test". - GeoAPI also provides an org.opengis.test.TestSuite class including all test classes defined in the - geoapi-conformance module, but Apache SIS does not use it. - Instead, Apache SIS inherits GeoAPI’s *Test classes on a case-by-case basis, - in the appropriate modules. - The example below gives an example of a customized GeoAPI test: - The parent test javadoc - documents the tests performed in detail. - In this example, only one test is modified and all the others are inherited as they are (it is not necessary to repeat them in the sub-class). - However, this example adds a supplemental verification, annotated with @After, which will be executed after each test. -

- -
import org.junit.*;
-import org.junit.runner.RunWith;
-import org.junit.runners.JUnit4;
-import org.opengis.test.referencing.ParameterizedTransformTest;
-import static org.junit.Assert.*;
-
-@RunWith(JUnit4.class)
-public class MyTest extends ParameterizedTransformTest {
-    /**
-     * Specify our own coordinate transformation factory for the GeoAPI tests.
-     * GeoAPI will test the objects created by this factory.
-     */
-    public MyTest() {
-        super(new MyMathTransformFactory());
-    }
-
-    /**
-     * Changes the behaviour of a test. This example relaxes the requirements of this test a little,
-     * by accepting errors of up to 10 centimetres, rather than the default value of 1 cm.
-     * This change only applies to this method, and does not affect the other inherited tests.
-     */
-    @Test
-    @Override
-    public void testLambertAzimuthalEqualArea() throws FactoryException, TransformException {
-        tolerance = 0.1; // 10 cm tolerance.
-        super.testLambertAzimuthalEqualArea();
-    }
-
-    /**
-     * Supplemental verification performed after each test, inherited or not.
-     * In this example, we are verifying that the transformation tested
-     * works correctly in two-dimensional spaces.
-     */
-    @After
-    public void ensureAllTransformAreMath2D() {
-        assertTrue(transform instanceof MathTransform2D);
-    }
-}
- - - -

Design notes

-

Following chapters explain the rational behind some implementation choices done in Apache SIS.

- - -

Affine transform

-

- Among the many kinds of operations performed by GIS softwares on spatial coordinates, - affine transforms are both relatively simple and very common. - Affine transforms can represent any combination of scales, shears, flips, rotations and translations, - which are linear operations. - Affine transforms can not handle non-linear operations like map projections, - but the affine transform capabilities nevertheless cover many other cases: -

- -

- 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. -

- -
-

Example: - given an image with pixel coordinates represented by (x,y) tuples - and given the following assumptions: -

- -

Then conversions from pixel coordinates (x,y) - to geographic coordinates (λ,φ) can be represented by the following equations, - where Nx is the image width and - Ny the image height in number of pixels: -

- -

- Above equations can be represented in matrix form as below: -

- -

- In this particular case, scale factors S are the pixel size in degrees - and translation terms T 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 S and T terms are set to the most straightforward values. - Then the y 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: - A×B×C is equivalent to first applying operation C, - then operation B and finally operation A. -

- - - - - - - - - - - - - - -

- 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 SIS 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. -

-
- -

Integration with graphical libraries

-

- About all graphical libraries support some kind of coordinate operations, usually as affine transforms - or a slight generalization like perspective transforms. - Each library defines its own API. Some examples are listed below: -

- - - - - - - - -
Affine transform implementations in graphical libraries
Library Transform implementation Dimensions
Java2D java.awt.geom.AffineTransform 2
Java3D javax.media.j3d.Transform3D 3
JavaFX javafx.scene.transform.Affine 2 or 3
Java Advanced Imaging (JAI) javax.media.jai.PerspectiveTransform 2
Android android.graphics.Matrix 2
-

- However in many cases, affine or perspective transforms are the only kind of coordinate operations supported by the graphical library. - Apache SIS 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. - SIS also needs to support arbitrary number of dimensions, - while above-cited API restrict the use to a fixed number of dimensions. - For those reasons SIS can not use directly the above-cited API. - Instead, SIS uses the more abstract org.opengis.referencing.transform.MathTransform interface. - But in the special case where the transform is actually affine, SIS may try to use an existing implementation, - in particular Java2D. The following Java code can be used in situations where the Java2D object is desired: -

- -
MathTransform mt = ...;    // Any math transform created by Apache SIS.
-if (mt instanceof AffineTransform) {
-    AffineTransform at = (AffineTransform) mt;
-    // Use Java2D API from here.
-}
- -

- Apache SIS uses Java2D on a best effort basis only. - The above cast is not guaranteed to succeed, - even when the MathTransform meets the requirements allowing Java2D usage. -

- - -

Specificities of a matrix library for GIS

-

- GIS 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, GIS have some specific needs that differ a little bit from the goals of many existent libraries. - Matrix operations like those described in the affine transform chapter - appear in almost all coordinate operations applied by Apache SIS. - But the analysis of those operations reveal some patterns: -

- -

- As a consequence of above points, accuracy of a matrix library is more important than performance for a GIS like Apache SIS. - Paradoxically, a good way to improve performance is to invest more CPU time for more accurate matrix operations - when preparing (not executing) 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. -

- 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 SIS needs to solve. - For that reason, and also for another reason described in next paragraphs, Apache SIS 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 preparation) where performance is not considered critical. -

- -

What to do with non-square matrices (and why)

-

- Apache SIS often needs to inverse matrices, in order to perform a coordinate operation in reverse direction. - Matrix inversions are typically performed on square matrices, but SIS also needs to inverse non-square matrices. - Depending on whether we have more lines than columns: -

- -

- To illustrate the issues caused by direct use of libraries designed for linear algebra, - consider a (φ₁, λ₁, h) → (φ₂, λ₂) conversion - from three-dimensional points to two-dimensional points on a surface. - The φ terms are latitudes, the λ terms are longitudes and - (φ₂, λ₂) may be different than (φ₁, λ₁) if h axis is not perpendicular to the surface. -

- -

- 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 (φ₂, λ₂) → (φ₁, λ₁, h) - operation because we do not know which value to assign to h. - Ignoring h implies that we can not assign values to (φ₁, λ₁) neither since those values may depend on h. - However in GIS case, the ellipsoidal h axis is perpendicular to the ellipsoid surface - on which the geodetic latitudes and longitudes (φ, λ) are represented - (note that this statement is not true for geocentric latitudes and longitudes). - This perpendicularity makes φ₁ and λ₁ independent of h. - In such cases, we can can still do some processing. -

- Apache SIS proceeds by checking if h values are independent of φ and λ values. - We identify such cases by checking which matrix coefficients are zero. - If SIS can identify independent dimensions, it can temporarily exclude those dimensions - and invert the matrix using only the remaining dimensions. - If SIS 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 SIS temporarily excluded. - By default, SIS assigns the NaN (Not-a-Number) value to those dimensions. - However in the particular case of ellipsoidal height h in a (φ₂, λ₂) → (φ₁, λ₁, h) 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 SIS sets to zero or NaN is based on the assumption - that the matrix represents a coordinate operation; this is not something that can be done with arbitrary matrices. -

- The above-described approach allows Apache SIS to resolve some under-determined equation systems commonly found in GIS. - In our example using NaN as the default value, the h ordinate stay unknown – we do not create information from nothing – - but at least the (φ, λ) 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 (φ₂, λ₂, h) → (φ₁, λ₁) operation - that seems the best compromise for various φ₂, λ₂ and h 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 h in metres and (φ, λ) in degrees. - Apache SIS 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, SIS 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). -

- -

Apache SIS matrix library

-

- In summary, Apache SIS provides its own matrix library for the following reasons: -

- -

- This library is provided in the org.apache.sis.matrix package of the sis-referencing module. -

-
+
Copied: sis/site/trunk/book/en/annex/Tests.html (from r1794573, sis/site/trunk/book/en/annexes.html) URL: http://svn.apache.org/viewvc/sis/site/trunk/book/en/annex/Tests.html?p2=sis/site/trunk/book/en/annex/Tests.html&p1=sis/site/trunk/book/en/annexes.html&r1=1794573&r2=1794656&rev=1794656&view=diff ============================================================================== --- sis/site/trunk/book/en/annexes.html [UTF-8] (original) +++ sis/site/trunk/book/en/annex/Tests.html [UTF-8] Tue May 9 23:04:35 2017 @@ -20,196 +20,21 @@ under the License. --> - + - Annexes + Tests - +
-

Annexes

+

Test suites

-

Reduce direct dependency to Apache SIS

-

- Previous chapters used Apache SIS static methods for convenience. - In some cases, usage of those convenience methods can be replaced by Java code using only GeoAPI methods. - Such replacements may be desirable for applications who want to reduce direct dependency toward Apache SIS, - for example in order to ease migrations between SIS and other GeoAPI implementations. - However this may require that applications write their own convenience methods. - The following sections provide some tip for easing this task. -

- -

Mapping given by @UML annotations

-

- For each class, method and constant defined by an OGC or ISO standard, - GeoAPI indicates its provenance using annotations defined in the org.opengis.annotation package. - This mapping is described in the chapter about GeoAPI. - Java reflection methods allow access to this information during the execution of an application. - Class org.apache.sis.util.iso.Types provides static convenience methods like - getStandardName(Class), but one can avoid those methods. - The following example displays the standard name for the method getTitle() from the Citation interface: -

- -
Class<?> type   = Citation.class;
-Method   method = type.getMethod("getTitle", (Class<?>[]) null);
-UML      annot  = method.getAnnotation(UML.class);
-String   id     = annot.identifier();
-System.out.println("The standard name for the " + method.getName() + " method is " + id);
- -

- The reverse operation — getting the Java class and method from a standard name — is a bit more complicated. - It requires reading the class-index.properties file provided in the org.opengis.annotation package. - The following example reads the files just before searching for the name of the interface corresponding to CI_Citation. - Users are always encouraged to only read this file once and then save its contents in their application's cache. -

- -
Properties isoToGeoAPI = new Properties();
-try (InputStream in = UML.class.getResourceAsStream("class-index.properties")) {
-    isoToGeoAPI.load(in);
-}
-String isoName = "CI_Citation";
-String geoName = getProperty(isoName);
-Class<?>  type = Class.forName(geoName);
-System.out.println("The GeoAPI interface for ISO type " + isoName + " is " + type);
- -

- The org.apache.sis.util.iso.Types convenience method for above task is - forStandardName(String). -

- - - -

Fetching implementations of GeoAPI interfaces

-

- GeoAPI defines factories (Factory) that can create implementations of interfaces. - For example, DatumFactory provides methods that can create instances which implement interfaces of the - org.opengis.referencing.datum package. - A Factory must be implemented by a geospatial library, - and declared as a service as defined by the java.util.ServiceLoader class. - The ServiceLoader javadoc explains this procedure. - In brief, the library must create a file in the META-INF/services/ directory, - with a name corresponding to the complete name of an interface in the factory - (in the preceding example, org.opengis.referencing.datum.DatumFactory). - On one line, this text file must include the complete name of the class that implements this interface. - This class may be hidden from users, as they do not need to know of its existence. -

-

- If the library has correctly declared its factories as services, - users may import them by using ServiceLoader, as in the example below. - This example only takes the first factory located; if there is more than one factory - - for example when multiple libraries coexist — then the choice is left to the user. -

- -
import org.opengis.referencing.GeodeticDatum;
-import org.opengis.referencing.DatumFactory;
-import java.util.ServiceLoader;
-
-public class MyApplication {
-    public void createMyDatum() {
-        ServiceLoader  loader = ServiceLoader.load(DatumFactory.class);
-        DatumFactory  factory = loader.iterator().next();
-        GeodeticDatum myDatum = factory.createGeodeticDatum(…);
-    }
-}
- - - -

Defining custom implementations

-

- 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, - while keeping other interfaces as extension points to eventually implement as needed. -

-

- 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 Coordinate System (CS) - and a Coordinate Reference System (CRS). - 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 geoapi-examples module, discussed later, provides such combinations. - The following table lists a few possible combinations: -

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Main InterfaceAuxiliary InterfaceUse
CoordinateReferenceSystemCoordinateSystemDescription of a spatial reference system (CRS).
GeodeticDatumEllipsoidDescription of the geodetic datum.
CoordinateOperationMathTransformCoordinate transformation operations.
IdentifiedObjectReferenceIdentifierAn objet (usually a CRS) that we can identify by a code.
CitationInternationalStringBibliographic reference consisting of a simple title.
GeographicBoundingBoxExtentSpatial area in degrees of longitude and latitude.
ParameterValueParameterDescriptorDescription of a parameter (name, type) associated with its value.
ParameterValueGroupParameterDescriptorGroupDescription of a set of parameters associated with their values.
-

- The geoapi-examples module provides examples of simple implementations. - Many of these classes implement more than one interface at a time in order to provide a simpler conceptual model. - The javadoc for this module - lists key packages and classes along with the combinations performed. - This module illustrates not only how GeoAPI might be implemented, - but also how the implementation might be tested using geoapi-conformance. -

-

- Although its primary goal is to serve as a source of inspiration for implementors, - geoapi-examples was also designed so as to be usable by applications with very simple needs. - As all the examples are in the public domain, developers are invited to freely adapt copies of these classes as necessary. - However, if changes are made outside the framework of the GeoAPI project, - fair use demands that modified copies be placed in a package with a different name than org.opengis. -

-

- For somewhat more involved needs, developers are invited to examine the - geoapi-proj4 and geoapi-netcdf modules. - These two modules provide examples of adaptors that are allowed, via GeoAPI interfaces, - to use some of the features of external libraries (Proj.4 and NetCDF). - The advantage of using these interfaces is to provide a unified model to operate two very different APIs, - while retaining the ability to switch easily to another library if desired. -

- - - -

Test suites

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 @@ -372,254 +197,6 @@ public class MyTest extends Parameterize assertTrue(transform instanceof MathTransform2D); } } - - - -

Design notes

-

Following chapters explain the rational behind some implementation choices done in Apache SIS.

- - -

Affine transform

-

- Among the many kinds of operations performed by GIS softwares on spatial coordinates, - affine transforms are both relatively simple and very common. - Affine transforms can represent any combination of scales, shears, flips, rotations and translations, - which are linear operations. - Affine transforms can not handle non-linear operations like map projections, - but the affine transform capabilities nevertheless cover many other cases: -

- -

- 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. -

- -
-

Example: - given an image with pixel coordinates represented by (x,y) tuples - and given the following assumptions: -

-
    -
  • There is no shear, no rotation and no flip.
  • -
  • All pixels have the same width in degrees of longitude.
  • -
  • All pixels have the same height in degrees of latitude.
  • -
  • Pixel indices are positive integers starting at (0,0) inclusive.
  • -
-

Then conversions from pixel coordinates (x,y) - to geographic coordinates (λ,φ) can be represented by the following equations, - where Nx is the image width and - Ny the image height in number of pixels: -

- -

- Above equations can be represented in matrix form as below: -

- -

- In this particular case, scale factors S are the pixel size in degrees - and translation terms T 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 S and T terms are set to the most straightforward values. - Then the y 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: - A×B×C is equivalent to first applying operation C, - then operation B and finally operation A. -

- - - - - - - - - - - - - - -

- 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 SIS 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. -

-
- -

Integration with graphical libraries

-

- About all graphical libraries support some kind of coordinate operations, usually as affine transforms - or a slight generalization like perspective transforms. - Each library defines its own API. Some examples are listed below: -

- - - - - - - - -
Affine transform implementations in graphical libraries
Library Transform implementation Dimensions
Java2D java.awt.geom.AffineTransform 2
Java3D javax.media.j3d.Transform3D 3
JavaFX javafx.scene.transform.Affine 2 or 3
Java Advanced Imaging (JAI) javax.media.jai.PerspectiveTransform 2
Android android.graphics.Matrix 2
-

- However in many cases, affine or perspective transforms are the only kind of coordinate operations supported by the graphical library. - Apache SIS 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. - SIS also needs to support arbitrary number of dimensions, - while above-cited API restrict the use to a fixed number of dimensions. - For those reasons SIS can not use directly the above-cited API. - Instead, SIS uses the more abstract org.opengis.referencing.transform.MathTransform interface. - But in the special case where the transform is actually affine, SIS may try to use an existing implementation, - in particular Java2D. The following Java code can be used in situations where the Java2D object is desired: -

- -
MathTransform mt = ...;    // Any math transform created by Apache SIS.
-if (mt instanceof AffineTransform) {
-    AffineTransform at = (AffineTransform) mt;
-    // Use Java2D API from here.
-}
- -

- Apache SIS uses Java2D on a best effort basis only. - The above cast is not guaranteed to succeed, - even when the MathTransform meets the requirements allowing Java2D usage. -

- - -

Specificities of a matrix library for GIS

-

- GIS 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, GIS have some specific needs that differ a little bit from the goals of many existent libraries. - Matrix operations like those described in the affine transform chapter - appear in almost all coordinate operations applied by Apache SIS. - But the analysis of those operations reveal some patterns: -

- -

- As a consequence of above points, accuracy of a matrix library is more important than performance for a GIS like Apache SIS. - Paradoxically, a good way to improve performance is to invest more CPU time for more accurate matrix operations - when preparing (not executing) 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. -

- 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 SIS needs to solve. - For that reason, and also for another reason described in next paragraphs, Apache SIS 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 preparation) where performance is not considered critical. -

- -

What to do with non-square matrices (and why)

-

- Apache SIS often needs to inverse matrices, in order to perform a coordinate operation in reverse direction. - Matrix inversions are typically performed on square matrices, but SIS also needs to inverse non-square matrices. - Depending on whether we have more lines than columns: -

- -

- To illustrate the issues caused by direct use of libraries designed for linear algebra, - consider a (φ₁, λ₁, h) → (φ₂, λ₂) conversion - from three-dimensional points to two-dimensional points on a surface. - The φ terms are latitudes, the λ terms are longitudes and - (φ₂, λ₂) may be different than (φ₁, λ₁) if h axis is not perpendicular to the surface. -

- -

- 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 (φ₂, λ₂) → (φ₁, λ₁, h) - operation because we do not know which value to assign to h. - Ignoring h implies that we can not assign values to (φ₁, λ₁) neither since those values may depend on h. - However in GIS case, the ellipsoidal h axis is perpendicular to the ellipsoid surface - on which the geodetic latitudes and longitudes (φ, λ) are represented - (note that this statement is not true for geocentric latitudes and longitudes). - This perpendicularity makes φ₁ and λ₁ independent of h. - In such cases, we can can still do some processing. -

- Apache SIS proceeds by checking if h values are independent of φ and λ values. - We identify such cases by checking which matrix coefficients are zero. - If SIS can identify independent dimensions, it can temporarily exclude those dimensions - and invert the matrix using only the remaining dimensions. - If SIS 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 SIS temporarily excluded. - By default, SIS assigns the NaN (Not-a-Number) value to those dimensions. - However in the particular case of ellipsoidal height h in a (φ₂, λ₂) → (φ₁, λ₁, h) 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 SIS sets to zero or NaN is based on the assumption - that the matrix represents a coordinate operation; this is not something that can be done with arbitrary matrices. -

- The above-described approach allows Apache SIS to resolve some under-determined equation systems commonly found in GIS. - In our example using NaN as the default value, the h ordinate stay unknown – we do not create information from nothing – - but at least the (φ, λ) 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 (φ₂, λ₂, h) → (φ₁, λ₁) operation - that seems the best compromise for various φ₂, λ₂ and h 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 h in metres and (φ, λ) in degrees. - Apache SIS 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, SIS 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). -

- -

Apache SIS matrix library

-

- In summary, Apache SIS provides its own matrix library for the following reasons: -

- -

- This library is provided in the org.apache.sis.matrix package of the sis-referencing module. -

-
+
Copied: sis/site/trunk/book/en/coverage/Coverage.html (from r1794655, sis/site/trunk/book/en/coverage.html) URL: http://svn.apache.org/viewvc/sis/site/trunk/book/en/coverage/Coverage.html?p2=sis/site/trunk/book/en/coverage/Coverage.html&p1=sis/site/trunk/book/en/coverage.html&r1=1794655&r2=1794656&rev=1794656&view=diff ============================================================================== --- sis/site/trunk/book/en/coverage.html [UTF-8] (original) +++ sis/site/trunk/book/en/coverage/Coverage.html [UTF-8] Tue May 9 23:04:35 2017 @@ -24,11 +24,11 @@ Data coverages - +
Copied: sis/site/trunk/book/en/geometry/Geometry.html (from r1794573, sis/site/trunk/book/en/geometry.html) URL: http://svn.apache.org/viewvc/sis/site/trunk/book/en/geometry/Geometry.html?p2=sis/site/trunk/book/en/geometry/Geometry.html&p1=sis/site/trunk/book/en/geometry.html&r1=1794573&r2=1794656&rev=1794656&view=diff ============================================================================== --- sis/site/trunk/book/en/geometry.html [UTF-8] (original) +++ sis/site/trunk/book/en/geometry/Geometry.html [UTF-8] Tue May 9 23:04:35 2017 @@ -20,11 +20,11 @@ under the License. --> - + - Geometries + Geometry - +
-

Geometries

+

Base classes

- This chapter introduces a few aspects of ISO 19107 standard (Spatial schema) - and the Apache SIS classes that implement them. -

- - - -

Base classes

-

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 java.util.Set in which the elements are points, Modified: sis/site/trunk/book/en/index.html URL: http://svn.apache.org/viewvc/sis/site/trunk/book/en/index.html?rev=1794656&r1=1794655&r2=1794656&view=diff ============================================================================== --- sis/site/trunk/book/en/index.html [UTF-8] (original) +++ sis/site/trunk/book/en/index.html [UTF-8] Tue May 9 23:04:35 2017 @@ -27,7 +27,7 @@ Introduction to Apache SIS - +

Introduction to Apache SIS®

@@ -43,13 +43,13 @@
- - - - - - - + + + + + + +