Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Spatial Reference System of geometries #32

Open
jdroenner opened this issue May 30, 2016 · 16 comments
Open

Spatial Reference System of geometries #32

jdroenner opened this issue May 30, 2016 · 16 comments

Comments

@jdroenner
Copy link
Member

Spatial data is always represented in a spatial / coordinate reference system. While most data, e.g. from GPS sensors, is represented in WGS84 (LatLon) this is not always the case.

Currently geometries in rust-geo have no information about a coordinate reference system. This allows to compare a LatLon- Point with an UTM- Point.

In JTS and GEOS each Geometry has a CRS-id field. Algorithms have to check if the CRS of two geometries are the same. This could also be done for geometries in rust-geo.

Maybe it would also be possible to use the advanced type-system of Rust to add a generic CRS-type to geometries....

@tmcw
Copy link
Contributor

tmcw commented Jul 22, 2016

My 2c is that this should be low on the list of priorities. While projected data is an intense focal point of traditional GIS, its modern relevance is iffy. Here's the author of PostGIS saying that projected data is mainly a case of legacy technology and expectations. Libraries like Shapely and Turf successfully avoid the question of projections, doing calculations in WGS84 only and expecting users to project on the way in & out if they must. And for that, we have the very robust proj4 library, which one fellow has already started porting into rust.

Relative to other priorities at this early stage, my personal instinct is that dealing with projected data shouldn't be one of them. We should make a distinction between x/y points and lat/lon points, but after that distinction is made, a distance algorithm should only deal with lat/lon points.

@frewsxcv
Copy link
Member

I agree with @tmcw. At least for now, I think it makes sense to leave projections out of rust-geo for now. If anyone is particularly interested in projections though, feel free to create a new repo+crate under the GeoRust organization and experiment.

@frewsxcv
Copy link
Member

And for that, we have the very robust proj4 library, which one fellow has already started porting into rust.

BTW https://github.com/georust/rust-proj

@jdroenner
Copy link
Member Author

Even if the most data created today (locations / GPS) is in WGS84 there are a lot of datasets with different coordinate systems. So a geometry should have a type or field representing its CRS. My experience is that no matter what you do there is always one dataset with an esoteric coordinate system ;)

I agree that transformations between CRSs should be handled by an other crate (e.g. proj) and algorithms like distance should only be implemented for WGS84. A type/ filed could be used to bound algorithms to coordinate systems (e.g. WGS84).
If you want to use proj4 for transformations you still need some information about the CRS. Or are you suggesting that rust-geo will only allow WGS84 geometries?

@tmcw
Copy link
Contributor

tmcw commented Jul 23, 2016

Or are you suggesting that rust-geo will only allow WGS84 geometries?

Yep, this is what I'm suggesting: geographic data in georust would normally be represented as lng/lat and would not have a CRS field. Reproject in and reproject out if you need compatibility. We'd document this, and support rust-proj: this approach doesn't ignore the fact that there is lots of projected data in the world, but it tries to limit the complexity creep that data would cause and contain the problem.

@jdroenner
Copy link
Member Author

jdroenner commented Jul 24, 2016

Reproject in and reproject out if you need compatibility.

So i would need a second crate to load/represent my geometries with different coordinate system?

@zarch
Copy link
Contributor

zarch commented Jul 27, 2016

Actually what I wonder is that generally meter projection are more accurate for distance and surface. And it is a pity to limit our self to WGS84.

In GRASS GIS all the data in a Location are with the same CRS (you can not even import in a location a dataset with a different one). This solve the problem to check every time if two data have the same CRS or not.

But then we still have to store somewhere the CRS, to be able to properly convert (through rust-proj) into lat/lon when using lat/lon method of a point.

@tmcw
Copy link
Contributor

tmcw commented Jul 27, 2016

Actually what I wonder is that generally meter projection are more accurate for distance and surface. And it is a pity to limit our self to WGS84.

Can you go into more detail here? There's quite a bit of datum FUD in the geo industry, and not much of it is backed up by research or evidence.

I'm suggesting reprojecting in & out; this would not limit rust-geo's usefulness to WGS84: it'd simply require people to reproject on the way in and the way out, instead of rust-geo reprojecting internally.

