diff --git a/README.md b/README.md index bc7f4341..82246f3f 100644 --- a/README.md +++ b/README.md @@ -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 + + org.geolatte + geolatte-geom + 1.17 + +``` + +# 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 pnt = point(WGS84, g(4.33,53.21)); + +LineString lstr = linestring(WGS84, g(4.43, 53.21), g(4.44, 53.20), g(4.45, 53.19)); + +Polygon 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 wgs84E = WGS84.addVerticalSystem(LinearUnit.METER, G3D.class); +... + +Point 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` is a different type than `Point`. 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.