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

point types #5

Open
calvinmetcalf opened this issue Jan 25, 2015 · 10 comments
Open

point types #5

calvinmetcalf opened this issue Jan 25, 2015 · 10 comments

Comments

@calvinmetcalf
Copy link
Member

how do we want to handle the difference between x,y, x,y,z, x,y,z,w (someone could conceivably want a 4th digit for something like time). Possibilities

  • WKT style: use templates or something to have distinct PointXY, PoingXYZ, types a draw back is that if things assume 2d points having a 3d point could break stuff
  • GeoJSON style: make it a vector functions would have to double check that that enough dimensions where present and the type system wouldn't be able to help
@sunng87
Copy link
Member

sunng87 commented Jan 25, 2015

How about make our Coordinate struct like

pub struct Coordinate {
  pub x: f64,
  pub y: f64,
  pub z: Option<f64>,
  pub m: Option<f64>
}

And also operators like distance are 2d by default. If any operation involves z, it must declare this nature on name like distance3d.

@frewsxcv
Copy link
Member

I think initially just having two coordinates (x, y) should be be an okay starting point, and if we want to expand we can do that in the future. Though, if we do think having more than two coordinates is important right now, I like @sunng87 's suggestion

@mgax
Copy link
Member

mgax commented Jan 25, 2015

We can use traits and generics to write code that handles several coordinate types. It's more efficient than Option because the type of coordinates is known at compile time. But, for now, I think we should stick to simple 2D coordinates, and postpone this decision until we get a better feel for the code.

@nixpulvis
Copy link

nixpulvis commented Feb 25, 2021

I'm looking into picking back up launchbadge/sqlx#166 for a personal project of mine, however I require 3D points, otherwise there's no point in my doing any of this. This seems like the place to start with this since I will really be needing the features of postgis instead of just three floats. I'm not sure I'll be needing the M or W parts for the supported "4D" points, so I'm tempted to ignore that for the first iteration of this.

With that said, I'm quite confident that I can generalize the code in coordinate.rs by either using a macro, or something more clever. However, I'm not sure how much I'd be allowed to break the interface of the existing Coordinate and Point. Something like struct Coordinate<T, const N: usize>([T; N]) could work very well in theory, but it would require some larger refactoring to the crate.

Moving into the "4D" case, at least 4D in the nomenclature of the WKT/WKB I feel like we're outside this crate's notion of a Point. I'm not sure if we can even define Add for a POINT ZM for example, since the M value may be used to encode some additional information like a "mile marker" on a highway. Again, I'm personally not in need of this (yet), so generalizing the euclidean points first seems like the first step, then supporting the full WKT/WKB types.

Let me know if I'm going in the wrong direction here, and how I should proceed if you can.

EDIT: I should also add a question about how geozero fits into this?

@michaelkirk
Copy link
Member

Wow! A very old issue!

My guess is that the majority of the work due here will be plotting forward a course that keeps things optimal for the vast majority of users who are not doing anything with 3D/4D points.

Are you familiar with how other geometry libraries deal with 3d/4d, like geos/JTS? We don't have to copy them, but it's a good jumping off point for discussion at least.

One aside, you mentioned postgis, but it seems like launchbadge/sqlx#166 is talking about postgres's built in geometric types, which, as I understand it, are not the same as the geometry types in postgis.

see e.g. https://gis.stackexchange.com/a/223490

@michaelkirk
Copy link
Member

EDIT: I should also add a question about how geozero fits into this?

/cc @pka the geozero author, who is likely to have better perspective on this than me.

@pka
Copy link
Member

pka commented Feb 25, 2021

The geozero API does support converting points with XYZM + t/tm dimensions, but has currently only complete 3D/4D implementations for FlatGeobuf, WKB and WKT. To read 3D points from SQLx an implementation of GeomProcessor for a point struct with z-support is required. Opened a meta-issue in georust/geozero#7.

@cmpute
Copy link

cmpute commented Nov 25, 2021

I would also like to upvote for the support for 3D points. I was using Shapely a lot for my projects, which is basically a Python wrapper of GEOS. AFAIK, shapely treat the z-value just as an associate attribute to be carried around without participating in the algorithms. Quoted from its docs:

Shapely is a planar geometry library and z, the height above or below the plane, is ignored in geometric analysis. There is a potential pitfall for users here: coordinate tuples that differ only in z are not distinguished from each other and their application can result in suprisingly invalid geometry objects. For example, LineString([(0, 0, 0), (0, 0, 1)]) does not return a vertical line of unit length, but an invalid line in the plane with zero length. Similarly, Polygon([(0, 0, 0), (0, 0, 1), (1, 1, 1)]) is not bounded by a closed ring and is invalid.

I personally like the proposal of

pub struct Coordinate {
  pub x: f64,
  pub y: f64,
  pub z: Option<f64>,
  pub m: Option<f64>
}

as proposed at the very beginning. Just having the slot for saving z value will already makes a huge difference, allowing other crates to take advantages of this API.

