Skip to main content

Reproject

reproject converts a shape from one coordinate reference system into another as the document is indexed. It exists because geo_shape means exactly one thing — WGS 84 in degrees — and most geospatial data does not arrive that way.

PUT _ingest/pipeline/to-wgs84
{
"processors": [
{
"reproject": {
"field": "geometry",
"target_field": "location",
"source_crs": "EPSG:23031"
}
}
]
}

Indexing a shape in ED50 / UTM zone 31N through that pipeline writes WGS 84 into location, and leaves geometry as it was.

Why this cannot be done afterwards​

A projected coordinate indexed into a geo_shape field is not wrong-looking, it is silently wrong. An easting of 556878 is not a valid longitude and will be rejected; an easting of 55 is, and will be accepted as a point in the Indian Ocean. Nothing fails, nothing warns, and the error is discovered when a map is drawn.

Converting at ingest is the last moment the source system is still known. Once the numbers are in the index, nothing records what they meant.

Options​

OptionRequiredDefaultMeaning
fieldyes—The field holding the shape, as WKT or GeoJSON.
target_fieldnofieldWhere the result is written. Defaults to overwriting the source.
source_crsyes—The system the shape is in, e.g. EPSG:23031. Never defaults — see below.
target_crsnoWGS 84The system to convert to, longitude first.
shape_typenogeo_shapegeo_shape for geographic output, shape for cartesian.
toleranceno0.01Positional tolerance passed to the provider.
providernosisWhich engine resolves the systems: sis or proj4j. They do not resolve the same codes — see below.
ignore_missingnofalseLeave the document untouched when field is absent.
ensure_indexablenofalseRepair geometry the shape index would refuse — see below.

source_crs is required on purpose. Defaulting it to WGS 84 would make the processor a no-op for precisely the mistake it exists to catch: a projected shape mislabelled as degrees. A default that silently does nothing is worse than an error.

The result keeps the format it arrived in​

A shape supplied as WKT comes back as WKT; one supplied as GeoJSON comes back as GeoJSON. The format is read from the input and reused, which matters when target_field is the source field — otherwise a round trip would quietly rewrite every shape in the index into the other notation.

Which coordinate systems resolve​

This depends on the provider, and the difference is the whole reason a second one ships.

sis is the default and does not carry the EPSG database — Apache SIS has a built-in subset, and that subset is what works. proj4j bundles the EPSG database as a resource, so it resolves national grids the default cannot. It is not a superset, though: it cannot read OGC:CRS84 at all.

Measured against the shipping dependency set:

Codesisproj4j
EPSG:4326yesyesWGS 84
OGC:CRS84, CRS:84yesnoWGS 84, longitude first
EPSG:3857yesyesPseudo-Mercator
EPSG:32633, EPSG:26910yesyesUTM zones, on WGS 84 and NAD 83
EPSG:4269, EPSG:4258yesyesNAD 83, ETRS 89
EPSG:23031yes†yesED 50 / UTM zone 31N — † see the datum-shift warning below
EPSG:27700noyesOSGB 36 / British National Grid

So a national grid needs "provider": "proj4j", and a longitude-first WGS 84 named as OGC:CRS84 needs the default. Neither covers the other, which is why both are registered.

The provider changes the answer where a datum shift is involved​

"Resolves" is not the same as "is correct". Converting between two systems on different datums needs a datum shift, and those parameters live in the EPSG database — which proj4j carries and the default does not.

Measured, converting 3.9°E 51.3°N to EPSG:23031 (ED 50):

easting
sis562745.87
proj4j562837.66

That is 91.78 m apart, and it is not noise: it is the size of ED 50's published shift, towgs84=-87,-98,-121. proj4j applies it; sis has no parameters for it and converts without one. The same point to EPSG:32631 — the same projection on the WGS 84 datum, needing no shift — agrees between the two providers to the millimetre, which is what identifies the datum shift as the cause.

If your data is on a non-WGS 84 datum — ED 50, OSGB 36, NAD 27 — name "provider": "proj4j". The default will convert it without the shift and place it roughly a hundred metres away, silently. For data already on WGS 84 or NAD 83 (which is most imagery, including every UTM zone in the table above), the two providers agree exactly and the choice does not matter.

proj4j also accepts a PROJ parameter string — +proj=merc +lat_ts=0 … — in place of an authority code, which is the only way to name a system that has no code at all.

An unresolvable code fails when the pipeline is created, not per document, so it reaches whoever made the change.

Axis order is handled, and is the thing that bites​

EPSG:4326 declares latitude first. OGC:CRS84 declares longitude first. They are the same datum under two orders, and the authority's declaration is honoured at both ends of the conversion rather than assumed — a transposed coordinate throws nothing, renders fine, and simply puts the shape somewhere else on Earth.

Repairing geometry the index would refuse​

Reprojection to WGS 84 is smooth but non-linear, so exact relationships in the source do not survive it: rings that touched at a shared vertex can come out crossing. Geometry traced from a raster runs along an integer lattice and is full of such contacts.

Measured over 300 regions of one Sentinel scene: 25 were refused before reprojection, 61 after, and 39 of those 61 only after. A validity check run in the source system cannot see two thirds of the problem.

{
"reproject": {
"field": "geometry",
"source_crs": "EPSG:32633",
"ensure_indexable": true
}
}

With ensure_indexable, the outer boundary is never given up and the fewest offending holes are dropped — on that sample, 138 holes of 18,987, or 0.7%. A region then reads very slightly larger than it is, a small pond filled in.

It is off by default because reprojection is a coordinate conversion, and quietly changing the shape of your data is not something you should get without asking. Where the outer boundary itself is refused — 6 of those 300 — the geometry is returned untouched for the index to reject and report, rather than reshaped into a different region.

Circles are refused​

A circle is a centre and a radius in metres, and reprojection does not preserve it: the image of a circle under a non-linear map is not a circle, so there is no honest radius to write back. The processor says so rather than emitting a shape that claims to be something it is not.

Licensing​

Creating a pipeline that uses reproject requires a license. Running one never does — see Licensing.