Skip to content

Commit

Permalink
Write Rect to WKB (#35)
Browse files Browse the repository at this point in the history
  • Loading branch information
kylebarron authored Nov 27, 2024
1 parent c4e09d0 commit 94d48d1
Show file tree
Hide file tree
Showing 3 changed files with 122 additions and 4 deletions.
8 changes: 4 additions & 4 deletions src/writer/geometry.rs
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
use crate::error::WKBResult;
use crate::writer::{
geometry_collection_wkb_size, line_string_wkb_size, line_wkb_size, multi_line_string_wkb_size,
multi_point_wkb_size, multi_polygon_wkb_size, point_wkb_size, polygon_wkb_size,
multi_point_wkb_size, multi_polygon_wkb_size, point_wkb_size, polygon_wkb_size, rect_wkb_size,
triangle_wkb_size, write_geometry_collection, write_line, write_line_string,
write_multi_line_string, write_multi_point, write_multi_polygon, write_point, write_polygon,
write_triangle,
write_rect, write_triangle,
};
use crate::Endianness;
use geo_traits::{GeometryTrait, GeometryType};
Expand All @@ -21,7 +21,7 @@ pub fn geometry_wkb_size(geom: &impl GeometryTrait<T = f64>) -> usize {
MultiLineString(ml) => multi_line_string_wkb_size(ml),
MultiPolygon(mp) => multi_polygon_wkb_size(mp),
GeometryCollection(gc) => geometry_collection_wkb_size(gc),
Rect(_) => todo!(),
Rect(r) => rect_wkb_size(r),
Triangle(tri) => triangle_wkb_size(tri),
Line(line) => line_wkb_size(line),
}
Expand All @@ -42,7 +42,7 @@ pub fn write_geometry<W: Write>(
MultiLineString(ml) => write_multi_line_string(writer, ml, endianness),
MultiPolygon(mp) => write_multi_polygon(writer, mp, endianness),
GeometryCollection(gc) => write_geometry_collection(writer, gc, endianness),
Rect(_) => todo!(),
Rect(r) => write_rect(writer, r, endianness),
Triangle(tri) => write_triangle(writer, tri, endianness),
Line(line) => write_line(writer, line, endianness),
}
Expand Down
2 changes: 2 additions & 0 deletions src/writer/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ mod multipoint;
mod multipolygon;
mod point;
mod polygon;
mod rect;
mod triangle;

pub use geometry::{geometry_wkb_size, write_geometry};
Expand All @@ -19,4 +20,5 @@ pub use multipoint::{multi_point_wkb_size, write_multi_point};
pub use multipolygon::{multi_polygon_wkb_size, write_multi_polygon};
pub use point::{point_wkb_size, write_point};
pub use polygon::{polygon_wkb_size, write_polygon};
pub use rect::{rect_wkb_size, write_rect};
pub use triangle::{triangle_wkb_size, write_triangle};
116 changes: 116 additions & 0 deletions src/writer/rect.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,116 @@
use std::io::Write;

use geo_traits::{CoordTrait, LineStringTrait, PolygonTrait, RectTrait};

use crate::error::WKBResult;
use crate::writer::{polygon_wkb_size, write_polygon};
use crate::Endianness;

struct Coord2D {
x: f64,
y: f64,
}

impl CoordTrait for Coord2D {
type T = f64;

fn x(&self) -> Self::T {
self.x
}

fn y(&self) -> Self::T {
self.y
}

fn dim(&self) -> geo_traits::Dimensions {
geo_traits::Dimensions::Xy
}

fn nth_or_panic(&self, n: usize) -> Self::T {
match n {
0 => self.x,
1 => self.y,
_ => panic!(),
}
}
}

/// A wrapper around an impl RectTrait to provide LineStringTrait and PolygonTrait
struct RectWrapper<'a, G: RectTrait<T = f64>>(&'a G);

impl<'a, G: RectTrait<T = f64>> LineStringTrait for &'a RectWrapper<'a, G> {
type T = f64;
type CoordType<'b> = Coord2D where G: 'b, Self: 'b;

fn dim(&self) -> geo_traits::Dimensions {
self.0.dim()
}

fn num_coords(&self) -> usize {
5
}

unsafe fn coord_unchecked(&self, i: usize) -> Self::CoordType<'_> {
let min_coord = self.0.min();
let max_coord = self.0.max();

match i {
0 => Coord2D {
x: min_coord.x(),
y: min_coord.y(),
},
1 => Coord2D {
x: min_coord.x(),
y: max_coord.y(),
},
2 => Coord2D {
x: max_coord.x(),
y: max_coord.y(),
},
3 => Coord2D {
x: max_coord.x(),
y: min_coord.y(),
},
4 => Coord2D {
x: min_coord.x(),
y: min_coord.y(),
},
_ => unreachable!(),
}
}
}

impl<'a, G: RectTrait<T = f64>> PolygonTrait for RectWrapper<'a, G> {
type T = f64;
type RingType<'b> = &'b RectWrapper<'b, G> where G: 'b, Self: 'b;

fn dim(&self) -> geo_traits::Dimensions {
self.0.dim()
}

fn exterior(&self) -> Option<Self::RingType<'_>> {
Some(self)
}

fn num_interiors(&self) -> usize {
0
}

unsafe fn interior_unchecked(&self, _i: usize) -> Self::RingType<'_> {
unreachable!()
}
}

/// The byte length of a Rect
pub fn rect_wkb_size(geom: &impl RectTrait<T = f64>) -> usize {
polygon_wkb_size(&RectWrapper(geom))
}

/// Write a Rect geometry to a Writer encoded as WKB
pub fn write_rect(
writer: &mut impl Write,
geom: &impl RectTrait<T = f64>,
endianness: Endianness,
) -> WKBResult<()> {
write_polygon(writer, &RectWrapper(geom), endianness)
}

0 comments on commit 94d48d1

Please sign in to comment.