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

docs update & bump to 0.12 #128

Merged
merged 5 commits into from
Nov 27, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions CHANGES.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,12 @@
# Changes

## 0.12.0 - 2024-11-26

* Writing WKT is now up to 50% faster by avoiding extra allocations and writing directly to an underlying buffer.
* Any `geo_traits` input is now supported when writing to WKT.
* Implements `geo_traits` on `Wkt` and all structs in `types`. This allows for easier interoperability when reading WKT data to other representations than `geo-types`.
* BREAKING: removed the `fmt::Display` impl on `wkt::Coord`.

## 0.11.1 - 2024-10-10

* Add an `infer_type` function to extract only the geometry type and dimension from a WKT string.
Expand Down
2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
[package]
name = "wkt"
description = "Rust read/write support for well-known text (WKT)"
version = "0.11.1"
version = "0.12.0"
license = "MIT OR Apache-2.0"
repository = "https://github.com/georust/wkt"
autobenches = true
Expand Down
45 changes: 32 additions & 13 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@
//! geometry format.
//!
//! Conversions are available via the [`TryFromWkt`] and [`ToWkt`] traits, with implementations for
//! [`geo_types`] primitives enabled by default.
//! [`geo_types`] and [`geo_traits`] primitives enabled by default.
//!
//! For advanced usage, see the [`types`](crate::types) module for a list of internally used types.
//!
Expand Down Expand Up @@ -57,25 +57,44 @@
//!
//! Not using `geo-types` for your geometries? No problem!
//!
//! As of `wkt` version 0.12, this crate provides read and write integration with [`geo_traits`],
//! a collection of geometry access traits, to provide zero-copy integration with geometry
//! representations other than `geo-types`.
//!
//! This integration allows you to transparently read data from this crate's intermediate geometry
//! structure, and it allows you to write WKT strings directly from your geometry without any
//! intermediate representation.
//!
//! ### Reading
//!
//! You can use [`Wkt::from_str`] to parse a WKT string into this crate's intermediate geometry
//! structure. You can use that directly, or if have your own geometry types that you'd prefer to
//! use, utilize that [`Wkt`] struct to implement the [`ToWkt`] or [`TryFromWkt`] traits for your
//! own types.
//! structure. `Wkt` (and all structs defined in [types]) implement traits from [geo_traits]. You
//! can write functions in terms of those traits and you'll be able to work with the parsed WKT
//! without any further overhead.
//!
//! In doing so, you'll likely want to match on one of the WKT [`types`] (Point, Linestring, etc.)
//! stored in its `item` field
//! ```
//! use std::str::FromStr;
//! use wkt::Wkt;
//! use geo_traits::{GeometryTrait, GeometryType};
//!
//! fn is_line_string(geom: &impl GeometryTrait<T = f64>) {
//! assert!(matches!(geom.as_type(), GeometryType::LineString(_)))
//! }
//!
//! let wktls: Wkt<f64> = Wkt::from_str("LINESTRING(10 20, 20 30)").unwrap();
//! let ls = match wktls {
//! Wkt::LineString(line_string) => {
//! // you now have access to the `wkt::types::LineString`.
//! assert_eq!(line_string.0[0].x, 10.0);
//! }
//! _ => unreachable!(),
//! };
//! is_line_string(&wktls);
//! ```
//!
//! Working with the trait definition is preferable to working with `wkt::Wkt` directly, as the
//! geometry trait will work with many different geometry representations; not just the one from
//! this crate.
//!
//! ### Writing
//!
//! Consult the functions provided in [`to_wkt`]. Those functions will write any `geo_traits` object to WKT without any intermediate overhead.
//!
//! Implement [`geo_traits`] on your own geometry representation and those functions will work out
//! of the box on your data.
use std::default::Default;
use std::fmt;
use std::str::FromStr;
Expand Down
53 changes: 37 additions & 16 deletions src/to_wkt/geo_trait_impl.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,17 +22,20 @@ enum PhysicalCoordinateDimension {
Four,
}

