Skip to content
Open
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
1 change: 1 addition & 0 deletions geozero/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
## UNRELEASED

* Implement `GeozeroGeometry::srid` and `dims` for wkb types
* Add `style` option to SVGWriter for writing \<style\> tags
* Add `BoundsProcessor` to compute bounds of geometry
* Update Deps:
Expand Down
78 changes: 77 additions & 1 deletion geozero/src/wkb/wkb_reader.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
use crate::error::{GeozeroError, Result};
use crate::wkb::{WKBGeometryType, WkbDialect};
use crate::{GeomProcessor, GeozeroGeometry};
use crate::{CoordDimensions, GeomProcessor, GeozeroGeometry};
use scroll::ctx::{FromCtx, SizeWith};
use scroll::{Endian, IOread};
use std::io::Read;
Expand All @@ -17,6 +17,11 @@ impl<B: AsRef<[u8]>> GeozeroGeometry for Wkb<B> {
fn process_geom<P: GeomProcessor>(&self, processor: &mut P) -> Result<()> {
process_wkb_geom(&mut self.0.as_ref(), processor)
}
fn dims(&self) -> CoordDimensions {
read_wkb_header(&mut self.0.as_ref())
.map(|info| info.dims())
.unwrap_or_default()
}
}

/// EWKB reader.
Expand All @@ -32,6 +37,16 @@ impl<B: AsRef<[u8]>> GeozeroGeometry for Ewkb<B> {
fn process_geom<P: GeomProcessor>(&self, processor: &mut P) -> Result<()> {
process_ewkb_geom(&mut self.0.as_ref(), processor)
}
fn dims(&self) -> CoordDimensions {
read_ewkb_header(&mut self.0.as_ref())
.map(|info| info.dims())
.unwrap_or_default()
}
fn srid(&self) -> Option<i32> {
read_ewkb_header(&mut self.0.as_ref())
.ok()
.and_then(|info| info.srid)
}
}

/// GeoPackage WKB reader.
Expand All @@ -41,6 +56,16 @@ impl<B: AsRef<[u8]>> GeozeroGeometry for GpkgWkb<B> {
fn process_geom<P: GeomProcessor>(&self, processor: &mut P) -> Result<()> {
process_gpkg_geom(&mut self.0.as_ref(), processor)
}
fn dims(&self) -> CoordDimensions {
read_gpkg_header(&mut self.0.as_ref())
.map(|info| info.dims())
.unwrap_or_default()
}
fn srid(&self) -> Option<i32> {
read_gpkg_header(&mut self.0.as_ref())
.ok()
.and_then(|info| info.srid)
}
}

/// GeoPackage WKB reader.
Expand All @@ -50,6 +75,16 @@ impl<B: AsRef<[u8]>> GeozeroGeometry for SpatiaLiteWkb<B> {
fn process_geom<P: GeomProcessor>(&self, processor: &mut P) -> Result<()> {
process_spatialite_geom(&mut self.0.as_ref(), processor)
}
fn dims(&self) -> CoordDimensions {
read_spatialite_header(&mut self.0.as_ref())
.map(|info| info.dims())
.unwrap_or_default()
}
fn srid(&self) -> Option<i32> {
read_spatialite_header(&mut self.0.as_ref())
.ok()
.and_then(|info| info.srid)
}
}

/// MySQL WKB reader.
Expand All @@ -59,6 +94,16 @@ impl<B: AsRef<[u8]>> GeozeroGeometry for MySQLWkb<B> {
fn process_geom<P: GeomProcessor>(&self, processor: &mut P) -> Result<()> {
process_mysql_geom(&mut self.0.as_ref(), processor)
}
fn dims(&self) -> CoordDimensions {
read_mysql_header(&mut self.0.as_ref())
.map(|info| info.dims())
.unwrap_or_default()
}
fn srid(&self) -> Option<i32> {
read_mysql_header(&mut self.0.as_ref())
.ok()
.and_then(|info| info.srid)
}
}

/// Process WKB geometry.
Expand Down Expand Up @@ -127,6 +172,17 @@ pub(crate) struct WkbInfo {
is_compressed: bool,
}

impl WkbInfo {
pub fn dims(&self) -> CoordDimensions {
CoordDimensions {
z: self.has_z,
m: self.has_m,
t: false,
tm: false,
}
}
}

