Skip to content

Commit

Permalink
Implement 3D and Measure support for geo-types only
Browse files Browse the repository at this point in the history
This PR includes georust#772 and georust#812

---

This PR focuses on `geo-types` only. This is a part of georust#742.

This PR changes the underlying geo-type data structures to support 3D data and measurement values (M and Z values). The PR attempts to cause relatively minor disruptions to the existing users (see breaking changes below). My knowledge of the actual geo algorithms is limited, so please ping me for any specific algo change.

## geo-types restructuring
All geo type structs have been renamed from `Foo<T>(...)` to `Foo<T, Z=NoValue, M=NoValue>(...)`, and several type aliases were added:

```rust
// old
pub struct LineString<T: CoordNum>(pub Vec<Coordinate<T>>);

// new
pub struct LineString<T: CoordNum, Z: ZCoord=NoValue, M: Measure=NoValue>(pub Vec<Coordinate<T, Z, M>>);

pub type LineStringM<T, M=T> = LineString<T, NoValue, M>;
pub type LineString3D<T> = LineString<T, T, NoValue>;
pub type LineString3DM<T, M=T> = LineString<T, T, M>;
```

## NoValue magic
`NoValue` is an empty struct that behaves just like a number. It supports all math and comparison operations. This means that a `Z` or `M` value can be manipulated without checking if it is actually there.  This code works for Z and M being either a number or a NoValue:

```rust
pub struct NoValue;

impl<T: CoordNum, Z: ZCoord, M: Measure> Sub for Coordinate<T, Z, M> {
    type Output = Self;

    fn sub(self, rhs: Self) -> Self {
        coord! {
            x: self.x - rhs.x,
            y: self.y - rhs.y,
            z: self.z - rhs.z,
            m: self.m - rhs.m,
        }
    }
}
```

## Variant algorithm implementations
Function implementations can keep just the original 2D `<T>` variant, or add support for 3D `<Z>` and/or the Measure `<M>`. The above example works for all combinations of objects. This function only works for 2D objects with and without the Measure.

```rust
impl<T: CoordNum, M: Measure> Line<T, NoValue, M> {
    /// Calculate the slope (Δy/Δx).
    pub fn slope(&self) -> T {
        self.dy() / self.dx()
    }
}
```

## Breaking changes
* It is no longer possible to create Coordinate with just `x` and `y` values using implicit tuple constructor. Use `coord!` instead.
  • Loading branch information
nyurik committed Apr 21, 2022
1 parent d040fe2 commit 64ccf54
Show file tree
Hide file tree
Showing 186 changed files with 56,583 additions and 1,003 deletions.
3 changes: 1 addition & 2 deletions .github/pull_request_template.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
- [ ] I agree to follow the project's [code of conduct](https://github.com/georust/geo/blob/master/CODE_OF_CONDUCT.md).
- [ ] I agree to follow the project's [code of conduct](https://github.com/georust/geo/blob/main/CODE_OF_CONDUCT.md).
- [ ] I added an entry to `CHANGES.md` if knowledge of this change could be valuable to users.
---