Furthermore, if we can support some basic operation on the z-value (just using interpolation between coordinates) will be an even huge improvement. (This is not supported by GEOS, but we can make our rust version better than them right 😄 )

@nyurik
Copy link
Member

nyurik commented Feb 21, 2022

I tried to hack a multi-dimensional geo types, first using traits, but later switched to constant generics as they seemed far easier and less surprising. WIP implementation.

Coordinates are stored with three generics -- T: CoordNum (as before), a metadata generic M: Metadata (could be empty ()), and a const D: usize representing coordinate dimensions (2D, 3D, ...).

struct Coordinate<T: CoordNum, M: Metadata, const D: usize> {
    coord: [T; D],
    meta: M,
}

Fixed length types (point, line, box, triangle) are stored with another param const P: usize representing the number of points:

struct SizedMultipoint<T: CoordNum, M: Metadata, const D: usize, const P: usize> {
    coords: [Coordinate<T, M, D>; P],
}

Variable-length types use vectors:

struct Multipoint<T: CoordNum, M: Metadata, const D: usize> {
    coords: Vec<Coordinate<T, M, D>>,
}

The actual types would become:

type Point<T, M, const D: usize> = SizedMultipoint<T, M, D, 1>;
type Point2D<T> = Point<T, (), 2>;
type Point2DM<T,M> = Point<T, M, 2>;
type Point3D<T> = Point<T, (), 3>;
type Point3DM<T, M> = Point<T, M, 3>;

type Line<T, M, const D: usize> = SizedMultipoint<T, M, D, 2>;
type Line2D<T> = Line<T, (), 2>;
type Line2DM<T, M> = Line<T, M, 2>;
type Line3D<T> = Line<T, (), 3>;
type Line3DM<T, M> = Line<T, M, 3>;

type Triangle<T, M, const D: usize> = SizedMultipoint<T, M, D, 3>;
type Triangle2D<T> = Triangle<T, (), 2>;
type Triangle2DM<T, M> = Triangle<T, M, 2>;
type Triangle3D<T> = Triangle<T, (), 3>;
type Triangle3DM<T, M> = Triangle<T, M, 3>;
  • See the current version of the above code here
  • See also an alternative single array variant (no generic M param): here

@nyurik
Copy link
Member

nyurik commented Feb 22, 2022

Very rough draft implementation of this is being done in https://github.com/georust/geo/pull/742/files
Basic idea is to treat Coordinate as an alias type (to reduce refactoring). Things like .x and .y will have to become functions .x() and .y() and corresponding setters. Surprisingly cargo test already passes when ran from the geo-types/ dir.

michaelkirk added a commit that referenced this issue Apr 23, 2022
plus some other methods to help migrate from direct field access.

This is intended to be a non-breaking change for now, to give people an upgrade
window. In an upcoming *breaking* release of geo-types we'll drop pub field
access altogether.

This is in pursuit of adding support for 3D/4D geometries. We'll leverage
generics in a way that is intended to avoid runtime cost for our mostly 2D
user base. See #5 for more.

This commit includes a bunch of new methods that correspond to the deprecated
field access. See geo-types/CHANGES.md for a summary.

`#[inline]` hints were added to maintain performance (it's actually improved in
some places!)

geo was updated to address all the deprecations.
michaelkirk added a commit that referenced this issue Apr 23, 2022
plus some other methods to help migrate from direct field access.

This is intended to be a non-breaking change for now, to give people an upgrade
window. In an upcoming *breaking* release of geo-types we'll drop pub field
access altogether.

This is in pursuit of adding support for 3D/4D geometries. We'll leverage
generics in a way that is intended to avoid runtime cost for our mostly 2D
user base. See #5 for more.

This commit includes a bunch of new methods that correspond to the deprecated
field access. See geo-types/CHANGES.md for a summary.

`#[inline]` hints were added to maintain performance (it's actually improved in
some places!)

geo was updated to address all the deprecations.
michaelkirk added a commit that referenced this issue Apr 23, 2022
plus some other methods to help migrate from direct field access.

This is intended to be a non-breaking change for now, to give people an upgrade
window. In an upcoming *breaking* release of geo-types we'll drop pub field
access altogether.

This is in pursuit of adding support for 3D/4D geometries. We'll leverage
generics in a way that is intended to avoid runtime cost for our mostly 2D
user base. See #5 for more.

This commit includes a bunch of new methods that correspond to the deprecated
field access. See geo-types/CHANGES.md for a summary.

`#[inline]` hints were added to maintain performance (it's actually improved in
some places!)

geo was updated to address all the deprecations.
michaelkirk added a commit that referenced this issue Apr 23, 2022
plus some other methods to help migrate from direct field access.

This is intended to be a non-breaking change for now, to give people an upgrade
window. In an upcoming *breaking* release of geo-types we'll drop pub field
access altogether.

This is in pursuit of adding support for 3D/4D geometries. We'll leverage
generics in a way that is intended to avoid runtime cost for our mostly 2D
user base. See #5 for more.