@jdroenner
Copy link
Member Author

jdroenner commented Jul 27, 2016

rust-geo doesn't need to handle transformations internally :)
Maybe we could create a trait for SRS/CRS with a method to get the corresponding proj4 string or the projection ID (e.g. Epsg code ). This should be enough to use an external crate (e.g. rust-proj) to handle transformations.
A generic type could be added to the geometrys to prevent mixed SRSs.
We could also add type aliases for WGS84 geometrys to make them easy to use...

I will try to create a prototype to see if this is to complicated :)

@turboladen
Copy link

While projected data is an intense focal point of traditional GIS, its modern relevance is iffy.

FWIW, I work in Ag, where we deal with a large number of different projections--often times in UTM projections--so I'd argue against this. I wouldn't necessarily argue that this functionality should belong in this library, but it could be nice to have a pointer to how to deal with this topic in the Readme, for those of us in this same bucket. This library looks really cool, but without the ability to transform geoms, I probably couldn't use it.

@urschrei
Copy link
Member

urschrei commented Mar 6, 2018

I wouldn't phrase it quite like Tom did, but the 2D algorithms in this library (and GEOS, and CGAL) assume coordinates in ℝ2.
Could you say a bit more about what might be lacking, @turboladen? I was under the impression (but I only work with one or two local projections, hence the questions) that in general, you project coordinates into a local (conformal?) projection (using PROJ.4, or PROJ.5, soon), "on the way in", treating the projected coordinates as lying in ℝ2 for the purposes of operations on them, and re-project back into whatever system you need "on the way out".
As such, there's nothing to stop you doing that today, using https://github.com/georust/rust-proj (I've actually never used it, and it could use some examples, but it looks pretty straightforward) for the re-projection steps.
I think everyone wants to see support for practical workflows, and I'm definitely interested in knowing more about how other people use (or want to use) the Rust-Geo libraries, so if there are functionality gaps or documentation gaps, let us know.

@turboladen
Copy link

turboladen commented Mar 6, 2018

Sure, I'm happy to share--I'm not yet using Rust for GIS things, but would like to, and would in general just like to see Rust grow more (and succeed) in that space.

I work in Agriculture, so we have quite a few ways we use GIS data. We've been using GDAL for much of what we do since we deal with both raster and vector data, and sometimes need to go back and forth between the two. (I'm not suggesting that this project support raster data, just conveying what we deal with.)

Lots of our customers use shapefiles for passing data around; many GIS-enabled tractors, for example, can accept a shapefile that essentially translate into instructions for the tractor to apply some product (herbicide, pesticide, fungicide, etc). Working with this data requires it to be projected into EPSG:4326. Once the app that ingests the shapefile receives it, it's dissected apart into vector data and any other relevant field data (thus the shapefile is no longer relevant).

We also deal with satellite imagery raster data, but often times need to extract vectors from those. That data can be defined in any number of projections, depending on the source of the data. One of our sources uses UTM projects (which can actually be a pain if we need to work with adjacent rasters, but they're in different UTM zones). Another raster data source uses EPSG:3857.

We also consume and use SSURGO data (soil sampling data) which has everything projected into ESPG:4326. Our frontend apps generally want everything projected into EPSG:3857.

...and that's just a handful of uses for us.

If we get projected data from some source, sometimes we like to store it in the same projection, sometimes we don't. It depends on the feature set. Sometimes we need to massage data from a source before storing it--I never really considered transforming it to ℝ2 for working with it, then transforming it back; that seems a bit wasteful.


My initial comment stems from... I initially jumped in to rust-geo's docs looking for how to reproject geometries (since that's a common thing for us when using GDAL), but landed on this ticket after some poking around. I expected this behavior to be here, but understand rationale for leaving it out. ...thus I expected to see some mention of the topic of "projections", but didn't find one. It'd be great to mention in docs somewhere that the library doesn't do this. It'd be even greater to have even just one example of using something like rust-proj and rust-geo together since to me, that's common functionality I'd need. My initial, cynical response to not seeing anything about the topic in your docs was to say to myself: "eh, this library is really young. I should use something else," and click away back to google ...when in reality you guys have specifically kept that "feature" out for a reason.

