CurrentLoop: factor out the tangent calculation

This commit is contained in:
2022-08-01 00:50:02 -07:00
parent 723fed4786
commit cc876d72d6
5 changed files with 40 additions and 7 deletions

View File

@@ -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};

View File

@@ -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)
}

View File

@@ -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,

View File

@@ -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())

View File

@@ -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