1use core::ffi::CStr;
18use core::marker::PhantomData;
19use core::ptr::NonNull;
20
21use crate::error::{Error, Result};
22use crate::{GeomType, Line, LineRef, Point, Poly, PolyRef, Rect};
23
24macro_rules! impl_geom_methods {
25 ($get_ptr:expr) => {
26 #[inline]
27 pub fn geom_type(&self) -> GeomType {
28 let ptr = $get_ptr(self);
29 let t = unsafe { tg_geom_sys::tg_geom_typeof(ptr) };
30 t.into()
31 }
32
33 #[inline]
34 pub fn rect(&self) -> Rect {
35 let ptr = $get_ptr(self);
36 let r = unsafe { tg_geom_sys::tg_geom_rect(ptr) };
37 r.into()
38 }
39
40 #[inline]
41 pub fn is_empty(&self) -> bool {
42 let ptr = $get_ptr(self);
43 unsafe { tg_geom_sys::tg_geom_is_empty(ptr) }
44 }
45 };
46}
47
48pub struct Geom {
59 ptr: NonNull<tg_geom_sys::tg_geom>,
60}
61
62impl Geom {
63 impl_geom_methods!(|s: &Self| s.ptr.as_ptr());
64
65 pub fn new_point(point: Point) -> Result<Self> {
66 let ptr = unsafe { tg_geom_sys::tg_geom_new_point(point.into()) };
67 NonNull::new(ptr)
68 .map(|ptr| Self { ptr })
69 .ok_or(Error::OutOfMemory)
70 }
71
72 pub fn new_point_z(point: Point, z: f64) -> Result<Self> {
73 let ptr = unsafe { tg_geom_sys::tg_geom_new_point_z(point.into(), z) };
74 NonNull::new(ptr)
75 .map(|ptr| Self { ptr })
76 .ok_or(Error::OutOfMemory)
77 }
78
79 pub fn new_point_m(point: Point, m: f64) -> Result<Self> {
80 let ptr = unsafe { tg_geom_sys::tg_geom_new_point_m(point.into(), m) };
81 NonNull::new(ptr)
82 .map(|ptr| Self { ptr })
83 .ok_or(Error::OutOfMemory)
84 }
85
86 pub fn new_point_zm(point: Point, z: f64, m: f64) -> Result<Self> {
87 let ptr = unsafe { tg_geom_sys::tg_geom_new_point_zm(point.into(), z, m) };
88 NonNull::new(ptr)
89 .map(|ptr| Self { ptr })
90 .ok_or(Error::OutOfMemory)
91 }
92
93 pub fn new_point_empty() -> Result<Self> {
94 let ptr = unsafe { tg_geom_sys::tg_geom_new_point_empty() };
95 NonNull::new(ptr)
96 .map(|ptr| Self { ptr })
97 .ok_or(Error::OutOfMemory)
98 }
99
100 pub fn new_linestring(line: &Line) -> Result<Self> {
101 let ptr = unsafe { tg_geom_sys::tg_geom_new_linestring(line.as_ptr()) };
102 NonNull::new(ptr)
103 .map(|ptr| Self { ptr })
104 .ok_or(Error::OutOfMemory)
105 }
106
107 pub fn new_linestring_z(line: &Line, extra_coords: &[f64]) -> Result<Self> {
108 let ptr = unsafe {
109 tg_geom_sys::tg_geom_new_linestring_z(
110 line.as_ptr(),
111 extra_coords.as_ptr(),
112 extra_coords.len() as libc::c_int,
113 )
114 };
115 NonNull::new(ptr)
116 .map(|ptr| Self { ptr })
117 .ok_or(Error::OutOfMemory)
118 }
119
120 pub fn new_linestring_m(line: &Line, extra_coords: &[f64]) -> Result<Self> {
121 let ptr = unsafe {
122 tg_geom_sys::tg_geom_new_linestring_m(
123 line.as_ptr(),
124 extra_coords.as_ptr(),
125 extra_coords.len() as libc::c_int,
126 )
127 };
128 NonNull::new(ptr)
129 .map(|ptr| Self { ptr })
130 .ok_or(Error::OutOfMemory)
131 }
132
133 pub fn new_linestring_zm(line: &Line, extra_coords: &[f64]) -> Result<Self> {
134 let ptr = unsafe {
135 tg_geom_sys::tg_geom_new_linestring_zm(
136 line.as_ptr(),
137 extra_coords.as_ptr(),
138 extra_coords.len() as libc::c_int,
139 )
140 };
141 NonNull::new(ptr)
142 .map(|ptr| Self { ptr })
143 .ok_or(Error::OutOfMemory)
144 }
145
146 pub fn new_linestring_empty() -> Result<Self> {
147 let ptr = unsafe { tg_geom_sys::tg_geom_new_linestring_empty() };
148 NonNull::new(ptr)
149 .map(|ptr| Self { ptr })
150 .ok_or(Error::OutOfMemory)
151 }
152
153 pub fn new_polygon(poly: &Poly) -> Result<Self> {
154 let ptr = unsafe { tg_geom_sys::tg_geom_new_polygon(poly.as_ptr()) };
155 NonNull::new(ptr)
156 .map(|ptr| Self { ptr })
157 .ok_or(Error::OutOfMemory)
158 }
159
160 pub fn new_polygon_z(poly: &Poly, extra_coords: &[f64]) -> Result<Self> {
161 let ptr = unsafe {
162 tg_geom_sys::tg_geom_new_polygon_z(
163 poly.as_ptr(),
164 extra_coords.as_ptr(),
165 extra_coords.len() as libc::c_int,
166 )
167 };
168 NonNull::new(ptr)
169 .map(|ptr| Self { ptr })
170 .ok_or(Error::OutOfMemory)
171 }
172
173 pub fn new_polygon_m(poly: &Poly, extra_coords: &[f64]) -> Result<Self> {
174 let ptr = unsafe {
175 tg_geom_sys::tg_geom_new_polygon_m(
176 poly.as_ptr(),
177 extra_coords.as_ptr(),
178 extra_coords.len() as libc::c_int,
179 )
180 };
181 NonNull::new(ptr)
182 .map(|ptr| Self { ptr })
183 .ok_or(Error::OutOfMemory)
184 }
185
186 pub fn new_polygon_zm(poly: &Poly, extra_coords: &[f64]) -> Result<Self> {
187 let ptr = unsafe {
188 tg_geom_sys::tg_geom_new_polygon_zm(
189 poly.as_ptr(),
190 extra_coords.as_ptr(),
191 extra_coords.len() as libc::c_int,
192 )
193 };
194 NonNull::new(ptr)
195 .map(|ptr| Self { ptr })
196 .ok_or(Error::OutOfMemory)
197 }
198
199 pub fn new_polygon_empty() -> Result<Self> {
200 let ptr = unsafe { tg_geom_sys::tg_geom_new_polygon_empty() };
201 NonNull::new(ptr)
202 .map(|ptr| Self { ptr })
203 .ok_or(Error::OutOfMemory)
204 }
205
206 pub fn new_multipoint(points: &[Point]) -> Result<Self> {
207 let ptr = unsafe {
208 tg_geom_sys::tg_geom_new_multipoint(
209 points.as_ptr() as *const tg_geom_sys::tg_point,
210 points.len() as libc::c_int,
211 )
212 };
213 NonNull::new(ptr)
214 .map(|ptr| Self { ptr })
215 .ok_or(Error::OutOfMemory)
216 }
217
218 pub fn new_multipoint_z(points: &[Point], extra_coords: &[f64]) -> Result<Self> {
219 let ptr = unsafe {
220 tg_geom_sys::tg_geom_new_multipoint_z(
221 points.as_ptr() as *const tg_geom_sys::tg_point,
222 points.len() as libc::c_int,
223 extra_coords.as_ptr(),
224 extra_coords.len() as libc::c_int,
225 )
226 };
227 NonNull::new(ptr)
228 .map(|ptr| Self { ptr })
229 .ok_or(Error::OutOfMemory)
230 }
231
232 pub fn new_multipoint_m(points: &[Point], extra_coords: &[f64]) -> Result<Self> {
233 let ptr = unsafe {
234 tg_geom_sys::tg_geom_new_multipoint_m(
235 points.as_ptr() as *const tg_geom_sys::tg_point,
236 points.len() as libc::c_int,
237 extra_coords.as_ptr(),
238 extra_coords.len() as libc::c_int,
239 )
240 };
241 NonNull::new(ptr)
242 .map(|ptr| Self { ptr })
243 .ok_or(Error::OutOfMemory)
244 }
245
246 pub fn new_multipoint_zm(points: &[Point], extra_coords: &[f64]) -> Result<Self> {
247 let ptr = unsafe {
248 tg_geom_sys::tg_geom_new_multipoint_zm(
249 points.as_ptr() as *const tg_geom_sys::tg_point,
250 points.len() as libc::c_int,
251 extra_coords.as_ptr(),
252 extra_coords.len() as libc::c_int,
253 )
254 };
255 NonNull::new(ptr)
256 .map(|ptr| Self { ptr })
257 .ok_or(Error::OutOfMemory)
258 }
259
260 pub fn new_multipoint_empty() -> Result<Self> {
261 let ptr = unsafe { tg_geom_sys::tg_geom_new_multipoint_empty() };
262 NonNull::new(ptr)
263 .map(|ptr| Self { ptr })
264 .ok_or(Error::OutOfMemory)
265 }
266
267 pub fn new_multilinestring(lines: &[&Line]) -> Result<Self> {
268 let line_ptrs: Vec<*const tg_geom_sys::tg_line> =
269 lines.iter().map(|l| l.as_ptr()).collect();
270 let ptr = unsafe {
271 tg_geom_sys::tg_geom_new_multilinestring(line_ptrs.as_ptr(), lines.len() as libc::c_int)
272 };
273 NonNull::new(ptr)
274 .map(|ptr| Self { ptr })
275 .ok_or(Error::OutOfMemory)
276 }
277
278 pub fn new_multilinestring_z(lines: &[&Line], extra_coords: &[f64]) -> Result<Self> {
279 let line_ptrs: Vec<*const tg_geom_sys::tg_line> =
280 lines.iter().map(|l| l.as_ptr()).collect();
281 let ptr = unsafe {
282 tg_geom_sys::tg_geom_new_multilinestring_z(
283 line_ptrs.as_ptr(),
284 lines.len() as libc::c_int,
285 extra_coords.as_ptr(),
286 extra_coords.len() as libc::c_int,
287 )
288 };
289 NonNull::new(ptr)
290 .map(|ptr| Self { ptr })
291 .ok_or(Error::OutOfMemory)
292 }
293
294 pub fn new_multilinestring_m(lines: &[&Line], extra_coords: &[f64]) -> Result<Self> {
295 let line_ptrs: Vec<*const tg_geom_sys::tg_line> =
296 lines.iter().map(|l| l.as_ptr()).collect();
297 let ptr = unsafe {
298 tg_geom_sys::tg_geom_new_multilinestring_m(
299 line_ptrs.as_ptr(),
300 lines.len() as libc::c_int,
301 extra_coords.as_ptr(),
302 extra_coords.len() as libc::c_int,
303 )
304 };
305 NonNull::new(ptr)
306 .map(|ptr| Self { ptr })
307 .ok_or(Error::OutOfMemory)
308 }
309
310 pub fn new_multilinestring_zm(lines: &[&Line], extra_coords: &[f64]) -> Result<Self> {
311 let line_ptrs: Vec<*const tg_geom_sys::tg_line> =
312 lines.iter().map(|l| l.as_ptr()).collect();
313 let ptr = unsafe {
314 tg_geom_sys::tg_geom_new_multilinestring_zm(
315 line_ptrs.as_ptr(),
316 lines.len() as libc::c_int,
317 extra_coords.as_ptr(),
318 extra_coords.len() as libc::c_int,
319 )
320 };
321 NonNull::new(ptr)
322 .map(|ptr| Self { ptr })
323 .ok_or(Error::OutOfMemory)
324 }
325
326 pub fn new_multilinestring_empty() -> Result<Self> {
327 let ptr = unsafe { tg_geom_sys::tg_geom_new_multilinestring_empty() };
328 NonNull::new(ptr)
329 .map(|ptr| Self { ptr })
330 .ok_or(Error::OutOfMemory)
331 }
332
333 pub fn new_multipolygon(polys: &[&Poly]) -> Result<Self> {
334 let poly_ptrs: Vec<*const tg_geom_sys::tg_poly> =
335 polys.iter().map(|p| p.as_ptr()).collect();
336 let ptr = unsafe {
337 tg_geom_sys::tg_geom_new_multipolygon(poly_ptrs.as_ptr(), polys.len() as libc::c_int)
338 };
339 NonNull::new(ptr)
340 .map(|ptr| Self { ptr })
341 .ok_or(Error::OutOfMemory)
342 }
343
344 pub fn new_multipolygon_z(polys: &[&Poly], extra_coords: &[f64]) -> Result<Self> {
345 let poly_ptrs: Vec<*const tg_geom_sys::tg_poly> =
346 polys.iter().map(|p| p.as_ptr()).collect();
347 let ptr = unsafe {
348 tg_geom_sys::tg_geom_new_multipolygon_z(
349 poly_ptrs.as_ptr(),
350 polys.len() as libc::c_int,
351 extra_coords.as_ptr(),
352 extra_coords.len() as libc::c_int,
353 )
354 };
355 NonNull::new(ptr)
356 .map(|ptr| Self { ptr })
357 .ok_or(Error::OutOfMemory)
358 }
359
360 pub fn new_multipolygon_m(polys: &[&Poly], extra_coords: &[f64]) -> Result<Self> {
361 let poly_ptrs: Vec<*const tg_geom_sys::tg_poly> =
362 polys.iter().map(|p| p.as_ptr()).collect();
363 let ptr = unsafe {
364 tg_geom_sys::tg_geom_new_multipolygon_m(
365 poly_ptrs.as_ptr(),
366 polys.len() as libc::c_int,
367 extra_coords.as_ptr(),
368 extra_coords.len() as libc::c_int,
369 )
370 };
371 NonNull::new(ptr)
372 .map(|ptr| Self { ptr })
373 .ok_or(Error::OutOfMemory)
374 }
375
376 pub fn new_multipolygon_zm(polys: &[&Poly], extra_coords: &[f64]) -> Result<Self> {
377 let poly_ptrs: Vec<*const tg_geom_sys::tg_poly> =
378 polys.iter().map(|p| p.as_ptr()).collect();
379 let ptr = unsafe {
380 tg_geom_sys::tg_geom_new_multipolygon_zm(
381 poly_ptrs.as_ptr(),
382 polys.len() as libc::c_int,
383 extra_coords.as_ptr(),
384 extra_coords.len() as libc::c_int,
385 )
386 };
387 NonNull::new(ptr)
388 .map(|ptr| Self { ptr })
389 .ok_or(Error::OutOfMemory)
390 }
391
392 pub fn new_multipolygon_empty() -> Result<Self> {
393 let ptr = unsafe { tg_geom_sys::tg_geom_new_multipolygon_empty() };
394 NonNull::new(ptr)
395 .map(|ptr| Self { ptr })
396 .ok_or(Error::OutOfMemory)
397 }
398
399 pub fn new_geometrycollection(geoms: &[&Geom]) -> Result<Self> {
400 let geom_ptrs: Vec<*const tg_geom_sys::tg_geom> =
401 geoms.iter().map(|g| g.as_ptr()).collect();
402 let ptr = unsafe {
403 tg_geom_sys::tg_geom_new_geometrycollection(
404 geom_ptrs.as_ptr(),
405 geoms.len() as libc::c_int,
406 )
407 };
408 NonNull::new(ptr)
409 .map(|ptr| Self { ptr })
410 .ok_or(Error::OutOfMemory)
411 }
412
413 pub fn new_geometrycollection_empty() -> Result<Self> {
414 let ptr = unsafe { tg_geom_sys::tg_geom_new_geometrycollection_empty() };
415 NonNull::new(ptr)
416 .map(|ptr| Self { ptr })
417 .ok_or(Error::OutOfMemory)
418 }
419
420 pub unsafe fn from_raw(ptr: *mut tg_geom_sys::tg_geom) -> Option<Self> {
423 NonNull::new(ptr).map(|ptr| Self { ptr })
424 }
425
426 #[inline]
427 pub fn as_ptr(&self) -> *const tg_geom_sys::tg_geom {
428 self.ptr.as_ptr()
429 }
430
431 pub fn into_raw(self) -> *mut tg_geom_sys::tg_geom {
432 let ptr = self.ptr.as_ptr();
433 core::mem::forget(self);
434 ptr
435 }
436
437 pub fn copy(&self) -> Result<Self> {
439 let ptr = unsafe { tg_geom_sys::tg_geom_copy(self.ptr.as_ptr()) };
440 NonNull::new(ptr)
441 .map(|ptr| Self { ptr })
442 .ok_or(Error::CopyFailed)
443 }
444
445 pub fn clone_ref(&self) -> Result<Self> {
447 let ptr = unsafe { tg_geom_sys::tg_geom_clone(self.ptr.as_ptr()) };
448 NonNull::new(ptr)
449 .map(|ptr| Self { ptr })
450 .ok_or(Error::CopyFailed)
451 }
452
453 pub fn is_feature(&self) -> bool {
454 unsafe { tg_geom_sys::tg_geom_is_feature(self.ptr.as_ptr()) }
455 }
456
457 pub fn is_featurecollection(&self) -> bool {
458 unsafe { tg_geom_sys::tg_geom_is_featurecollection(self.ptr.as_ptr()) }
459 }
460
461 pub fn point(&self) -> Point {
462 let p = unsafe { tg_geom_sys::tg_geom_point(self.ptr.as_ptr()) };
463 p.into()
464 }
465
466 pub fn line(&self) -> Option<LineRef<'_>> {
467 let ptr = unsafe { tg_geom_sys::tg_geom_line(self.ptr.as_ptr()) };
468 unsafe { LineRef::from_raw(ptr) }
469 }
470
471 pub fn poly(&self) -> Option<PolyRef<'_>> {
472 let ptr = unsafe { tg_geom_sys::tg_geom_poly(self.ptr.as_ptr()) };
473 unsafe { PolyRef::from_raw(ptr) }
474 }
475
476 pub fn num_points(&self) -> usize {
477 unsafe { tg_geom_sys::tg_geom_num_points(self.ptr.as_ptr()) as usize }
478 }
479
480 pub fn point_at(&self, index: usize) -> Option<Point> {
481 if index >= self.num_points() {
482 None
483 } else {
484 let p =
485 unsafe { tg_geom_sys::tg_geom_point_at(self.ptr.as_ptr(), index as libc::c_int) };
486 Some(p.into())
487 }
488 }
489
490 pub fn num_lines(&self) -> usize {
491 unsafe { tg_geom_sys::tg_geom_num_lines(self.ptr.as_ptr()) as usize }
492 }
493
494 pub fn line_at(&self, index: usize) -> Option<LineRef<'_>> {
495 if index >= self.num_lines() {
496 None
497 } else {
498 let ptr =
499 unsafe { tg_geom_sys::tg_geom_line_at(self.ptr.as_ptr(), index as libc::c_int) };
500 unsafe { LineRef::from_raw(ptr) }
501 }
502 }
503
504 pub fn num_polys(&self) -> usize {
505 unsafe { tg_geom_sys::tg_geom_num_polys(self.ptr.as_ptr()) as usize }
506 }
507
508 pub fn poly_at(&self, index: usize) -> Option<PolyRef<'_>> {
509 if index >= self.num_polys() {
510 None
511 } else {
512 let ptr =
513 unsafe { tg_geom_sys::tg_geom_poly_at(self.ptr.as_ptr(), index as libc::c_int) };
514 unsafe { PolyRef::from_raw(ptr) }
515 }
516 }
517
518 pub fn num_geometries(&self) -> usize {
519 unsafe { tg_geom_sys::tg_geom_num_geometries(self.ptr.as_ptr()) as usize }
520 }
521
522 pub fn geometry_at(&self, index: usize) -> Option<GeomRef<'_>> {
523 if index >= self.num_geometries() {
524 None
525 } else {
526 let ptr = unsafe {
527 tg_geom_sys::tg_geom_geometry_at(self.ptr.as_ptr(), index as libc::c_int)
528 };
529 unsafe { GeomRef::from_raw(ptr) }
530 }
531 }
532
533 pub fn extra_json(&self) -> Option<&str> {
534 let ptr = unsafe { tg_geom_sys::tg_geom_extra_json(self.ptr.as_ptr()) };
535 if ptr.is_null() {
536 None
537 } else {
538 let c_str = unsafe { CStr::from_ptr(ptr) };
539 c_str.to_str().ok()
540 }
541 }
542
543 pub fn dims(&self) -> i32 {
544 unsafe { tg_geom_sys::tg_geom_dims(self.ptr.as_ptr()) }
545 }
546
547 pub fn has_z(&self) -> bool {
548 unsafe { tg_geom_sys::tg_geom_has_z(self.ptr.as_ptr()) }
549 }
550
551 pub fn has_m(&self) -> bool {
552 unsafe { tg_geom_sys::tg_geom_has_m(self.ptr.as_ptr()) }
553 }
554
555 pub fn z(&self) -> f64 {
556 unsafe { tg_geom_sys::tg_geom_z(self.ptr.as_ptr()) }
557 }
558
559 pub fn m(&self) -> f64 {
560 unsafe { tg_geom_sys::tg_geom_m(self.ptr.as_ptr()) }
561 }
562
563 pub fn extra_coords(&self) -> &[f64] {
564 let ptr = unsafe { tg_geom_sys::tg_geom_extra_coords(self.ptr.as_ptr()) };
565 let len = unsafe { tg_geom_sys::tg_geom_num_extra_coords(self.ptr.as_ptr()) as usize };
566 if ptr.is_null() || len == 0 {
567 &[]
568 } else {
569 unsafe { core::slice::from_raw_parts(ptr, len) }
570 }
571 }
572
573 pub fn memsize(&self) -> usize {
574 unsafe { tg_geom_sys::tg_geom_memsize(self.ptr.as_ptr()) }
575 }
576
577 pub fn fullrect(&self) -> (i32, [f64; 4], [f64; 4]) {
579 let mut min = [0.0f64; 4];
580 let mut max = [0.0f64; 4];
581 let dims = unsafe {
582 tg_geom_sys::tg_geom_fullrect(self.ptr.as_ptr(), min.as_mut_ptr(), max.as_mut_ptr())
583 };
584 (dims, min, max)
585 }
586
587 pub fn error(&self) -> Option<&str> {
588 let ptr = unsafe { tg_geom_sys::tg_geom_error(self.ptr.as_ptr()) };
589 if ptr.is_null() {
590 None
591 } else {
592 let c_str = unsafe { CStr::from_ptr(ptr) };
593 c_str.to_str().ok()
594 }
595 }
596
597 pub fn equals(&self, other: &Geom) -> bool {
598 unsafe { tg_geom_sys::tg_geom_equals(self.ptr.as_ptr(), other.ptr.as_ptr()) }
599 }
600
601 pub fn intersects(&self, other: &Geom) -> bool {
602 unsafe { tg_geom_sys::tg_geom_intersects(self.ptr.as_ptr(), other.ptr.as_ptr()) }
603 }
604
605 pub fn disjoint(&self, other: &Geom) -> bool {
606 unsafe { tg_geom_sys::tg_geom_disjoint(self.ptr.as_ptr(), other.ptr.as_ptr()) }
607 }
608
609 pub fn contains(&self, other: &Geom) -> bool {
610 unsafe { tg_geom_sys::tg_geom_contains(self.ptr.as_ptr(), other.ptr.as_ptr()) }
611 }
612
613 pub fn within(&self, other: &Geom) -> bool {
614 unsafe { tg_geom_sys::tg_geom_within(self.ptr.as_ptr(), other.ptr.as_ptr()) }
615 }
616
617 pub fn covers(&self, other: &Geom) -> bool {
618 unsafe { tg_geom_sys::tg_geom_covers(self.ptr.as_ptr(), other.ptr.as_ptr()) }
619 }
620
621 pub fn coveredby(&self, other: &Geom) -> bool {
622 unsafe { tg_geom_sys::tg_geom_coveredby(self.ptr.as_ptr(), other.ptr.as_ptr()) }
623 }
624
625 pub fn touches(&self, other: &Geom) -> bool {
626 unsafe { tg_geom_sys::tg_geom_touches(self.ptr.as_ptr(), other.ptr.as_ptr()) }
627 }
628
629 pub fn intersects_rect(&self, rect: Rect) -> bool {
630 unsafe { tg_geom_sys::tg_geom_intersects_rect(self.ptr.as_ptr(), rect.into()) }
631 }
632
633 pub fn intersects_xy(&self, x: f64, y: f64) -> bool {
634 unsafe { tg_geom_sys::tg_geom_intersects_xy(self.ptr.as_ptr(), x, y) }
635 }
636
637 pub fn search<F>(&self, rect: Rect, mut iter: F)
640 where
641 F: FnMut(GeomRef<'_>, usize) -> bool,
642 {
643 unsafe extern "C" fn trampoline<F>(
644 geom: *const tg_geom_sys::tg_geom, index: libc::c_int, udata: *mut libc::c_void,
645 ) -> bool
646 where
647 F: FnMut(GeomRef<'_>, usize) -> bool,
648 {
649 let iter = unsafe { &mut *(udata as *mut F) };
650 if let Some(geom_ref) = unsafe { GeomRef::from_raw(geom) } {
651 iter(geom_ref, index as usize)
652 } else {
653 true }
655 }
656
657 unsafe {
658 tg_geom_sys::tg_geom_search(
659 self.ptr.as_ptr(),
660 rect.into(),
661 Some(trampoline::<F>),
662 core::ptr::from_mut(&mut iter).cast(),
663 );
664 }
665 }
666}
667
668impl Drop for Geom {
669 fn drop(&mut self) {
670 unsafe { tg_geom_sys::tg_geom_free(self.ptr.as_ptr()) }
671 }
672}
673
674impl core::fmt::Debug for Geom {
675 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
676 f.debug_struct("Geom")
677 .field("type", &self.geom_type())
678 .field("is_empty", &self.is_empty())
679 .field("rect", &self.rect())
680 .finish()
681 }
682}
683
684impl core::fmt::Display for Geom {
685 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
686 write!(f, "{}", self.to_wkt())
687 }
688}
689
690impl PartialEq for Geom {
691 fn eq(&self, other: &Self) -> bool {
692 self.equals(other)
693 }
694}
695
696unsafe impl Send for Geom {}
698unsafe impl Sync for Geom {}
699
700#[derive(Clone, Copy)]
702pub struct GeomRef<'a> {
703 ptr: *const tg_geom_sys::tg_geom,
704 _marker: PhantomData<&'a ()>,
705}
706
707unsafe impl Send for GeomRef<'_> {}
708unsafe impl Sync for GeomRef<'_> {}
709
710impl GeomRef<'_> {
711 impl_geom_methods!(|s: &Self| s.ptr);
712
713 #[inline]
716 pub unsafe fn from_raw(ptr: *const tg_geom_sys::tg_geom) -> Option<Self> {
717 if ptr.is_null() {
718 None
719 } else {
720 Some(Self {
721 ptr,
722 _marker: PhantomData,
723 })
724 }
725 }
726
727 #[inline]
728 pub fn as_ptr(&self) -> *const tg_geom_sys::tg_geom {
729 self.ptr
730 }
731
732 pub fn to_owned(&self) -> Result<Geom> {
733 let ptr = unsafe { tg_geom_sys::tg_geom_copy(self.ptr) };
734 NonNull::new(ptr)
735 .map(|ptr| Geom { ptr })
736 .ok_or(Error::CopyFailed)
737 }
738}
739
740#[cfg(test)]
741mod tests {
742 use super::*;
743 use crate::{Line, Poly, Ring};
744
745 fn p(x: f64, y: f64) -> Point {
746 Point::new(x, y)
747 }
748
749 fn r(min_x: f64, min_y: f64, max_x: f64, max_y: f64) -> Rect {
750 Rect::from_coords(min_x, min_y, max_x, max_y)
751 }
752
753 fn rectangle() -> Vec<Point> {
754 vec![
755 p(0.0, 0.0),
756 p(10.0, 0.0),
757 p(10.0, 10.0),
758 p(0.0, 10.0),
759 p(0.0, 0.0),
760 ]
761 }
762
763 fn octagon() -> Vec<Point> {
764 vec![
765 p(3.0, 0.0),
766 p(7.0, 0.0),
767 p(10.0, 3.0),
768 p(10.0, 7.0),
769 p(7.0, 10.0),
770 p(3.0, 10.0),
771 p(0.0, 7.0),
772 p(0.0, 3.0),
773 p(3.0, 0.0),
774 ]
775 }
776
777 #[test]
778 fn test_geom_point() {
779 let geom = Geom::new_point(p(5.0, 6.0)).unwrap();
780 assert_eq!(geom.geom_type(), GeomType::Point);
781 assert_eq!(geom.rect(), r(5.0, 6.0, 5.0, 6.0));
782 assert_eq!(geom.point(), p(5.0, 6.0));
783 assert!(!geom.is_empty());
784 assert_eq!(geom.memsize(), 24);
785 }
786
787 #[test]
788 fn test_geom_point_z() {
789 let geom = Geom::new_point_z(p(5.0, 6.0), 7.0).unwrap();
790 assert_eq!(geom.z(), 7.0);
791 assert!(geom.has_z());
792 assert!(!geom.has_m());
793 assert_eq!(geom.dims(), 3);
794 }
795
796 #[test]
797 fn test_geom_point_m() {
798 let geom = Geom::new_point_m(p(5.0, 6.0), 7.0).unwrap();
799 assert_eq!(geom.m(), 7.0);
800 assert!(!geom.has_z());
801 assert!(geom.has_m());
802 }
803
804 #[test]
805 fn test_geom_point_zm() {
806 let geom = Geom::new_point_zm(p(5.0, 6.0), 7.0, 8.0).unwrap();
807 assert_eq!(geom.z(), 7.0);
808 assert_eq!(geom.m(), 8.0);
809 assert!(geom.has_z());
810 assert!(geom.has_m());
811 assert_eq!(geom.dims(), 4);
812 }
813
814 #[test]
815 fn test_geom_point_empty() {
816 let geom = Geom::new_point_empty().unwrap();
817 assert_eq!(geom.geom_type(), GeomType::Point);
818 assert!(geom.is_empty());
819 }
820
821 #[test]
822 fn test_geom_linestring() {
823 let line = Line::new(&[p(2.0, 2.0), p(8.0, 8.0)]).unwrap();
824 let geom = Geom::new_linestring(&line).unwrap();
825 assert_eq!(geom.geom_type(), GeomType::LineString);
826 assert!(!geom.is_empty());
827 assert!(geom.line().is_some());
828 assert!(geom.poly().is_none());
829 }
830
831 #[test]
832 fn test_geom_linestring_z() {
833 let line = Line::new(&[p(2.0, 2.0), p(8.0, 8.0)]).unwrap();
834 let geom = Geom::new_linestring_z(&line, &[1.0, 2.0]).unwrap();
835 assert_eq!(geom.dims(), 3);
836 assert!(geom.has_z());
837 assert_eq!(geom.extra_coords().len(), 2);
838 }
839
840 #[test]
841 fn test_geom_linestring_zm() {
842 let line = Line::new(&[p(2.0, 2.0), p(8.0, 8.0)]).unwrap();
843 let geom = Geom::new_linestring_zm(&line, &[1.0, 2.0, 3.0, 4.0]).unwrap();
844 assert_eq!(geom.dims(), 4);
845 assert!(geom.has_z());
846 assert!(geom.has_m());
847 assert_eq!(geom.extra_coords().len(), 4);
848 }
849
850 #[test]
851 fn test_geom_linestring_empty() {
852 let geom = Geom::new_linestring_empty().unwrap();
853 assert_eq!(geom.geom_type(), GeomType::LineString);
854 assert!(geom.is_empty());
855 assert!(geom.line().is_none());
856 }
857
858 #[test]
859 fn test_geom_polygon() {
860 let ring = Ring::new(&rectangle()).unwrap();
861 let poly = Poly::new_simple(&ring).unwrap();
862 let geom = Geom::new_polygon(&poly).unwrap();
863
864 assert_eq!(geom.geom_type(), GeomType::Polygon);
865 assert!(!geom.is_empty());
866 assert!(geom.poly().is_some());
867 assert!(geom.line().is_none());
868 assert_eq!(geom.num_lines(), 0);
869 assert_eq!(geom.num_polys(), 0);
870 assert_eq!(geom.num_points(), 0);
871 assert_eq!(geom.num_geometries(), 0);
872 }
873
874 #[test]
875 fn test_geom_polygon_with_hole() {
876 let exterior = Ring::new(&octagon()).unwrap();
877 let hole = Ring::new(&[
878 p(4.0, 4.0),
879 p(6.0, 4.0),
880 p(6.0, 6.0),
881 p(4.0, 6.0),
882 p(4.0, 4.0),
883 ])
884 .unwrap();
885 let poly = Poly::new(&exterior, &[&hole]).unwrap();
886 let geom = Geom::new_polygon(&poly).unwrap();
887
888 assert_eq!(geom.geom_type(), GeomType::Polygon);
889 let poly_ref = geom.poly().unwrap();
890 assert_eq!(poly_ref.num_holes(), 1);
891 }
892
893 #[test]
894 fn test_geom_polygon_empty() {
895 let geom = Geom::new_polygon_empty().unwrap();
896 assert_eq!(geom.geom_type(), GeomType::Polygon);
897 assert!(geom.is_empty());
898 assert!(geom.poly().is_none());
899 }
900
901 #[test]
902 fn test_geom_multipoint() {
903 let points = vec![p(1.0, 2.0), p(3.0, 4.0), p(5.0, 6.0)];
904 let geom = Geom::new_multipoint(&points).unwrap();
905
906 assert_eq!(geom.geom_type(), GeomType::MultiPoint);
907 assert!(!geom.is_empty());
908 assert_eq!(geom.num_points(), 3);
909 assert_eq!(geom.point_at(0).unwrap(), p(1.0, 2.0));
910 assert_eq!(geom.point_at(1).unwrap(), p(3.0, 4.0));
911 assert_eq!(geom.point_at(2).unwrap(), p(5.0, 6.0));
912 assert!(geom.point_at(3).is_none());
913 }
914
915 #[test]
916 fn test_geom_multipoint_empty() {
917 let geom = Geom::new_multipoint_empty().unwrap();
918 assert_eq!(geom.geom_type(), GeomType::MultiPoint);
919 assert!(geom.is_empty());
920 assert_eq!(geom.num_points(), 0);
921 }
922
923 #[test]
924 fn test_geom_multilinestring() {
925 let line1 = Line::new(&[p(0.0, 0.0), p(1.0, 1.0)]).unwrap();
926 let line2 = Line::new(&[p(2.0, 2.0), p(3.0, 3.0)]).unwrap();
927 let geom = Geom::new_multilinestring(&[&line1, &line2]).unwrap();
928
929 assert_eq!(geom.geom_type(), GeomType::MultiLineString);
930 assert!(!geom.is_empty());
931 assert_eq!(geom.num_lines(), 2);
932 assert!(geom.line_at(0).is_some());
933 assert!(geom.line_at(1).is_some());
934 assert!(geom.line_at(2).is_none());
935 }
936
937 #[test]
938 fn test_geom_multilinestring_empty() {
939 let geom = Geom::new_multilinestring_empty().unwrap();
940 assert_eq!(geom.geom_type(), GeomType::MultiLineString);
941 assert!(geom.is_empty());
942 assert_eq!(geom.num_lines(), 0);
943 }
944
945 #[test]
946 fn test_geom_multipolygon() {
947 let ring1 = Ring::new(&[
948 p(0.0, 0.0),
949 p(1.0, 0.0),
950 p(1.0, 1.0),
951 p(0.0, 1.0),
952 p(0.0, 0.0),
953 ])
954 .unwrap();
955 let poly1 = Poly::new_simple(&ring1).unwrap();
956 let ring2 = Ring::new(&[
957 p(5.0, 5.0),
958 p(6.0, 5.0),
959 p(6.0, 6.0),
960 p(5.0, 6.0),
961 p(5.0, 5.0),
962 ])
963 .unwrap();
964 let poly2 = Poly::new_simple(&ring2).unwrap();
965 let geom = Geom::new_multipolygon(&[&poly1, &poly2]).unwrap();
966
967 assert_eq!(geom.geom_type(), GeomType::MultiPolygon);
968 assert!(!geom.is_empty());
969 assert_eq!(geom.num_polys(), 2);
970 assert!(geom.poly_at(0).is_some());
971 assert!(geom.poly_at(1).is_some());
972 assert!(geom.poly_at(2).is_none());
973 }
974
975 #[test]
976 fn test_geom_multipolygon_empty() {
977 let geom = Geom::new_multipolygon_empty().unwrap();
978 assert_eq!(geom.geom_type(), GeomType::MultiPolygon);
979 assert!(geom.is_empty());
980 assert_eq!(geom.num_polys(), 0);
981 }
982
983 #[test]
984 fn test_geom_geometrycollection() {
985 let point_geom = Geom::new_point(p(1.0, 2.0)).unwrap();
986 let line = Line::new(&[p(0.0, 0.0), p(1.0, 1.0)]).unwrap();
987 let line_geom = Geom::new_linestring(&line).unwrap();
988 let geom = Geom::new_geometrycollection(&[&point_geom, &line_geom]).unwrap();
989
990 assert_eq!(geom.geom_type(), GeomType::GeometryCollection);
991 assert!(!geom.is_empty());
992 assert_eq!(geom.num_geometries(), 2);
993 assert!(geom.geometry_at(0).is_some());
994 assert!(geom.geometry_at(1).is_some());
995 assert!(geom.geometry_at(2).is_none());
996 }
997
998 #[test]
999 fn test_geom_geometrycollection_empty() {
1000 let geom = Geom::new_geometrycollection_empty().unwrap();
1001 assert_eq!(geom.geom_type(), GeomType::GeometryCollection);
1002 assert!(geom.is_empty());
1003 assert_eq!(geom.num_geometries(), 0);
1004 }
1005
1006 #[test]
1007 fn test_geom_covers() {
1008 let point = Geom::new_point(p(5.0, 5.0)).unwrap();
1009 let ring = Ring::new(&rectangle()).unwrap();
1010 let poly = Poly::new_simple(&ring).unwrap();
1011 let polygon = Geom::new_polygon(&poly).unwrap();
1012
1013 assert!(polygon.covers(&point));
1015 assert!(point.covers(&point));
1017 assert!(!point.covers(&polygon));
1019 }
1020
1021 #[test]
1022 fn test_geom_intersects() {
1023 let point = Geom::new_point(p(5.0, 5.0)).unwrap();
1024 let ring = Ring::new(&rectangle()).unwrap();
1025 let poly = Poly::new_simple(&ring).unwrap();
1026 let polygon = Geom::new_polygon(&poly).unwrap();
1027
1028 assert!(polygon.intersects(&point));
1030 assert!(point.intersects(&polygon));
1031
1032 let outside_point = Geom::new_point(p(20.0, 20.0)).unwrap();
1034 assert!(!polygon.intersects(&outside_point));
1035 }
1036
1037 #[test]
1038 fn test_geom_intersects_rect() {
1039 let ring = Ring::new(&[
1040 p(1.0, 1.0),
1041 p(2.0, 1.0),
1042 p(2.0, 2.0),
1043 p(1.0, 2.0),
1044 p(1.0, 1.0),
1045 ])
1046 .unwrap();
1047 let poly = Poly::new_simple(&ring).unwrap();
1048 let geom = Geom::new_polygon(&poly).unwrap();
1049
1050 assert!(!geom.intersects_rect(r(5.0, 5.0, 6.0, 6.0)));
1052 assert!(geom.intersects_rect(r(1.5, 1.5, 2.5, 2.5)));
1054 }
1055
1056 #[test]
1057 fn test_geom_contains() {
1058 let ring = Ring::new(&rectangle()).unwrap();
1059 let poly = Poly::new_simple(&ring).unwrap();
1060 let polygon = Geom::new_polygon(&poly).unwrap();
1061 let point_inside = Geom::new_point(p(5.0, 5.0)).unwrap();
1062 let point_outside = Geom::new_point(p(20.0, 20.0)).unwrap();
1063
1064 assert!(polygon.contains(&point_inside));
1065 assert!(!polygon.contains(&point_outside));
1066 }
1067
1068 #[test]
1069 fn test_geom_within() {
1070 let ring = Ring::new(&rectangle()).unwrap();
1071 let poly = Poly::new_simple(&ring).unwrap();
1072 let polygon = Geom::new_polygon(&poly).unwrap();
1073 let point_inside = Geom::new_point(p(5.0, 5.0)).unwrap();
1074
1075 assert!(point_inside.within(&polygon));
1076 assert!(!polygon.within(&point_inside));
1077 }
1078
1079 #[test]
1080 fn test_geom_disjoint() {
1081 let ring = Ring::new(&rectangle()).unwrap();
1082 let poly = Poly::new_simple(&ring).unwrap();
1083 let polygon = Geom::new_polygon(&poly).unwrap();
1084 let point_outside = Geom::new_point(p(20.0, 20.0)).unwrap();
1085 let point_inside = Geom::new_point(p(5.0, 5.0)).unwrap();
1086
1087 assert!(polygon.disjoint(&point_outside));
1088 assert!(!polygon.disjoint(&point_inside));
1089 }
1090
1091 #[test]
1092 fn test_geom_copy() {
1093 let geom = Geom::new_point(p(1.0, 2.0)).unwrap();
1094 let copy = geom.copy().unwrap();
1095 assert!(copy.intersects_xy(1.0, 2.0));
1096 assert_eq!(geom.geom_type(), copy.geom_type());
1097 }
1098
1099 #[test]
1100 fn test_geom_clone_ref() {
1101 let geom = Geom::new_point(p(1.0, 2.0)).unwrap();
1102 let cloned = geom.clone_ref().unwrap();
1103 assert_eq!(geom.geom_type(), cloned.geom_type());
1104 assert_eq!(geom.point(), cloned.point());
1105 }
1106
1107 #[test]
1108 fn test_geom_equals() {
1109 let geom1 = Geom::new_point(p(1.0, 2.0)).unwrap();
1110 let geom2 = Geom::new_point(p(1.0, 2.0)).unwrap();
1111 let geom3 = Geom::new_point(p(3.0, 4.0)).unwrap();
1112
1113 assert!(geom1.equals(&geom2));
1114 assert!(!geom1.equals(&geom3));
1115 }
1116
1117 #[test]
1118 fn test_geom_partial_eq() {
1119 let geom1 = Geom::new_point(p(1.0, 2.0)).unwrap();
1120 let geom2 = Geom::new_point(p(1.0, 2.0)).unwrap();
1121 let geom3 = Geom::new_point(p(3.0, 4.0)).unwrap();
1122
1123 assert!(geom1 == geom2);
1124 assert!(geom1 != geom3);
1125 }
1126
1127 #[test]
1128 fn test_geom_fullrect() {
1129 let geom = Geom::new_point_zm(p(1.0, 2.0), 3.0, 4.0).unwrap();
1130 let (dims, min, _max) = geom.fullrect();
1131 assert!(dims >= 2);
1132 assert_eq!(min[0], 1.0);
1133 assert_eq!(min[1], 2.0);
1134 }
1135
1136 #[test]
1137 fn test_geom_memsize() {
1138 let point = Geom::new_point(p(1.0, 2.0)).unwrap();
1139 assert_eq!(point.memsize(), 24);
1140
1141 let point_zm = Geom::new_point_zm(p(1.0, 2.0), 3.0, 4.0).unwrap();
1142 assert!(point_zm.memsize() > point.memsize());
1143 }
1144
1145 #[test]
1146 fn test_geom_debug() {
1147 let geom = Geom::new_point(p(1.0, 2.0)).unwrap();
1148 let debug_str = format!("{geom:?}");
1149 assert!(debug_str.contains("Geom"));
1150 assert!(debug_str.contains("Point"));
1151 }
1152
1153 #[test]
1154 fn test_geom_display() {
1155 let geom = Geom::new_point(p(1.0, 2.0)).unwrap();
1156 let display_str = format!("{geom}");
1157 assert!(display_str.contains("POINT"));
1158 }
1159
1160 #[test]
1161 fn test_geom_send_sync() {
1162 fn assert_send<T: Send>() {}
1163 fn assert_sync<T: Sync>() {}
1164 assert_send::<Geom>();
1165 assert_sync::<Geom>();
1166 }
1167
1168 #[test]
1169 fn test_geom_raw_pointer() {
1170 let geom = Geom::new_point(p(1.0, 2.0)).unwrap();
1171 let ptr = geom.into_raw();
1172 let recovered = unsafe { Geom::from_raw(ptr).unwrap() };
1173 assert_eq!(recovered.point(), p(1.0, 2.0));
1174 }
1175
1176 #[test]
1177 fn test_geomref() {
1178 let gc_child = Geom::new_point(p(1.0, 2.0)).unwrap();
1179 let gc = Geom::new_geometrycollection(&[&gc_child]).unwrap();
1180
1181 let geom_ref = gc.geometry_at(0).unwrap();
1182 assert_eq!(geom_ref.geom_type(), GeomType::Point);
1183
1184 let owned = geom_ref.to_owned().unwrap();
1185 assert_eq!(owned.geom_type(), GeomType::Point);
1186 }
1187
1188 #[test]
1189 fn test_geom_search() {
1190 let point1 = Geom::new_point(p(1.0, 1.0)).unwrap();
1191 let point2 = Geom::new_point(p(5.0, 5.0)).unwrap();
1192 let point3 = Geom::new_point(p(10.0, 10.0)).unwrap();
1193 let gc = Geom::new_geometrycollection(&[&point1, &point2, &point3]).unwrap();
1194
1195 let mut found = Vec::new();
1196 gc.search(r(0.0, 0.0, 6.0, 6.0), |geom, idx| {
1197 found.push(idx);
1198 let _ = geom.geom_type();
1199 true
1200 });
1201 assert!(!found.is_empty());
1203 }
1204
1205 #[test]
1206 fn test_geom_intersects_xy() {
1207 let ring = Ring::new(&[
1208 p(0.0, 0.0),
1209 p(10.0, 0.0),
1210 p(10.0, 10.0),
1211 p(0.0, 10.0),
1212 p(0.0, 0.0),
1213 ])
1214 .unwrap();
1215 let poly = Poly::new_simple(&ring).unwrap();
1216 let geom = Geom::new_polygon(&poly).unwrap();
1217
1218 assert!(geom.intersects_xy(5.0, 5.0));
1219 assert!(!geom.intersects_xy(20.0, 20.0));
1220 }
1221
1222 #[test]
1223 fn test_geom_extra_json() {
1224 let geom = Geom::new_point(p(1.0, 2.0)).unwrap();
1226 assert!(geom.extra_json().is_none() || geom.extra_json().is_some());
1228 }
1229
1230 #[test]
1231 fn test_geom_feature_types() {
1232 let geom = Geom::new_point(p(1.0, 2.0)).unwrap();
1233 assert!(!geom.is_feature());
1235 assert!(!geom.is_featurecollection());
1236 }
1237
1238 #[test]
1239 fn test_geom_coveredby() {
1240 let ring = Ring::new(&rectangle()).unwrap();
1241 let poly = Poly::new_simple(&ring).unwrap();
1242 let polygon = Geom::new_polygon(&poly).unwrap();
1243 let point_inside = Geom::new_point(p(5.0, 5.0)).unwrap();
1244
1245 assert!(point_inside.coveredby(&polygon));
1246 assert!(!polygon.coveredby(&point_inside));
1247 }
1248
1249 #[test]
1250 fn test_geom_touches() {
1251 let ring = Ring::new(&rectangle()).unwrap();
1252 let poly = Poly::new_simple(&ring).unwrap();
1253 let polygon = Geom::new_polygon(&poly).unwrap();
1254 let point_on_boundary = Geom::new_point(p(0.0, 5.0)).unwrap();
1256
1257 assert!(polygon.touches(&point_on_boundary));
1258 }
1259
1260 fn concave1() -> Vec<Point> {
1261 vec![
1262 p(5.0, 0.0),
1263 p(10.0, 0.0),
1264 p(10.0, 10.0),
1265 p(0.0, 10.0),
1266 p(0.0, 5.0),
1267 p(5.0, 5.0),
1268 p(5.0, 0.0),
1269 ]
1270 }
1271
1272 fn small_hole() -> Vec<Point> {
1273 vec![
1274 p(4.0, 4.0),
1275 p(6.0, 4.0),
1276 p(6.0, 6.0),
1277 p(4.0, 6.0),
1278 p(4.0, 4.0),
1279 ]
1280 }
1281
1282 #[test]
1283 fn test_geom_polygon_with_hole_contains_point() {
1284 let exterior = Ring::new(&octagon()).unwrap();
1285 let hole = Ring::new(&small_hole()).unwrap();
1286 let poly = Poly::new(&exterior, &[&hole]).unwrap();
1287 let polygon = Geom::new_polygon(&poly).unwrap();
1288
1289 let point_outside = Geom::new_point(p(0.0, 0.0)).unwrap();
1291 assert!(!polygon.contains(&point_outside));
1292 assert!(!polygon.intersects(&point_outside));
1293
1294 let point_on_edge = Geom::new_point(p(0.0, 5.0)).unwrap();
1296 assert!(polygon.covers(&point_on_edge));
1297
1298 let point_in_polygon = Geom::new_point(p(3.0, 5.0)).unwrap();
1300 assert!(polygon.contains(&point_in_polygon));
1301 assert!(polygon.intersects(&point_in_polygon));
1302
1303 let point_in_hole = Geom::new_point(p(5.0, 5.0)).unwrap();
1305 assert!(!polygon.contains(&point_in_hole));
1306 assert!(!polygon.intersects(&point_in_hole));
1307 }
1308
1309 #[test]
1310 fn test_geom_polygon_with_hole_intersects_rect() {
1311 let exterior = Ring::new(&octagon()).unwrap();
1312 let hole = Ring::new(&small_hole()).unwrap();
1313 let poly = Poly::new(&exterior, &[&hole]).unwrap();
1314 let polygon = Geom::new_polygon(&poly).unwrap();
1315
1316 assert!(polygon.intersects_rect(r(0.0, 4.0, 4.0, 6.0)));
1318
1319 assert!(polygon.intersects_rect(r(4.0, 4.0, 6.0, 6.0)));
1321
1322 assert!(!polygon.intersects_rect(r(4.1, 4.1, 5.9, 5.9)));
1324
1325 let moved = r(11.0, 0.0, 21.0, 10.0);
1327 assert!(!polygon.intersects_rect(moved));
1328 }
1329
1330 #[test]
1331 fn test_geom_concave_polygon_contains() {
1332 let concave = Ring::new(&concave1()).unwrap();
1333 let poly = Poly::new_simple(&concave).unwrap();
1334 let polygon = Geom::new_polygon(&poly).unwrap();
1335
1336 let point_in_notch = Geom::new_point(p(2.5, 2.5)).unwrap();
1338 assert!(!polygon.contains(&point_in_notch));
1339
1340 let point_inside = Geom::new_point(p(7.5, 5.0)).unwrap();
1342 assert!(polygon.contains(&point_inside));
1343
1344 let point_in_vertical = Geom::new_point(p(2.5, 7.5)).unwrap();
1346 assert!(polygon.contains(&point_in_vertical));
1347
1348 let point_at_corner = Geom::new_point(p(5.0, 5.0)).unwrap();
1350 assert!(polygon.covers(&point_at_corner));
1351 }
1352
1353 #[test]
1354 fn test_geom_boundary_covers_vs_contains() {
1355 let ring = Ring::new(&rectangle()).unwrap();
1356 let poly = Poly::new_simple(&ring).unwrap();
1357 let polygon = Geom::new_polygon(&poly).unwrap();
1358
1359 let corner = Geom::new_point(p(0.0, 0.0)).unwrap();
1361 assert!(polygon.covers(&corner));
1362 assert!(polygon.touches(&corner));
1363
1364 let edge_point = Geom::new_point(p(5.0, 0.0)).unwrap();
1366 assert!(polygon.covers(&edge_point));
1367 assert!(polygon.touches(&edge_point));
1368
1369 let interior = Geom::new_point(p(5.0, 5.0)).unwrap();
1371 assert!(polygon.covers(&interior));
1372 assert!(polygon.contains(&interior));
1373 assert!(!polygon.touches(&interior));
1374 }
1375
1376 #[test]
1377 fn test_geom_line_touches_polygon() {
1378 let ring = Ring::new(&rectangle()).unwrap();
1379 let poly = Poly::new_simple(&ring).unwrap();
1380 let polygon = Geom::new_polygon(&poly).unwrap();
1381
1382 let line_on_edge = Line::new(&[p(2.0, 0.0), p(8.0, 0.0)]).unwrap();
1384 let geom_edge = Geom::new_linestring(&line_on_edge).unwrap();
1385 assert!(polygon.intersects(&geom_edge));
1386
1387 let line_from_corner = Line::new(&[p(0.0, 0.0), p(-5.0, -5.0)]).unwrap();
1389 let geom_corner = Geom::new_linestring(&line_from_corner).unwrap();
1390 assert!(polygon.touches(&geom_corner));
1391 }
1392
1393 #[test]
1394 fn test_geom_line_polygon_intersects() {
1395 let ring = Ring::new(&rectangle()).unwrap();
1396 let poly = Poly::new_simple(&ring).unwrap();
1397 let polygon = Geom::new_polygon(&poly).unwrap();
1398
1399 let line_inside = Line::new(&[p(2.0, 2.0), p(8.0, 8.0)]).unwrap();
1401 let geom_inside = Geom::new_linestring(&line_inside).unwrap();
1402 assert!(polygon.intersects(&geom_inside));
1403 assert!(polygon.covers(&geom_inside));
1404
1405 let line_cross = Line::new(&[p(-5.0, 5.0), p(15.0, 5.0)]).unwrap();
1407 let geom_cross = Geom::new_linestring(&line_cross).unwrap();
1408 assert!(polygon.intersects(&geom_cross));
1409 assert!(!polygon.covers(&geom_cross));
1410
1411 let line_outside = Line::new(&[p(15.0, 15.0), p(20.0, 20.0)]).unwrap();
1413 let geom_outside = Geom::new_linestring(&line_outside).unwrap();
1414 assert!(!polygon.intersects(&geom_outside));
1415 assert!(polygon.disjoint(&geom_outside));
1416 }
1417
1418 #[test]
1419 fn test_geom_line_through_hole() {
1420 let exterior = Ring::new(&octagon()).unwrap();
1421 let hole = Ring::new(&small_hole()).unwrap();
1422 let poly = Poly::new(&exterior, &[&hole]).unwrap();
1423 let polygon = Geom::new_polygon(&poly).unwrap();
1424
1425 let line_around = Line::new(&[p(3.0, 3.0), p(3.0, 7.0), p(7.0, 7.0), p(7.0, 3.0)]).unwrap();
1427 let geom_around = Geom::new_linestring(&line_around).unwrap();
1428 assert!(polygon.intersects(&geom_around));
1429 assert!(polygon.covers(&geom_around));
1430
1431 let line_through = Line::new(&[p(3.0, 5.0), p(7.0, 5.0)]).unwrap();
1433 let geom_through = Geom::new_linestring(&line_through).unwrap();
1434 assert!(polygon.intersects(&geom_through));
1435 assert!(!polygon.covers(&geom_through)); }
1437
1438 #[test]
1439 fn test_geom_polygon_covers_polygon() {
1440 let big_ring = Ring::new(&rectangle()).unwrap();
1441 let big_poly = Poly::new_simple(&big_ring).unwrap();
1442 let big = Geom::new_polygon(&big_poly).unwrap();
1443
1444 let small_ring = Ring::new(&[
1446 p(2.0, 2.0),
1447 p(8.0, 2.0),
1448 p(8.0, 8.0),
1449 p(2.0, 8.0),
1450 p(2.0, 2.0),
1451 ])
1452 .unwrap();
1453 let small_poly = Poly::new_simple(&small_ring).unwrap();
1454 let small = Geom::new_polygon(&small_poly).unwrap();
1455
1456 assert!(big.covers(&small));
1457 assert!(big.contains(&small));
1458 assert!(!small.covers(&big));
1459 assert!(small.within(&big));
1460 }
1461
1462 #[test]
1463 fn test_geom_polygon_overlap() {
1464 let ring1 = Ring::new(&[
1465 p(0.0, 0.0),
1466 p(10.0, 0.0),
1467 p(10.0, 10.0),
1468 p(0.0, 10.0),
1469 p(0.0, 0.0),
1470 ])
1471 .unwrap();
1472 let poly1 = Poly::new_simple(&ring1).unwrap();
1473 let geom1 = Geom::new_polygon(&poly1).unwrap();
1474
1475 let ring2 = Ring::new(&[
1476 p(5.0, 5.0),
1477 p(15.0, 5.0),
1478 p(15.0, 15.0),
1479 p(5.0, 15.0),
1480 p(5.0, 5.0),
1481 ])
1482 .unwrap();
1483 let poly2 = Poly::new_simple(&ring2).unwrap();
1484 let geom2 = Geom::new_polygon(&poly2).unwrap();
1485
1486 assert!(geom1.intersects(&geom2));
1488 assert!(geom2.intersects(&geom1));
1489 assert!(!geom1.covers(&geom2));
1490 assert!(!geom2.covers(&geom1));
1491 assert!(!geom1.disjoint(&geom2));
1492 }
1493
1494 #[test]
1495 fn test_geom_polygon_disjoint() {
1496 let ring1 = Ring::new(&rectangle()).unwrap();
1497 let poly1 = Poly::new_simple(&ring1).unwrap();
1498 let geom1 = Geom::new_polygon(&poly1).unwrap();
1499
1500 let ring2 = Ring::new(&[
1501 p(20.0, 20.0),
1502 p(30.0, 20.0),
1503 p(30.0, 30.0),
1504 p(20.0, 30.0),
1505 p(20.0, 20.0),
1506 ])
1507 .unwrap();
1508 let poly2 = Poly::new_simple(&ring2).unwrap();
1509 let geom2 = Geom::new_polygon(&poly2).unwrap();
1510
1511 assert!(geom1.disjoint(&geom2));
1512 assert!(geom2.disjoint(&geom1));
1513 assert!(!geom1.intersects(&geom2));
1514 }
1515
1516 #[test]
1517 fn test_geom_polygon_adjacent() {
1518 let ring1 = Ring::new(&[
1519 p(0.0, 0.0),
1520 p(10.0, 0.0),
1521 p(10.0, 10.0),
1522 p(0.0, 10.0),
1523 p(0.0, 0.0),
1524 ])
1525 .unwrap();
1526 let poly1 = Poly::new_simple(&ring1).unwrap();
1527 let geom1 = Geom::new_polygon(&poly1).unwrap();
1528
1529 let ring2 = Ring::new(&[
1531 p(10.0, 0.0),
1532 p(20.0, 0.0),
1533 p(20.0, 10.0),
1534 p(10.0, 10.0),
1535 p(10.0, 0.0),
1536 ])
1537 .unwrap();
1538 let poly2 = Poly::new_simple(&ring2).unwrap();
1539 let geom2 = Geom::new_polygon(&poly2).unwrap();
1540
1541 assert!(geom1.touches(&geom2));
1543 assert!(geom1.intersects(&geom2));
1544 }
1545
1546 #[test]
1547 fn test_geom_polygon_hole_relations() {
1548 let exterior = Ring::new(&[
1549 p(0.0, 0.0),
1550 p(20.0, 0.0),
1551 p(20.0, 20.0),
1552 p(0.0, 20.0),
1553 p(0.0, 0.0),
1554 ])
1555 .unwrap();
1556 let hole = Ring::new(&[
1557 p(5.0, 5.0),
1558 p(15.0, 5.0),
1559 p(15.0, 15.0),
1560 p(5.0, 15.0),
1561 p(5.0, 5.0),
1562 ])
1563 .unwrap();
1564 let poly_with_hole = Poly::new(&exterior, &[&hole]).unwrap();
1565 let geom_with_hole = Geom::new_polygon(&poly_with_hole).unwrap();
1566
1567 let inner_ring = Ring::new(&[
1569 p(7.0, 7.0),
1570 p(13.0, 7.0),
1571 p(13.0, 13.0),
1572 p(7.0, 13.0),
1573 p(7.0, 7.0),
1574 ])
1575 .unwrap();
1576 let inner_poly = Poly::new_simple(&inner_ring).unwrap();
1577 let inner = Geom::new_polygon(&inner_poly).unwrap();
1578
1579 assert!(geom_with_hole.disjoint(&inner));
1581 assert!(!geom_with_hole.contains(&inner));
1582 assert!(!geom_with_hole.covers(&inner));
1583 }
1584
1585 #[test]
1586 fn test_geom_identical_polygons() {
1587 let ring = Ring::new(&rectangle()).unwrap();
1588 let poly = Poly::new_simple(&ring).unwrap();
1589 let geom1 = Geom::new_polygon(&poly).unwrap();
1590 let geom2 = Geom::new_polygon(&poly).unwrap();
1591
1592 assert!(geom1.equals(&geom2));
1593 assert!(geom1.covers(&geom2));
1594 assert!(geom2.covers(&geom1));
1595 assert!(geom1.intersects(&geom2));
1596 }
1597
1598 #[test]
1599 fn test_geom_multipolygon_contains() {
1600 let ring1 = Ring::new(&rectangle()).unwrap();
1601 let poly1 = Poly::new_simple(&ring1).unwrap();
1602
1603 let ring2 = Ring::new(&[
1604 p(20.0, 0.0),
1605 p(30.0, 0.0),
1606 p(30.0, 10.0),
1607 p(20.0, 10.0),
1608 p(20.0, 0.0),
1609 ])
1610 .unwrap();
1611 let poly2 = Poly::new_simple(&ring2).unwrap();
1612
1613 let mp = Geom::new_multipolygon(&[&poly1, &poly2]).unwrap();
1614
1615 let p1 = Geom::new_point(p(5.0, 5.0)).unwrap();
1617 assert!(mp.contains(&p1));
1618
1619 let p2 = Geom::new_point(p(25.0, 5.0)).unwrap();
1621 assert!(mp.contains(&p2));
1622
1623 let p3 = Geom::new_point(p(15.0, 5.0)).unwrap();
1625 assert!(!mp.contains(&p3));
1626 }
1627}