impl From<geo_traits::Dimensions> for PhysicalCoordinateDimension {
fn from(value: geo_traits::Dimensions) -> Self {
impl TryFrom<geo_traits::Dimensions> for PhysicalCoordinateDimension {
type Error = Error;

fn try_from(value: geo_traits::Dimensions) -> Result<Self, Self::Error> {
match value.size() {
2 => Self::Two,
3 => Self::Three,
4 => Self::Four,
size => panic!("Unexpected dimension for coordinate: {}", size),
2 => Ok(Self::Two),
3 => Ok(Self::Three),
4 => Ok(Self::Four),
_ => Err(Error::UnknownDimension),
}
}
}

/// Write an object implementing [`PointTrait`] to a WKT string.
pub fn write_point<T: WktNum + fmt::Display>(
f: &mut impl Write,
g: &impl PointTrait<T = T>,
Expand All @@ -48,7 +51,7 @@ pub fn write_point<T: WktNum + fmt::Display>(
}
geo_traits::Dimensions::Unknown(_) => return Err(Error::UnknownDimension),
}?;
let size = PhysicalCoordinateDimension::from(dim);
let size = dim.try_into()?;
if let Some(coord) = g.coord() {
f.write_char('(')?;
write_coord(f, &coord, size)?;
Expand All @@ -59,6 +62,7 @@ pub fn write_point<T: WktNum + fmt::Display>(
}
}

/// Write an object implementing [`LineStringTrait`] to a WKT string.
pub fn write_linestring<T: WktNum + fmt::Display>(
f: &mut impl Write,
linestring: &impl LineStringTrait<T = T>,
Expand All @@ -78,14 +82,15 @@ pub fn write_linestring<T: WktNum + fmt::Display>(
}
geo_traits::Dimensions::Unknown(_) => return Err(Error::UnknownDimension),
}?;
let size = PhysicalCoordinateDimension::from(dim);
let size = dim.try_into()?;
if linestring.num_coords() == 0 {
Ok(f.write_str(" EMPTY")?)
} else {
write_coord_sequence(f, linestring.coords(), size)
}
}

/// Write an object implementing [`PolygonTrait`] to a WKT string.
pub fn write_polygon<T: WktNum + fmt::Display>(
f: &mut impl Write,
polygon: &impl PolygonTrait<T = T>,
Expand All @@ -103,7 +108,7 @@ pub fn write_polygon<T: WktNum + fmt::Display>(
}
geo_traits::Dimensions::Unknown(_) => return Err(Error::UnknownDimension),
}?;
let size = PhysicalCoordinateDimension::from(dim);
let size = dim.try_into()?;
if let Some(exterior) = polygon.exterior() {
if exterior.num_coords() != 0 {
f.write_str("(")?;
Expand All @@ -123,6 +128,7 @@ pub fn write_polygon<T: WktNum + fmt::Display>(
}
}

/// Write an object implementing [`MultiPointTrait`] to a WKT string.
pub fn write_multi_point<T: WktNum + fmt::Display>(
f: &mut impl Write,
multipoint: &impl MultiPointTrait<T = T>,
Expand All @@ -142,7 +148,7 @@ pub fn write_multi_point<T: WktNum + fmt::Display>(
}
geo_traits::Dimensions::Unknown(_) => return Err(Error::UnknownDimension),
}?;
let size = PhysicalCoordinateDimension::from(dim);
let size = dim.try_into()?;

let mut points = multipoint.points();

Expand All @@ -167,6 +173,7 @@ pub fn write_multi_point<T: WktNum + fmt::Display>(
Ok(())
}

/// Write an object implementing [`MultiLineStringTrait`] to a WKT string.
pub fn write_multi_linestring<T: WktNum + fmt::Display>(
f: &mut impl Write,
multilinestring: &impl MultiLineStringTrait<T = T>,
Expand All @@ -186,7 +193,7 @@ pub fn write_multi_linestring<T: WktNum + fmt::Display>(
}
geo_traits::Dimensions::Unknown(_) => return Err(Error::UnknownDimension),
}?;
let size = PhysicalCoordinateDimension::from(dim);
let size = dim.try_into()?;
let mut line_strings = multilinestring.line_strings();
if let Some(first_linestring) = line_strings.next() {
f.write_str("(")?;
Expand All @@ -205,6 +212,7 @@ pub fn write_multi_linestring<T: WktNum + fmt::Display>(
Ok(())
}

/// Write an object implementing [`MultiPolygonTrait`] to a WKT string.
pub fn write_multi_polygon<T: WktNum + fmt::Display>(
f: &mut impl Write,
multipolygon: &impl MultiPolygonTrait<T = T>,
Expand All @@ -224,7 +232,7 @@ pub fn write_multi_polygon<T: WktNum + fmt::Display>(
}
geo_traits::Dimensions::Unknown(_) => return Err(Error::UnknownDimension),
}?;
let size = PhysicalCoordinateDimension::from(dim);
let size = dim.try_into()?;

let mut polygons = multipolygon.polygons();

Expand Down Expand Up @@ -255,8 +263,7 @@ pub fn write_multi_polygon<T: WktNum + fmt::Display>(
Ok(())
}

/// Create geometry to WKT representation.

/// Write an object implementing [`GeometryTrait`] to a WKT string.
pub fn write_geometry<T: WktNum + fmt::Display>(
f: &mut impl Write,
geometry: &impl GeometryTrait<T = T>,
Expand All @@ -277,6 +284,7 @@ pub fn write_geometry<T: WktNum + fmt::Display>(
}
}

/// Write an object implementing [`GeometryCollectionTrait`] to a WKT string.
pub fn write_geometry_collection<T: WktNum + fmt::Display>(
f: &mut impl Write,
gc: &impl GeometryCollectionTrait<T = T>,
Expand Down Expand Up @@ -314,6 +322,13 @@ pub fn write_geometry_collection<T: WktNum + fmt::Display>(
Ok(())
}

/// Write an object implementing [`RectTrait`] to a WKT string.
///
/// The Rect will written as a Polygon with one exterior ring.
///
/// Note that only 2D `Rect`s are supported, because it's unclear how to map a higher-dimensional
/// Rect to a Polygon. For higher dimensional `Rect`, transform your data to a Polygon and use
/// [`write_polygon`].
pub fn write_rect<T: WktNum + fmt::Display>(
f: &mut impl Write,
rect: &impl RectTrait<T = T>,
Expand Down Expand Up @@ -366,6 +381,9 @@ pub fn write_rect<T: WktNum + fmt::Display>(
Ok(f.write_char(')')?)
}

/// Write an object implementing [`TriangleTrait`] to a WKT string.
///
/// The Triangle will written as a Polygon with one exterior ring.
pub fn write_triangle<T: WktNum + fmt::Display>(
f: &mut impl Write,
triangle: &impl TriangleTrait<T = T>,
Expand All @@ -383,7 +401,7 @@ pub fn write_triangle<T: WktNum + fmt::Display>(
}
geo_traits::Dimensions::Unknown(_) => return Err(Error::UnknownDimension),
}?;
let size = PhysicalCoordinateDimension::from(dim);
let size = dim.try_into()?;
f.write_str("(")?;

let coords_iter = triangle
Expand All @@ -395,6 +413,9 @@ pub fn write_triangle<T: WktNum + fmt::Display>(
Ok(f.write_char(')')?)
}

/// Write an object implementing [`LineTrait`] to a WKT string.
///
/// The Line will written as a LineString with two coordinates.
pub fn write_line<T: WktNum + fmt::Display>(
f: &mut impl Write,
line: &impl LineTrait<T = T>,
Expand All @@ -414,7 +435,7 @@ pub fn write_line<T: WktNum + fmt::Display>(
}
geo_traits::Dimensions::Unknown(_) => return Err(Error::UnknownDimension),
}?;
let size = PhysicalCoordinateDimension::from(dim);
let size = dim.try_into()?;
write_coord_sequence(f, line.coords().into_iter(), size)
}

Expand Down
2 changes: 2 additions & 0 deletions src/to_wkt/mod.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
//! Serialize geometries to WKT strings.

use crate::{Wkt, WktNum};

mod geo_trait_impl;
Expand Down
Loading