/// OGC WKB header.
pub(crate) fn read_wkb_header<R: Read>(raw: &mut R) -> Result<WkbInfo> {
let byte_order = raw.ioread::<u8>()?;
Expand Down Expand Up @@ -624,6 +680,13 @@ mod test {
use crate::wkt::WktWriter;
use crate::{CoordDimensions, ToWkt};

#[track_caller]
fn assert_srid_dims(wkb: &impl GeozeroGeometry, srid: Option<i32>, z: bool, m: bool) {
assert_eq!(wkb.srid(), srid);
assert_eq!(wkb.dims().z, z, "z dimension mismatch");
assert_eq!(wkb.dims().m, m, "m dimension mismatch");
}

#[test]
fn ewkb_format() {
// SELECT 'POINT(10 -20 100 1)'::geometry
Expand All @@ -636,6 +699,7 @@ mod test {
assert_eq!(info.srid, None);
assert!(info.has_z);
assert!(info.has_m);
assert_srid_dims(&Ewkb(&ewkb), None, true, true);

// Process xy only
let mut wkt_data: Vec<u8> = Vec::new();
Expand All @@ -661,6 +725,7 @@ mod test {
assert_eq!(info.base_type, WKBGeometryType::MultiPoint);
assert_eq!(info.srid, Some(4326));
assert!(info.has_z);
assert_srid_dims(&Ewkb(&ewkb), Some(4326), true, false);

let mut wkt_data: Vec<u8> = Vec::new();
let mut writer = WktWriter::with_dims(&mut wkt_data, CoordDimensions::xyz());
Expand Down Expand Up @@ -861,6 +926,7 @@ mod test {
assert_eq!(info.srid, Some(4326));
assert!(info.has_z);
assert!(info.has_m);
assert_srid_dims(&SpatiaLiteWkb(&ewkb), Some(4326), true, true);

// Process xy only
let mut wkt_data: Vec<u8> = Vec::new();
Expand Down Expand Up @@ -889,6 +955,7 @@ mod test {
assert_eq!(info.srid, Some(4326));
assert!(info.has_z);
assert!(info.has_m);
assert_srid_dims(&SpatiaLiteWkb(&ewkb), Some(4326), true, true);

let mut wkt_data: Vec<u8> = Vec::new();
assert!(
Expand All @@ -904,6 +971,7 @@ mod test {
assert_eq!(info.srid, Some(4326));
assert!(info.has_z);
assert!(info.has_m);
assert_srid_dims(&SpatiaLiteWkb(&ewkb), Some(4326), true, true);

let mut wkt_data: Vec<u8> = Vec::new();
let mut writer = WktWriter::with_dims(&mut wkt_data, CoordDimensions::xyzm());
Expand All @@ -921,6 +989,7 @@ mod test {
assert!(info.has_m);
// Spatialite store envelope as [minx, miny, maxx, maxy]
assert_eq!(info.envelope, vec![10.0, 10.0, 20.0, 20.0]);
assert_srid_dims(&SpatiaLiteWkb(&wkb), None, true, true);

let mut wkt_data: Vec<u8> = Vec::new();
assert!(
Expand All @@ -937,6 +1006,7 @@ mod test {
let info = read_spatialite_header(&mut wkb.as_slice()).unwrap();
assert_eq!(info.base_type, WKBGeometryType::GeometryCollection);
assert_eq!(info.envelope, vec![1.0, 3.0, 22.0, 22.0]);
assert_srid_dims(&SpatiaLiteWkb(&wkb), None, false, false);

let mut wkt_data: Vec<u8> = Vec::new();
assert!(
Expand All @@ -958,6 +1028,7 @@ mod test {
assert_eq!(info.srid, Some(4326));
assert!(!info.has_z);
assert!(!info.has_m);
assert_srid_dims(&MySQLWkb(&ewkb), Some(4326), false, false);

let mut wkt_data: Vec<u8> = Vec::new();
assert!(
Expand All @@ -971,6 +1042,7 @@ mod test {
assert_eq!(info.base_type, WKBGeometryType::MultiLineString);
assert!(!info.has_z);
assert!(!info.has_m);
assert_srid_dims(&MySQLWkb(&wkb), Some(0), false, false);

let mut wkt_data: Vec<u8> = Vec::new();
assert!(
Expand All @@ -985,6 +1057,7 @@ mod test {
let wkb = hex::decode("000000000107000000020000000101000000000000000000F03F00000000000008400103000000010000000400000000000000000035400000000000003540000000000000364000000000000035400000000000003540000000000000364000000000000035400000000000003540").unwrap();
let info = read_mysql_header(&mut wkb.as_slice()).unwrap();
assert_eq!(info.base_type, WKBGeometryType::GeometryCollection);
assert_srid_dims(&MySQLWkb(&wkb), Some(0), false, false);

let mut wkt_data: Vec<u8> = Vec::new();
assert!(
Expand All @@ -1005,6 +1078,7 @@ mod test {
assert!(!info.has_z);
assert!(!info.has_m);
assert_eq!(info.srid, Some(4326));
assert_srid_dims(&GpkgWkb(&wkb), Some(4326), false, false);

let mut wkt_data: Vec<u8> = Vec::new();
assert!(process_gpkg_geom(&mut wkb.as_slice(), &mut WktWriter::new(&mut wkt_data)).is_ok());
Expand All @@ -1018,6 +1092,7 @@ mod test {
assert!(info.has_m);
// GPKG stores envelope as [minx, maxx, miny, maxy]
assert_eq!(info.envelope, vec![10.0, 20.0, 10.0, 20.0]);
assert_srid_dims(&GpkgWkb(&wkb), Some(4326), true, true);

let mut wkt_data: Vec<u8> = Vec::new();
assert!(process_gpkg_geom(&mut wkb.as_slice(), &mut WktWriter::new(&mut wkt_data)).is_ok());
Expand All @@ -1031,6 +1106,7 @@ mod test {
let info = read_gpkg_header(&mut wkb.as_slice()).unwrap();
assert_eq!(info.base_type, WKBGeometryType::GeometryCollection);
assert_eq!(info.envelope, vec![1.0, 22.0, 3.0, 22.0]);
assert_srid_dims(&GpkgWkb(&wkb), Some(4326), false, false);

let mut wkt_data: Vec<u8> = Vec::new();
assert!(process_gpkg_geom(&mut wkb.as_slice(), &mut WktWriter::new(&mut wkt_data)).is_ok());
Expand Down
Loading