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
140
141
142
143
144
145
146
147
148
149
150
151
//! Wrapper enum for 2D primitives

use cgmath::{BaseFloat, Point2, Vector2};
use cgmath::prelude::*;

use {Aabb2, Line2, Ray2};
use prelude::*;
use primitive::{Circle, ConvexPolygon, Particle2, Rectangle, Square};

/// Wrapper enum for 2D primitives, that also implements the `Primitive` trait, making it easier
/// to use many different primitives in algorithms.
#[derive(Debug, Clone, PartialEq)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
pub enum Primitive2<S> {
    /// Particle
    Particle(Particle2<S>),
    /// Line
    Line(Line2<S>),
    /// Circle
    Circle(Circle<S>),
    /// Rectangle
    Rectangle(Rectangle<S>),
    /// Square
    Square(Square<S>),
    /// Convex polygon with any number of vertices.
    ConvexPolygon(ConvexPolygon<S>),
}

impl<S> From<Particle2<S>> for Primitive2<S> {
    fn from(particle: Particle2<S>) -> Primitive2<S> {
        Primitive2::Particle(particle)
    }
}

impl<S> From<Line2<S>> for Primitive2<S> {
    fn from(line: Line2<S>) -> Primitive2<S> {
        Primitive2::Line(line)
    }
}

impl<S> From<Circle<S>> for Primitive2<S> {
    fn from(circle: Circle<S>) -> Primitive2<S> {
        Primitive2::Circle(circle)
    }
}

impl<S> From<Rectangle<S>> for Primitive2<S> {
    fn from(rectangle: Rectangle<S>) -> Primitive2<S> {
        Primitive2::Rectangle(rectangle)
    }
}

impl<S> From<Square<S>> for Primitive2<S> {
    fn from(rectangle: Square<S>) -> Primitive2<S> {
        Primitive2::Square(rectangle)
    }
}

impl<S> From<ConvexPolygon<S>> for Primitive2<S> {
    fn from(polygon: ConvexPolygon<S>) -> Primitive2<S> {
        Primitive2::ConvexPolygon(polygon)
    }
}

impl<S> ComputeBound<Aabb2<S>> for Primitive2<S>
where
    S: BaseFloat,
{
    fn compute_bound(&self) -> Aabb2<S> {
        match *self {
            Primitive2::Particle(_) => Aabb2::zero(),
            Primitive2::Line(ref line) => line.compute_bound(),
            Primitive2::Circle(ref circle) => circle.compute_bound(),
            Primitive2::Rectangle(ref rectangle) => rectangle.compute_bound(),
            Primitive2::Square(ref square) => square.compute_bound(),
            Primitive2::ConvexPolygon(ref polygon) => polygon.compute_bound(),
        }
    }
}

impl<S> Primitive for Primitive2<S>
where
    S: BaseFloat,
{
    type Point = Point2<S>;

    fn support_point<T>(&self, direction: &Vector2<S>, transform: &T) -> Point2<S>
    where
        T: Transform<Point2<S>>,
    {
        match *self {
            Primitive2::Particle(_) => transform.transform_point(Point2::origin()),
            Primitive2::Line(ref line) => line.support_point(direction, transform),
            Primitive2::Circle(ref circle) => circle.support_point(direction, transform),
            Primitive2::Rectangle(ref rectangle) => rectangle.support_point(direction, transform),
            Primitive2::Square(ref square) => square.support_point(direction, transform),
            Primitive2::ConvexPolygon(ref polygon) => polygon.support_point(direction, transform),
        }
    }
}

impl<S> DiscreteTransformed<Ray2<S>> for Primitive2<S>
where
    S: BaseFloat,
{
    type Point = Point2<S>;

    fn intersects_transformed<T>(&self, ray: &Ray2<S>, transform: &T) -> bool
    where
        T: Transform<Self::Point>,
    {
        match *self {
            Primitive2::Particle(ref particle) => particle.intersects_transformed(ray, transform),
            Primitive2::Line(ref line) => line.intersects_transformed(ray, transform),
            Primitive2::Circle(ref circle) => circle.intersects_transformed(ray, transform),
            Primitive2::Rectangle(ref rectangle) => {
                rectangle.intersects_transformed(ray, transform)
            }
            Primitive2::Square(ref square) => square.intersects_transformed(ray, transform),
            Primitive2::ConvexPolygon(ref polygon) => {
                polygon.intersects_transformed(ray, transform)
            }
        }
    }
}

impl<S> ContinuousTransformed<Ray2<S>> for Primitive2<S>
where
    S: BaseFloat,
{
    type Point = Point2<S>;
    type Result = Point2<S>;

    fn intersection_transformed<T>(&self, ray: &Ray2<S>, transform: &T) -> Option<Point2<S>>
    where
        T: Transform<Point2<S>>,
    {
        match *self {
            Primitive2::Particle(ref particle) => particle.intersection_transformed(ray, transform),
            Primitive2::Line(ref line) => line.intersection_transformed(ray, transform),
            Primitive2::Circle(ref circle) => circle.intersection_transformed(ray, transform),
            Primitive2::Rectangle(ref rectangle) => {
                rectangle.intersection_transformed(ray, transform)
            }
            Primitive2::Square(ref square) => square.intersection_transformed(ray, transform),
            Primitive2::ConvexPolygon(ref polygon) => {
                polygon.intersection_transformed(ray, transform)
            }
        }
    }
}