1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139
// Copyright 2017 The Spade Developers.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
use cgmath as cg;
use num::{Signed, BigInt, BigRational, zero};
use num::rational::Ratio;
use boundingrect::BoundingRect;
use bigvec::{AdaptiveInt};
use point_traits::{PointN, PointNExtensions, TwoDimensional};
use std::fmt::Debug;
/// Number types that can be used with spade.
///
/// Number types that can be used for spade's datastructures will need to
/// implement this trait. Can be an integer or floating point type.
/// Note that `copy` is not necessary to support big integers from the `num`
/// crate.
pub trait SpadeNum: Signed + Clone + Debug + PartialOrd { }
/// Floating point types that can be used with spade.
///
/// Used by all operations that require precise division.
pub trait SpadeFloat: SpadeNum + cg::BaseFloat { }
impl SpadeNum for i32 { }
impl SpadeNum for i64 { }
impl SpadeNum for f32 { }
impl SpadeNum for f64 { }
impl SpadeFloat for f32 { }
impl SpadeFloat for f64 { }
impl SpadeNum for BigInt { }
impl SpadeNum for BigRational { }
impl SpadeNum for AdaptiveInt { }
impl SpadeNum for Ratio<AdaptiveInt> { }
/// Describes objects that can be located by r-trees.
///
/// See the `primitives` module for some basic implementations which can also serve
/// as useful examples for own implementations.
pub trait SpatialObject {
/// The object's point type.
type Point: PointN;
/// Returns the object's minimal bounding rectangle.
///
/// The minimal bounding rectangle is the smallest axis aligned rectangle that completely
/// contains the object.
/// <b>Note:</b> The rectangle must be as small as possible, otherwise some queries
/// might fail.
fn mbr(&self) -> BoundingRect<Self::Point>;
/// Returns the squared euclidean distance from the object's contour.
/// Returns a value samller than zero if the point is contained within the object.
fn distance2(&self, point: &Self::Point) -> <Self::Point as PointN>::Scalar;
/// Returns true if a given point is contained in this object.
fn contains(&self, point: &Self::Point) -> bool {
self.distance2(point) <= zero()
}
}
/// An object that has a position.
///
/// Describes a point like object that has a well defined position.
/// Since this trait also implements `SpatialObject`, `HasPosition` can serve as a quick and
/// easy implementation of your own pointlike objects that can be inserted into r-trees
/// or delaunay triangulations:
///
/// ```
/// extern crate cgmath;
/// extern crate spade;
///
/// use cgmath::Point3;
/// use spade::HasPosition;
/// use spade::rtree::RTree;
///
/// struct MyPoint {
/// position: Point3<f32>,
/// my_data: i32,
/// }
/// impl HasPosition for MyPoint {
/// type Point = Point3<f32>;
/// fn position(&self) -> Point3<f32> {
/// self.position
/// }
/// }
/// fn main() {
/// let mut tree = RTree::new();
/// tree.insert(MyPoint { position: Point3::new(0.0, 1.0, 0.0), my_data: 42 });
/// assert_eq!(tree.lookup(&Point3::new(0.0, 1.0, 0.0)).unwrap().my_data, 42);
/// }
/// ```
pub trait HasPosition {
/// The object's point type
type Point: PointN;
/// Return's the object's position.
fn position(&self) -> Self::Point;
}
/// An object with a two dimensional position.
///
/// This trait is similar to `HasPosition`, but is only implemented for two dimensional points.
pub trait HasPosition2D: HasPosition where Self::Point: TwoDimensional { }
impl <V: HasPosition> HasPosition2D for V where V::Point: TwoDimensional { }
impl <V> HasPosition for V where V: PointN {
type Point = V;
fn position(&self) -> V {
self.clone()
}
}
impl <S> SpatialObject for S where S: HasPosition {
type Point = S::Point;
fn mbr(&self) -> BoundingRect<S::Point> {
BoundingRect::from_point(self.position())
}
fn distance2(&self, point: &S::Point) -> <S::Point as PointN>::Scalar {
self.position().sub(point).length2()
}
fn contains(&self, point: &S::Point) -> bool {
self.position() == *point
}
}