pub use super::circle_field::*;
use serde_derive::{Deserialize, Serialize};
use crate::utils::conversions::Angle;
use crate::magnets::{GetCenter, GetField, MagnetTrait};
use crate::points::{Point2, PolarPoint};
use crate::MagnetError;
use std::fmt;
#[derive(Copy, Clone, Debug, Deserialize, Serialize, PartialEq)]
pub struct Circle {
pub radius: f64,
pub center: Point2,
pub alpha: Angle,
pub jr: f64,
pub phi: Angle,
pub jx: f64,
pub jy: f64,
}
impl Default for Circle {
fn default() -> Self {
Circle {
radius: 1.0,
center: Point2::new(0.0, 0.0),
alpha: Angle::Degrees(0.0),
jr: 1.0,
phi: Angle::Degrees(90.0),
jx: 0.0,
jy: 1.0,
}
}
}
impl Circle {
pub fn new<C>(radius: f64, center: C, alpha: Angle, jr: f64, phi: Angle) -> Circle
where
C: GetCenter<Point2>,
{
let phi_rad = phi.to_radians();
Circle {
radius,
center: center.center(),
alpha,
jr,
phi,
jx: jr * phi_rad.cos(),
jy: jr * phi_rad.sin(),
}
}
}
impl fmt::Display for Circle {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(
f,
"[r: {}\tc: {},\talpha:{}\tJ ({:.3}, {:.3})]",
self.radius,
self.center,
self.alpha.to_degrees(),
self.jr,
self.phi.to_degrees()
)
}
}
impl MagnetTrait<[f64; 2], Point2, f64, PolarPoint> for Circle {
fn center(&self) -> Point2 {
self.center
}
fn size(&self) -> f64 {
self.radius
}
fn magnetisation(self) -> PolarPoint {
PolarPoint::new(self.jr, self.phi.to_radians())
}
fn set_center(&mut self, point: Point2) {
self.center = point;
}
fn set_size(&mut self, radius: f64) {
self.radius = radius;
}
fn set_magnetisation(&mut self, magnetisation: PolarPoint) {
self.jr = magnetisation.rho;
self.phi = Angle::Radians(magnetisation.phi);
self.jx = self.jr * (magnetisation.phi.cos());
self.jy = self.jr * (magnetisation.phi.sin());
}
}
impl GetField<&Point2, Result<Point2, MagnetError>> for Circle {
fn field(&self, point: &Point2) -> Result<Point2, MagnetError> {
get_field_circle(self, point)
}
}
impl GetField<&(f64, f64), Result<(f64, f64), MagnetError>> for Circle {
fn field(&self, point: &(f64, f64)) -> Result<(f64, f64), MagnetError> {
let field_vec = get_field_circle(
self,
&Point2 {
x: point.0,
y: point.1,
},
)?;
Ok((field_vec.x, field_vec.y))
}
}
#[cfg(test)]
mod tests {
use crate::utils::comparison::nearly_equal;
use super::*;
#[test]
fn test_circle_surface_field_y_rot_90() {
let magnet = Circle::new(
1.0,
(0.0, 0.0),
Angle::Degrees(90.0),
1.0,
Angle::Degrees(90.0),
);
let point1 = Point2::new(0.0, 1.0);
let field = magnet.field(&point1).unwrap();
let comp_field = Point2::new(0.5, 0.0);
assert!(nearly_equal(field.x, comp_field.x));
assert!(nearly_equal(field.y, comp_field.y));
}
}