Skip to content

Commit

Permalink
Updated README
Browse files Browse the repository at this point in the history
  • Loading branch information
maesenka committed Mar 6, 2021
1 parent f9e7dcd commit ee67d84
Showing 1 changed file with 134 additions and 47 deletions.
181 changes: 134 additions & 47 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,71 +2,158 @@

# Geolatte-geom

A geometry model for Java that conforms to the Simple Features For SQL specification 1.2.1.

It is intended as a drop-in replacement for the Java Topology Suite (JTS) geometry model. GeoLatte-geom is fully
interoperable with JTS but offers the following additional features:
* immutable data structures (Geometries are value objects).
A geometry model for Java with:
* immutable data structures
* support for 2D, 3D, 2DM and 3DM geometries
* support for several dialects of WKT/WKB (Postgis, Sql Server, SFS 1.21)
* pluggable, extendable Geometry operations
* CRS-awareness (knowledge of coordinate reference system (projected/geodetic, angular units of metres)
* geodetic operations (length, distance and area calculations)
* A DSL for creating Geometries
* support for several dialects of WKT/WKB (Postgis, Sql Server, SFA 1.1.0 and 1.2.1)
* Codecs for translating from/to native database formats for Postgis, Mysql, Oracle, and Microsoft SQL Server.
* Pluggable, extendable Geometry operations
* Coordinate reference system aware
* space filling curves

The library's geometry model is largely based on the
[Simple Feature Access (1.2.1) specification](https://portal.ogc.org/files/?artifact_id=25355).

GeoLatte-geom is fully interoperable with [the Java Topology Suite (JTS)](https://github.com/locationtech/jts).

# Using Geolatte-geom

Currently we require Java 1.8 or later.

The library is published on Maven Central. For Maven, you can include the following dependency.

```xml
<dependency>
<groupId>org.geolatte</groupId>
<artifactId>geolatte-geom</artifactId>
<version>1.17</version>
</dependency>
```

# Quick start

## Creating Geometries
To create a Geometry we first need to specify the Coordinate Reference System we will be working in. Let's say we use
WGS84 (for other options, see [below](#coordinate-reference-systems)).

```java
import org.geolatte.geom.*;
import static org.geolatte.geom.crs.CoordinateReferenceSystems.WGS84;

```

The easiest way to create `Geometry` instances is by using the built-in builder DSL. This allows you to specify 2D `Position`s
(coordinates) using `c(x,y)`for Cartesian or projected coordinates, and
`g(long,lat)` for geodetic or spherical coordinates. (There are also variants for the higher dimensions).

```java
import static org.geolatte.geom.builder.DSL.*;
```
Now we can create geometries like so.
```java
...
Point<G2D> pnt = point(WGS84, g(4.33,53.21));

LineString<G2D> lstr = linestring(WGS84, g(4.43, 53.21), g(4.44, 53.20), g(4.45, 53.19));

Polygon<G2D> pgn = polygon(WGS84, ring(g(4.43, 53.21), g(4.44, 53.22), g(4.43, 53.21)));
```
We can also create Geometries in a higher-dimensional space. Let's do it in 3D.

First we again need to specify the coordinate reference system we will be working in. In this case, we derive
the system from WGS84 by adding a Vertical system for the elevation.

```java

# Redesign 0.x to 1.0
CoordinateReferenceSystem<G3D> wgs84E = WGS84.addVerticalSystem(LinearUnit.METER, G3D.class);
...

Point<G3D> pntWithElevation = point(wgs84E, g(4.33, 53.21, 350));

This version is a complete redesign. The redesign is aimed at:
* increasing the level of type-safety in the API;
* the ability to incorporate geographic (or geodetic) data without duplication of the Geometry class hierarchy;
* making full use of the information on coordinate reference systems that is now available in the CRSRegistry.
```

## The Coordinate Reference System model (crs package)
## Encoding and Decoding Geometries to WKT/WKB

The availability of the CRSRegistry, and the explicit modelling of coordinate reference systems,
made it obvious that a better way was available for handling the different dimensions of a Geometry's coordinate space.
In previous versions this dimensionality was specified with a DimensionalFlag. Having a complete model of the
Coordinate Reference System, including it's coordinate space, means we no longer need this. Rather than
associating a DimensionalFlag with the Geometry, we only need it's Coordinate Reference System.
Now let's write these out as WKT string.
```java
import org.geolatte.geom.codec.Wkt;

Since in the Coordinate Reference System model Projected and Geographic systems are distinguished, we can use a
single Geometry class-hierarchy, and let the implementations inspect the associated Coordinate Reference System
to determine which operations are valid, or which algorithms are selected (e.g. geodetic length rather than length in 2D plane).
String wkt = Wkt.toWkt(pnt);
// "SRID=4326;POINT(4.33 53.21)"

## Base and compound Coordinate Reference Systems
// or maybe using a specific dialect such as SFA 1.2.1
String wktZ = Wkt.toWkt(pntWithElevation, Wkt.Dialect.SFA_1_2_1);
// "POINT Z (4.33 53.21 350)"
```

The CRSRegistry only provides access to base systems, which are always 2D. Users can add axes (Vertical or Measure) to
a base system, and so create a Compound system. Vertical axes are axes with a Direction of UP (DOWN), measure axes have
direction OTHER or UNKNOWN. Although it is possible to add several Measure axes, many measure operations will only take the first
such axis into account.
There is a very similar API for WKB encoding/decoding (see the `Wkb` codec class).

For historical and practical reasons. The default dialects for WKB/WKT are those
used in [Postgis](http://postgis.org).

## Geometry operations

[TODO]

# The Geometry model

## Positions

A Position is essentially a tuple of coordinates which together with a Coordinate Reference System specify
a position in that Coordinate Reference System.
A `Position` is a tuple of coordinates that specify a position relative to a coordinate reference system.
It corresponds with to the concept of **direct position** in the Simple Feature
and ISO-19107 specifications.

The coordinate space can be 2-, 3- or 4-dimensional. The first two dimensions are used to specify a
point on the earth's surface. The third dimension usually represent altitude or elevation,
and the fourth a measurement.

There are two major types of 2D coordinate reference systems. `GeographicCoordinateReferenceSystem`s specify
points on the earth's surface using spherical coordinates (i.e. latitude` and longitude).
`ProjectedCoordinateReferenceSystem`s use cartesian coordinates (x and y) on a projected plane.

From these 2D-spaces the higher-dimensional spaces can be constructed by adding a
`VerticalCoordinateReferenceSystem` and/or a `LinearCoordinateReferenceSystem`.

Consequently, the instantiable (2D) types of `Position` are `G2D` (spherical coordinates) and `C2D` (cartesian coordinates) in a
geographic, resp. projected coordinate reference system. From these the higher-dimensional subtypes
can be derived. E.g. from `C2D`, we can build `C3D`, `C2DM` and `C3DM` positions.


## Geometry

A `Geometry` is a topologically closed set (in the mathematical sense) of `Position`s. The instantiable `Geometry`
subclasses all specify this set using one or more boundaries. The boundaries in turn are specified by
interpolation between consecutive elements in a list of `Position`s. These `Position`s are called the _vertices_ of the
`Geometry`.

A distinctive feature of this library is that `Geometry` class is parameterized by `Position` type. This means that e.g.
a `Point<C2D>` is a different type than `Point<G2D>`. This ensures that it is always explicit what the coordinates mean
(projected or spherical), and what types of operation make sense. E.g. the euclydian distance on the plane works for
projected coordinates, but makes no sense for spherical coordinates.


The instantiable subclasses of `Geometry` are:

- `Point` a single position
- `LineString` a 1-dimensional curve specified by linear interpolation between its vertices
- `Polygon` a 2-dimensional space enclosed by an outer `LinearRing` (a closed `LineString`), minus the space enclosed
by any inner `LinearRing`s.
- `MultiPoint` a collection of `Point`s
- `MultiLineString` a collection of `LineString`s
- `MultiPolygon` a collection of `Polygon`s
- `GeometryCollection` a collection of `Geometry`s

## Coordinate Reference Systems
[TODO]

# JTS interop

In previous versions, Points played the role of Positions. The concept of a Position, distinguished from
a Point, was introduced to have different types of Positions, each corresponding to a type of
Coordinate Reference System.
[TODO]

In this new model, a Geometry is conceptually a set of Positions (all associated with the same Coordinate Reference System).
The set is determined by one or more sequences of Positions and a type enum value (GeometryType) that determine how the
sequence(s) determine the Geometry (e.g. for LineString it is by linear interpolation between the consecutive positions).

## De-emphasizing the Simple Features Specification (SFS)

This library started as an attempt to have a JTS-interoperable library that is SFS-compliant, but has a more
modern design and better support for geometries not in the 2-dimensional projected plane. As design progressed, it became
no longer obvious what the advantage of SFS compliance are.

With open source and more expressive languages, the advantage of standardisation on the API level
are becoming less-and-less obvious. The only advantages to the SFS model (or it's more complicated cousin SQL/MM-Part 3)
that I can see are a familiar Geometry model and a precise specification of topological relations. These advantages are
offset by the disadvantages of a bias to 2D planar coordinate systems, and a (by current tastes) problematic API design.
(Should complex operations really be part of the Geometry interface? What with alternative algorithm implementations?)

Because of these misgivings, we will de-emphasize SFS compliance.



0 comments on commit ee67d84

Please sign in to comment.