26 changes: 13 additions & 13 deletions .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,9 @@ on:
push:
branches:
- main
- master
- staging
- trying
- release/**
pull_request:
schedule: [cron: "45 6 * * *"]

Expand Down Expand Up @@ -43,7 +43,7 @@ jobs:
matrix:
container_image:
# Use the latest stable version. No need for older versions.
- "georust/geo-ci:rust-1.59"
- "georust/geo-ci:proj-9.0.0-rust-1.59"
container:
image: ${{ matrix.container_image }}
steps:
Expand All @@ -67,10 +67,10 @@ jobs:
# giving us about 6 months of coverage.
#
# Minimum supported rust version (MSRV)
- "georust/geo-ci:rust-1.56"
- "georust/geo-ci:proj-9.0.0-rust-1.56"
# Two most recent releases - we omit older ones for expedient CI
- "georust/geo-ci:rust-1.58"
- "georust/geo-ci:rust-1.59"
- "georust/geo-ci:proj-9.0.0-rust-1.58"
- "georust/geo-ci:proj-9.0.0-rust-1.59"
container:
image: ${{ matrix.container_image }}
steps:
Expand All @@ -93,10 +93,10 @@ jobs:
# giving us about 6 months of coverage.
#
# Minimum supported rust version (MSRV)
- "georust/geo-ci:rust-1.56"
- "georust/geo-ci:proj-9.0.0-rust-1.56"
# Two most recent releases - we omit older ones for expedient CI
- "georust/geo-ci:rust-1.58"
- "georust/geo-ci:rust-1.59"
- "georust/geo-ci:proj-9.0.0-rust-1.58"
- "georust/geo-ci:proj-9.0.0-rust-1.59"
container:
image: ${{ matrix.container_image }}
steps:
Expand All @@ -120,10 +120,10 @@ jobs:
# giving us about 6 months of coverage.
#
# Minimum supported rust version (MSRV)
- "georust/geo-ci:rust-1.56"
- "georust/geo-ci:proj-9.0.0-rust-1.56"
# Two most recent releases - we omit older ones for expedient CI
- "georust/geo-ci:rust-1.58"
- "georust/geo-ci:rust-1.59"
- "georust/geo-ci:proj-9.0.0-rust-1.58"
- "georust/geo-ci:proj-9.0.0-rust-1.59"
container:
image: ${{ matrix.container_image }}
steps:
Expand All @@ -143,7 +143,7 @@ jobs:
matrix:
container_image:
# Fuzz only on latest
- "georust/geo-ci:rust-1.59"
- "georust/geo-ci:proj-9.0.0-rust-1.59"
container:
image: ${{ matrix.container_image }}
steps:
Expand All @@ -156,7 +156,7 @@ jobs:
runs-on: ubuntu-latest
if: "!contains(github.event.head_commit.message, '[skip ci]')"
container:
image: georust/geo-ci:rust-1.59
image: georust/geo-ci:proj-9.0.0-rust-1.59
steps:
- name: Checkout repository
uses: actions/checkout@v2
Expand Down
6 changes: 3 additions & 3 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ sections:

As a reminder, all contributors are expected to follow our [Code of Conduct][coc].

[coc]: https://github.com/georust/geo/blob/master/CODE_OF_CONDUCT.md
[coc]: https://github.com/georust/geo/blob/main/CODE_OF_CONDUCT.md

## Feature Requests
[feature-requests]: #feature-requests
Expand Down Expand Up @@ -94,7 +94,7 @@ those changes into the source repository.
[about-pull-requests]: https://help.github.com/articles/about-pull-requests/
[development-models]: https://help.github.com/articles/about-collaborative-development-models/

Please make pull requests against the `master` branch.
Please make pull requests against the `main` branch.

All pull requests are reviewed by another person.

Expand All @@ -108,7 +108,7 @@ This tells @bors, our lovable integration bot, that your
pull request has been approved. The PR then enters the merge
queue, where @bors will run all the tests on every platform
we support. If it all works out, @bors will merge your code
into `master` and close the pull request.
into `main` and close the pull request.

## Writing Tests and Documentation

Expand Down
2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
[workspace]
members = ["geo", "geo-types", "geo-postgis", "geo-test-fixtures"]
members = ["geo", "geo-types", "geo-postgis", "geo-test-fixtures", "jts-test-runner"]

[patch.crates-io]

Expand Down
8 changes: 4 additions & 4 deletions geo-postgis/src/from_postgis.rs
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ where
{
fn from_postgis(mp: &'a T) -> Self {
let ret = mp.points().map(Point::from_postgis).collect();
MultiPoint(ret)
MultiPoint::new(ret)
}
}
impl<'a, T> FromPostgis<&'a T> for MultiLineString<f64>
Expand All @@ -65,7 +65,7 @@ where
{
fn from_postgis(mp: &'a T) -> Self {
let ret = mp.lines().map(LineString::from_postgis).collect();
MultiLineString(ret)
MultiLineString::new(ret)
}
}
impl<'a, T> FromPostgis<&'a T> for MultiPolygon<f64>
Expand All @@ -76,7 +76,7 @@ where
/// (return `None` when `from_postgis()` is called on them).
fn from_postgis(mp: &'a T) -> Self {
let ret = mp.polygons().filter_map(Option::from_postgis).collect();
MultiPolygon(ret)
MultiPolygon::new(ret)
}
}
impl<'a, T> FromPostgis<&'a GeometryCollectionT<T>> for GeometryCollection<f64>
Expand All @@ -91,7 +91,7 @@ where
.iter()
.filter_map(Option::from_postgis)
.collect();
GeometryCollection(geoms)
GeometryCollection::new_from(geoms)
}
}
impl<'a, T> FromPostgis<&'a GeometryT<T>> for Option<Geometry<f64>>
Expand Down
29 changes: 29 additions & 0 deletions geo-types/CHANGES.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,31 @@

## Unreleased

### Breaking changes
* All geo types now support optional 3D (z coordinate) and M (measure) values. For example, `LineM` contains `x`, `y`, and `m` values, whereas `Line3D` has `x,y,z`. `Line3DM` has both `z` and `m`. When not used, `z` and `m` values are represented by the `NoValue` empty struct. `NoValue` behaves like a number.
* Remove deprecated functions on the `Geometry<T>`:
* `into_point` - Switch to `std::convert::TryInto<Point>`
* `into_line_string` - Switch to `std::convert::TryInto<LineString>`
* `into_line` - Switch to `std::convert::TryInto<Line>`
* `into_polygon` - Switch to `std::convert::TryInto<Polygon>`
* `into_multi_point` - Switch to `std::convert::TryInto<MultiPoint>`
* `into_multi_line_string` - Switch to `std::convert::TryInto<MultiLineString>`
* `into_multi_polygon` - Switch to `std::convert::TryInto<MultiPolygon>`
* Remove deprecated `CoordinateType` trait. Use `CoordFloat` or `CoordNum` instead.
* Remove deprecated functions from `LineString<T>`
* Remove `points_iter()` -- use `points()` instead.
* Remove `num_coords()` -- use `geo::algorithm::coords_iter::CoordsIter::coords_count` instead.
* Remove deprecated functions from `Point<T>`
* Remove `lng()` -- use `x()` instead.
* Remove `set_lng()` -- use `set_x()` instead.
* Remove `lat()` -- use `y()` instead.
* Remove `set_lat()` -- use `set_y()` instead.
* Remove deprecated `Polygon<T>::is_convex()` -- use `geo::is_convex` on `poly.exterior()` instead.
* Remove deprecated `Rect<T>::try_new()` -- use `Rect::new` instead, since `Rect::try_new` will never Error. Also removes corresponding `InvalidRectCoordinatesError`.
* Replace deprecated `GeometryCollection::new()` with `GeometryCollection::new(value)`, and remove deprecated `GeometryCollection::new_from(value)`.

## 0.7.4

* BREAKING: Make `Rect::to_lines` return lines in winding order for `Rect::to_polygon`.
* <https://github.com/georust/geo/pull/757>
* Note: All crates have been migrated to Rust 2021 edition. The MSRV when installing the latest dependencies has increased to 1.56.
Expand All @@ -14,6 +39,10 @@
* <https://github.com/georust/geo/issues/762>
* Add ExactsizeIterator impl for Points iterator on LineString
* <https://github.com/georust/geo/pull/767>
* Extend `point!` macro to support single coordinate expression arguments `point!(coordinate)` (coordinate can be created with the `coord!` macro)
* <https://github.com/georust/geo/pull/775>
* `LineString`, `MultiPoint`, `MultiPolygon`, `Triangle`, `MultiLineString` now have a new constructor `new(...)`. `GeometryCollection` has a `new_from(...)` constructor. `GeometryCollection::new()` has been deprecated - use `GeometryCollection::default()` instead. Do not use tuple constructors like ~~`MultiPoint(...)`~~ for any of the geo-types. Use `MultiPoint::new(...)` and similar ones instead.
* PRs: [MultiPolygon::new](https://github.com/georust/geo/pull/786), [MultiLineString::new](https://github.com/georust/geo/pull/784), [Triangle::new](https://github.com/georust/geo/pull/783), [GeometryCollection::new_from](https://github.com/georust/geo/pull/782), [LineString::new](https://github.com/georust/geo/pull/781), [MultiPoint::new](https://github.com/georust/geo/pull/778), [Point::from](https://github.com/georust/geo/pull/777)

## 0.7.3

Expand Down
3 changes: 1 addition & 2 deletions geo-types/Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
[package]
name = "geo-types"
version = "0.7.3"
authors = ["Corey Farwell <[email protected]>"]
version = "0.7.4"
license = "MIT/Apache-2.0"
repository = "https://github.com/georust/geo"
documentation = "https://docs.rs/geo-types/"
Expand Down
Loading

0 comments on commit 64ccf54

Please sign in to comment.