This commit includes a bunch of new methods that correspond to the deprecated
field access. See geo-types/CHANGES.md for a summary.

`#[inline]` hints were added to maintain performance (it's actually improved in
some places!)

geo was updated to address all the deprecations.
michaelkirk added a commit that referenced this issue Apr 23, 2022
plus some other methods to help migrate from direct field access.

This is intended to be a non-breaking change for now, to give people an upgrade
window. In an upcoming *breaking* release of geo-types we'll drop pub field
access altogether.

This is in pursuit of adding support for 3D/4D geometries. We'll leverage
generics in a way that is intended to avoid runtime cost for our mostly 2D
user base. See #5 for more.

This commit includes a bunch of new methods that correspond to the deprecated
field access. See geo-types/CHANGES.md for a summary.

`#[inline]` hints were added to maintain performance (it's actually improved in
some places!)

geo was updated to address all the deprecations.
michaelkirk added a commit that referenced this issue Apr 23, 2022
plus some other methods to help migrate from direct field access.

This is intended to be a non-breaking change for now, to give people an upgrade
window. In an upcoming *breaking* release of geo-types we'll drop pub field
access altogether.

This is in pursuit of adding support for 3D/4D geometries. We'll leverage
generics in a way that is intended to avoid runtime cost for our mostly 2D
user base. See #5 for more.

This commit includes a bunch of new methods that correspond to the deprecated
field access. See geo-types/CHANGES.md for a summary.

`#[inline]` hints were added to maintain performance (it's actually improved in
some places!)

geo was updated to address all the deprecations.
michaelkirk added a commit that referenced this issue Apr 23, 2022
plus some other methods to help migrate from direct field access.

This is intended to be a non-breaking change for now, to give people an upgrade
window. In an upcoming *breaking* release of geo-types we'll drop pub field
access altogether.

This is in pursuit of adding support for 3D/4D geometries. We'll leverage
generics in a way that is intended to avoid runtime cost for our mostly 2D
user base. See #5 for more.

This commit includes a bunch of new methods that correspond to the deprecated
field access. See geo-types/CHANGES.md for a summary.

`#[inline]` hints were added to maintain performance (it's actually improved in
some places!)

geo was updated to address all the deprecations.
michaelkirk added a commit that referenced this issue Apr 23, 2022
plus some other methods to help migrate from direct field access.

This is intended to be a non-breaking change for now, to give people an upgrade
window. In an upcoming *breaking* release of geo-types we'll drop pub field
access altogether.

This is in pursuit of adding support for 3D/4D geometries. We'll leverage
generics in a way that is intended to avoid runtime cost for our mostly 2D
user base. See #5 for more.

This commit includes a bunch of new methods that correspond to the deprecated
field access. See geo-types/CHANGES.md for a summary.

`#[inline]` hints were added to maintain performance (it's actually improved in
some places!)

geo was updated to address all the deprecations.
michaelkirk added a commit that referenced this issue Apr 23, 2022
plus some other methods to help migrate from direct field access.

This is intended to be a non-breaking change for now, to give people an upgrade
window. In an upcoming *breaking* release of geo-types we'll drop pub field
access altogether.

This is in pursuit of adding support for 3D/4D geometries. We'll leverage
generics in a way that is intended to avoid runtime cost for our mostly 2D
user base. See #5 for more.

This commit includes a bunch of new methods that correspond to the deprecated
field access. See geo-types/CHANGES.md for a summary.

`#[inline]` hints were added to maintain performance (it's actually improved in
some places!)

geo was updated to address all the deprecations.
michaelkirk added a commit that referenced this issue Apr 23, 2022
plus some other methods to help migrate from direct field access.

This is intended to be a non-breaking change for now, to give people an upgrade
window. In an upcoming *breaking* release of geo-types we'll drop pub field
access altogether.

This is in pursuit of adding support for 3D/4D geometries. We'll leverage
generics in a way that is intended to avoid runtime cost for our mostly 2D
user base. See #5 for more.

This commit includes a bunch of new methods that correspond to the deprecated
field access. See geo-types/CHANGES.md for a summary.

`#[inline]` hints were added to maintain performance (it's actually improved in
some places!)

geo was updated to address all the deprecations.
michaelkirk added a commit that referenced this issue Apr 23, 2022
plus some other methods to help migrate from direct field access.

This is intended to be a non-breaking change for now, to give people an upgrade
window. In an upcoming *breaking* release of geo-types we'll drop pub field
access altogether.

This is in pursuit of adding support for 3D/4D geometries. We'll leverage
generics in a way that is intended to avoid runtime cost for our mostly 2D
user base. See #5 for more.

This commit includes a bunch of new methods that correspond to the deprecated
field access. See geo-types/CHANGES.md for a summary.

`#[inline]` hints were added to maintain performance (it's actually improved in
some places!)

geo was updated to address all the deprecations.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

9 participants