1#![allow(clippy::derived_hash_with_manual_eq)]
2use std::cmp::Ordering;
3use std::hash;
4use std::iter::once;
5
6use common::fmt::Fmt;
7use geo::algorithm::contains::Contains;
8use geo::algorithm::intersects::Intersects;
9use geo::{Coord, LineString, LinesIter, Point, Polygon};
10use geo_types::{MultiLineString, MultiPoint, MultiPolygon};
11use revision::revisioned;
12use storekey::{BorrowDecode, Encode};
13use surrealdb_types::{SqlFormat, ToSql, write_sql};
14
15use super::Object;
16use crate::val::{Array, Value};
17
18#[revisioned(revision = 1)]
19#[derive(Clone, Debug, PartialEq)]
20#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
21pub enum Geometry {
22 Point(Point<f64>),
23 Line(LineString<f64>),
24 Polygon(Polygon<f64>),
25 MultiPoint(MultiPoint<f64>),
26 MultiLine(MultiLineString<f64>),
27 MultiPolygon(MultiPolygon<f64>),
28 Collection(Vec<Geometry>),
29 }
31
32impl Geometry {
33 pub fn is_geometry(&self) -> bool {
35 !matches!(self, Self::Collection(_))
36 }
37 pub fn is_collection(&self) -> bool {
39 matches!(self, Self::Collection(_))
40 }
41
42 pub fn is_valid(&self) -> bool {
46 match self {
47 Geometry::Point(p) => {
48 (-90.0..=90.0).contains(&p.0.y) && (-180.0..=180.0).contains(&p.0.x)
49 }
50 Geometry::MultiPoint(v) => v
51 .iter()
52 .all(|p| (-90.0..=90.0).contains(&p.0.y) && (-180.0..=180.0).contains(&p.0.x)),
53 Geometry::Line(v) => v.lines_iter().all(|l| {
54 (-90.0..=90.0).contains(&l.start.y)
55 && (-180.0..=180.0).contains(&l.start.x)
56 && (-90.0..=90.0).contains(&l.end.y)
57 && (-180.0..=180.0).contains(&l.end.x)
58 }),
59 Geometry::Polygon(v) => v.lines_iter().all(|l| {
60 (-90.0..=90.0).contains(&l.start.y)
61 && (-180.0..=180.0).contains(&l.start.x)
62 && (-90.0..=90.0).contains(&l.end.y)
63 && (-180.0..=180.0).contains(&l.end.x)
64 }),
65 Geometry::MultiLine(v) => v.iter().all(|l| {
66 l.lines_iter().all(|l| {
67 (-90.0..=90.0).contains(&l.start.y)
68 && (-180.0..=180.0).contains(&l.start.x)
69 && (-90.0..=90.0).contains(&l.end.y)
70 && (-180.0..=180.0).contains(&l.end.x)
71 })
72 }),
73 Geometry::MultiPolygon(v) => v.iter().all(|p| {
74 p.lines_iter().all(|l| {
75 (-90.0..=90.0).contains(&l.start.y)
76 && (-180.0..=180.0).contains(&l.start.x)
77 && (-90.0..=90.0).contains(&l.end.y)
78 && (-180.0..=180.0).contains(&l.end.x)
79 })
80 }),
81 Geometry::Collection(v) => v.iter().all(Geometry::is_valid),
82 }
83 }
84 pub fn as_type(&self) -> &'static str {
86 match self {
87 Self::Point(_) => "Point",
88 Self::Line(_) => "LineString",
89 Self::Polygon(_) => "Polygon",
90 Self::MultiPoint(_) => "MultiPoint",
91 Self::MultiLine(_) => "MultiLineString",
92 Self::MultiPolygon(_) => "MultiPolygon",
93 Self::Collection(_) => "GeometryCollection",
94 }
95 }
96 pub fn as_coordinates(&self) -> Value {
98 fn point(v: &Point) -> Value {
99 Array::from(vec![v.x(), v.y()]).into()
100 }
101
102 fn line(v: &LineString) -> Value {
103 v.points().map(|v| point(&v)).collect::<Vec<Value>>().into()
104 }
105
106 fn polygon(v: &Polygon) -> Value {
107 once(v.exterior()).chain(v.interiors()).map(line).collect::<Vec<Value>>().into()
108 }
109
110 fn multipoint(v: &MultiPoint) -> Value {
111 v.iter().map(point).collect::<Vec<Value>>().into()
112 }
113
114 fn multiline(v: &MultiLineString) -> Value {
115 v.iter().map(line).collect::<Vec<Value>>().into()
116 }
117
118 fn multipolygon(v: &MultiPolygon) -> Value {
119 v.iter().map(polygon).collect::<Vec<Value>>().into()
120 }
121
122 fn collection(v: &[Geometry]) -> Value {
123 v.iter().map(Geometry::as_coordinates).collect::<Vec<Value>>().into()
124 }
125
126 match self {
127 Self::Point(v) => point(v),
128 Self::Line(v) => line(v),
129 Self::Polygon(v) => polygon(v),
130 Self::MultiPoint(v) => multipoint(v),
131 Self::MultiLine(v) => multiline(v),
132 Self::MultiPolygon(v) => multipolygon(v),
133 Self::Collection(v) => collection(v),
134 }
135 }
136
137 pub fn as_object(&self) -> Object {
139 let mut obj = Object::default();
140 obj.insert("type", self.as_type().into());
141 obj.insert(
142 match self {
143 Self::Collection(_) => "geometries",
144 _ => "coordinates",
145 },
146 self.as_coordinates(),
147 );
148 obj
149 }
150
151 pub fn try_from_object(object: &Object) -> Option<Geometry> {
152 if object.len() != 2 {
153 return None;
154 }
155
156 let Some(Value::String(key)) = object.get("type") else {
157 return None;
158 };
159
160 match key.as_str() {
161 "Point" => {
162 object.get("coordinates").and_then(Geometry::array_to_point).map(Geometry::Point)
163 }
164 "LineString" => {
165 object.get("coordinates").and_then(Geometry::array_to_line).map(Geometry::Line)
166 }
167 "Polygon" => object
168 .get("coordinates")
169 .and_then(Geometry::array_to_polygon)
170 .map(Geometry::Polygon),
171 "MultiPoint" => object
172 .get("coordinates")
173 .and_then(Geometry::array_to_multipoint)
174 .map(Geometry::MultiPoint),
175 "MultiLineString" => object
176 .get("coordinates")
177 .and_then(Geometry::array_to_multiline)
178 .map(Geometry::MultiLine),
179 "MultiPolygon" => object
180 .get("coordinates")
181 .and_then(Geometry::array_to_multipolygon)
182 .map(Geometry::MultiPolygon),
183 "GeometryCollection" => {
184 let Some(Value::Array(x)) = object.get("geometries") else {
185 return None;
186 };
187
188 let mut res = Vec::with_capacity(x.len());
189
190 for x in x.iter() {
191 let Value::Geometry(x) = x else {
192 return None;
193 };
194 res.push(x.clone());
195 }
196
197 Some(Geometry::Collection(res))
198 }
199
200 _ => None,
201 }
202 }
203
204 pub fn array_to_multipolygon(v: &Value) -> Option<MultiPolygon<f64>> {
207 let mut res = Vec::new();
208 let Value::Array(v) = v else {
209 return None;
210 };
211 for x in v.iter() {
212 res.push(Self::array_to_polygon(x)?);
213 }
214 Some(MultiPolygon::new(res))
215 }
216
217 pub fn array_to_multiline(v: &Value) -> Option<MultiLineString<f64>> {
220 let mut res = Vec::new();
221 let Value::Array(v) = v else {
222 return None;
223 };
224 for x in v.iter() {
225 res.push(Self::array_to_line(x)?);
226 }
227 Some(MultiLineString::new(res))
228 }
229
230 pub fn array_to_multipoint(v: &Value) -> Option<MultiPoint<f64>> {
233 let mut res = Vec::new();
234 let Value::Array(v) = v else {
235 return None;
236 };
237 for x in v.iter() {
238 res.push(Self::array_to_point(x)?);
239 }
240 Some(MultiPoint::new(res))
241 }
242
243 pub fn array_to_polygon(v: &Value) -> Option<Polygon<f64>> {
245 let mut res = Vec::new();
246 let Value::Array(v) = v else {
247 return None;
248 };
249 if v.is_empty() {
250 return None;
251 }
252 let first = Self::array_to_line(&v[0])?;
253 for x in &v[1..] {
254 res.push(Self::array_to_line(x)?);
255 }
256 Some(Polygon::new(first, res))
257 }
258
259 pub fn array_to_line(v: &Value) -> Option<LineString<f64>> {
262 let mut res = Vec::new();
263 let Value::Array(v) = v else {
264 return None;
265 };
266 for x in v.iter() {
267 res.push(Self::array_to_point(x)?);
268 }
269 Some(LineString::from(res))
270 }
271
272 pub fn array_to_point(v: &Value) -> Option<Point<f64>> {
274 let Value::Array(v) = v else {
275 return None;
276 };
277 if v.len() != 2 {
278 return None;
279 }
280 let Value::Number(ref a) = v.0[0] else {
282 return None;
283 };
284 let Value::Number(ref b) = v.0[1] else {
285 return None;
286 };
287 Some(Point::from(((*a).try_into().ok()?, (*b).try_into().ok()?)))
288 }
289
290 pub fn contains(&self, other: &Self) -> bool {
295 match self {
296 Self::Point(v) => match other {
297 Self::Point(w) => v.contains(w),
298 Self::MultiPoint(w) => w.iter().all(|x| v.contains(x)),
299 Self::Collection(w) => w.iter().all(|x| self.contains(x)),
300 _ => false,
301 },
302 Self::Line(v) => match other {
303 Self::Point(w) => v.contains(w),
304 Self::Line(w) => v.contains(w),
305 Self::MultiLine(w) => w.iter().all(|x| w.contains(x)),
306 Self::Collection(w) => w.iter().all(|x| self.contains(x)),
307 _ => false,
308 },
309 Self::Polygon(v) => match other {
310 Self::Point(w) => v.contains(w),
311 Self::Line(w) => v.contains(w),
312 Self::Polygon(w) => v.contains(w),
313 Self::MultiPolygon(w) => w.iter().all(|x| w.contains(x)),
314 Self::Collection(w) => w.iter().all(|x| self.contains(x)),
315 _ => false,
316 },
317 Self::MultiPoint(v) => match other {
318 Self::Point(w) => v.contains(w),
319 Self::MultiPoint(w) => w.iter().all(|x| w.contains(x)),
320 Self::Collection(w) => w.iter().all(|x| self.contains(x)),
321 _ => false,
322 },
323 Self::MultiLine(v) => match other {
324 Self::Point(w) => v.contains(w),
325 Self::Line(w) => v.contains(w),
326 Self::MultiLine(w) => w.iter().all(|x| w.contains(x)),
327 Self::Collection(w) => w.iter().all(|x| self.contains(x)),
328 _ => false,
329 },
330 Self::MultiPolygon(v) => match other {
331 Self::Point(w) => v.contains(w),
332 Self::Line(w) => v.contains(w),
333 Self::Polygon(w) => v.contains(w),
334 Self::MultiPoint(w) => v.contains(w),
335 Self::MultiLine(w) => v.contains(w),
336 Self::MultiPolygon(w) => v.contains(w),
337 Self::Collection(w) => w.iter().all(|x| self.contains(x)),
338 },
339 Self::Collection(v) => v.iter().all(|x| x.contains(other)),
340 }
341 }
342
343 pub fn intersects(&self, other: &Self) -> bool {
344 match self {
345 Self::Point(v) => match other {
346 Self::Point(w) => v.intersects(w),
347 Self::Line(w) => v.intersects(w),
348 Self::Polygon(w) => v.intersects(w),
349 Self::MultiPoint(w) => v.intersects(w),
350 Self::MultiLine(w) => w.iter().any(|x| v.intersects(x)),
351 Self::MultiPolygon(w) => v.intersects(w),
352 Self::Collection(w) => w.iter().all(|x| self.intersects(x)),
353 },
354 Self::Line(v) => match other {
355 Self::Point(w) => v.intersects(w),
356 Self::Line(w) => v.intersects(w),
357 Self::Polygon(w) => v.intersects(w),
358 Self::MultiPoint(w) => v.intersects(w),
359 Self::MultiLine(w) => w.iter().any(|x| v.intersects(x)),
360 Self::MultiPolygon(w) => v.intersects(w),
361 Self::Collection(w) => w.iter().all(|x| self.intersects(x)),
362 },
363 Self::Polygon(v) => match other {
364 Self::Point(w) => v.intersects(w),
365 Self::Line(w) => v.intersects(w),
366 Self::Polygon(w) => v.intersects(w),
367 Self::MultiPoint(w) => v.intersects(w),
368 Self::MultiLine(w) => v.intersects(w),
369 Self::MultiPolygon(w) => v.intersects(w),
370 Self::Collection(w) => w.iter().all(|x| self.intersects(x)),
371 },
372 Self::MultiPoint(v) => match other {
373 Self::Point(w) => v.intersects(w),
374 Self::Line(w) => v.intersects(w),
375 Self::Polygon(w) => v.intersects(w),
376 Self::MultiPoint(w) => v.intersects(w),
377 Self::MultiLine(w) => w.iter().any(|x| v.intersects(x)),
378 Self::MultiPolygon(w) => v.intersects(w),
379 Self::Collection(w) => w.iter().all(|x| self.intersects(x)),
380 },
381 Self::MultiLine(v) => match other {
382 Self::Point(w) => v.intersects(w),
383 Self::Line(w) => v.intersects(w),
384 Self::Polygon(w) => v.intersects(w),
385 Self::MultiPoint(w) => v.intersects(w),
386 Self::MultiLine(w) => w.iter().any(|x| v.intersects(x)),
387 Self::MultiPolygon(w) => v.intersects(w),
388 Self::Collection(w) => w.iter().all(|x| self.intersects(x)),
389 },
390 Self::MultiPolygon(v) => match other {
391 Self::Point(w) => v.intersects(w),
392 Self::Line(w) => v.intersects(w),
393 Self::Polygon(w) => v.intersects(w),
394 Self::MultiPoint(w) => v.intersects(w),
395 Self::MultiLine(w) => v.intersects(w),
396 Self::MultiPolygon(w) => v.intersects(w),
397 Self::Collection(w) => w.iter().all(|x| self.intersects(x)),
398 },
399 Self::Collection(v) => v.iter().all(|x| x.intersects(other)),
400 }
401 }
402}
403
404impl PartialOrd for Geometry {
405 fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
406 fn coord(v: &Coord) -> (f64, f64) {
407 v.x_y()
408 }
409
410 fn point(v: &Point) -> (f64, f64) {
411 coord(&v.0)
412 }
413
414 fn line(v: &LineString) -> impl Iterator<Item = (f64, f64)> + '_ {
415 v.into_iter().map(coord)
416 }
417
418 fn polygon(v: &Polygon) -> impl Iterator<Item = (f64, f64)> + '_ {
419 v.interiors().iter().chain(once(v.exterior())).flat_map(line)
420 }
421
422 fn multipoint(v: &MultiPoint) -> impl Iterator<Item = (f64, f64)> + '_ {
423 v.iter().map(point)
424 }
425
426 fn multiline(v: &MultiLineString) -> impl Iterator<Item = (f64, f64)> + '_ {
427 v.iter().flat_map(line)
428 }
429
430 fn multipolygon(v: &MultiPolygon) -> impl Iterator<Item = (f64, f64)> + '_ {
431 v.iter().flat_map(polygon)
432 }
433
434 match (self, other) {
435 (Self::Point(_), Self::Line(_)) => Some(Ordering::Less),
437 (Self::Point(_), Self::Polygon(_)) => Some(Ordering::Less),
438 (Self::Point(_), Self::MultiPoint(_)) => Some(Ordering::Less),
439 (Self::Point(_), Self::MultiLine(_)) => Some(Ordering::Less),
440 (Self::Point(_), Self::MultiPolygon(_)) => Some(Ordering::Less),
441 (Self::Point(_), Self::Collection(_)) => Some(Ordering::Less),
442 (Self::Line(_), Self::Point(_)) => Some(Ordering::Greater),
444 (Self::Line(_), Self::Polygon(_)) => Some(Ordering::Less),
445 (Self::Line(_), Self::MultiPoint(_)) => Some(Ordering::Less),
446 (Self::Line(_), Self::MultiLine(_)) => Some(Ordering::Less),
447 (Self::Line(_), Self::MultiPolygon(_)) => Some(Ordering::Less),
448 (Self::Line(_), Self::Collection(_)) => Some(Ordering::Less),
449 (Self::Polygon(_), Self::Point(_)) => Some(Ordering::Greater),
451 (Self::Polygon(_), Self::Line(_)) => Some(Ordering::Greater),
452 (Self::Polygon(_), Self::MultiPoint(_)) => Some(Ordering::Less),
453 (Self::Polygon(_), Self::MultiLine(_)) => Some(Ordering::Less),
454 (Self::Polygon(_), Self::MultiPolygon(_)) => Some(Ordering::Less),
455 (Self::Polygon(_), Self::Collection(_)) => Some(Ordering::Less),
456 (Self::MultiPoint(_), Self::Point(_)) => Some(Ordering::Greater),
458 (Self::MultiPoint(_), Self::Line(_)) => Some(Ordering::Greater),
459 (Self::MultiPoint(_), Self::Polygon(_)) => Some(Ordering::Greater),
460 (Self::MultiPoint(_), Self::MultiLine(_)) => Some(Ordering::Less),
461 (Self::MultiPoint(_), Self::MultiPolygon(_)) => Some(Ordering::Less),
462 (Self::MultiPoint(_), Self::Collection(_)) => Some(Ordering::Less),
463 (Self::MultiLine(_), Self::Point(_)) => Some(Ordering::Greater),
465 (Self::MultiLine(_), Self::Line(_)) => Some(Ordering::Greater),
466 (Self::MultiLine(_), Self::Polygon(_)) => Some(Ordering::Greater),
467 (Self::MultiLine(_), Self::MultiPoint(_)) => Some(Ordering::Greater),
468 (Self::MultiLine(_), Self::MultiPolygon(_)) => Some(Ordering::Less),
469 (Self::MultiLine(_), Self::Collection(_)) => Some(Ordering::Less),
470 (Self::MultiPolygon(_), Self::Point(_)) => Some(Ordering::Greater),
472 (Self::MultiPolygon(_), Self::Line(_)) => Some(Ordering::Greater),
473 (Self::MultiPolygon(_), Self::Polygon(_)) => Some(Ordering::Greater),
474 (Self::MultiPolygon(_), Self::MultiPoint(_)) => Some(Ordering::Greater),
475 (Self::MultiPolygon(_), Self::MultiLine(_)) => Some(Ordering::Greater),
476 (Self::MultiPolygon(_), Self::Collection(_)) => Some(Ordering::Less),
477 (Self::Collection(_), Self::Point(_)) => Some(Ordering::Greater),
479 (Self::Collection(_), Self::Line(_)) => Some(Ordering::Greater),
480 (Self::Collection(_), Self::Polygon(_)) => Some(Ordering::Greater),
481 (Self::Collection(_), Self::MultiPoint(_)) => Some(Ordering::Greater),
482 (Self::Collection(_), Self::MultiLine(_)) => Some(Ordering::Greater),
483 (Self::Collection(_), Self::MultiPolygon(_)) => Some(Ordering::Greater),
484 (Self::Point(a), Self::Point(b)) => point(a).partial_cmp(&point(b)),
486 (Self::Line(a), Self::Line(b)) => line(a).partial_cmp(line(b)),
487 (Self::Polygon(a), Self::Polygon(b)) => polygon(a).partial_cmp(polygon(b)),
488 (Self::MultiPoint(a), Self::MultiPoint(b)) => multipoint(a).partial_cmp(multipoint(b)),
489 (Self::MultiLine(a), Self::MultiLine(b)) => multiline(a).partial_cmp(multiline(b)),
490 (Self::MultiPolygon(a), Self::MultiPolygon(b)) => {
491 multipolygon(a).partial_cmp(multipolygon(b))
492 }
493 (Self::Collection(a), Self::Collection(b)) => a.partial_cmp(b),
494 }
495 }
496}
497
498impl From<(f64, f64)> for Geometry {
499 fn from(v: (f64, f64)) -> Self {
500 Self::Point(v.into())
501 }
502}
503
504impl From<[f64; 2]> for Geometry {
505 fn from(v: [f64; 2]) -> Self {
506 Self::Point(v.into())
507 }
508}
509
510impl From<Point<f64>> for Geometry {
511 fn from(v: Point<f64>) -> Self {
512 Self::Point(v)
513 }
514}
515
516impl From<LineString<f64>> for Geometry {
517 fn from(v: LineString<f64>) -> Self {
518 Self::Line(v)
519 }
520}
521
522impl From<Polygon<f64>> for Geometry {
523 fn from(v: Polygon<f64>) -> Self {
524 Self::Polygon(v)
525 }
526}
527
528impl From<MultiPoint<f64>> for Geometry {
529 fn from(v: MultiPoint<f64>) -> Self {
530 Self::MultiPoint(v)
531 }
532}
533
534impl From<MultiLineString<f64>> for Geometry {
535 fn from(v: MultiLineString<f64>) -> Self {
536 Self::MultiLine(v)
537 }
538}
539
540impl From<MultiPolygon<f64>> for Geometry {
541 fn from(v: MultiPolygon<f64>) -> Self {
542 Self::MultiPolygon(v)
543 }
544}
545
546impl From<Vec<Geometry>> for Geometry {
547 fn from(v: Vec<Geometry>) -> Self {
548 Self::Collection(v)
549 }
550}
551
552impl From<Vec<Point<f64>>> for Geometry {
553 fn from(v: Vec<Point<f64>>) -> Self {
554 Self::MultiPoint(MultiPoint(v))
555 }
556}
557
558impl From<Vec<LineString<f64>>> for Geometry {
559 fn from(v: Vec<LineString<f64>>) -> Self {
560 Self::MultiLine(MultiLineString(v))
561 }
562}
563
564impl From<Vec<Polygon<f64>>> for Geometry {
565 fn from(v: Vec<Polygon<f64>>) -> Self {
566 Self::MultiPolygon(MultiPolygon(v))
567 }
568}
569
570impl From<Geometry> for geo::Geometry<f64> {
571 fn from(v: Geometry) -> Self {
572 match v {
573 Geometry::Point(v) => v.into(),
574 Geometry::Line(v) => v.into(),
575 Geometry::Polygon(v) => v.into(),
576 Geometry::MultiPoint(v) => v.into(),
577 Geometry::MultiLine(v) => v.into(),
578 Geometry::MultiPolygon(v) => v.into(),
579 Geometry::Collection(v) => v.into_iter().collect::<geo::Geometry<f64>>(),
580 }
581 }
582}
583
584impl From<geo::Geometry<f64>> for Geometry {
585 fn from(v: geo::Geometry<f64>) -> Self {
591 match v {
592 geo::Geometry::Point(v) => Geometry::Point(v),
593 geo::Geometry::Line(v) => Geometry::Line(LineString::from(vec![v.start, v.end])),
594 geo::Geometry::LineString(v) => Geometry::Line(v),
595 geo::Geometry::Polygon(v) => Geometry::Polygon(v),
596 geo::Geometry::MultiPoint(v) => Geometry::MultiPoint(v),
597 geo::Geometry::MultiLineString(v) => Geometry::MultiLine(v),
598 geo::Geometry::MultiPolygon(v) => Geometry::MultiPolygon(v),
599 geo::Geometry::GeometryCollection(v) => {
600 Geometry::Collection(v.0.into_iter().map(Geometry::from).collect())
601 }
602 geo::Geometry::Rect(v) => Geometry::Polygon(v.to_polygon()),
603 geo::Geometry::Triangle(v) => Geometry::Polygon(v.to_polygon()),
604 }
605 }
606}
607
608impl FromIterator<Geometry> for geo::Geometry<f64> {
609 fn from_iter<I: IntoIterator<Item = Geometry>>(iter: I) -> Self {
610 let mut c: Vec<geo::Geometry<f64>> = vec![];
611 for i in iter {
612 c.push(i.into())
613 }
614 geo::Geometry::GeometryCollection(geo::GeometryCollection(c))
615 }
616}
617
618impl From<Geometry> for surrealdb_types::Geometry {
619 fn from(v: Geometry) -> Self {
620 match v {
621 Geometry::Point(v) => surrealdb_types::Geometry::Point(v),
622 Geometry::Line(v) => surrealdb_types::Geometry::Line(v),
623 Geometry::Polygon(v) => surrealdb_types::Geometry::Polygon(v),
624 Geometry::MultiPoint(v) => surrealdb_types::Geometry::MultiPoint(v),
625 Geometry::MultiLine(v) => surrealdb_types::Geometry::MultiLine(v),
626 Geometry::MultiPolygon(v) => surrealdb_types::Geometry::MultiPolygon(v),
627 Geometry::Collection(v) => {
628 surrealdb_types::Geometry::Collection(v.into_iter().map(Into::into).collect())
629 }
630 }
631 }
632}
633
634impl From<surrealdb_types::Geometry> for Geometry {
635 fn from(v: surrealdb_types::Geometry) -> Self {
636 match v {
637 surrealdb_types::Geometry::Point(v) => Geometry::Point(v),
638 surrealdb_types::Geometry::Line(v) => Geometry::Line(v),
639 surrealdb_types::Geometry::Polygon(v) => Geometry::Polygon(v),
640 surrealdb_types::Geometry::MultiPoint(v) => Geometry::MultiPoint(v),
641 surrealdb_types::Geometry::MultiLine(v) => Geometry::MultiLine(v),
642 surrealdb_types::Geometry::MultiPolygon(v) => Geometry::MultiPolygon(v),
643 surrealdb_types::Geometry::Collection(v) => {
644 Geometry::Collection(v.into_iter().map(Into::into).collect())
645 }
646 }
647 }
648}
649
650impl ToSql for Geometry {
651 fn fmt_sql(&self, f: &mut String, sql_fmt: SqlFormat) {
652 match self {
653 Self::Point(v) => {
654 write_sql!(f, sql_fmt, "({}, {})", v.x(), v.y())
655 }
656 Self::Line(v) => write_sql!(
657 f,
658 sql_fmt,
659 "{{ type: 'LineString', coordinates: [{}] }}",
660 Fmt::comma_separated(v.points().map(|v| Fmt::new(v, |v, f, fmt| write_sql!(
661 f,
662 fmt,
663 "[{}, {}]",
664 v.x(),
665 v.y()
666 ))))
667 ),
668 Self::Polygon(v) => write_sql!(
669 f,
670 sql_fmt,
671 "{{ type: 'Polygon', coordinates: [{}] }}",
672 Fmt::comma_separated(once(v.exterior()).chain(v.interiors()).map(|v| Fmt::new(
673 v,
674 |v, f, fmt| write_sql!(
675 f,
676 fmt,
677 "[{}]",
678 Fmt::comma_separated(v.points().map(|v| Fmt::new(
679 v,
680 |v, f, fmt| write_sql!(f, fmt, "[{}, {}]", v.x(), v.y())
681 )))
682 )
683 )))
684 ),
685 Self::MultiPoint(v) => {
686 write_sql!(
687 f,
688 sql_fmt,
689 "{{ type: 'MultiPoint', coordinates: [{}] }}",
690 Fmt::comma_separated(v.iter().map(|v| Fmt::new(v, |v, f, fmt| write_sql!(
691 f,
692 fmt,
693 "[{}, {}]",
694 v.x(),
695 v.y()
696 ))))
697 )
698 }
699 Self::MultiLine(v) => {
700 write_sql!(
701 f,
702 sql_fmt,
703 "{{ type: 'MultiLineString', coordinates: [{}] }}",
704 Fmt::comma_separated(v.iter().map(|v| Fmt::new(v, |v, f, fmt| write_sql!(
705 f,
706 fmt,
707 "[{}]",
708 Fmt::comma_separated(v.points().map(|v| Fmt::new(
709 v,
710 |v, f, fmt| write_sql!(f, fmt, "[{}, {}]", v.x(), v.y())
711 )))
712 ))))
713 )
714 }
715 Self::MultiPolygon(v) => {
716 write_sql!(
717 f,
718 sql_fmt,
719 "{{ type: 'MultiPolygon', coordinates: [{}] }}",
720 Fmt::comma_separated(v.iter().map(|v| Fmt::new(v, |v, f, fmt| {
721 write_sql!(
722 f,
723 fmt,
724 "[{}]",
725 Fmt::comma_separated(once(v.exterior()).chain(v.interiors()).map(
726 |v| Fmt::new(v, |v, f, fmt| write_sql!(
727 f,
728 fmt,
729 "[{}]",
730 Fmt::comma_separated(v.points().map(|v| Fmt::new(
731 v,
732 |v, f, fmt| write_sql!(f, fmt, "[{}, {}]", v.x(), v.y())
733 )))
734 ))
735 ))
736 )
737 }))),
738 )
739 }
740 Self::Collection(v) => {
741 write_sql!(
742 f,
743 sql_fmt,
744 "{{ type: 'GeometryCollection', geometries: [{}] }}",
745 Fmt::comma_separated(v)
746 )
747 }
748 }
749 }
750}
751
752impl hash::Hash for Geometry {
753 fn hash<H: hash::Hasher>(&self, state: &mut H) {
754 match self {
755 Geometry::Point(p) => {
756 "Point".hash(state);
757 p.x().to_bits().hash(state);
758 p.y().to_bits().hash(state);
759 }
760 Geometry::Line(l) => {
761 "Line".hash(state);
762 l.points().for_each(|v| {
763 v.x().to_bits().hash(state);
764 v.y().to_bits().hash(state);
765 });
766 }
767 Geometry::Polygon(p) => {
768 "Polygon".hash(state);
769 p.exterior().points().for_each(|ext| {
770 ext.x().to_bits().hash(state);
771 ext.y().to_bits().hash(state);
772 });
773 p.interiors().iter().for_each(|int| {
774 int.points().for_each(|v| {
775 v.x().to_bits().hash(state);
776 v.y().to_bits().hash(state);
777 });
778 });
779 }
780 Geometry::MultiPoint(v) => {
781 "MultiPoint".hash(state);
782 v.0.iter().for_each(|v| {
783 v.x().to_bits().hash(state);
784 v.y().to_bits().hash(state);
785 });
786 }
787 Geometry::MultiLine(ml) => {
788 "MultiLine".hash(state);
789 ml.0.iter().for_each(|ls| {
790 ls.points().for_each(|p| {
791 p.x().to_bits().hash(state);
792 p.y().to_bits().hash(state);
793 });
794 });
795 }
796 Geometry::MultiPolygon(mp) => {
797 "MultiPolygon".hash(state);
798 mp.0.iter().for_each(|p| {
799 p.exterior().points().for_each(|ext| {
800 ext.x().to_bits().hash(state);
801 ext.y().to_bits().hash(state);
802 });
803 p.interiors().iter().for_each(|int| {
804 int.points().for_each(|v| {
805 v.x().to_bits().hash(state);
806 v.y().to_bits().hash(state);
807 });
808 });
809 });
810 }
811 Geometry::Collection(v) => {
812 "GeometryCollection".hash(state);
813 v.iter().for_each(|v| v.hash(state));
814 }
815 }
816 }
817}
818
819impl<F> Encode<F> for Geometry {
820 fn encode<W: std::io::Write>(
821 &self,
822 w: &mut storekey::Writer<W>,
823 ) -> Result<(), storekey::EncodeError> {
824 match self {
825 Geometry::Point(point) => {
826 w.write_u8(2)?;
827 Encode::<F>::encode(&point.x(), w)?;
828 Encode::<F>::encode(&point.y(), w)?;
829 }
830 Geometry::Line(line_string) => {
831 w.write_u8(3)?;
832 for p in line_string.points() {
833 w.mark_terminator();
834 Encode::<F>::encode(&p.x(), w)?;
835 Encode::<F>::encode(&p.y(), w)?;
836 }
837 w.write_terminator()?;
838 }
839 Geometry::Polygon(polygon) => {
840 w.write_u8(4)?;
841 for p in polygon.exterior().points() {
842 w.mark_terminator();
843 Encode::<F>::encode(&p.x(), w)?;
844 Encode::<F>::encode(&p.y(), w)?;
845 }
846 w.write_terminator()?;
847 for l in polygon.interiors() {
848 for p in l.points() {
849 w.mark_terminator();
850 Encode::<F>::encode(&p.x(), w)?;
851 Encode::<F>::encode(&p.y(), w)?;
852 }
853 w.write_terminator()?;
854 }
855 w.write_terminator()?;
856 }
857 Geometry::MultiPoint(multi_point) => {
858 w.write_u8(5)?;
859 for p in multi_point.iter() {
860 w.mark_terminator();
861 Encode::<F>::encode(&p.x(), w)?;
862 Encode::<F>::encode(&p.y(), w)?;
863 }
864 w.write_terminator()?;
865 }
866 Geometry::MultiLine(multi_line_string) => {
867 w.write_u8(6)?;
868 for l in multi_line_string.iter() {
869 for p in l.points() {
870 w.mark_terminator();
871 Encode::<F>::encode(&p.x(), w)?;
872 Encode::<F>::encode(&p.y(), w)?;
873 }
874 w.write_terminator()?;
875 }
876 w.write_terminator()?;
877 }
878 Geometry::MultiPolygon(multi_polygon) => {
879 w.write_u8(7)?;
880 for p in multi_polygon.iter() {
881 for p in p.exterior().points() {
882 w.mark_terminator();
883 Encode::<F>::encode(&p.x(), w)?;
884 Encode::<F>::encode(&p.y(), w)?;
885 }
886 w.write_terminator()?;
887 for l in p.interiors() {
888 for p in l.points() {
889 w.mark_terminator();
890 Encode::<F>::encode(&p.x(), w)?;
891 Encode::<F>::encode(&p.y(), w)?;
892 }
893 w.write_terminator()?;
894 }
895 w.write_terminator()?;
896 }
897 w.write_terminator()?;
898 }
899 Geometry::Collection(items) => {
900 w.write_u8(8)?;
901 for g in items.iter() {
902 w.mark_terminator();
903 Encode::<F>::encode(g, w)?;
904 }
905 w.write_terminator()?;
906 }
907 }
908 Ok(())
909 }
910}
911
912impl<'de, F> BorrowDecode<'de, F> for Geometry {
913 fn borrow_decode(r: &mut storekey::BorrowReader<'de>) -> Result<Self, storekey::DecodeError> {
914 match r.read_u8()? {
915 2 => {
916 let point = <(f64, f64) as BorrowDecode<'de, F>>::borrow_decode(r)?;
917 Ok(Geometry::Point(Point::from(point)))
918 }
919 3 => {
920 let mut res = Vec::new();
921 while !r.read_terminal()? {
922 let point = <(f64, f64) as BorrowDecode<'de, F>>::borrow_decode(r)?;
923 res.push(Coord::from(point))
924 }
925 Ok(Geometry::Line(LineString::new(res)))
926 }
927 4 => {
928 let mut ext = Vec::new();
929 while !r.read_terminal()? {
930 let point = <(f64, f64) as BorrowDecode<'de, F>>::borrow_decode(r)?;
931 ext.push(Coord::from(point))
932 }
933 let ext = LineString::new(ext);
934 let mut int = Vec::new();
935 while !r.read_terminal()? {
936 let mut line = Vec::new();
937 while !r.read_terminal()? {
938 let point = <(f64, f64) as BorrowDecode<'de, F>>::borrow_decode(r)?;
939 line.push(Coord::from(point))
940 }
941 int.push(LineString::new(line))
942 }
943 Ok(Geometry::Polygon(Polygon::new(ext, int)))
944 }
945 5 => {
946 let mut res = Vec::new();
947 while !r.read_terminal()? {
948 let point = <(f64, f64) as BorrowDecode<'de, F>>::borrow_decode(r)?;
949 res.push(Point::from(point))
950 }
951 Ok(Geometry::MultiPoint(MultiPoint::new(res)))
952 }
953 6 => {
954 let mut lines = Vec::new();
955 while !r.read_terminal()? {
956 let mut res = Vec::new();
957 while !r.read_terminal()? {
958 let point = <(f64, f64) as BorrowDecode<'de, F>>::borrow_decode(r)?;
959 res.push(Coord::from(point))
960 }
961 lines.push(LineString::new(res));
962 }
963 Ok(Geometry::MultiLine(MultiLineString::new(lines)))
964 }
965 7 => {
966 let mut polygons = Vec::new();
967 while !r.read_terminal()? {
968 let mut ext = Vec::new();
969 while !r.read_terminal()? {
970 let point = <(f64, f64) as BorrowDecode<'de, F>>::borrow_decode(r)?;
971 ext.push(Coord::from(point))
972 }
973 let ext = LineString::new(ext);
974 let mut int = Vec::new();
975 while !r.read_terminal()? {
976 let mut line = Vec::new();
977 while !r.read_terminal()? {
978 let point = <(f64, f64) as BorrowDecode<'de, F>>::borrow_decode(r)?;
979 line.push(Coord::from(point))
980 }
981 int.push(LineString::new(line))
982 }
983 polygons.push(Polygon::new(ext, int));
984 }
985 Ok(Geometry::MultiPolygon(MultiPolygon::new(polygons)))
986 }
987 8 => {
988 let mut geoms = Vec::new();
989 while !r.read_terminal()? {
990 geoms.push(BorrowDecode::<'de, F>::borrow_decode(r)?)
991 }
992 Ok(Geometry::Collection(geoms))
993 }
994 _ => Err(storekey::DecodeError::InvalidFormat),
995 }
996 }
997}
998
999#[cfg(test)]
1000mod test {
1001 use core::f64;
1002
1003 use geo::{Coord, LineString, MultiLineString, MultiPoint, MultiPolygon, Point, Polygon};
1004
1005 use super::Geometry;
1006
1007 fn round_trip(geom: &Geometry) {
1008 let enc = storekey::encode_vec(geom).unwrap();
1009 let dec = storekey::decode_borrow(&enc).unwrap();
1010 assert_eq!(geom, &dec)
1011 }
1012
1013 #[test]
1014 fn encode_decode() {
1015 round_trip(&Geometry::Point(Point::new(0.0, f64::INFINITY)));
1016 round_trip(&Geometry::Line(LineString::new(vec![
1017 Coord::from((0.0, f64::INFINITY)),
1018 Coord::from((f64::NEG_INFINITY, 1.0)),
1019 ])));
1020 round_trip(&Geometry::Polygon(Polygon::new(
1021 LineString::new(vec![
1022 Coord::from((0.0, f64::INFINITY)),
1023 Coord::from((f64::NEG_INFINITY, 1.0)),
1024 ]),
1025 vec![
1026 LineString::new(vec![Coord::from((1.0, 2.0)), Coord::from((3.0, 4.0))]),
1027 LineString::new(vec![Coord::from((5.0, 6.0)), Coord::from((7.0, 8.0))]),
1028 ],
1029 )));
1030 round_trip(&Geometry::MultiPoint(MultiPoint::new(vec![
1031 Point::from((0.0, f64::INFINITY)),
1032 Point::from((f64::NEG_INFINITY, 1.0)),
1033 ])));
1034 round_trip(&Geometry::MultiLine(MultiLineString::new(vec![
1035 LineString::new(vec![
1036 Coord::from((0.0, f64::INFINITY)),
1037 Coord::from((f64::NEG_INFINITY, 1.0)),
1038 ]),
1039 LineString::new(vec![Coord::from((1.0, 2.0)), Coord::from((3.0, 4.0))]),
1040 ])));
1041 round_trip(&Geometry::MultiPolygon(MultiPolygon::new(vec![
1042 Polygon::new(
1043 LineString::new(vec![
1044 Coord::from((0.0, f64::INFINITY)),
1045 Coord::from((f64::NEG_INFINITY, 1.0)),
1046 ]),
1047 vec![
1048 LineString::new(vec![Coord::from((1.0, 2.0)), Coord::from((3.0, 4.0))]),
1049 LineString::new(vec![Coord::from((5.0, 6.0)), Coord::from((7.0, 8.0))]),
1050 ],
1051 ),
1052 Polygon::new(
1053 LineString::new(vec![Coord::from((9.0, 10.0)), Coord::from((11.0, 12.0))]),
1054 vec![
1055 LineString::new(vec![Coord::from((13.0, 14.0)), Coord::from((15.0, 16.0))]),
1056 LineString::new(vec![Coord::from((17.0, 18.0)), Coord::from((19.0, 20.0))]),
1057 ],
1058 ),
1059 ])));
1060 }
1061}