Like you said, it is common to use varying GIS libraries in conjunction. As such, I think it's a benefit to all of these projects to say "here's what we do well; here's what some other things do well. Here's how you can use things together for solving bigger picture problems." I think I could use something like rust-geo for some specific use cases, so it's nice to see it active and doing good things. 👍

@urschrei
Copy link
Member

urschrei commented Mar 6, 2018

Thanks, @turboladen that's really helpful (also interesting! I had no idea tractors were using shapefiles, although it makes perfect sense).
With regard to the practical stuff:

I never really considered transforming it to ℝ2 for working with it

I was being unclear there – I should have said "in cases where you want to keep your data in a geographic coordinate system, but use a projected system to work with it".

In terms of actually talking about and using projections, I think there are a few things we could do for now:

  1. Make it clearer that this library (currently) makes no assumptions about the SRS of your coordinates
  2. Add some documentation to Rust-Proj
  3. Make it easy to use Rust-Proj with map-coords, similar to the way in which Shapely can take a pyproj instance as input to its transform method. This would give us an ergonomic way to apply arbitrary EPSG projections to geometries. – we can specify rust-proj as an optional dependency.

I have no idea how 3 is going to work yet, but it should be pretty straightforward to implement. @frewsxcv @rory what do you think?

@jdroenner
Copy link
Member Author

I would really like to see some progress on this issue 😄
In my experience data sets with non WGS84 CRS are still very common.

My original idea was to use the type system to separate WGS84 geometries from others. Any ideas about that?

@turboladen
Copy link

@urschrei Awesome. I think any/all of those 3 options would be helpful.

@urschrei
Copy link
Member

See #192 for (hopefully) some progress~

bors bot added a commit that referenced this issue Apr 8, 2018
192: Implement rust-proj as an optional feature within geo r=frewsxcv a=urschrei

Continuing the discussion from #190 and #32.

## Introduction
`rust-proj` is currently (as of `0.3.0`) using PROJ v4.9.x, and depends upon `Geo` for its `Point` type. However, we now have a `proj-sys` crate, with low-level bindings to PROJ v5.0.0. Unfortunately, `rust-proj's` dependency on `Geo` means that we can't directly use its functions within `Geo`, as this introduces a circular dependency (see #190).
### This PR:
- Re-implements `rust-proj`'s functionality as an optional feature ("`proj`") within `Geo` using `proj-sys`
    - it has to be optional, as it requires PROJ v5.0.0 to be present
- Makes two new traits –`Project` and `Convert` – available to any geometries implementing the `MapCoordsFallible` trait (see #191), allowing them to be (inverse) projected to and from Geodetic coordinates, and converted between projections. This functionality is a slightly more granular version (in keeping with the new PROJ API, which makes the same distinction) of what's possible using `pyproj` and `Shapely` geometries (see [here](http://shapely.readthedocs.io/en/stable/manual.html#other-transformations) for the official example):
```python
from shapely.geometry import Point, LineString
import pyproj
# LineString in projected coordinates (OSGB36)
ls = LineString([(548295.39, 182498.46), (548296.39, 182499.46)])
osgb36=pyproj.Proj("+init=EPSG:27700")
eastings, northings = list(zip(*ls.coords))
# inverse-project to geodetic lon, lat coordinates (WGS 84)
conv_ls = zip(*osgb36(eastings, northings, inverse=True))
# compare to command-line proj output
assert conv_ls == [(0.13774816464635564, 51.52142699952049), (0.1377629902608001, 51.5214357231341)]
```

I propose that we leave `rust-proj` at 0.3.0, clearly marking it as deprecated, directing users to install `Geo` with the `proj` feature if they want v5.0.x features, and linking to `proj-sys` for implementers who don't wish to use `Geo`, for whatever reason.

We can also (as per my and @turboladen's discussion in #32) highlight the availability of this feature more clearly, if need be.

Co-authored-by: Stephan Hügel <urschrei@gmail.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

6 participants