From 0a4dfff361d94eefea66483139bc6cf328030af9 Mon Sep 17 00:00:00 2001 From: Corey Farwell Date: Wed, 30 Aug 2017 09:45:44 -0400 Subject: [PATCH 1/6] linestring validation --- src/algorithm/area.rs | 3 --- src/algorithm/boundingbox.rs | 2 +- src/algorithm/centroid.rs | 5 ++--- src/algorithm/contains.rs | 2 +- src/algorithm/convexhull.rs | 22 ++++++++++++---------- src/algorithm/distance.rs | 2 +- src/algorithm/extremes.rs | 20 ++++++++++---------- src/algorithm/intersects.rs | 15 ++++++++------- src/algorithm/map_coords.rs | 4 +++- src/algorithm/orient.rs | 19 ++++++++----------- src/algorithm/rotate.rs | 11 ++++++++++- src/algorithm/simplify.rs | 3 ++- src/algorithm/simplifyvw.rs | 2 +- src/types.rs | 27 ++++++++++++++++++++++++++- 14 files changed, 85 insertions(+), 52 deletions(-) diff --git a/src/algorithm/area.rs b/src/algorithm/area.rs index 61cc8c364..a1feb5354 100644 --- a/src/algorithm/area.rs +++ b/src/algorithm/area.rs @@ -21,9 +21,6 @@ pub trait Area where T: Float } fn get_linestring_area(linestring: &LineString) -> T where T: Float { - if linestring.0.is_empty() || linestring.0.len() == 1 { - return T::zero(); - } let mut tmp = T::zero(); for line in linestring.lines() { tmp = tmp + (line.start.x() * line.end.y() - line.end.x() * line.start.y()); diff --git a/src/algorithm/boundingbox.rs b/src/algorithm/boundingbox.rs index 9d5288466..7718b9432 100644 --- a/src/algorithm/boundingbox.rs +++ b/src/algorithm/boundingbox.rs @@ -120,7 +120,7 @@ impl BoundingBox for Polygon /// fn bbox(&self) -> Self::Output { let line = &self.exterior; - get_bbox(&line.0) + get_bbox(line.points()) } } diff --git a/src/algorithm/centroid.rs b/src/algorithm/centroid.rs index 98f4adf61..fc3f1ec5b 100644 --- a/src/algorithm/centroid.rs +++ b/src/algorithm/centroid.rs @@ -29,9 +29,6 @@ pub trait Centroid { fn simple_polygon_area(linestring: &LineString) -> T where T: Float { - if linestring.0.is_empty() || linestring.0.len() == 1 { - return T::zero(); - } let mut tmp = T::zero(); for line in linestring.lines() { tmp = tmp + (line.start.x() * line.end.y() - line.end.x() * line.start.y()); @@ -94,6 +91,7 @@ impl Centroid for LineString } Some(Point::new(sum_x / total_length, sum_y / total_length)) } + Some(Point::new(sum_x / total_length, sum_y / total_length)) } } @@ -141,6 +139,7 @@ impl Centroid for Polygon } Some(external_centroid) } + Some(external_centroid) } } diff --git a/src/algorithm/contains.rs b/src/algorithm/contains.rs index 03b81e061..639bb344b 100644 --- a/src/algorithm/contains.rs +++ b/src/algorithm/contains.rs @@ -90,7 +90,7 @@ impl Contains> for Line where T: Float { fn contains(&self, linestring: &LineString) -> bool { - linestring.0.iter().all(|pt| self.contains(pt)) + linestring.points().iter().all(|pt| self.contains(pt)) } } diff --git a/src/algorithm/convexhull.rs b/src/algorithm/convexhull.rs index 078197476..1ca49c337 100644 --- a/src/algorithm/convexhull.rs +++ b/src/algorithm/convexhull.rs @@ -70,12 +70,12 @@ fn pseudo_distance(p_a: &Point, p_b: &Point, p_c: &Point) -> T } // Adapted from http://www.ahristov.com/tutorial/geometry-games/convex-hull.html -fn quick_hull(mut points: &mut [Point]) -> Vec> +fn quick_hull(mut points: &mut [Point]) -> Polygon where T: Float { // can't build a hull from fewer than four points if points.len() < 4 { - return points.to_vec(); + return Polygon::new(LineString::new(points.to_vec()).expect("did not supply enough points"), vec![]); } let mut hull = vec![]; let min = swap_remove_to_first(&mut points, 0); @@ -100,7 +100,9 @@ fn quick_hull(mut points: &mut [Point]) -> Vec> // close the polygon let final_element = *hull.first().unwrap(); hull.push(final_element); - hull + // we add `hull` at least three points to `hull`, which makes it valid + let linestring = unsafe { LineString::new_unchecked(hull) }; + Polygon::new(linestring, vec![]) } // recursively calculate the convex hull of a subset of points @@ -163,7 +165,7 @@ impl ConvexHull for Polygon where T: Float { fn convex_hull(&self) -> Polygon { - Polygon::new(LineString(quick_hull(&mut self.exterior.0.clone())), vec![]) + quick_hull(&mut self.exterior.points().to_owned()) } } @@ -172,9 +174,9 @@ impl ConvexHull for MultiPolygon { fn convex_hull(&self) -> Polygon { let mut aggregated: Vec> = self.0.iter() - .flat_map(|elem| elem.exterior.0.iter().cloned()) + .flat_map(|elem| elem.exterior.points().iter().cloned()) .collect(); - Polygon::new(LineString(quick_hull(&mut aggregated)), vec![]) + quick_hull(&mut aggregated) } } @@ -182,7 +184,7 @@ impl ConvexHull for LineString where T: Float { fn convex_hull(&self) -> Polygon { - Polygon::new(LineString(quick_hull(&mut self.0.clone())), vec![]) + quick_hull(&mut self.points().to_owned()) } } @@ -191,9 +193,9 @@ impl ConvexHull for MultiLineString { fn convex_hull(&self) -> Polygon { let mut aggregated: Vec> = self.0.iter() - .flat_map(|elem| elem.0.iter().cloned()) + .flat_map(|elem| elem.points().iter().cloned()) .collect(); - Polygon::new(LineString(quick_hull(&mut aggregated)), vec![]) + quick_hull(&mut aggregated) } } @@ -201,7 +203,7 @@ impl ConvexHull for MultiPoint where T: Float { fn convex_hull(&self) -> Polygon { - Polygon::new(LineString(quick_hull(&mut self.0.clone())), vec![]) + quick_hull(&mut self.0.clone()) } } diff --git a/src/algorithm/distance.rs b/src/algorithm/distance.rs index 5bf2db839..2e8a3dc77 100644 --- a/src/algorithm/distance.rs +++ b/src/algorithm/distance.rs @@ -232,7 +232,7 @@ impl Distance> for Point /// Minimum distance from a Point to a LineString fn distance(&self, linestring: &LineString) -> T { // No need to continue if the point is on the LineString, or it's empty - if linestring.contains(self) || linestring.0.is_empty() { + if linestring.contains(self) { return T::zero(); } // minimum priority queue diff --git a/src/algorithm/extremes.rs b/src/algorithm/extremes.rs index f468e3114..de79dbc76 100644 --- a/src/algorithm/extremes.rs +++ b/src/algorithm/extremes.rs @@ -57,7 +57,7 @@ impl Polygon fn previous_vertex(&self, current_vertex: &usize) -> usize where T: Float { - (current_vertex + (self.exterior.0.len() - 1) - 1) % (self.exterior.0.len() - 1) + (current_vertex + (self.exterior.points().len() - 1) - 1) % (self.exterior.points().len() - 1) } } @@ -82,15 +82,15 @@ fn find_extreme_indices(func: F, polygon: &Polygon) -> Result(func: F, polygon: &Polygon) -> Result(u: &Point, poly: &Polygon) -> Result where T: Float { - let vertices = &poly.exterior.0; + let vertices = &poly.exterior.points(); let mut max: usize = 0; for (i, _) in vertices.iter().enumerate() { // if vertices[i] is above prior vertices[max] @@ -209,10 +209,10 @@ impl ExtremePoints for G // safe to unwrap, since we're guaranteeing the polygon's convexity let indices = ch.extreme_indices().unwrap(); ExtremePoint { - ymin: ch.exterior.0[indices.ymin], - xmax: ch.exterior.0[indices.xmax], - ymax: ch.exterior.0[indices.ymax], - xmin: ch.exterior.0[indices.xmin], + ymin: ch.exterior.points()[indices.ymin], + xmax: ch.exterior.points()[indices.xmax], + ymax: ch.exterior.points()[indices.ymax], + xmin: ch.exterior.points()[indices.xmin], } } } diff --git a/src/algorithm/intersects.rs b/src/algorithm/intersects.rs index 574e9396e..d2acb5395 100644 --- a/src/algorithm/intersects.rs +++ b/src/algorithm/intersects.rs @@ -167,7 +167,7 @@ impl Intersects> for Polygon return true; } else { // or if it's contained in the polygon - return linestring.0.iter().any(|point| self.contains(point)) + return linestring.points().iter().any(|point| self.contains(point)) } } } @@ -198,12 +198,13 @@ impl Intersects> for Polygon where T: Float { fn intersects(&self, bbox: &Bbox) -> bool { - let p = Polygon::new(LineString(vec![Point::new(bbox.xmin, bbox.ymin), - Point::new(bbox.xmin, bbox.ymax), - Point::new(bbox.xmax, bbox.ymax), - Point::new(bbox.xmax, bbox.ymin), - Point::new(bbox.xmin, bbox.ymin)]), - vec![]); + let p = Polygon::new(unsafe { LineString::new_unchecked( + vec![Point::new(bbox.xmin, bbox.ymin), + Point::new(bbox.xmin, bbox.ymax), + Point::new(bbox.xmax, bbox.ymax), + Point::new(bbox.xmax, bbox.ymin), + Point::new(bbox.xmin, bbox.ymin)] + )}, vec![]); self.intersects(&p) } } diff --git a/src/algorithm/map_coords.rs b/src/algorithm/map_coords.rs index 08168b6fa..48d5a9632 100644 --- a/src/algorithm/map_coords.rs +++ b/src/algorithm/map_coords.rs @@ -58,7 +58,9 @@ impl MapCoords for LineString { fn map_coords(&self, func: &Fn(&(T, T)) -> (NT, NT)) -> Self::Output { - LineString(self.0.iter().map(|p| p.map_coords(func)).collect()) + unsafe { + LineString::new_unchecked(self.points().iter().map(|p| p.map_coords(func)).collect()) + } } } diff --git a/src/algorithm/orient.rs b/src/algorithm/orient.rs index 4f91f0ff3..63e230893 100644 --- a/src/algorithm/orient.rs +++ b/src/algorithm/orient.rs @@ -65,9 +65,6 @@ pub enum Direction { fn signed_ring_area(linestring: &LineString) -> T where T: Float { - if linestring.0.is_empty() || linestring.0.len() == 1 { - return T::zero(); - } let mut tmp = T::zero(); for line in linestring.lines() { tmp = tmp + (line.start.x() * line.end.y() - line.end.x() * line.start.y()); @@ -88,17 +85,17 @@ fn orient(poly: &Polygon, direction: Direction) -> Polygon let mut rings = vec![]; // process interiors first, so push and pop work for ring in &poly.interiors { - if signed_ring_area(&ring) / sign <= T::zero() { - rings.push(LineString(ring.0.iter().cloned().collect())); - } else { - rings.push(LineString(ring.0.iter().rev().cloned().collect())); + let mut ring = ring.clone(); + if signed_ring_area(&ring) / sign >= T::zero() { + ring.points_mut().reverse(); } + rings.push(ring); } - if signed_ring_area(&poly.exterior) / sign >= T::zero() { - rings.push(LineString(poly.exterior.0.iter().cloned().collect())); - } else { - rings.push(LineString(poly.exterior.0.iter().rev().cloned().collect())); + let mut ring = poly.exterior.clone(); + if signed_ring_area(&ring) / sign >= T::zero() { + ring.points_mut().reverse(); } + rings.push(ring); Polygon::new(rings.pop().unwrap(), rings) } diff --git a/src/algorithm/rotate.rs b/src/algorithm/rotate.rs index 723bee493..5fbf7a291 100644 --- a/src/algorithm/rotate.rs +++ b/src/algorithm/rotate.rs @@ -130,7 +130,16 @@ where { /// Rotate the LineString about its centroid by the given number of degrees fn rotate(&self, angle: T) -> Self { - LineString(rotation_matrix(angle, &self.centroid().unwrap(), &self.0)) + unsafe { LineString::new_unchecked(rotation_matrix(angle, &self.centroid().unwrap(), &self.points())) } + } +} + +impl RotatePoint for LineString + where T: Float +{ + /// Rotate the LineString about a point by the given number of degrees + fn rotate_around_point(&self, angle: T, point: &Point) -> Self { + unsafe { LineString::new_unchecked(rotation_matrix(angle, point, &self.points())) } } } diff --git a/src/algorithm/simplify.rs b/src/algorithm/simplify.rs index dc42daf27..add4b29b8 100644 --- a/src/algorithm/simplify.rs +++ b/src/algorithm/simplify.rs @@ -85,7 +85,8 @@ impl Simplify for LineString where T: Float { fn simplify(&self, epsilon: &T) -> LineString { - LineString(rdp(&self.0, epsilon)) + LineString::new(rdp(&self.points(), epsilon)) + .expect("simplify operation resulted in invalid linestring") } } diff --git a/src/algorithm/simplifyvw.rs b/src/algorithm/simplifyvw.rs index b2dd0b8a6..eaaf4115b 100644 --- a/src/algorithm/simplifyvw.rs +++ b/src/algorithm/simplifyvw.rs @@ -554,7 +554,7 @@ where T: Float, { fn simplifyvw(&self, epsilon: &T) -> LineString { - LineString(visvalingam(&self.0, epsilon)) + LineString::new(visvalingam(&self.points(), epsilon)).expect("simplify returned invalid linestring") } } diff --git a/src/types.rs b/src/types.rs index 151d9a3f3..a5620d382 100644 --- a/src/types.rs +++ b/src/types.rs @@ -485,7 +485,32 @@ impl Line /// ``` /// #[derive(PartialEq, Clone, Debug, Serialize, Deserialize)] -pub struct LineString(pub Vec>) where T: Float; +pub struct LineString(Vec>) where T: Float; + +impl LineString { + pub fn new(points: Vec>) -> Result { + if points.len() > 1 { + Ok(LineString(points)) + } else { + Err(()) + } + } + + /// Only use this if you know _for certain_ that `point` has at least two elements. + pub unsafe fn new_unchecked(points: Vec>) -> Self { + debug_assert!(points.len() > 1); + LineString(points) + } + + pub fn points(&self) -> &[Point] { + &self.0 + } + + // FIXME: this can cause the linestring to become invalid + pub fn points_mut(&mut self) -> &mut [Point] { + &mut self.0 + } +} impl LineString { /// Return an `Line` iterator that yields one `Line` for each line segment From 7d3683136b69563f4489c8ef2eb0c86753c60ee0 Mon Sep 17 00:00:00 2001 From: Corey Farwell Date: Mon, 11 Sep 2017 22:16:22 -0400 Subject: [PATCH 2/6] tmp --- src/algorithm/boundingbox.rs | 7 ++-- src/algorithm/centroid.rs | 72 ++++++++++++++---------------------- src/algorithm/contains.rs | 16 +------- src/algorithm/distance.rs | 2 +- src/algorithm/intersects.rs | 3 -- src/algorithm/rotate.rs | 15 ++------ src/algorithm/simplifyvw.rs | 16 ++++---- 7 files changed, 47 insertions(+), 84 deletions(-) diff --git a/src/algorithm/boundingbox.rs b/src/algorithm/boundingbox.rs index 7718b9432..8bada9a6b 100644 --- a/src/algorithm/boundingbox.rs +++ b/src/algorithm/boundingbox.rs @@ -93,7 +93,8 @@ impl BoundingBox for LineString /// Return the BoundingBox for a LineString /// fn bbox(&self) -> Self::Output { - get_bbox(&self.0) + // TODO this should return a Bbox + get_bbox(self.points()) } } @@ -106,7 +107,7 @@ impl BoundingBox for MultiLineString /// Return the BoundingBox for a MultiLineString /// fn bbox(&self) -> Self::Output { - get_bbox(self.0.iter().flat_map(|line| line.0.iter())) + get_bbox(self.0.iter().flat_map(|line| line.points().iter())) } } @@ -133,7 +134,7 @@ impl BoundingBox for MultiPolygon /// Return the BoundingBox for a MultiPolygon /// fn bbox(&self) -> Self::Output { - get_bbox(self.0.iter().flat_map(|poly| (poly.exterior).0.iter())) + get_bbox(self.0.iter().flat_map(|poly| poly.exterior.points().iter())) } } diff --git a/src/algorithm/centroid.rs b/src/algorithm/centroid.rs index fc3f1ec5b..a00904e83 100644 --- a/src/algorithm/centroid.rs +++ b/src/algorithm/centroid.rs @@ -73,23 +73,15 @@ impl Centroid for LineString // The Centroid of a LineString is the mean of the middle of the segment // weighted by the length of the segments. fn centroid(&self) -> Self::Output { - if self.0.is_empty() { - return None; - } - if self.0.len() == 1 { - Some(self.0[0].clone()) - } else { - let mut sum_x = T::zero(); - let mut sum_y = T::zero(); - let mut total_length = T::zero(); - for line in self.lines() { - let segment_len = line.length(); - let (x1, y1, x2, y2) = (line.start.x(), line.start.y(), line.end.x(), line.end.y()); - total_length = total_length + segment_len; - sum_x = sum_x + segment_len * ((x1 + x2) / (T::one() + T::one())); - sum_y = sum_y + segment_len * ((y1 + y2) / (T::one() + T::one())); - } - Some(Point::new(sum_x / total_length, sum_y / total_length)) + let mut sum_x = T::zero(); + let mut sum_y = T::zero(); + let mut total_length = T::zero(); + for line in self.lines() { + let segment_len = line.length(); + let (x1, y1, x2, y2) = (line.start.x(), line.start.y(), line.end.x(), line.end.y()); + total_length = total_length + segment_len; + sum_x = sum_x + segment_len * ((x1 + x2) / (T::one() + T::one())); + sum_y = sum_y + segment_len * ((y1 + y2) / (T::one() + T::one())); } Some(Point::new(sum_x / total_length, sum_y / total_length)) } @@ -110,34 +102,24 @@ impl Centroid for Polygon // See here for a formula: http://math.stackexchange.com/a/623849 // See here for detail on alternative methods: https://fotino.me/calculating-centroids/ fn centroid(&self) -> Self::Output { - let linestring = &self.exterior; - let vect = &linestring.0; - if vect.is_empty() { - return None; - } - if vect.len() == 1 { - Some(Point::new(vect[0].x(), vect[0].y())) - } else { - let external_centroid = simple_polygon_centroid(&self.exterior).unwrap(); - if !self.interiors.is_empty() { - let external_area = simple_polygon_area(&self.exterior).abs(); - // accumulate interior Polygons - let (totals_x, totals_y, internal_area) = - self.interiors - .iter() - .map(|ring| { - let area = simple_polygon_area(ring).abs(); - let centroid = simple_polygon_centroid(ring).unwrap(); - ((centroid.x() * area), (centroid.y() * area), area) - }) - .fold((T::zero(), T::zero(), T::zero()), - |accum, val| (accum.0 + val.0, accum.1 + val.1, accum.2 + val.2)); - return Some(Point::new(((external_centroid.x() * external_area) - totals_x) / - (external_area - internal_area), - ((external_centroid.y() * external_area) - totals_y) / - (external_area - internal_area))); - } - Some(external_centroid) + let external_centroid = simple_polygon_centroid(&self.exterior).unwrap(); + if !self.interiors.is_empty() { + let external_area = simple_polygon_area(&self.exterior).abs(); + // accumulate interior Polygons + let (totals_x, totals_y, internal_area) = + self.interiors + .iter() + .map(|ring| { + let area = simple_polygon_area(ring).abs(); + let centroid = simple_polygon_centroid(ring).unwrap(); + ((centroid.x() * area), (centroid.y() * area), area) + }) + .fold((T::zero(), T::zero(), T::zero()), + |accum, val| (accum.0 + val.0, accum.1 + val.1, accum.2 + val.2)); + return Some(Point::new(((external_centroid.x() * external_area) - totals_x) / + (external_area - internal_area), + ((external_centroid.y() * external_area) - totals_y) / + (external_area - internal_area))); } Some(external_centroid) } diff --git a/src/algorithm/contains.rs b/src/algorithm/contains.rs index 639bb344b..78adc2d04 100644 --- a/src/algorithm/contains.rs +++ b/src/algorithm/contains.rs @@ -44,16 +44,8 @@ impl Contains> for LineString where T: Float { fn contains(&self, p: &Point) -> bool { - // LineString without points - if self.0.is_empty() { - return false; - } - // LineString with one point equal p - if self.0.len() == 1 { - return self.0[0].contains(p); - } // check if point is a vertex - if self.0.contains(p) { + if self.points().contains(p) { return true; } for line in self.lines() { @@ -142,10 +134,6 @@ fn get_position(p: &Point, linestring: &LineString) -> PositionPoint // ?updated-min=2011-01-01T00:00:00-06:00&updated-max=2012-01-01T00:00:00-06:00&max-results=19 // Return the position of the point relative to a linestring - // LineString without points - if linestring.0.is_empty() { - return PositionPoint::Outside; - } // Point is on linestring if linestring.contains(p) { return PositionPoint::OnBoundary; @@ -223,7 +211,7 @@ impl Contains> for Polygon { fn contains(&self, linestring: &LineString) -> bool { // All LineString points must be inside the Polygon - if linestring.0.iter().all(|point| self.contains(point)) { + if linestring.points().iter().all(|point| self.contains(point)) { // The Polygon interior is allowed to intersect with the LineString // but the Polygon's rings are not !self.interiors.iter().any(|ring| ring.intersects(linestring)) diff --git a/src/algorithm/distance.rs b/src/algorithm/distance.rs index 2e8a3dc77..9580bd209 100644 --- a/src/algorithm/distance.rs +++ b/src/algorithm/distance.rs @@ -156,7 +156,7 @@ impl Distance> for Point // get exterior ring let exterior = &polygon.exterior; // No need to continue if the polygon contains the point, or is zero-length - if polygon.contains(self) || exterior.0.is_empty() { + if polygon.contains(self) { return T::zero(); } // minimum priority queue diff --git a/src/algorithm/intersects.rs b/src/algorithm/intersects.rs index d2acb5395..208d2f640 100644 --- a/src/algorithm/intersects.rs +++ b/src/algorithm/intersects.rs @@ -133,9 +133,6 @@ impl Intersects> for LineString { // See: https://github.com/brandonxiang/geojson-python-utils/blob/33b4c00c6cf27921fb296052d0c0341bd6ca1af2/geojson_utils.py fn intersects(&self, linestring: &LineString) -> bool { - if self.0.is_empty() || linestring.0.is_empty() { - return false; - } for a in self.lines() { for b in linestring.lines() { let u_b = (b.end.y() - b.start.y()) * (a.end.x() - a.start.x()) - diff --git a/src/algorithm/rotate.rs b/src/algorithm/rotate.rs index 5fbf7a291..515fa9590 100644 --- a/src/algorithm/rotate.rs +++ b/src/algorithm/rotate.rs @@ -134,15 +134,6 @@ where } } -impl RotatePoint for LineString - where T: Float -{ - /// Rotate the LineString about a point by the given number of degrees - fn rotate_around_point(&self, angle: T, point: &Point) -> Self { - unsafe { LineString::new_unchecked(rotation_matrix(angle, point, &self.points())) } - } -} - impl Rotate for Polygon where T: Float + FromPrimitive, @@ -155,11 +146,13 @@ where true => self.centroid().unwrap(), }; Polygon::new( - LineString(rotation_matrix(angle, ¢roid, &self.exterior.0)), + // TODO: can this be unchecked + LineString::new(rotation_matrix(angle, ¢roid, self.exterior.points())).unwrap(), self.interiors .iter() .map(|ring| { - LineString(rotation_matrix(angle, ¢roid, &ring.0)) + // TODO: can this be unchecked + LineString::new(rotation_matrix(angle, ¢roid, ring.points())).unwrap() }) .collect(), ) diff --git a/src/algorithm/simplifyvw.rs b/src/algorithm/simplifyvw.rs index eaaf4115b..1044e7d1b 100644 --- a/src/algorithm/simplifyvw.rs +++ b/src/algorithm/simplifyvw.rs @@ -207,11 +207,11 @@ where } } // Simplify shell - rings.push(visvalingam_preserve(geomtype, &exterior.0, epsilon, &mut tree)); + rings.push(visvalingam_preserve(geomtype, exterior.points(), epsilon, &mut tree)); // Simplify interior rings, if any if let Some(interior_rings) = interiors { for ring in interior_rings { - rings.push(visvalingam_preserve(geomtype, &ring.0, epsilon, &mut tree)) + rings.push(visvalingam_preserve(geomtype, ring.points(), epsilon, &mut tree)) } } rings @@ -370,11 +370,11 @@ where let point_a = orig[triangle.left]; let point_b = orig[triangle.current]; let point_c = orig[triangle.right]; - let bbox = LineString(vec![ + let bbox = unsafe { LineString::new_unchecked(vec![ orig[triangle.left], orig[triangle.current], orig[triangle.right], - ]).bbox() + ]) }.bbox() .unwrap(); let br = Point::new(bbox.xmin, bbox.ymin); let tl = Point::new(bbox.xmax, bbox.ymax); @@ -500,7 +500,8 @@ where geomtype: GeomType::Line, }; let mut simplified = vwp_wrapper(>, &self, None, epsilon); - LineString(simplified.pop().unwrap()) + // can this be unchecked? + LineString::new(simplified.pop().unwrap()).unwrap() } } @@ -529,8 +530,9 @@ where geomtype: GeomType::Ring, }; let mut simplified = vwp_wrapper(>, &self.exterior, Some(&self.interiors), epsilon); - let exterior = LineString(simplified.remove(0)); - let interiors = simplified.into_iter().map(LineString).collect(); + // todo: can these be unchecked? + let exterior = LineString::new(simplified.remove(0)).unwrap(); + let interiors = simplified.into_iter().map(|l| LineString::new(l).unwrap()).collect(); Polygon::new(exterior, interiors) } } From 65bbe29ceae712e5e053de303a9df3f40a475a38 Mon Sep 17 00:00:00 2001 From: Corey Farwell Date: Mon, 11 Sep 2017 23:13:53 -0400 Subject: [PATCH 3/6] tmp --- src/algorithm/extremes.rs | 13 ++++++++----- src/algorithm/simplifyvw.rs | 13 ++++++++----- src/types.rs | 19 ------------------- 3 files changed, 16 insertions(+), 29 deletions(-) diff --git a/src/algorithm/extremes.rs b/src/algorithm/extremes.rs index de79dbc76..eea8fb1cd 100644 --- a/src/algorithm/extremes.rs +++ b/src/algorithm/extremes.rs @@ -208,11 +208,14 @@ impl ExtremePoints for G let ch = self.convex_hull(); // safe to unwrap, since we're guaranteeing the polygon's convexity let indices = ch.extreme_indices().unwrap(); - ExtremePoint { - ymin: ch.exterior.points()[indices.ymin], - xmax: ch.exterior.points()[indices.xmax], - ymax: ch.exterior.points()[indices.ymax], - xmin: ch.exterior.points()[indices.xmin], + // unsafe: indices should all be valid, no bounds checking required + unsafe { + ExtremePoint { + ymin: *ch.exterior.points().get_unchecked(indices.ymin), + xmax: *ch.exterior.points().get_unchecked(indices.xmax), + ymax: *ch.exterior.points().get_unchecked(indices.ymax), + xmin: *ch.exterior.points().get_unchecked(indices.xmin), + } } } } diff --git a/src/algorithm/simplifyvw.rs b/src/algorithm/simplifyvw.rs index 1044e7d1b..e9a23fcc1 100644 --- a/src/algorithm/simplifyvw.rs +++ b/src/algorithm/simplifyvw.rs @@ -370,11 +370,14 @@ where let point_a = orig[triangle.left]; let point_b = orig[triangle.current]; let point_c = orig[triangle.right]; - let bbox = unsafe { LineString::new_unchecked(vec![ - orig[triangle.left], - orig[triangle.current], - orig[triangle.right], - ]) }.bbox() + let bbox = unsafe { + // unsafe: + LineString::new_unchecked(vec![ + orig[triangle.left], + orig[triangle.current], + orig[triangle.right], + ]) + }.bbox() .unwrap(); let br = Point::new(bbox.xmin, bbox.ymin); let tl = Point::new(bbox.xmax, bbox.ymax); diff --git a/src/types.rs b/src/types.rs index a5620d382..7530e987e 100644 --- a/src/types.rs +++ b/src/types.rs @@ -505,11 +505,6 @@ impl LineString { pub fn points(&self) -> &[Point] { &self.0 } - - // FIXME: this can cause the linestring to become invalid - pub fn points_mut(&mut self) -> &mut [Point] { - &mut self.0 - } } impl LineString { @@ -547,20 +542,6 @@ impl LineString { } } -/// Turn a `Vec` of `Point`-ish objects into a `LineString`. -impl>> From> for LineString { - fn from(v: Vec) -> Self { - LineString(v.into_iter().map(|p| p.into()).collect()) - } -} - -/// Turn a `Point`-ish iterator into a `LineString`. -impl>> FromIterator for LineString { - fn from_iter>(iter: I) -> Self { - LineString(iter.into_iter().map(|p| p.into()).collect()) - } -} - /// Iterate over all the [Point](struct.Point.html)s in this linestring impl IntoIterator for LineString { type Item = Point; From a19529e2975f834316f3169f0da7824de8f5cc6e Mon Sep 17 00:00:00 2001 From: Corey Farwell Date: Mon, 11 Sep 2017 23:16:16 -0400 Subject: [PATCH 4/6] tmp --- src/types.rs | 3 --- 1 file changed, 3 deletions(-) diff --git a/src/types.rs b/src/types.rs index 7530e987e..005ffa998 100644 --- a/src/types.rs +++ b/src/types.rs @@ -531,9 +531,6 @@ impl LineString { /// assert!(lines.next().is_none()); /// ``` pub fn lines<'a>(&'a self) -> Box> + 'a> { - if self.0.len() < 2 { - return Box::new(iter::empty()); - } Box::new(self.0.windows(2).map(|w| unsafe { // As long as the LineString has at least two points, we shouldn't // need to do bounds checking here. From 082a1467d9b6bdccafb6dbfcb0d5843c03512777 Mon Sep 17 00:00:00 2001 From: Corey Farwell Date: Mon, 11 Sep 2017 23:28:16 -0400 Subject: [PATCH 5/6] tmp --- src/algorithm/orient.rs | 4 ++-- src/types.rs | 6 +++++- 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/src/algorithm/orient.rs b/src/algorithm/orient.rs index 63e230893..10132ba8b 100644 --- a/src/algorithm/orient.rs +++ b/src/algorithm/orient.rs @@ -87,13 +87,13 @@ fn orient(poly: &Polygon, direction: Direction) -> Polygon for ring in &poly.interiors { let mut ring = ring.clone(); if signed_ring_area(&ring) / sign >= T::zero() { - ring.points_mut().reverse(); + unsafe { ring.points_mut().reverse(); } } rings.push(ring); } let mut ring = poly.exterior.clone(); if signed_ring_area(&ring) / sign >= T::zero() { - ring.points_mut().reverse(); + unsafe { ring.points_mut().reverse(); } } rings.push(ring); Polygon::new(rings.pop().unwrap(), rings) diff --git a/src/types.rs b/src/types.rs index 005ffa998..bb62f5195 100644 --- a/src/types.rs +++ b/src/types.rs @@ -5,7 +5,7 @@ use std::ops::Sub; use std::fmt::Debug; -use std::iter::{self, Iterator, FromIterator}; +use std::iter::{Iterator, FromIterator}; use num_traits::{Float, ToPrimitive}; use spade::SpadeNum; @@ -505,6 +505,10 @@ impl LineString { pub fn points(&self) -> &[Point] { &self.0 } + + pub unsafe fn points_mut(&mut self) -> &mut [Point] { + &mut self.0 + } } impl LineString { From 93cafa0cdcfd77247f196a5c71d6ca932845e994 Mon Sep 17 00:00:00 2001 From: Corey Farwell Date: Tue, 12 Sep 2017 08:44:10 -0400 Subject: [PATCH 6/6] tmp --- src/algorithm/area.rs | 20 +++---- src/algorithm/boundingbox.rs | 24 ++++---- src/algorithm/centroid.rs | 30 +++++----- src/algorithm/contains.rs | 80 ++++++++++++------------- src/algorithm/convexhull.rs | 16 ++--- src/algorithm/distance.rs | 44 +++++++------- src/algorithm/extremes.rs | 14 ++--- src/algorithm/intersects.rs | 110 +++++++++++++++++------------------ src/algorithm/length.rs | 12 ++-- src/algorithm/map_coords.rs | 36 ++++++------ src/algorithm/orient.rs | 10 ++-- src/algorithm/rotate.rs | 30 +++++----- src/algorithm/simplify.rs | 28 ++++----- src/algorithm/simplifyvw.rs | 46 +++++++-------- src/algorithm/translate.rs | 18 +++--- src/types.rs | 14 ++--- 16 files changed, 266 insertions(+), 266 deletions(-) diff --git a/src/algorithm/area.rs b/src/algorithm/area.rs index a1feb5354..e7233e9d0 100644 --- a/src/algorithm/area.rs +++ b/src/algorithm/area.rs @@ -13,7 +13,7 @@ pub trait Area where T: Float /// use geo::algorithm::area::Area; /// let p = |x, y| Point(Coordinate { x: x, y: y }); /// let v = Vec::new(); - /// let linestring = LineString(vec![p(0., 0.), p(5., 0.), p(5., 6.), p(0., 6.), p(0., 0.)]); + /// let linestring = LineString::new(vec![p(0., 0.), p(5., 0.), p(5., 6.), p(0., 6.), p(0., 0.)]).unwrap(); /// let poly = Polygon::new(linestring, v); /// assert_eq!(poly.area(), 30.); /// ``` @@ -69,19 +69,19 @@ mod test { // Area of the polygon #[test] fn area_empty_polygon_test() { - let poly = Polygon::::new(LineString(Vec::new()), Vec::new()); + let poly = Polygon::::new(LineString::new(Vec::new()), Vec::new()).unwrap(); assert_relative_eq!(poly.area(), 0.); } #[test] fn area_one_point_polygon_test() { - let poly = Polygon::new(LineString(vec![Point::new(1., 0.)]), Vec::new()); + let poly = Polygon::new(LineString::new(vec![Point::new(1., 0.)]), Vec::new()).unwrap(); assert_relative_eq!(poly.area(), 0.); } #[test] fn area_polygon_test() { let p = |x, y| Point(Coordinate { x: x, y: y }); - let linestring = LineString(vec![p(0., 0.), p(5., 0.), p(5., 6.), p(0., 6.), p(0., 0.)]); + let linestring = LineString::new(vec![p(0., 0.), p(5., 0.), p(5., 6.), p(0., 6.), p(0., 0.)]).unwrap(); let poly = Polygon::new(linestring, Vec::new()); assert_relative_eq!(poly.area(), 30.); } @@ -93,22 +93,22 @@ mod test { #[test] fn area_polygon_inner_test() { let p = |x, y| Point(Coordinate { x: x, y: y }); - let outer = LineString(vec![p(0., 0.), p(10., 0.), p(10., 10.), p(0., 10.), p(0., 0.)]); - let inner0 = LineString(vec![p(1., 1.), p(2., 1.), p(2., 2.), p(1., 2.), p(1., 1.)]); - let inner1 = LineString(vec![p(5., 5.), p(6., 5.), p(6., 6.), p(5., 6.), p(5., 5.)]); + let outer = LineString::new(vec![p(0., 0.), p(10., 0.), p(10., 10.), p(0., 10.), p(0., 0.)]).unwrap(); + let inner0 = LineString::new(vec![p(1., 1.), p(2., 1.), p(2., 2.), p(1., 2.), p(1., 1.)]).unwrap(); + let inner1 = LineString::new(vec![p(5., 5.), p(6., 5.), p(6., 6.), p(5., 6.), p(5., 5.)]).unwrap(); let poly = Polygon::new(outer, vec![inner0, inner1]); assert_relative_eq!(poly.area(), 98.); } #[test] fn area_multipolygon_test() { let p = |x, y| Point(Coordinate { x: x, y: y }); - let poly0 = Polygon::new(LineString(vec![p(0., 0.), p(10., 0.), p(10., 10.), p(0., 10.), + let poly0 = Polygon::new(LineString::new(vec![p(0., 0.), p(10., 0.), p(10., 10.), p(0., 10.).unwrap(), p(0., 0.)]), Vec::new()); - let poly1 = Polygon::new(LineString(vec![p(1., 1.), p(2., 1.), p(2., 2.), p(1., 2.), + let poly1 = Polygon::new(LineString::new(vec![p(1., 1.), p(2., 1.), p(2., 2.), p(1., 2.).unwrap(), p(1., 1.)]), Vec::new()); - let poly2 = Polygon::new(LineString(vec![p(5., 5.), p(6., 5.), p(6., 6.), p(5., 6.), + let poly2 = Polygon::new(LineString::new(vec![p(5., 5.), p(6., 5.), p(6., 6.), p(5., 6.).unwrap(), p(5., 5.)]), Vec::new()); let mpoly = MultiPolygon(vec![poly0, poly1, poly2]); diff --git a/src/algorithm/boundingbox.rs b/src/algorithm/boundingbox.rs index 8bada9a6b..18ed0eb3b 100644 --- a/src/algorithm/boundingbox.rs +++ b/src/algorithm/boundingbox.rs @@ -17,7 +17,7 @@ pub trait BoundingBox { /// vec.push(Point::new(40.02f64, 116.34)); /// vec.push(Point::new(42.02f64, 116.34)); /// vec.push(Point::new(42.02f64, 118.34)); - /// let linestring = LineString(vec); + /// let linestring = LineString::new(vec).unwrap(); /// let bbox = linestring.bbox().unwrap(); /// /// assert_eq!(40.02f64, bbox.xmin); @@ -148,7 +148,7 @@ mod test { #[test] fn empty_linestring_test() { let vect = Vec::>::new(); - let linestring = LineString(vect); + let linestring = LineString::new(vect).unwrap(); let bbox = linestring.bbox(); assert!(bbox.is_none()); } @@ -157,24 +157,24 @@ mod test { let p = Point::new(40.02f64, 116.34); let mut vect = Vec::>::new(); vect.push(p); - let linestring = LineString(vect); + let linestring = LineString::new(vect).unwrap(); let bbox = Bbox{xmin: 40.02f64, ymax: 116.34, xmax: 40.02, ymin: 116.34}; assert_eq!(bbox, linestring.bbox().unwrap()); } #[test] fn linestring_test() { let p = |x, y| Point(Coordinate { x: x, y: y }); - let linestring = LineString(vec![p(1., 1.), p(2., -2.), p(-3., -3.), p(-4., 4.)]); + let linestring = LineString::new(vec![p(1., 1.), p(2., -2.), p(-3., -3.), p(-4., 4.)]).unwrap(); let bbox = Bbox{xmin: -4., ymax: 4., xmax: 2., ymin: -3.}; assert_eq!(bbox, linestring.bbox().unwrap()); } #[test] fn multilinestring_test() { let p = |x, y| Point(Coordinate { x: x, y: y }); - let multiline = MultiLineString(vec![LineString(vec![p(1., 1.), p(-40., 1.)]), - LineString(vec![p(1., 1.), p(50., 1.)]), - LineString(vec![p(1., 1.), p(1., -60.)]), - LineString(vec![p(1., 1.), p(1., 70.)])]); + let multiline = MultiLineString::new(vec![LineString::new(vec![p(1., 1.), p(-40., 1.)]).unwrap(), + LineString::new(vec![p(1., 1.), p(50., 1.)]).unwrap(), + LineString::new(vec![p(1., 1.), p(1., -60.)]).unwrap(), + LineString::new(vec![p(1., 1.), p(1., 70.)])]).unwrap(); let bbox = Bbox{xmin: -40., ymax: 70., xmax: 50., ymin: -60.}; assert_eq!(bbox, multiline.bbox().unwrap()); } @@ -188,7 +188,7 @@ mod test { #[test] fn polygon_test(){ let p = |x, y| Point(Coordinate { x: x, y: y }); - let linestring = LineString(vec![p(0., 0.), p(5., 0.), p(5., 6.), p(0., 6.), p(0., 0.)]); + let linestring = LineString::new(vec![p(0., 0.), p(5., 0.), p(5., 6.), p(0., 6.), p(0., 0.)]).unwrap(); let line_bbox = linestring.bbox().unwrap(); let poly = Polygon::new(linestring, Vec::new()); assert_eq!(line_bbox, poly.bbox().unwrap()); @@ -196,9 +196,9 @@ mod test { #[test] fn multipolygon_test(){ let p = |x, y| Point(Coordinate { x: x, y: y }); - let mpoly = MultiPolygon(vec![Polygon::new(LineString(vec![p(0., 0.), p(50., 0.), p(0., -70.), p(0., 0.)]), Vec::new()), - Polygon::new(LineString(vec![p(0., 0.), p(5., 0.), p(0., 80.), p(0., 0.)]), Vec::new()), - Polygon::new(LineString(vec![p(0., 0.), p(-60., 0.), p(0., 6.), p(0., 0.)]), Vec::new()), + let mpoly = MultiPolygon(vec![Polygon::new(LineString::new(vec![p(0., 0.), p(50., 0.), p(0., -70.), p(0., 0.)]), Vec::new()).unwrap(), + Polygon::new(LineString::new(vec![p(0., 0.), p(5., 0.), p(0., 80.), p(0., 0.)]), Vec::new()).unwrap(), + Polygon::new(LineString::new(vec![p(0., 0.), p(-60., 0.), p(0., 6.), p(0., 0.)]), Vec::new()).unwrap(), ]); let bbox = Bbox{xmin: -60., ymax: 80., xmax: 50., ymin: -70.}; assert_eq!(bbox, mpoly.bbox().unwrap()); diff --git a/src/algorithm/centroid.rs b/src/algorithm/centroid.rs index a00904e83..c173b386c 100644 --- a/src/algorithm/centroid.rs +++ b/src/algorithm/centroid.rs @@ -17,7 +17,7 @@ pub trait Centroid { /// let mut vec = Vec::new(); /// vec.push(Point::new(40.02f64, 116.34)); /// vec.push(Point::new(40.02f64, 118.23)); - /// let linestring = LineString(vec); + /// let linestring = LineString::new(vec).unwrap(); /// /// assert_eq!(linestring.centroid().unwrap(), Point::new(40.02, 117.285)); /// ``` @@ -181,7 +181,7 @@ mod test { #[test] fn empty_linestring_test() { let vec = Vec::>::new(); - let linestring = LineString(vec); + let linestring = LineString::new(vec).unwrap(); let centroid = linestring.centroid(); assert!(centroid.is_none()); } @@ -190,14 +190,14 @@ mod test { let p = Point::new(40.02f64, 116.34); let mut vect = Vec::>::new(); vect.push(p); - let linestring = LineString(vect); + let linestring = LineString::new(vect).unwrap(); let centroid = linestring.centroid(); assert_eq!(centroid, Some(p)); } #[test] fn linestring_test() { let p = |x| Point(Coordinate { x: x, y: 1. }); - let linestring = LineString(vec![p(1.), p(7.), p(8.), p(9.), p(10.), p(11.)]); + let linestring = LineString::new(vec![p(1.), p(7.), p(8.), p(9.), p(10.), p(11.)]).unwrap(); assert_eq!(linestring.centroid(), Some(Point(Coordinate { x: 6., y: 1. }))); } @@ -206,7 +206,7 @@ mod test { fn empty_polygon_test() { let v1 = Vec::new(); let v2 = Vec::new(); - let linestring = LineString::(v1); + let linestring = LineString::::new(v1).unwrap(); let poly = Polygon::new(linestring, v2); assert!(poly.centroid().is_none()); } @@ -214,7 +214,7 @@ mod test { fn polygon_one_point_test() { let p = Point(Coordinate { x: 2., y: 1. }); let v = Vec::new(); - let linestring = LineString(vec![p]); + let linestring = LineString::new(vec![p]).unwrap(); let poly = Polygon::new(linestring, v); assert_eq!(poly.centroid(), Some(p)); } @@ -222,13 +222,13 @@ mod test { fn polygon_test() { let p = |x, y| Point(Coordinate { x: x, y: y }); let v = Vec::new(); - let linestring = LineString(vec![p(0., 0.), p(2., 0.), p(2., 2.), p(0., 2.), p(0., 0.)]); + let linestring = LineString::new(vec![p(0., 0.), p(2., 0.), p(2., 2.), p(0., 2.), p(0., 0.)]).unwrap(); let poly = Polygon::new(linestring, v); assert_eq!(poly.centroid(), Some(p(1., 1.))); } #[test] fn polygon_hole_test() { - let ls1 = LineString(vec![Point::new(5.0, 1.0), + let ls1 = LineString::new(vec![Point::new(5.0, 1.0).unwrap(), Point::new(4.0, 2.0), Point::new(4.0, 3.0), Point::new(5.0, 4.0), @@ -238,12 +238,12 @@ mod test { Point::new(6.0, 1.0), Point::new(5.0, 1.0)]); - let ls2 = LineString(vec![Point::new(5.0, 1.3), + let ls2 = LineString::new(vec![Point::new(5.0, 1.3).unwrap(), Point::new(5.5, 2.0), Point::new(6.0, 1.3), Point::new(5.0, 1.3)]); - let ls3 = LineString(vec![Point::new(5., 2.3), + let ls3 = LineString::new(vec![Point::new(5., 2.3).unwrap(), Point::new(5.5, 3.0), Point::new(6., 2.3), Point::new(5., 2.3)]); @@ -260,16 +260,16 @@ mod test { #[test] fn multipolygon_one_polygon_test() { let p = |x, y| Point(Coordinate { x: x, y: y }); - let linestring = LineString(vec![p(0., 0.), p(2., 0.), p(2., 2.), p(0., 2.), p(0., 0.)]); + let linestring = LineString::new(vec![p(0., 0.), p(2., 0.), p(2., 2.), p(0., 2.), p(0., 0.)]).unwrap(); let poly = Polygon::new(linestring, Vec::new()); assert_eq!(MultiPolygon(vec![poly]).centroid(), Some(p(1., 1.))); } #[test] fn multipolygon_two_polygons_test() { let p = |x, y| Point(Coordinate { x: x, y: y }); - let linestring = LineString(vec![p(2., 1.), p(5., 1.), p(5., 3.), p(2., 3.), p(2., 1.)]); + let linestring = LineString::new(vec![p(2., 1.), p(5., 1.), p(5., 3.), p(2., 3.), p(2., 1.)]).unwrap(); let poly1 = Polygon::new(linestring, Vec::new()); - let linestring = LineString(vec![p(7., 1.), p(8., 1.), p(8., 2.), p(7., 2.), p(7., 1.)]); + let linestring = LineString::new(vec![p(7., 1.), p(8., 1.), p(8., 2.), p(7., 2.), p(7., 1.)]).unwrap(); let poly2 = Polygon::new(linestring, Vec::new()); let dist = MultiPolygon(vec![poly1, poly2]) .centroid() @@ -280,9 +280,9 @@ mod test { #[test] fn multipolygon_two_polygons_of_opposite_clockwise_test() { let p = |x, y| Point(Coordinate { x: x, y: y }); - let linestring = LineString(vec![p(0., 0.), p(2., 0.), p(2., 2.), p(0., 2.), p(0., 0.)]); + let linestring = LineString::new(vec![p(0., 0.), p(2., 0.), p(2., 2.), p(0., 2.), p(0., 0.)]).unwrap(); let poly1 = Polygon::new(linestring, Vec::new()); - let linestring = LineString(vec![p(0., 0.), p(-2., 0.), p(-2., 2.), p(0., 2.), p(0., 0.)]); + let linestring = LineString::new(vec![p(0., 0.), p(-2., 0.), p(-2., 2.), p(0., 2.), p(0., 0.)]).unwrap(); let poly2 = Polygon::new(linestring, Vec::new()); assert_eq!(MultiPolygon(vec![poly1, poly2]).centroid(), Some(p(0., 1.))); } diff --git a/src/algorithm/contains.rs b/src/algorithm/contains.rs index 78adc2d04..f3d87de15 100644 --- a/src/algorithm/contains.rs +++ b/src/algorithm/contains.rs @@ -15,7 +15,7 @@ pub trait Contains { /// /// let p = |x, y| Point(Coordinate { x: x, y: y }); /// let v = Vec::new(); - /// let linestring = LineString(vec![p(0., 0.), p(2., 0.), p(2., 2.), p(0., 2.), p(0., 0.)]); + /// let linestring = LineString::new(vec![p(0., 0.), p(2., 0.), p(2., 2.), p(0., 2.), p(0., 0.)]).unwrap(); /// let poly = Polygon::new(linestring.clone(), v); /// /// //Point in Point @@ -261,51 +261,51 @@ mod test { // LineString is fully contained fn linestring_fully_contained_in_polygon() { let p = |x, y| Point(Coordinate { x: x, y: y }); - let poly = Polygon::new(LineString(vec![p(0., 0.), p(5., 0.), p(5., 6.), p(0., 6.), p(0., 0.)]), vec![]); - let ls = LineString(vec![Point::new(3.0, 0.5), Point::new(3.0, 3.5)]); + let poly = Polygon::new(LineString::new(vec![p(0., 0.), p(5., 0.), p(5., 6.), p(0., 6.), p(0., 0.)]), vec![]).unwrap(); + let ls = LineString::new(vec![Point::new(3.0, 0.5), Point::new(3.0, 3.5)]).unwrap(); assert_eq!(poly.contains(&ls), true); } /// Tests: Point in LineString #[test] fn empty_linestring_test() { - let linestring = LineString(Vec::new()); + let linestring = LineString::new(Vec::new()).unwrap(); assert!(!linestring.contains(&Point::new(2., 1.))); } #[test] fn linestring_point_is_vertex_test() { let p = |x, y| Point(Coordinate { x: x, y: y }); - let linestring = LineString(vec![p(0., 0.), p(2., 0.), p(2., 2.)]); + let linestring = LineString::new(vec![p(0., 0.), p(2., 0.), p(2., 2.)]).unwrap(); assert!(linestring.contains(&p(2., 2.))); } #[test] fn linestring_test() { let p = |x, y| Point(Coordinate { x: x, y: y }); - let linestring = LineString(vec![p(0., 0.), p(2., 0.), p(2., 2.)]); + let linestring = LineString::new(vec![p(0., 0.), p(2., 0.), p(2., 2.)]).unwrap(); assert!(linestring.contains(&p(1., 0.))); } /// Tests: Point in Polygon #[test] fn empty_polygon_test() { - let linestring = LineString(Vec::new()); + let linestring = LineString::new(Vec::new()).unwrap(); let poly = Polygon::new(linestring, Vec::new()); assert!(!poly.contains(&Point::new(2., 1.))); } #[test] fn polygon_with_one_point_test() { - let linestring = LineString(vec![Point::new(2., 1.)]); + let linestring = LineString::new(vec![Point::new(2., 1.)]).unwrap(); let poly = Polygon::new(linestring, Vec::new()); assert!(!poly.contains(&Point::new(3., 1.))); } #[test] fn polygon_with_one_point_is_vertex_test() { - let linestring = LineString(vec![Point::new(2., 1.)]); + let linestring = LineString::new(vec![Point::new(2., 1.)]).unwrap(); let poly = Polygon::new(linestring, Vec::new()); assert!(!poly.contains(&Point::new(2., 1.))); } #[test] fn polygon_with_point_on_boundary_test() { let p = |x, y| Point(Coordinate { x: x, y: y }); - let linestring = LineString(vec![p(0., 0.), p(2., 0.), p(2., 2.), p(0., 2.), p(0., 0.)]); + let linestring = LineString::new(vec![p(0., 0.), p(2., 0.), p(2., 2.), p(0., 2.), p(0., 0.)]).unwrap(); let poly = Polygon::new(linestring, Vec::new()); assert!(!poly.contains(&p(1., 0.))); assert!(!poly.contains(&p(2., 1.))); @@ -315,14 +315,14 @@ mod test { #[test] fn point_in_polygon_test() { let p = |x, y| Point(Coordinate { x: x, y: y }); - let linestring = LineString(vec![p(0., 0.), p(2., 0.), p(2., 2.), p(0., 2.), p(0., 0.)]); + let linestring = LineString::new(vec![p(0., 0.), p(2., 0.), p(2., 2.), p(0., 2.), p(0., 0.)]).unwrap(); let poly = Polygon::new(linestring, Vec::new()); assert!(poly.contains(&p(1., 1.))); } #[test] fn point_out_polygon_test() { let p = |x, y| Point(Coordinate { x: x, y: y }); - let linestring = LineString(vec![p(0., 0.), p(2., 0.), p(2., 2.), p(0., 2.), p(0., 0.)]); + let linestring = LineString::new(vec![p(0., 0.), p(2., 0.), p(2., 2.), p(0., 2.), p(0., 0.)]).unwrap(); let poly = Polygon::new(linestring, Vec::new()); assert!(!poly.contains(&p(2.1, 1.))); assert!(!poly.contains(&p(1., 2.1))); @@ -331,8 +331,8 @@ mod test { #[test] fn point_polygon_with_inner_test() { let p = |x, y| Point(Coordinate { x: x, y: y }); - let linestring = LineString(vec![p(0., 0.), p(2., 0.), p(2., 2.), p(0., 2.), p(0., 0.)]); - let inner_linestring = LineString(vec![p(0.5, 0.5), + let linestring = LineString::new(vec![p(0., 0.), p(2., 0.), p(2., 2.), p(0., 2.), p(0., 0.)]).unwrap(); + let inner_linestring = LineString::new(vec![p(0.5, 0.5).unwrap(), p(1.5, 0.5), p(1.5, 1.5), p(0.0, 1.5), @@ -352,9 +352,9 @@ mod test { #[test] fn empty_multipolygon_two_polygons_test() { let p = |x, y| Point(Coordinate { x: x, y: y }); - let poly1 = Polygon::new(LineString(vec![p(0., 0.), p(1., 0.), p(1., 1.), p(0., 1.), p(0., 0.)]), + let poly1 = Polygon::new(LineString::new(vec![p(0., 0.), p(1., 0.), p(1., 1.), p(0., 1.), p(0., 0.)]).unwrap(), Vec::new()); - let poly2 = Polygon::new(LineString(vec![p(2., 0.), p(3., 0.), p(3., 1.), p(2., 1.), p(2., 0.)]), + let poly2 = Polygon::new(LineString::new(vec![p(2., 0.), p(3., 0.), p(3., 1.), p(2., 1.), p(2., 0.)]).unwrap(), Vec::new()); let multipoly = MultiPolygon(vec![poly1, poly2]); assert!(multipoly.contains(&Point::new(0.5, 0.5))); @@ -364,9 +364,9 @@ mod test { #[test] fn empty_multipolygon_two_polygons_and_inner_test() { let p = |x, y| Point(Coordinate { x: x, y: y }); - let poly1 = Polygon::new(LineString(vec![p(0., 0.), p(5., 0.), p(5., 6.), p(0., 6.), p(0., 0.)]), - vec![LineString(vec![p(1., 1.), p(4., 1.), p(4., 4.), p(1., 1.)])]); - let poly2 = Polygon::new(LineString(vec![p(9., 0.), p(14., 0.), p(14., 4.), p(9., 4.), p(9., 0.)]), + let poly1 = Polygon::new(LineString::new(vec![p(0., 0.), p(5., 0.), p(5., 6.), p(0., 6.), p(0., 0.)]).unwrap(), + vec![LineString::new(vec![p(1., 1.), p(4., 1.), p(4., 4.), p(1., 1.)])]).unwrap(); + let poly2 = Polygon::new(LineString::new(vec![p(9., 0.), p(14., 0.), p(14., 4.), p(9., 4.), p(9., 0.)]).unwrap(), Vec::new()); let multipoly = MultiPolygon(vec![poly1, poly2]); @@ -379,30 +379,30 @@ mod test { #[test] fn linestring_in_polygon_with_linestring_is_boundary_test() { let p = |x, y| Point(Coordinate { x: x, y: y }); - let linestring = LineString(vec![p(0., 0.), p(2., 0.), p(2., 2.), p(0., 2.), p(0., 0.)]); + let linestring = LineString::new(vec![p(0., 0.), p(2., 0.), p(2., 2.), p(0., 2.), p(0., 0.)]).unwrap(); let poly = Polygon::new(linestring.clone(), Vec::new()); assert!(!poly.contains(&linestring.clone())); - assert!(!poly.contains(&LineString(vec![p(0., 0.), p(2., 0.)]))); - assert!(!poly.contains(&LineString(vec![p(2., 0.), p(2., 2.)]))); - assert!(!poly.contains(&LineString(vec![p(0., 2.), p(0., 0.)]))); + assert!(!poly.contains(&LineString::new(vec![p(0., 0.), p(2., 0.)]))).unwrap(); + assert!(!poly.contains(&LineString::new(vec![p(2., 0.), p(2., 2.)]))).unwrap(); + assert!(!poly.contains(&LineString::new(vec![p(0., 2.), p(0., 0.)]))).unwrap(); } #[test] fn linestring_outside_polygon_test() { let p = |x, y| Point(Coordinate { x: x, y: y }); - let linestring = LineString(vec![p(0., 0.), p(2., 0.), p(2., 2.), p(0., 2.), p(0., 0.)]); + let linestring = LineString::new(vec![p(0., 0.), p(2., 0.), p(2., 2.), p(0., 2.), p(0., 0.)]).unwrap(); let poly = Polygon::new(linestring, Vec::new()); - assert!(!poly.contains(&LineString(vec![p(1., 1.), p(3., 0.)]))); - assert!(!poly.contains(&LineString(vec![p(3., 0.), p(5., 2.)]))); + assert!(!poly.contains(&LineString::new(vec![p(1., 1.), p(3., 0.)]))).unwrap(); + assert!(!poly.contains(&LineString::new(vec![p(3., 0.), p(5., 2.)]))).unwrap(); } #[test] fn linestring_in_inner_polygon_test() { let p = |x, y| Point(Coordinate { x: x, y: y }); - let poly = Polygon::new(LineString(vec![p(0., 0.), p(5., 0.), p(5., 6.), p(0., 6.), p(0., 0.)]), - vec![LineString(vec![p(1., 1.), p(4., 1.), p(4., 4.), p(1., 4.), p(1., 1.)])]); - assert!(!poly.contains(&LineString(vec![p(2., 2.), p(3., 3.)]))); - assert!(!poly.contains(&LineString(vec![p(2., 2.), p(2., 5.)]))); - assert!(!poly.contains(&LineString(vec![p(3., 0.5), p(3., 5.)]))); + let poly = Polygon::new(LineString::new(vec![p(0., 0.), p(5., 0.), p(5., 6.), p(0., 6.), p(0., 0.)]).unwrap(), + vec![LineString::new(vec![p(1., 1.), p(4., 1.), p(4., 4.), p(1., 4.), p(1., 1.)])]).unwrap(); + assert!(!poly.contains(&LineString::new(vec![p(2., 2.), p(3., 3.)]))).unwrap(); + assert!(!poly.contains(&LineString::new(vec![p(2., 2.), p(2., 5.)]))).unwrap(); + assert!(!poly.contains(&LineString::new(vec![p(3., 0.5), p(3., 5.)]))).unwrap(); } #[test] fn bbox_in_inner_bbox_test() { @@ -444,13 +444,13 @@ mod test { let p = |x, y| Point(Coordinate { x: x, y: y }); let line = Line::new(p(0., 1.), p(3., 4.)); // linestring0 in line - let linestring0 = LineString(vec![p(0.1, 1.1), p(1., 2.), p(1.5, 2.5)]); + let linestring0 = LineString::new(vec![p(0.1, 1.1), p(1., 2.), p(1.5, 2.5)]).unwrap(); // linestring1 starts and ends in line, but wanders in the middle - let linestring1 = LineString(vec![p(0.1, 1.1), p(2., 2.), p(1.5, 2.5)]); + let linestring1 = LineString::new(vec![p(0.1, 1.1), p(2., 2.), p(1.5, 2.5)]).unwrap(); // linestring2 is co-linear, but extends beyond line - let linestring2 = LineString(vec![p(0.1, 1.1), p(1., 2.), p(4., 5.)]); + let linestring2 = LineString::new(vec![p(0.1, 1.1), p(1., 2.), p(4., 5.)]).unwrap(); // no part of linestring3 is contained in line - let linestring3 = LineString(vec![p(1.1, 1.1), p(2., 2.), p(2.5, 2.5)]); + let linestring3 = LineString::new(vec![p(1.1, 1.1), p(2., 2.), p(2.5, 2.5)]).unwrap(); assert!(line.contains(&linestring0)); assert!(!line.contains(&linestring1)); assert!(!line.contains(&linestring2)); @@ -460,9 +460,9 @@ mod test { fn line_in_polygon_test() { let p = |x, y| Point(Coordinate { x: x, y: y }); let line = Line::new(p(0., 1.), p(3., 4.)); - let linestring0 = LineString(vec![p(-1., 0.), p(5., 0.), p(5., 5.), p(0., 5.), p(-1., 0.)]); + let linestring0 = LineString::new(vec![p(-1., 0.), p(5., 0.), p(5., 5.), p(0., 5.), p(-1., 0.)]).unwrap(); let poly0 = Polygon::new(linestring0, Vec::new()); - let linestring1 = LineString(vec![p(0., 0.), p(0., 2.), p(2., 2.), p(2., 0.), p(0., 0.)]); + let linestring1 = LineString::new(vec![p(0., 0.), p(0., 2.), p(2., 2.), p(2., 0.), p(0., 0.)]).unwrap(); let poly1 = Polygon::new(linestring1, Vec::new()); assert!(poly0.contains(&line)); assert!(!poly1.contains(&line)); @@ -471,14 +471,14 @@ mod test { fn line_in_linestring_test() { let line0 = Line::new(Point::new(1., 1.), Point::new(2., 2.)); // line0 is completely contained in the second segment - let linestring0 = LineString(vec![Point::new(0., 0.5), Point::new(0.5, 0.5), + let linestring0 = LineString::new(vec![Point::new(0., 0.5), Point::new(0.5, 0.5).unwrap(), Point::new(3., 3.)]); // line0 is contained in the last three segments - let linestring1 = LineString(vec![Point::new(0., 0.5), Point::new(0.5, 0.5), + let linestring1 = LineString::new(vec![Point::new(0., 0.5), Point::new(0.5, 0.5).unwrap(), Point::new(1.2, 1.2), Point::new(1.5, 1.5), Point::new(3., 3.)]); // line0 endpoints are contained in the linestring, but the fourth point is off the line - let linestring2 = LineString(vec![Point::new(0., 0.5), Point::new(0.5, 0.5), + let linestring2 = LineString::new(vec![Point::new(0., 0.5), Point::new(0.5, 0.5).unwrap(), Point::new(1.2, 1.2), Point::new(1.5, 0.), Point::new(2., 2.), Point::new(3., 3.)]); assert!(linestring0.contains(&line0)); diff --git a/src/algorithm/convexhull.rs b/src/algorithm/convexhull.rs index 1ca49c337..7e47e6926 100644 --- a/src/algorithm/convexhull.rs +++ b/src/algorithm/convexhull.rs @@ -148,12 +148,12 @@ pub trait ConvexHull { /// use geo::convexhull::ConvexHull; /// // an L shape /// let coords = vec![(0.0, 0.0), (4.0, 0.0), (4.0, 1.0), (1.0, 1.0), (1.0, 4.0), (0.0, 4.0), (0.0, 0.0)]; - /// let ls = LineString(coords.iter().map(|e| Point::new(e.0, e.1)).collect()); + /// let ls = LineString::new(coords.iter().map(|e| Point::new(e.0, e.1)).collect()).unwrap(); /// let poly = Polygon::new(ls, vec![]); /// /// // The correct convex hull coordinates /// let hull_coords = vec![(4.0, 0.0), (4.0, 1.0), (1.0, 4.0), (0.0, 4.0), (0.0, 0.0), (4.0, 0.0)]; - /// let correct_hull = LineString(hull_coords.iter().map(|e| Point::new(e.0, e.1)).collect()); + /// let correct_hull = LineString::new(hull_coords.iter().map(|e| Point::new(e.0, e.1)).collect()).unwrap(); /// /// let res = poly.convex_hull(); /// assert_eq!(res.exterior, correct_hull); @@ -320,7 +320,7 @@ mod test { Point::new(-10.0, 0.0), Point::new(-1.0, 1.0), Point::new(0.0, 10.0)]; - let mp = LineString(v); + let mp = LineString::new(v).unwrap(); let correct = vec![ Point::new(0.0, -10.0), Point::new(10.0, 0.0), @@ -332,9 +332,9 @@ mod test { } #[test] fn quick_hull_multilinestring_test() { - let v1 = LineString(vec![Point::new(0.0, 0.0), Point::new(1.0, 10.0)]); - let v2 = LineString(vec![Point::new(1.0, 10.0), Point::new(2.0, 0.0), Point::new(3.0, 1.0)]); - let mls = MultiLineString(vec![v1, v2]); + let v1 = LineString::new(vec![Point::new(0.0, 0.0), Point::new(1.0, 10.0)]).unwrap(); + let v2 = LineString::new(vec![Point::new(1.0, 10.0), Point::new(2.0, 0.0), Point::new(3.0, 1.0)]).unwrap(); + let mls = MultiLineString::new(vec![v1, v2]).unwrap(); let correct = vec![ Point::new(2.0, 0.0), Point::new(3.0, 1.0), @@ -346,8 +346,8 @@ mod test { } #[test] fn quick_hull_multipolygon_test() { - let ls1 = LineString(vec![Point::new(0.0, 0.0), Point::new(1.0, 10.0), Point::new(2.0, 0.0), Point::new(0.0, 0.0)]); - let ls2 = LineString(vec![Point::new(3.0, 0.0), Point::new(4.0, 10.0), Point::new(5.0, 0.0), Point::new(3.0, 0.0)]); + let ls1 = LineString::new(vec![Point::new(0.0, 0.0), Point::new(1.0, 10.0), Point::new(2.0, 0.0), Point::new(0.0, 0.0)]).unwrap(); + let ls2 = LineString::new(vec![Point::new(3.0, 0.0), Point::new(4.0, 10.0), Point::new(5.0, 0.0), Point::new(3.0, 0.0)]).unwrap(); let p1 = Polygon::new(ls1, vec![]); let p2 = Polygon::new(ls2, vec![]); let mp = MultiPolygon(vec![p1, p2]); diff --git a/src/algorithm/distance.rs b/src/algorithm/distance.rs index 9580bd209..a468de5ea 100644 --- a/src/algorithm/distance.rs +++ b/src/algorithm/distance.rs @@ -38,7 +38,7 @@ pub trait Distance { /// (6., 1.), /// (5., 1.) /// ]; - /// let ls = LineString(points.iter().map(|e| Point::new(e.0, e.1)).collect()); + /// let ls = LineString::new(points.iter().map(|e| Point::new(e.0, e.1)).collect()).unwrap(); /// let poly = Polygon::new(ls, vec![]); /// // A Random point outside the polygon /// let p = Point::new(2.5, 0.5); @@ -56,7 +56,7 @@ pub trait Distance { /// (7., 2.), /// (6., 1.), /// ]; - /// let ls = LineString(points.iter().map(|e| Point::new(e.0, e.1)).collect()); + /// let ls = LineString::new(points.iter().map(|e| Point::new(e.0, e.1)).collect()).unwrap(); /// // A Random point outside the LineString /// let p = Point::new(5.5, 2.1); /// let dist = p.distance(&ls); @@ -315,7 +315,7 @@ mod test { (6., 1.), (5., 1.), ]; - let ls = LineString(points.iter().map(|e| Point::new(e.0, e.1)).collect()); + let ls = LineString::new(points.iter().map(|e| Point::new(e.0, e.1)).collect()).unwrap(); let poly = Polygon::new(ls, vec![]); // A Random point outside the octagon let p = Point::new(2.5, 0.5); @@ -337,7 +337,7 @@ mod test { (6., 1.), (5., 1.), ]; - let ls = LineString(points.iter().map(|e| Point::new(e.0, e.1)).collect()); + let ls = LineString::new(points.iter().map(|e| Point::new(e.0, e.1)).collect()).unwrap(); let poly = Polygon::new(ls, vec![]); // A Random point inside the octagon let p = Point::new(5.5, 2.1); @@ -359,7 +359,7 @@ mod test { (6., 1.), (5., 1.), ]; - let ls = LineString(points.iter().map(|e| Point::new(e.0, e.1)).collect()); + let ls = LineString::new(points.iter().map(|e| Point::new(e.0, e.1)).collect()).unwrap(); let poly = Polygon::new(ls, vec![]); // A point on the octagon let p = Point::new(5.0, 1.0); @@ -369,13 +369,13 @@ mod test { #[test] // Point to Polygon, on boundary fn flibble() { - let exterior = LineString(vec![ + let exterior = LineString::new(vec![ Point::new(0., 0.), Point::new(0., 0.0004), Point::new(0.0004, 0.0004), Point::new(0.0004, 0.), Point::new(0., 0.), - ]); + ]).unwrap(); let poly = Polygon::new(exterior.clone(), vec![]); let bugged_point = Point::new(0.0001, 0.); @@ -386,7 +386,7 @@ mod test { fn point_polygon_empty_test() { // an empty Polygon let points = vec![]; - let ls = LineString(points); + let ls = LineString::new(points).unwrap(); let poly = Polygon::new(ls, vec![]); // A point on the octagon let p = Point::new(2.5, 0.5); @@ -410,8 +410,8 @@ mod test { ]; // cut out a triangle inside octagon let int_points = vec![(3.5, 3.5), (4.4, 1.5), (2.6, 1.5), (3.5, 3.5)]; - let ls_ext = LineString(ext_points.iter().map(|e| Point::new(e.0, e.1)).collect()); - let ls_int = LineString(int_points.iter().map(|e| Point::new(e.0, e.1)).collect()); + let ls_ext = LineString::new(ext_points.iter().map(|e| Point::new(e.0, e.1)).collect()).unwrap(); + let ls_int = LineString::new(int_points.iter().map(|e| Point::new(e.0, e.1)).collect()).unwrap(); let poly = Polygon::new(ls_ext, vec![ls_int]); // A point inside the cutout triangle let p = Point::new(3.5, 2.5); @@ -421,18 +421,18 @@ mod test { } #[test] fn point_distance_multipolygon_test() { - let ls1 = LineString(vec![ + let ls1 = LineString::new(vec![ Point::new(0.0, 0.0), Point::new(1.0, 10.0), Point::new(2.0, 0.0), Point::new(0.0, 0.0), - ]); - let ls2 = LineString(vec![ + ]).unwrap(); + let ls2 = LineString::new(vec![ Point::new(3.0, 0.0), Point::new(4.0, 10.0), Point::new(5.0, 0.0), Point::new(3.0, 0.0), - ]); + ]).unwrap(); let p1 = Polygon::new(ls1, vec![]); let p2 = Polygon::new(ls2, vec![]); let mp = MultiPolygon(vec![p1, p2]); @@ -453,7 +453,7 @@ mod test { (7., 2.), (6., 1.), ]; - let ls = LineString(points.iter().map(|e| Point::new(e.0, e.1)).collect()); + let ls = LineString::new(points.iter().map(|e| Point::new(e.0, e.1)).collect()).unwrap(); // A Random point "inside" the LineString let p = Point::new(5.5, 2.1); let dist = p.distance(&ls); @@ -473,7 +473,7 @@ mod test { (7., 2.), (6., 1.), ]; - let ls = LineString(points.iter().map(|e| Point::new(e.0, e.1)).collect()); + let ls = LineString::new(points.iter().map(|e| Point::new(e.0, e.1)).collect()).unwrap(); // A point which lies on the LineString let p = Point::new(5.0, 4.0); let dist = p.distance(&ls); @@ -483,7 +483,7 @@ mod test { // Point to LineString, closed triangle fn point_linestring_triangle_test() { let points = vec![(3.5, 3.5), (4.4, 2.0), (2.6, 2.0), (3.5, 3.5)]; - let ls = LineString(points.iter().map(|e| Point::new(e.0, e.1)).collect()); + let ls = LineString::new(points.iter().map(|e| Point::new(e.0, e.1)).collect()).unwrap(); let p = Point::new(3.5, 2.5); let dist = p.distance(&ls); assert_relative_eq!(dist, 0.5); @@ -492,20 +492,20 @@ mod test { // Point to LineString, empty LineString fn point_linestring_empty_test() { let points = vec![]; - let ls = LineString(points); + let ls = LineString::new(points).unwrap(); let p = Point::new(5.0, 4.0); let dist = p.distance(&ls); assert_relative_eq!(dist, 0.0); } #[test] fn distance_multilinestring_test() { - let v1 = LineString(vec![Point::new(0.0, 0.0), Point::new(1.0, 10.0)]); - let v2 = LineString(vec![ + let v1 = LineString::new(vec![Point::new(0.0, 0.0), Point::new(1.0, 10.0)]).unwrap(); + let v2 = LineString::new(vec![ Point::new(1.0, 10.0), Point::new(2.0, 0.0), Point::new(3.0, 1.0), - ]); - let mls = MultiLineString(vec![v1, v2]); + ]).unwrap(); + let mls = MultiLineString::new(vec![v1, v2]).unwrap(); let p = Point::new(50.0, 50.0); assert_relative_eq!(p.distance(&mls), 63.25345840347388); } diff --git a/src/algorithm/extremes.rs b/src/algorithm/extremes.rs index eea8fb1cd..1318f2935 100644 --- a/src/algorithm/extremes.rs +++ b/src/algorithm/extremes.rs @@ -143,7 +143,7 @@ pub trait ExtremeIndices { /// // a diamond shape /// let points_raw = vec![(1.0, 0.0), (2.0, 1.0), (1.0, 2.0), (0.0, 1.0), (1.0, 0.0)]; /// let points = points_raw.iter().map(|e| Point::new(e.0, e.1)).collect::>(); - /// let poly = Polygon::new(LineString(points), vec![]); + /// let poly = Polygon::new(LineString::new(points), vec![]).unwrap(); /// // Polygon is both convex and oriented counter-clockwise /// let extremes = poly.extreme_indices().unwrap(); /// assert_eq!(extremes.ymin, 0); @@ -191,7 +191,7 @@ pub trait ExtremePoints { /// .iter() /// .map(|e| Point::new(e.0, e.1)) /// .collect::>(); - /// let poly1 = Polygon::new(LineString(points), vec![]); + /// let poly1 = Polygon::new(LineString::new(points), vec![]).unwrap(); /// let extremes = poly1.extreme_points(); /// let correct = Point::new(0.0, 1.0); /// assert_eq!(extremes.xmin, correct); @@ -233,7 +233,7 @@ mod test { .iter() .map(|e| Point::new(e.0, e.1)) .collect::>(); - let poly1 = Polygon::new(LineString(points), vec![]); + let poly1 = Polygon::new(LineString::new(points), vec![]).unwrap(); let min_x = polymax_naive_indices(&Point::new(-1., 0.), &poly1).unwrap(); let correct = 3_usize; assert_eq!(min_x, correct); @@ -253,7 +253,7 @@ mod test { .iter() .map(|e| Point::new(e.0, e.1)) .collect::>(); - let poly1 = Polygon::new(LineString(points), vec![]); + let poly1 = Polygon::new(LineString::new(points), vec![]).unwrap(); let extremes = find_extreme_indices(polymax_naive_indices, &poly1).unwrap(); let correct = Extremes { ymin: 0, @@ -277,7 +277,7 @@ mod test { .iter() .map(|e| Point::new(e.0, e.1)) .collect::>(); - let poly1 = Polygon::new(LineString(points), vec![]); + let poly1 = Polygon::new(LineString::new(points), vec![]).unwrap(); let extremes = find_extreme_indices(polymax_naive_indices, &poly1.convex_hull()).unwrap(); let correct = Extremes { ymin: 0, @@ -296,7 +296,7 @@ mod test { .iter() .map(|e| Point::new(e.0, e.1)) .collect::>(); - let poly1 = Polygon::new(LineString(points), vec![]); + let poly1 = Polygon::new(LineString::new(points), vec![]).unwrap(); let extremes = find_extreme_indices(polymax_naive_indices, &poly1.convex_hull()).unwrap(); let correct = Extremes { ymin: 0, @@ -314,7 +314,7 @@ mod test { .iter() .map(|e| Point::new(e.0, e.1)) .collect::>(); - let poly1 = Polygon::new(LineString(points), vec![]); + let poly1 = Polygon::new(LineString::new(points), vec![]).unwrap(); let extremes = poly1.extreme_points(); let correct = Point::new(0.0, 1.0); assert_eq!(extremes.xmin, correct); diff --git a/src/algorithm/intersects.rs b/src/algorithm/intersects.rs index 208d2f640..e08f2726e 100644 --- a/src/algorithm/intersects.rs +++ b/src/algorithm/intersects.rs @@ -12,10 +12,10 @@ pub trait Intersects { /// use geo::algorithm::intersects::Intersects; /// /// let p = |x, y| Point(Coordinate { x: x, y: y }); - /// let linestring = LineString(vec![p(3., 2.), p(7., 6.)]); + /// let linestring = LineString::new(vec![p(3., 2.), p(7., 6.)]).unwrap(); /// - /// assert!(linestring.intersects(&LineString(vec![p(3., 4.), p(8., 4.)]))); - /// assert!(!linestring.intersects(&LineString(vec![p(9., 2.), p(11., 5.)]))); + /// assert!(linestring.intersects(&LineString::new(vec![p(3., 4.), p(8., 4.)]))).unwrap(); + /// assert!(!linestring.intersects(&LineString::new(vec![p(9., 2.), p(11., 5.)]))).unwrap(); /// /// ``` /// @@ -226,79 +226,79 @@ mod test { #[test] fn empty_linestring1_test() { let p = |x, y| Point(Coordinate { x: x, y: y }); - let linestring = LineString(vec![p(3., 2.), p(7., 6.)]); - assert!(!LineString(Vec::new()).intersects(&linestring)); + let linestring = LineString::new(vec![p(3., 2.), p(7., 6.)]).unwrap(); + assert!(!LineString::new(Vec::new()).intersects(&linestring)).unwrap(); } #[test] fn empty_linestring2_test() { let p = |x, y| Point(Coordinate { x: x, y: y }); - let linestring = LineString(vec![p(3., 2.), p(7., 6.)]); - assert!(!linestring.intersects(&LineString(Vec::new()))); + let linestring = LineString::new(vec![p(3., 2.), p(7., 6.)]).unwrap(); + assert!(!linestring.intersects(&LineString::new(Vec::new()))).unwrap(); } #[test] fn empty_all_linestring_test() { - assert!(!LineString::(Vec::new()).intersects(&LineString(Vec::new()))); + assert!(!LineString::::new(Vec::new()).unwrap().intersects(&LineString::new(Vec::new()))).unwrap(); } #[test] fn intersect_linestring_test() { let p = |x, y| Point(Coordinate { x: x, y: y }); - let linestring = LineString(vec![p(3., 2.), p(7., 6.)]); - assert!(linestring.intersects(&LineString(vec![p(3., 4.), p(8., 4.)]))); + let linestring = LineString::new(vec![p(3., 2.), p(7., 6.)]).unwrap(); + assert!(linestring.intersects(&LineString::new(vec![p(3., 4.), p(8., 4.)]))).unwrap(); } #[test] fn parallel_linestrings_test() { let p = |x, y| Point(Coordinate { x: x, y: y }); - let linestring = LineString(vec![p(3., 2.), p(7., 6.)]); - assert!(!linestring.intersects(&LineString(vec![p(3., 1.), p(7., 5.)]))); + let linestring = LineString::new(vec![p(3., 2.), p(7., 6.)]).unwrap(); + assert!(!linestring.intersects(&LineString::new(vec![p(3., 1.), p(7., 5.)]))).unwrap(); } /// Tests: intersection LineString and Polygon #[test] fn linestring_in_polygon_test() { let p = |x, y| Point(Coordinate { x: x, y: y }); - let linestring = LineString(vec![p(0., 0.), p(5., 0.), p(5., 6.), p(0., 6.), p(0., 0.)]); + let linestring = LineString::new(vec![p(0., 0.), p(5., 0.), p(5., 6.), p(0., 6.), p(0., 0.)]).unwrap(); let poly = Polygon::new(linestring, Vec::new()); - assert!(poly.intersects(&LineString(vec![p(2., 2.), p(3., 3.)]))); + assert!(poly.intersects(&LineString::new(vec![p(2., 2.), p(3., 3.)]))).unwrap(); } #[test] fn linestring_on_boundary_polygon_test() { let p = |x, y| Point(Coordinate { x: x, y: y }); - let poly = Polygon::new(LineString(vec![p(0., 0.), p(5., 0.), p(5., 6.), p(0., 6.), p(0., 0.)]), + let poly = Polygon::new(LineString::new(vec![p(0., 0.), p(5., 0.), p(5., 6.), p(0., 6.), p(0., 0.)]).unwrap(), Vec::new()); - assert!(poly.intersects(&LineString(vec![p(0., 0.), p(5., 0.)]))); - assert!(poly.intersects(&LineString(vec![p(5., 0.), p(5., 6.)]))); - assert!(poly.intersects(&LineString(vec![p(5., 6.), p(0., 6.)]))); - assert!(poly.intersects(&LineString(vec![p(0., 6.), p(0., 0.)]))); + assert!(poly.intersects(&LineString::new(vec![p(0., 0.), p(5., 0.)]))).unwrap(); + assert!(poly.intersects(&LineString::new(vec![p(5., 0.), p(5., 6.)]))).unwrap(); + assert!(poly.intersects(&LineString::new(vec![p(5., 6.), p(0., 6.)]))).unwrap(); + assert!(poly.intersects(&LineString::new(vec![p(0., 6.), p(0., 0.)]))).unwrap(); } #[test] fn intersect_linestring_polygon_test() { let p = |x, y| Point(Coordinate { x: x, y: y }); - let poly = Polygon::new(LineString(vec![p(0., 0.), p(5., 0.), p(5., 6.), p(0., 6.), p(0., 0.)]), + let poly = Polygon::new(LineString::new(vec![p(0., 0.), p(5., 0.), p(5., 6.), p(0., 6.), p(0., 0.)]).unwrap(), Vec::new()); - assert!(poly.intersects(&LineString(vec![p(2., 2.), p(6., 6.)]))); + assert!(poly.intersects(&LineString::new(vec![p(2., 2.), p(6., 6.)]))).unwrap(); } #[test] fn linestring_outside_polygon_test() { let p = |x, y| Point(Coordinate { x: x, y: y }); - let poly = Polygon::new(LineString(vec![p(0., 0.), p(5., 0.), p(5., 6.), p(0., 6.), p(0., 0.)]), + let poly = Polygon::new(LineString::new(vec![p(0., 0.), p(5., 0.), p(5., 6.), p(0., 6.), p(0., 0.)]).unwrap(), Vec::new()); - assert!(!poly.intersects(&LineString(vec![p(7., 2.), p(9., 4.)]))); + assert!(!poly.intersects(&LineString::new(vec![p(7., 2.), p(9., 4.)]))).unwrap(); } #[test] fn linestring_in_inner_polygon_test() { let p = |x, y| Point(Coordinate { x: x, y: y }); - let e = LineString(vec![p(0., 0.), p(5., 0.), p(5., 6.), p(0., 6.), p(0., 0.)]); - let v = vec![LineString(vec![p(1., 1.), p(4., 1.), p(4., 4.), p(1., 4.), p(1., 1.)])]; + let e = LineString::new(vec![p(0., 0.), p(5., 0.), p(5., 6.), p(0., 6.), p(0., 0.)]).unwrap(); + let v = vec![LineString::new(vec![p(1., 1.), p(4., 1.), p(4., 4.), p(1., 4.), p(1., 1.)]).unwrap()]; let poly = Polygon::new(e, v); - assert!(!poly.intersects(&LineString(vec![p(2., 2.), p(3., 3.)]))); - assert!(poly.intersects(&LineString(vec![p(2., 2.), p(4., 4.)]))); + assert!(!poly.intersects(&LineString::new(vec![p(2., 2.), p(3., 3.)]))).unwrap(); + assert!(poly.intersects(&LineString::new(vec![p(2., 2.), p(4., 4.)]))).unwrap(); } #[test] fn linestring_traverse_polygon_test() { let p = |x, y| Point(Coordinate { x: x, y: y }); - let e = LineString(vec![p(0., 0.), p(5., 0.), p(5., 6.), p(0., 6.), p(0., 0.)]); - let v = vec![LineString(vec![p(1., 1.), p(4., 1.), p(4., 4.), p(1., 4.), p(1., 1.)])]; + let e = LineString::new(vec![p(0., 0.), p(5., 0.), p(5., 6.), p(0., 6.), p(0., 0.)]).unwrap(); + let v = vec![LineString::new(vec![p(1., 1.), p(4., 1.), p(4., 4.), p(1., 4.), p(1., 1.)]).unwrap()]; let poly = Polygon::new(e, v); - assert!(poly.intersects(&LineString(vec![p(2., 0.5), p(2., 5.)]))); + assert!(poly.intersects(&LineString::new(vec![p(2., 0.5), p(2., 5.)]))).unwrap(); } #[test] fn linestring_in_inner_with_2_inner_polygon_test() { @@ -327,21 +327,21 @@ mod test { // let p = |x, y| Point(Coordinate { x: x, y: y }); - let e = LineString(vec![p(2., 2.), p(14., 2.), p(14., 8.), p(2., 8.), p(2., 2.)]); - let v = vec![LineString(vec![p(4., 3.), p(7., 3.), p(7., 6.), p(4., 6.), p(4., 3.)]), - LineString(vec![p(9., 3.), p(12., 3.), p(12., 6.), p(9., 6.), p(9., 3.)])]; + let e = LineString::new(vec![p(2., 2.), p(14., 2.), p(14., 8.), p(2., 8.), p(2., 2.)]).unwrap(); + let v = vec![LineString::new(vec![p(4., 3.), p(7., 3.), p(7., 6.), p(4., 6.), p(4., 3.)]).unwrap(), + LineString::new(vec![p(9., 3.), p(12., 3.), p(12., 6.), p(9., 6.), p(9., 3.)]).unwrap()]; let poly = Polygon::new(e, v); - assert!(!poly.intersects(&LineString(vec![p(5., 4.), p(6., 5.)]))); - assert!(poly.intersects(&LineString(vec![p(11., 2.5), p(11., 7.)]))); - assert!(poly.intersects(&LineString(vec![p(4., 7.), p(6., 7.)]))); - assert!(poly.intersects(&LineString(vec![p(8., 1.), p(8., 9.)]))); + assert!(!poly.intersects(&LineString::new(vec![p(5., 4.), p(6., 5.)]))).unwrap(); + assert!(poly.intersects(&LineString::new(vec![p(11., 2.5), p(11., 7.)]))).unwrap(); + assert!(poly.intersects(&LineString::new(vec![p(4., 7.), p(6., 7.)]))).unwrap(); + assert!(poly.intersects(&LineString::new(vec![p(8., 1.), p(8., 9.)]))).unwrap(); } #[test] fn polygons_do_not_intersect() { let p = |x, y| Point(Coordinate { x: x, y: y }); - let p1 = Polygon::new(LineString(vec![p(1., 3.), p(3., 3.), p(3., 5.), p(1., 5.), p(1., 3.)]), + let p1 = Polygon::new(LineString::new(vec![p(1., 3.), p(3., 3.), p(3., 5.), p(1., 5.), p(1., 3.)]).unwrap(), Vec::new()); - let p2 = Polygon::new(LineString(vec![p(10., 30.), p(30., 30.), p(30., 50.), p(10., 50.), p(10., 30.)]), + let p2 = Polygon::new(LineString::new(vec![p(10., 30.), p(30., 30.), p(30., 50.), p(10., 50.), p(10., 30.)]).unwrap(), Vec::new()); assert!(!p1.intersects(&p2)); @@ -350,9 +350,9 @@ mod test { #[test] fn polygons_overlap() { let p = |x, y| Point(Coordinate { x: x, y: y }); - let p1 = Polygon::new(LineString(vec![p(1., 3.), p(3., 3.), p(3., 5.), p(1., 5.), p(1., 3.)]), + let p1 = Polygon::new(LineString::new(vec![p(1., 3.), p(3., 3.), p(3., 5.), p(1., 5.), p(1., 3.)]).unwrap(), Vec::new()); - let p2 = Polygon::new(LineString(vec![p(2., 3.), p(4., 3.), p(4., 7.), p(2., 7.), p(2., 3.)]), + let p2 = Polygon::new(LineString::new(vec![p(2., 3.), p(4., 3.), p(4., 7.), p(2., 7.), p(2., 3.)]).unwrap(), Vec::new()); assert!(p1.intersects(&p2)); @@ -361,9 +361,9 @@ mod test { #[test] fn polygon_contained() { let p = |x, y| Point(Coordinate { x: x, y: y }); - let p1 = Polygon::new(LineString(vec![p(1., 3.), p(4., 3.), p(4., 6.), p(1., 6.), p(1., 3.)]), + let p1 = Polygon::new(LineString::new(vec![p(1., 3.), p(4., 3.), p(4., 6.), p(1., 6.), p(1., 3.)]).unwrap(), Vec::new()); - let p2 = Polygon::new(LineString(vec![p(2., 4.), p(3., 4.), p(3., 5.), p(2., 5.), p(2., 4.)]), + let p2 = Polygon::new(LineString::new(vec![p(2., 4.), p(3., 4.), p(3., 5.), p(2., 5.), p(2., 4.)]).unwrap(), Vec::new()); assert!(p1.intersects(&p2)); @@ -372,9 +372,9 @@ mod test { #[test] fn polygons_conincident() { let p = |x, y| Point(Coordinate { x: x, y: y }); - let p1 = Polygon::new(LineString(vec![p(1., 3.), p(4., 3.), p(4., 6.), p(1., 6.), p(1., 3.)]), + let p1 = Polygon::new(LineString::new(vec![p(1., 3.), p(4., 3.), p(4., 6.), p(1., 6.), p(1., 3.)]).unwrap(), Vec::new()); - let p2 = Polygon::new(LineString(vec![p(1., 3.), p(4., 3.), p(4., 6.), p(1., 6.), p(1., 3.)]), + let p2 = Polygon::new(LineString::new(vec![p(1., 3.), p(4., 3.), p(4., 6.), p(1., 6.), p(1., 3.)]).unwrap(), Vec::new()); assert!(p1.intersects(&p2)); @@ -402,8 +402,8 @@ mod test { // └──────────────────────┘ // (0,0) (12,0) let p = |x, y| Point(Coordinate { x: x, y: y }); - let poly = Polygon::new(LineString(vec![p(0., 0.), p(12., 0.), p(12., 8.), p(0., 8.), p(0., 0.)]), - vec![LineString(vec![p(7., 4.), p(11., 4.), p(11., 7.), p(7., 7.), p(7., 4.)])]); + let poly = Polygon::new(LineString::new(vec![p(0., 0.), p(12., 0.), p(12., 8.), p(0., 8.), p(0., 0.)]).unwrap(), + vec![LineString::new(vec![p(7., 4.), p(11., 4.), p(11., 7.), p(7., 7.), p(7., 4.)])]).unwrap(); let b1 = Bbox { xmin: 11.0, xmax: 13.0, ymin: 1.0, ymax: 2.0 }; let b2 = Bbox { xmin: 2.0, xmax: 8.0, ymin: 2.0, ymax: 5.0 }; let b3 = Bbox { xmin: 8.0, xmax: 10.0, ymin: 5.0, ymax: 6.0 }; @@ -488,12 +488,12 @@ mod test { #[test] fn line_intersects_linestring_test() { let line0 = Line::new(Point::new(0., 0.), Point::new(3., 4.)); - let linestring0 = LineString( + let linestring0 = LineString::new( vec![Point::new(0., 1.), Point::new(1., 0.), Point::new(2., 0.)] - ); - let linestring1 = LineString( + ).unwrap(); + let linestring1 = LineString::new( vec![Point::new(0.5, 0.2), Point::new(1., 0.), Point::new(2., 0.)] - ); + ).unwrap(); assert!(line0.intersects(&linestring0)); assert!(!line0.intersects(&linestring1)); assert!(linestring0.intersects(&line0)); @@ -503,20 +503,20 @@ mod test { fn line_intersects_polygon_test() { let line0 = Line::new(Point::new(0.5, 0.5), Point::new(2., 1.)); let poly0 = Polygon::new( - LineString(vec![Point::new(0.,0.), Point::new(1., 2.), + LineString::new(vec![Point::new(0.,0.), Point::new(1., 2.).unwrap(), Point::new(1., 0.), Point::new(0., 0.)]), vec![] ); let poly1 = Polygon::new( - LineString(vec![Point::new(1., -1.), Point::new(2., -1.), + LineString::new(vec![Point::new(1., -1.), Point::new(2., -1.).unwrap(), Point::new(2., -2.), Point::new(1., -1.)]), vec![] ); // line contained in the hole let poly2 = Polygon::new( - LineString(vec![Point::new(-1., -1.), Point::new(-1., 10.), + LineString::new(vec![Point::new(-1., -1.), Point::new(-1., 10.).unwrap(), Point::new(10., -1.), Point::new(-1., -1.)]), - vec![LineString(vec![Point::new(0., 0.), Point::new(3., 4.), + vec![LineString::new(vec![Point::new(0., 0.), Point::new(3., 4.).unwrap(), Point::new(3., 0.), Point::new(0., 0.)])] ); assert!(line0.intersects(&poly0)); diff --git a/src/algorithm/length.rs b/src/algorithm/length.rs index 3e76e05ac..39fbf0703 100644 --- a/src/algorithm/length.rs +++ b/src/algorithm/length.rs @@ -15,7 +15,7 @@ pub trait Length { /// let mut vec = Vec::new(); /// vec.push(Point::new(40.02f64, 116.34)); /// vec.push(Point::new(42.02f64, 116.34)); - /// let linestring = LineString(vec); + /// let linestring = LineString::new(vec).unwrap(); /// /// println!("Length {}", linestring.length()); /// ``` @@ -56,25 +56,25 @@ mod test { #[test] fn empty_linestring_test() { - let linestring = LineString::(Vec::new()); + let linestring = LineString::::new(Vec::new()).unwrap(); assert_eq!(0.0_f64, linestring.length()); } #[test] fn linestring_one_point_test() { - let linestring = LineString(vec![Point::new(0., 0.)]); + let linestring = LineString::new(vec![Point::new(0., 0.)]).unwrap(); assert_eq!(0.0_f64, linestring.length()); } #[test] fn linestring_test() { let p = |x| Point(Coordinate { x: x, y: 1. }); - let linestring = LineString(vec![p(1.), p(7.), p(8.), p(9.), p(10.), p(11.)]); + let linestring = LineString::new(vec![p(1.), p(7.), p(8.), p(9.), p(10.), p(11.)]).unwrap(); assert_eq!(10.0_f64, linestring.length()); } #[test] fn multilinestring_test() { let p = |x, y| Point(Coordinate { x: x, y: y }); - let mline = MultiLineString(vec![LineString(vec![p(1., 0.), p(7., 0.), p(8., 0.), p(9., 0.), p(10., 0.), p(11., 0.)]), - LineString(vec![p(0., 0.), p(0., 5.)])]); + let mline = MultiLineString(vec![LineString::new(vec![p(1., 0.), p(7., 0.), p(8., 0.), p(9., 0.), p(10., 0.), p(11., 0.)]).unwrap(), + LineString::new(vec![p(0., 0.), p(0., 5.)])]).unwrap(); assert_eq!(15.0_f64, mline.length()); } #[test] diff --git a/src/algorithm/map_coords.rs b/src/algorithm/map_coords.rs index 48d5a9632..2cca3a5d1 100644 --- a/src/algorithm/map_coords.rs +++ b/src/algorithm/map_coords.rs @@ -150,7 +150,7 @@ mod test { #[test] fn linestring() { - let line1: LineString = LineString(vec![Point::new(0., 0.), Point::new(1., 2.)]); + let line1: LineString = LineString::new(vec![Point::new(0., 0.), Point::new(1., 2.)]).unwrap(); let line2 = line1.map_coords(&|&(x, y)| (x+10., y-100.)); assert_eq!(line2.0[0], Point::new(10., -100.)); assert_eq!(line2.0[1], Point::new(11., -98.)); @@ -158,17 +158,17 @@ mod test { #[test] fn polygon() { - let exterior = LineString(vec![Point::new(0., 0.), Point::new(1., 1.), + let exterior = LineString::new(vec![Point::new(0., 0.), Point::new(1., 1.).unwrap(), Point::new(1., 0.), Point::new(0., 0.)]); - let interiors = vec![LineString(vec![Point::new(0.1, 0.1), Point::new(0.9, 0.9), + let interiors = vec![LineString::new(vec![Point::new(0.1, 0.1), Point::new(0.9, 0.9).unwrap(), Point::new(0.9, 0.1), Point::new(0.1, 0.1)])]; let p = Polygon::new(exterior, interiors); let p2 = p.map_coords(&|&(x, y)| (x+10., y-100.)); - let exterior2 = LineString(vec![Point::new(10., -100.), Point::new(11., -99.), + let exterior2 = LineString::new(vec![Point::new(10., -100.), Point::new(11., -99.).unwrap(), Point::new(11., -100.), Point::new(10., -100.)]); - let interiors2 = vec![LineString(vec![Point::new(10.1, -99.9), Point::new(10.9, -99.1), + let interiors2 = vec![LineString::new(vec![Point::new(10.1, -99.9), Point::new(10.9, -99.1).unwrap(), Point::new(10.9, -99.9), Point::new(10.1, -99.9)])]; let expected_p2 = Polygon::new(exterior2, interiors2); @@ -189,14 +189,14 @@ mod test { #[test] fn multilinestring() { - let line1: LineString = LineString(vec![Point::new(0., 0.), Point::new(1., 2.)]); - let line2: LineString = LineString(vec![Point::new(-1., 0.), Point::new(0., 0.), Point::new(1., 2.)]); - let mline = MultiLineString(vec![line1, line2]); + let line1: LineString = LineString::new(vec![Point::new(0., 0.), Point::new(1., 2.)]).unwrap(); + let line2: LineString = LineString::new(vec![Point::new(-1., 0.), Point::new(0., 0.), Point::new(1., 2.)]).unwrap(); + let mline = MultiLineString::new(vec![line1, line2]).unwrap(); let mline2 = mline.map_coords(&|&(x, y)| (x+10., y-100.)); assert_eq!(mline2, MultiLineString(vec![ - LineString(vec![Point::new(10., -100.), Point::new(11., -98.)]), - LineString(vec![Point::new(9., -100.), Point::new(10., -100.), Point::new(11., -98.)]), + LineString::new(vec![Point::new(10., -100.), Point::new(11., -98.)]).unwrap(), + LineString::new(vec![Point::new(9., -100.), Point::new(10., -100.), Point::new(11., -98.)]).unwrap(), ]) ); @@ -204,24 +204,24 @@ mod test { #[test] fn multipolygon() { - let poly1 = Polygon::new(LineString(vec![Point::new(0., 0.), Point::new(10., 0.), Point::new(10., 10.), Point::new(0., 10.), Point::new(0., 0.)]), vec![]); + let poly1 = Polygon::new(LineString::new(vec![Point::new(0., 0.), Point::new(10., 0.), Point::new(10., 10.), Point::new(0., 10.), Point::new(0., 0.)]), vec![]).unwrap(); let poly2 = Polygon::new( - LineString(vec![Point::new(11., 11.), Point::new(20., 11.), Point::new(20., 20.), Point::new(11., 20.), Point::new(11., 11.)]), + LineString::new(vec![Point::new(11., 11.), Point::new(20., 11.), Point::new(20., 20.), Point::new(11., 20.), Point::new(11., 11.)]).unwrap(), vec![ - LineString(vec![Point::new(13., 13.), Point::new(13., 17.), Point::new(17., 17.), Point::new(17., 13.), Point::new(13., 13.)]) + LineString::new(vec![Point::new(13., 13.), Point::new(13., 17.), Point::new(17., 17.), Point::new(17., 13.), Point::new(13., 13.)]).unwrap() ]); let mp = MultiPolygon(vec![poly1, poly2]); let mp2 = mp.map_coords(&|&(x, y)| (x*2., y+100.)); assert_eq!(mp2.0.len(), 2); assert_eq!(mp2.0[0], - Polygon::new(LineString(vec![Point::new(0., 100.), Point::new(20., 100.), Point::new(20., 110.), Point::new(0., 110.), Point::new(0., 100.)]), vec![]) + Polygon::new(LineString::new(vec![Point::new(0., 100.), Point::new(20., 100.), Point::new(20., 110.), Point::new(0., 110.), Point::new(0., 100.)]), vec![]).unwrap() ); assert_eq!(mp2.0[1], Polygon::new( - LineString(vec![Point::new(22., 111.), Point::new(40., 111.), Point::new(40., 120.), Point::new(22., 120.), Point::new(22., 111.)]), + LineString::new(vec![Point::new(22., 111.), Point::new(40., 111.), Point::new(40., 120.), Point::new(22., 120.), Point::new(22., 111.)]).unwrap(), vec![ - LineString(vec![Point::new(26., 113.), Point::new(26., 117.), Point::new(34., 117.), Point::new(34., 113.), Point::new(26., 113.)]) + LineString::new(vec![Point::new(26., 113.), Point::new(26., 117.), Point::new(34., 117.), Point::new(34., 113.), Point::new(26., 113.)]).unwrap() ]) ); } @@ -229,14 +229,14 @@ mod test { #[test] fn geometrycollection() { let p1 = Geometry::Point(Point::new(10., 10.)); - let line1 = Geometry::LineString(LineString(vec![Point::new(0., 0.), Point::new(1., 2.)])); + let line1 = Geometry::LineString(LineString::new(vec![Point::new(0., 0.), Point::new(1., 2.)]).unwrap()); let gc = GeometryCollection(vec![p1, line1]); assert_eq!(gc.map_coords(&|&(x, y)| (x+10., y+100.)), GeometryCollection(vec![ Geometry::Point(Point::new(20., 110.)), - Geometry::LineString(LineString(vec![Point::new(10., 100.), Point::new(11., 102.)])), + Geometry::LineString(LineString::new(vec![Point::new(10., 100.), Point::new(11., 102.)]).unwrap()), ]) ); } diff --git a/src/algorithm/orient.rs b/src/algorithm/orient.rs index 10132ba8b..38012afc1 100644 --- a/src/algorithm/orient.rs +++ b/src/algorithm/orient.rs @@ -117,19 +117,19 @@ mod test { .iter() .map(|e| Point::new(e.0, e.1)) .collect::>(); - let poly1 = Polygon::new(LineString(points_ext), vec![LineString(points_int)]); + let poly1 = Polygon::new(LineString::new(points_ext).unwrap(), vec![LineString::new(points_int).unwrap()]); // a diamond shape, oriented counter-clockwise outside, let oriented_ext = vec![(1.0, 0.0), (2.0, 1.0), (1.0, 2.0), (0.0, 1.0), (1.0, 0.0)]; - let oriented_ext_ls = LineString(oriented_ext + let oriented_ext_ls = LineString::new(oriented_ext .iter() .map(|e| Point::new(e.0, e.1)) - .collect::>()); + .collect::>()).unwrap(); // clockwise interior let oriented_int_raw = vec![(1.0, 0.5), (0.5, 1.0), (1.0, 1.5), (1.5, 1.0), (1.0, 0.5)]; - let oriented_int_ls = LineString(oriented_int_raw + let oriented_int_ls = LineString::new(oriented_int_raw .iter() .map(|e| Point::new(e.0, e.1)) - .collect::>()); + .collect::>()).unwrap(); // build corrected Polygon let oriented = orient(&poly1, Direction::Default); assert_eq!(oriented.exterior.0, oriented_ext_ls.0); diff --git a/src/algorithm/rotate.rs b/src/algorithm/rotate.rs index 515fa9590..35a032a08 100644 --- a/src/algorithm/rotate.rs +++ b/src/algorithm/rotate.rs @@ -40,13 +40,13 @@ pub trait Rotate { /// vec.push(Point::new(0.0, 0.0)); /// vec.push(Point::new(5.0, 5.0)); /// vec.push(Point::new(10.0, 10.0)); - /// let linestring = LineString(vec); + /// let linestring = LineString::new(vec).unwrap(); /// let rotated = linestring.rotate(-45.0); /// let mut correct = Vec::new(); /// correct.push(Point::new(-2.0710678118654755, 5.0)); /// correct.push(Point::new(5.0, 5.0)); /// correct.push(Point::new(12.071067811865476, 5.0)); - /// let correct_ls = LineString(correct); + /// let correct_ls = LineString::new(correct).unwrap(); /// assert_eq!(rotated, correct_ls); /// ``` fn rotate(&self, angle: T) -> Self @@ -67,13 +67,13 @@ pub trait RotatePoint { /// vec.push(Point::new(0.0, 0.0)); /// vec.push(Point::new(5.0, 5.0)); /// vec.push(Point::new(10.0, 10.0)); - /// let linestring = LineString(vec); + /// let linestring = LineString::new(vec).unwrap(); /// let rotated = linestring.rotate_around_point(-45.0, &Point::new(10.0, 0.0)); /// let mut correct = Vec::new(); /// correct.push(Point::new(2.9289321881345245, 7.071067811865475)); /// correct.push(Point::new(10.0, 7.0710678118654755)); /// correct.push(Point::new(17.071067811865476, 7.0710678118654755)); - /// let correct_ls = LineString(correct); + /// let correct_ls = LineString::new(correct).unwrap(); /// assert_eq!(rotated, correct_ls); /// ``` fn rotate_around_point(&self, angle: T, point: &Point) -> Self @@ -206,13 +206,13 @@ mod test { vec.push(Point::new(0.0, 0.0)); vec.push(Point::new(5.0, 5.0)); vec.push(Point::new(10.0, 10.0)); - let linestring = LineString(vec); + let linestring = LineString::new(vec).unwrap(); let rotated = linestring.rotate(-45.0); let mut correct = Vec::new(); correct.push(Point::new(-2.0710678118654755, 5.0)); correct.push(Point::new(5.0, 5.0)); correct.push(Point::new(12.071067811865476, 5.0)); - let correct_ls = LineString(correct); + let correct_ls = LineString::new(correct).unwrap(); // results agree with Shapely / GEOS assert_eq!(rotated, correct_ls); } @@ -233,7 +233,7 @@ mod test { .iter() .map(|e| Point::new(e.0, e.1)) .collect::>(); - let poly1 = Polygon::new(LineString(points), vec![]); + let poly1 = Polygon::new(LineString::new(points), vec![]).unwrap(); let rotated = poly1.rotate(-15.0); let correct_outside = vec![ (4.628808519201685, 1.1805207831176578), @@ -247,12 +247,12 @@ mod test { (4.628808519201685, 1.1805207831176578), ]; let correct = Polygon::new( - LineString( + LineString::new( correct_outside .iter() .map(|e| Point::new(e.0, e.1)) .collect::>(), - ), + ).unwrap(), vec![], ); // results agree with Shapely / GEOS @@ -260,7 +260,7 @@ mod test { } #[test] fn test_rotate_polygon_holes() { - let ls1 = LineString(vec![ + let ls1 = LineString::new(vec![ Point::new(5.0, 1.0), Point::new(4.0, 2.0), Point::new(4.0, 3.0), @@ -270,21 +270,21 @@ mod test { Point::new(7.0, 2.0), Point::new(6.0, 1.0), Point::new(5.0, 1.0), - ]); + ]).unwrap(); - let ls2 = LineString(vec![ + let ls2 = LineString::new(vec![ Point::new(5.0, 1.3), Point::new(5.5, 2.0), Point::new(6.0, 1.3), Point::new(5.0, 1.3), - ]); + ]).unwrap(); - let ls3 = LineString(vec![ + let ls3 = LineString::new(vec![ Point::new(5., 2.3), Point::new(5.5, 3.0), Point::new(6., 2.3), Point::new(5., 2.3), - ]); + ]).unwrap(); let poly1 = Polygon::new(ls1, vec![ls2, ls3]); let rotated = poly1.rotate(-15.0); diff --git a/src/algorithm/simplify.rs b/src/algorithm/simplify.rs index add4b29b8..568597a8b 100644 --- a/src/algorithm/simplify.rs +++ b/src/algorithm/simplify.rs @@ -68,13 +68,13 @@ pub trait Simplify { /// vec.push(Point::new(11.0, 5.5)); /// vec.push(Point::new(17.3, 3.2)); /// vec.push(Point::new(27.8, 0.1)); - /// let linestring = LineString(vec); + /// let linestring = LineString::new(vec).unwrap(); /// let mut compare = Vec::new(); /// compare.push(Point::new(0.0, 0.0)); /// compare.push(Point::new(5.0, 4.0)); /// compare.push(Point::new(11.0, 5.5)); /// compare.push(Point::new(27.8, 0.1)); - /// let ls_compare = LineString(compare); + /// let ls_compare = LineString::new(compare).unwrap(); /// let simplified = linestring.simplify(&1.0); /// assert_eq!(simplified, ls_compare) /// ``` @@ -164,68 +164,68 @@ mod test { #[test] fn multilinestring() { - let mline = MultiLineString(vec![LineString(vec![ + let mline = MultiLineString(vec![LineString::new(vec![ Point::new(0.0, 0.0), Point::new(5.0, 4.0), Point::new(11.0, 5.5), Point::new(17.3, 3.2), Point::new(27.8, 0.1), - ])]); + ]).unwrap()]); let mline2 = mline.simplify(&1.0); - assert_eq!(mline2, MultiLineString(vec![LineString(vec![ + assert_eq!(mline2, MultiLineString(vec![LineString::new(vec![ Point::new(0.0, 0.0), Point::new(5.0, 4.0), Point::new(11.0, 5.5), Point::new(27.8, 0.1), - ])])); + ]).unwrap()])); } #[test] fn polygon() { - let poly = Polygon::new(LineString(vec![ + let poly = Polygon::new(LineString::new(vec![ Point::new(0., 0.), Point::new(0., 10.), Point::new(5., 11.), Point::new(10., 10.), Point::new(10., 0.), Point::new(0., 0.), - ]), vec![]); + ]).unwrap(), vec![]); let poly2 = poly.simplify(&2.); - assert_eq!(poly2, Polygon::new(LineString(vec![ + assert_eq!(poly2, Polygon::new(LineString::new(vec![ Point::new(0., 0.), Point::new(0., 10.), Point::new(10., 10.), Point::new(10., 0.), Point::new(0., 0.), - ]), vec![]) + ]).unwrap(), vec![]) ); } #[test] fn multipolygon() { - let mpoly = MultiPolygon(vec![Polygon::new(LineString(vec![ + let mpoly = MultiPolygon(vec![Polygon::new(LineString::new(vec![ Point::new(0., 0.), Point::new(0., 10.), Point::new(5., 11.), Point::new(10., 10.), Point::new(10., 0.), Point::new(0., 0.), - ]), vec![])]); + ]).unwrap(), vec![])]); let mpoly2 = mpoly.simplify(&2.); - assert_eq!(mpoly2, MultiPolygon(vec![Polygon::new(LineString(vec![ + assert_eq!(mpoly2, MultiPolygon(vec![Polygon::new(LineString::new(vec![ Point::new(0., 0.), Point::new(0., 10.), Point::new(10., 10.), Point::new(10., 0.), Point::new(0., 0.), - ]), vec![])]) + ]).unwrap(), vec![])]) ); } } diff --git a/src/algorithm/simplifyvw.rs b/src/algorithm/simplifyvw.rs index e9a23fcc1..dbc4a03c4 100644 --- a/src/algorithm/simplifyvw.rs +++ b/src/algorithm/simplifyvw.rs @@ -424,12 +424,12 @@ pub trait SimplifyVW { /// vec.push(Point::new(6.0, 20.0)); /// vec.push(Point::new(7.0, 25.0)); /// vec.push(Point::new(10.0, 10.0)); - /// let linestring = LineString(vec); + /// let linestring = LineString::new(vec).unwrap(); /// let mut compare = Vec::new(); /// compare.push(Point::new(5.0, 2.0)); /// compare.push(Point::new(7.0, 25.0)); /// compare.push(Point::new(10.0, 10.0)); - /// let ls_compare = LineString(compare); + /// let ls_compare = LineString::new(compare).unwrap(); /// let simplified = linestring.simplifyvw(&30.0); /// assert_eq!(simplified, ls_compare) /// ``` @@ -475,7 +475,7 @@ pub trait SimplifyVWPreserve { /// vec.push(Point::new(117., 48.)); /// vec.push(Point::new(300., 40.)); /// vec.push(Point::new(301., 10.)); - /// let linestring = LineString(vec); + /// let linestring = LineString::new(vec).unwrap(); /// let mut compare = Vec::new(); /// compare.push(Point::new(10., 60.)); /// compare.push(Point::new(126., 31.)); @@ -483,7 +483,7 @@ pub trait SimplifyVWPreserve { /// compare.push(Point::new(117., 48.)); /// compare.push(Point::new(300., 40.)); /// compare.push(Point::new(301., 10.)); - /// let ls_compare = LineString(compare); + /// let ls_compare = LineString::new(compare).unwrap(); /// let simplified = linestring.simplifyvw_preserve(&668.6); /// assert_eq!(simplified, ls_compare) /// ``` @@ -680,14 +680,14 @@ mod test { // with the inner ring, which would also trigger removal of outer[1], // leaving the geometry below min_points. It is thus retained. // Inner should also be reduced, but has points == initial_min for the Polygon type - let outer = LineString(vec![ + let outer = LineString::new(vec![ Point::new(-54.4921875, 21.289374355860424), Point::new(-33.5, 56.9449741808516), Point::new(-22.5, 44.08758502824516), Point::new(-19.5, 23.241346102386135), Point::new(-54.4921875, 21.289374355860424), ]); - let inner = LineString(vec![ + let inner = LineString::new(vec![ Point::new(-24.451171875, 35.266685523707665), Point::new(-29.513671875, 47.32027765985069), Point::new(-22.869140625, 43.80817468459856), @@ -704,21 +704,21 @@ mod test { // with the inner ring, which would also trigger removal of outer[1], // leaving the geometry below min_points. It is thus retained. // Inner should be reduced to four points by removing inner[2] - let outer = LineString(vec![ + let outer = LineString::new(vec![ Point::new(-54.4921875, 21.289374355860424), Point::new(-33.5, 56.9449741808516), Point::new(-22.5, 44.08758502824516), Point::new(-19.5, 23.241346102386135), Point::new(-54.4921875, 21.289374355860424), - ]); - let inner = LineString(vec![ + ]).unwrap(); + let inner = LineString::new(vec![ Point::new(-24.451171875, 35.266685523707665), Point::new(-40.0, 45.), Point::new(-29.513671875, 47.32027765985069), Point::new(-22.869140625, 43.80817468459856), Point::new(-24.451171875, 35.266685523707665), - ]); - let correct_inner = LineString(vec![ + ]).unwrap(); + let correct_inner = LineString::new(vec![ Point::new(-24.451171875, 35.266685523707665), Point::new(-40.0, 45.0), Point::new(-22.869140625, 43.80817468459856), @@ -759,8 +759,8 @@ mod test { let points_ls: Vec<_> = points.iter().map(|e| Point::new(e[0], e[1])).collect(); let correct = include!("test_fixtures/vw_simplified.rs"); let correct_ls: Vec<_> = correct.iter().map(|e| Point::new(e[0], e[1])).collect(); - let simplified = LineString(points_ls).simplifyvw_preserve(&0.0005); - assert_eq!(simplified, LineString(correct_ls)); + let simplified = LineString::new(points_ls).simplifyvw_preserve(&0.0005).unwrap(); + assert_eq!(simplified, LineString::new(correct_ls)).unwrap(); } #[test] fn visvalingam_test_empty_linestring() { @@ -796,24 +796,24 @@ mod test { let correct = vec![(5.0, 2.0), (7.0, 25.0), (10.0, 10.0)]; let correct_ls: Vec<_> = correct.iter().map(|e| Point::new(e.0, e.1)).collect(); - let mline = MultiLineString(vec![LineString(points_ls)]); + let mline = MultiLineString::new(vec![LineString::new(points_ls).unwrap()]).unwrap(); assert_eq!( mline.simplifyvw(&30.), - MultiLineString(vec![LineString(correct_ls)]) + MultiLineString::new(vec![LineString::new(correct_ls).unwrap()]).unwrap() ); } #[test] fn polygon() { let poly = Polygon::new( - LineString(vec![ + LineString::new(vec![ Point::new(0., 0.), Point::new(0., 10.), Point::new(5., 11.), Point::new(10., 10.), Point::new(10., 0.), Point::new(0., 0.), - ]), + ]).unwrap(), vec![], ); @@ -822,13 +822,13 @@ mod test { assert_eq!( poly2, Polygon::new( - LineString(vec![ + LineString::new(vec![ Point::new(0., 0.), Point::new(0., 10.), Point::new(10., 10.), Point::new(10., 0.), Point::new(0., 0.), - ]), + ]).unwrap(), vec![], ) ); @@ -838,14 +838,14 @@ mod test { fn multipolygon() { let mpoly = MultiPolygon(vec![ Polygon::new( - LineString(vec![ + LineString::new(vec![ Point::new(0., 0.), Point::new(0., 10.), Point::new(5., 11.), Point::new(10., 10.), Point::new(10., 0.), Point::new(0., 0.), - ]), + ]).unwrap(), vec![] ), ]); @@ -856,13 +856,13 @@ mod test { mpoly2, MultiPolygon(vec![ Polygon::new( - LineString(vec![ + LineString::new(vec![ Point::new(0., 0.), Point::new(0., 10.), Point::new(10., 10.), Point::new(10., 0.), Point::new(0., 0.), - ]), + ]).unwrap(), vec![] ), ]) diff --git a/src/algorithm/translate.rs b/src/algorithm/translate.rs index a55729cbb..03c42d452 100644 --- a/src/algorithm/translate.rs +++ b/src/algorithm/translate.rs @@ -13,13 +13,13 @@ pub trait Translate { /// vec.push(Point::new(0.0, 0.0)); /// vec.push(Point::new(5.0, 5.0)); /// vec.push(Point::new(10.0, 10.0)); - /// let linestring = LineString(vec); + /// let linestring = LineString::new(vec).unwrap(); /// let translated = linestring.translate(1.5, 3.5); /// let mut correct = Vec::new(); /// correct.push(Point::new(1.5, 3.5)); /// correct.push(Point::new(6.5, 8.5)); /// correct.push(Point::new(11.5, 13.5)); - /// let correct_ls = LineString(correct); + /// let correct_ls = LineString::new(correct).unwrap(); /// assert_eq!(translated, correct_ls); /// ``` fn translate(&self, xoff: T, yoff: T) -> Self where T: Float; @@ -50,13 +50,13 @@ mod test { vec.push(Point::new(0.0, 0.0)); vec.push(Point::new(5.0, 1.0)); vec.push(Point::new(10.0, 0.0)); - let linestring = LineString(vec); + let linestring = LineString::new(vec).unwrap(); let translated = linestring.translate(17.0, 18.0); let mut correct = Vec::new(); correct.push(Point::new(17.0, 18.0)); correct.push(Point::new(22.0, 19.0)); correct.push(Point::new(27., 18.)); - let correct_ls = LineString(correct); + let correct_ls = LineString::new(correct).unwrap(); assert_eq!(translated, correct_ls); } #[test] @@ -67,7 +67,7 @@ mod test { .iter() .map(|e| Point::new(e.0, e.1)) .collect::>(); - let poly1 = Polygon::new(LineString(points), vec![]); + let poly1 = Polygon::new(LineString::new(points), vec![]).unwrap(); let translated = poly1.translate(17.0, 18.0); let correct_outside = vec![(22.0, 19.0), (21.0, 20.0), @@ -78,17 +78,17 @@ mod test { (24.0, 20.0), (23.0, 19.0), (22.0, 19.0)]; - let correct = Polygon::new(LineString(correct_outside + let correct = Polygon::new(LineString::new(correct_outside .iter() .map(|e| Point::new(e.0, e.1)) - .collect::>()), + .collect::>()).unwrap(), vec![]); // results agree with Shapely / GEOS assert_eq!(translated, correct); } #[test] fn test_rotate_polygon_holes() { - let ls1 = LineString(vec![Point::new(5.0, 1.0), + let ls1 = LineString::new(vec![Point::new(5.0, 1.0).unwrap(), Point::new(4.0, 2.0), Point::new(4.0, 3.0), Point::new(5.0, 4.0), @@ -98,7 +98,7 @@ mod test { Point::new(6.0, 1.0), Point::new(5.0, 1.0)]); - let ls2 = LineString(vec![Point::new(5.0, 1.3), + let ls2 = LineString::new(vec![Point::new(5.0, 1.3).unwrap(), Point::new(5.5, 2.0), Point::new(6.0, 1.3), Point::new(5.0, 1.3)]); diff --git a/src/types.rs b/src/types.rs index bb62f5195..ef76acb71 100644 --- a/src/types.rs +++ b/src/types.rs @@ -456,7 +456,7 @@ impl Line /// /// ``` /// use geo::{LineString, Point}; -/// let line = LineString(vec![Point::new(0., 0.), Point::new(10., 0.)]); +/// let line = LineString::new(vec![Point::new(0., 0.), Point::new(10., 0.)]).unwrap(); /// ``` /// /// Converting a `Vec` of `Point`-like things: @@ -478,7 +478,7 @@ impl Line /// /// ``` /// use geo::{LineString, Point}; -/// let line = LineString(vec![Point::new(0., 0.), Point::new(10., 0.)]); +/// let line = LineString::new(vec![Point::new(0., 0.), Point::new(10., 0.)]).unwrap(); /// for point in line { /// println!("Point x = {}, y = {}", point.x(), point.y()); /// } @@ -499,7 +499,7 @@ impl LineString { /// Only use this if you know _for certain_ that `point` has at least two elements. pub unsafe fn new_unchecked(points: Vec>) -> Self { debug_assert!(points.len() > 1); - LineString(points) + LineString::new(points).unwrap() } pub fn points(&self) -> &[Point] { @@ -601,9 +601,9 @@ impl Polygon /// ``` /// use geo::{Point, LineString, Polygon}; /// - /// let exterior = LineString(vec![Point::new(0., 0.), Point::new(1., 1.), + /// let exterior = LineString::new(vec![Point::new(0., 0.), Point::new(1., 1.).unwrap(), /// Point::new(1., 0.), Point::new(0., 0.)]); - /// let interiors = vec![LineString(vec![Point::new(0.1, 0.1), Point::new(0.9, 0.9), + /// let interiors = vec![LineString::new(vec![Point::new(0.1, 0.1), Point::new(0.9, 0.9).unwrap(), /// Point::new(0.9, 0.1), Point::new(0.1, 0.1)])]; /// let p = Polygon::new(exterior.clone(), interiors.clone()); /// assert_eq!(p.exterior, exterior); @@ -722,9 +722,9 @@ mod test { #[test] fn polygon_new_test() { - let exterior = LineString(vec![Point::new(0., 0.), Point::new(1., 1.), + let exterior = LineString::new(vec![Point::new(0., 0.), Point::new(1., 1.).unwrap(), Point::new(1., 0.), Point::new(0., 0.)]); - let interiors = vec![LineString(vec![Point::new(0.1, 0.1), Point::new(0.9, 0.9), + let interiors = vec![LineString::new(vec![Point::new(0.1, 0.1), Point::new(0.9, 0.9).unwrap(), Point::new(0.9, 0.1), Point::new(0.1, 0.1)])]; let p = Polygon::new(exterior.clone(), interiors.clone());