CurrentLoop: factor out the tangent calculation
This commit is contained in:
@@ -6,7 +6,22 @@ mod units;
|
||||
pub use line::Line2d;
|
||||
pub use polygon::Polygon2d;
|
||||
pub use region::{
|
||||
Cube, CylinderZ, Dilate, InvertedRegion, Memoize, Region, Sphere, Spiral, SwapXZ, SwapYZ, Torus, Translate, Union, WorldRegion, Wrap
|
||||
Cube,
|
||||
CylinderZ,
|
||||
Dilate,
|
||||
HasTangent,
|
||||
InvertedRegion,
|
||||
Memoize,
|
||||
Region,
|
||||
Sphere,
|
||||
Spiral,
|
||||
SwapXZ,
|
||||
SwapYZ,
|
||||
Torus,
|
||||
Translate,
|
||||
Union,
|
||||
WorldRegion,
|
||||
Wrap,
|
||||
};
|
||||
pub use units::{Coord, Meters, OrdMeters, Index};
|
||||
|
||||
|
@@ -1,5 +1,7 @@
|
||||
use crate::geom::{Coord, Meters, OrdMeters};
|
||||
|
||||
use coremem_cross::vec::Vec3;
|
||||
|
||||
use dyn_clone::{self, DynClone};
|
||||
use rayon::prelude::*;
|
||||
use serde::{Serialize, Deserialize};
|
||||
@@ -16,6 +18,13 @@ pub trait Region: Send + Sync + DynClone {
|
||||
}
|
||||
dyn_clone::clone_trait_object!(Region);
|
||||
|
||||
/// some (volume) which has a tangent vector everywhere inside/on it.
|
||||
/// for example, a cylinder has tangents everywhere except its axis.
|
||||
/// the return vector should be normalized, or zero.
|
||||
pub trait HasTangent {
|
||||
fn tangent(&self, p: Meters) -> Vec3<f32>;
|
||||
}
|
||||
|
||||
pub fn and<T1: Region + 'static, T2: Region + 'static>(r1: T1, r2: T2) -> Intersection {
|
||||
Intersection::new().and(r1).and(r2)
|
||||
}
|
||||
|
@@ -6,7 +6,7 @@ use serde::{Serialize, Deserialize};
|
||||
use std::fmt::{self, Display};
|
||||
use std::ops::Range;
|
||||
|
||||
use super::Region;
|
||||
use super::{HasTangent, Region};
|
||||
|
||||
#[derive(Copy, Clone, Serialize, Deserialize)]
|
||||
pub struct CylinderZ {
|
||||
@@ -104,6 +104,15 @@ impl Region for Torus {
|
||||
}
|
||||
}
|
||||
|
||||
impl HasTangent for Torus {
|
||||
fn tangent(&self, coord: Meters) -> Vec3<f32> {
|
||||
let normal = self.axis();
|
||||
let to_coord = *coord - *self.center();
|
||||
// this creates a tangent which always points "counter-clockwise" along the shape
|
||||
normal.cross(to_coord).norm()
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone, Serialize, Deserialize)]
|
||||
pub struct Sphere {
|
||||
center: Meters,
|
||||
|
@@ -1,4 +1,4 @@
|
||||
use crate::geom::{Meters, Region, Torus, WorldRegion};
|
||||
use crate::geom::{HasTangent as _, Meters, Region, Torus, WorldRegion};
|
||||
use crate::real::{Real as _, ToFloat as _};
|
||||
use crate::cross::vec::{Vec3, Vec3u};
|
||||
use crate::sim::AbstractSim;
|
||||
@@ -309,7 +309,7 @@ impl<S: AbstractSim> AbstractMeasurement<S> for Current {
|
||||
#[derive(Clone, Serialize, Deserialize)]
|
||||
pub struct CurrentLoop {
|
||||
name: String,
|
||||
region: Torus
|
||||
region: Torus,
|
||||
}
|
||||
|
||||
impl CurrentLoop {
|
||||
@@ -321,9 +321,7 @@ impl CurrentLoop {
|
||||
}
|
||||
fn data<S: AbstractSim>(&self, state: &S) -> f32 {
|
||||
let FieldSample(volume, directed_current, _current_vec) = state.map_sum_over_enumerated(&self.region, |coord: Meters, _cell| {
|
||||
let normal = self.region.axis();
|
||||
let to_coord = *coord - *self.region.center();
|
||||
let tangent = normal.cross(to_coord).norm();
|
||||
let tangent = self.region.tangent(coord);
|
||||
let current = state.current(coord);
|
||||
let directed_current = current.dot(tangent.cast());
|
||||
FieldSample(1, directed_current.cast(), current.cast())
|
||||
|
@@ -333,6 +333,8 @@ impl<R: Real> Vec3<R> {
|
||||
Self::new(self.x().exp(), self.y().exp(), self.z().exp())
|
||||
}
|
||||
|
||||
/// the only condition upon which this returns `None` is if the current magnitude is zero
|
||||
/// and the new magnitude and NON-zero.
|
||||
pub fn with_mag(&self, new_mag: R) -> Option<Self> {
|
||||
if new_mag.is_zero() {
|
||||
// avoid div-by-zero if self.mag() == 0 and new_mag == 0
|
||||
|
Reference in New Issue
Block a user