```
#[allow(unused_variables)]
use std::ops::Add;
#[derive(Debug, Clone, Copy, PartialEq)]
pub struct Point {
x: f64,
y: f64,
}
impl Point {
pub fn new(x: i64, y: i64) -> Self {
Self {
x: x as f64,
y: y as f64,
}
}
pub fn magnitude(&self) -> f64 {
f64::sqrt(f64::powf(self.x, 2.0) + f64::powf(self.y, 2.0))
}
pub fn dist(&self, other: Point) -> f64 {
let dx = other.x - self.x;
let dy = other.y - self.y;
f64::sqrt(f64::powf(dx, 2.0) + f64::powf(dy, 2.0))
}
}
impl Add for Point {
type Output = Point;
fn add(self, other: Point) -> Point {
Point {
x: self.x + other.x,
y: self.y + other.y,
}
}
}
trait Circumference {
fn circumference(&self) -> f64;
}
pub struct Polygon {
points: Vec<Point>,
}
impl Polygon {
pub fn new() -> Self {
Self {
points: Vec::new(),
}
}
pub fn add_point(&mut self, point: Point) {
self.points.push(point);
}
pub fn left_most_point(&self) -> Option<Point> {
self.points.iter().min_by(|a, b| a.x.partial_cmp(&b.x).unwrap()).cloned()
}
fn iter(&self) -> std::slice::Iter<Point> {
self.points.iter()
}
}
impl Circumference for Polygon {
fn circumference(&self) -> f64 {
let p1 = &self.points;
let mut p2 = self.points.clone();
p2.rotate_right(1);
let mut sum = 0.0;
for i in 0..p1.len() {
sum += p1[i].dist(p2[i]);
}
sum
}
}
pub struct Circle {
center: Point,
radius: f64
}
impl Circle {
pub fn new(center: Point, radius: i64) -> Self {
Self {
center,
radius: radius as f64,
}
}
}
impl Circumference for Circle {
fn circumference(&self) -> f64 {
2.0 * std::f64::consts::PI * self.radius
}
}
pub enum Shape {
Polygon(Polygon),
Circle(Circle),
}
// impl Shape {
// pub fn from(obj: dyn Any) -> Shape {
// match obj {
// Polygon => Shape::Polygon(obj),
// Circle => Shape::Circle(obj),
// }
// }
// }
impl Shape {
// pub fn from(obj: dyn Any) -> Shape {
// match obj {
// Polygon => Shape::Polygon(obj.downcast_ref::<crate::Polygon>()),
// Circle => Shape::Circle(obj.downcast_ref::<crate::Circle>()),
// }
// }
// pub fn from(polygon: Polygon) -> Self {
// Shape::Polygon(polygon)
// }
// pub fn from(circle: Circle) -> Self {
// Shape::Circle(circle)
// }
}
impl From<Polygon> for Shape {
fn from(polygon: Polygon) -> Self {
Shape::Polygon(polygon)
}
}
impl From<Circle> for Shape {
fn from(circle: Circle) -> Self {
Shape::Circle(circle)
}
}
impl Circumference for Shape {
fn circumference(&self) -> f64 {
match self {
Shape::Polygon(polygon) => polygon.circumference(),
Shape::Circle(circle) => circle.circumference(),
}
}
}
#[cfg(test)]
mod tests {
use super::*;
fn round_two_digits(x: f64) -> f64 {
(x * 100.0).round() / 100.0
}
#[test]
fn test_point_magnitude() {
let p1 = Point::new(12, 13);
assert_eq!(round_two_digits(p1.magnitude()), 17.69);
}
#[test]
fn test_point_dist() {
let p1 = Point::new(10, 10);
let p2 = Point::new(14, 13);
assert_eq!(round_two_digits(p1.dist(p2)), 5.00);
}
#[test]
fn test_point_add() {
let p1 = Point::new(16, 16);
let p2 = p1 + Point::new(-4, 3);
assert_eq!(p2, Point::new(12, 19));
}
#[test]
fn test_polygon_left_most_point() {
let p1 = Point::new(12, 13);
let p2 = Point::new(16, 16);
let mut poly = Polygon::new();
poly.add_point(p1);
poly.add_point(p2);
assert_eq!(poly.left_most_point(), Some(p1));
}
#[test]
fn test_polygon_iter() {
let p1 = Point::new(12, 13);
let p2 = Point::new(16, 16);
let mut poly = Polygon::new();
poly.add_point(p1);
poly.add_point(p2);
let points = poly.iter().cloned().collect::<Vec<_>>();
assert_eq!(points, vec![Point::new(12, 13), Point::new(16, 16)]);
}
#[test]
fn test_shape_circumferences() {
let mut poly = Polygon::new();
poly.add_point(Point::new(12, 13));
poly.add_point(Point::new(17, 11));
poly.add_point(Point::new(16, 16));
let shapes = vec![
Shape::from(poly),
Shape::from(Circle::new(Point::new(10, 20), 5)),
];
let circumferences = shapes
.iter()
.map(Shape::circumference)
.map(round_two_digits)
.collect::<Vec<_>>();
assert_eq!(circumferences, vec![15.48, 31.42]);
}
}
#[allow(dead_code)]
fn main() {}
```