summaryrefslogtreecommitdiff
path: root/physics/src/constraint/beam.rs
diff options
context:
space:
mode:
authoreug-vs <eugene@eug-vs.xyz>2024-12-17 17:16:12 +0100
committereug-vs <eugene@eug-vs.xyz>2024-12-17 17:16:49 +0100
commitcc162a42127077744705dc6194de302bff069171 (patch)
tree0f225e7694a2de8088304703532651f7fb4bef0d /physics/src/constraint/beam.rs
parent9a19677c53dd8d3735027d03c6bc923b3fd9c3e6 (diff)
downloadparticle-physics-cc162a42127077744705dc6194de302bff069171.tar.gz
refactor: generalize anchor constraint via beam
Diffstat (limited to 'physics/src/constraint/beam.rs')
-rw-r--r--physics/src/constraint/beam.rs41
1 files changed, 35 insertions, 6 deletions
diff --git a/physics/src/constraint/beam.rs b/physics/src/constraint/beam.rs
index 14b1c1f..b353e13 100644
--- a/physics/src/constraint/beam.rs
+++ b/physics/src/constraint/beam.rs
@@ -1,12 +1,18 @@
use nalgebra::{DVector, RowDVector};
+use crate::algebra::{Point, Scalar, N};
use crate::particle_system::ParticleSystem;
-use crate::algebra::{Scalar, N};
use super::Constraint;
+#[derive(Clone, Copy)]
+enum BeamPoint {
+ Static(Point),
+ FromParticle(usize),
+}
+
pub struct BeamConstraint {
- pub particle_ids: [usize; 2],
+ points: [BeamPoint; 2],
pub length: Scalar,
jacobian: RowDVector<Scalar>,
@@ -18,21 +24,44 @@ impl ParticleSystem {
let b = &self.particles[particle_ids[1]];
self.constraints.push(Box::new(BeamConstraint {
- particle_ids,
+ points: [
+ BeamPoint::FromParticle(particle_ids[0]),
+ BeamPoint::FromParticle(particle_ids[1]),
+ ],
length: (a.position - b.position).norm(),
jacobian: RowDVector::zeros(self.particles.len() * N),
}));
}
+
+ pub fn add_anchor_constraint(&mut self, particle_id: usize, point: Point) {
+ let position = &self.particles[particle_id].position;
+
+ self.constraints.push(Box::new(BeamConstraint {
+ points: [
+ BeamPoint::FromParticle(particle_id),
+ BeamPoint::Static(point),
+ ],
+ length: (position - point).norm(),
+ jacobian: RowDVector::zeros(self.particles.len() * N),
+ }));
+ }
}
impl Constraint for BeamConstraint {
fn get_particles(&self) -> Vec<usize> {
- Vec::from(self.particle_ids)
+ self.points.iter().filter_map(|p| match p {
+ BeamPoint::FromParticle(id) => Some(*id),
+ BeamPoint::Static(_) => None,
+ }).collect()
}
fn c(&self, q: &DVector<Scalar>) -> Scalar {
- let a = q.fixed_rows::<N>(self.particle_ids[0] * N);
- let b = q.fixed_rows::<N>(self.particle_ids[1] * N);
+ let [a, b] = self.points.map(|p| {
+ match p {
+ BeamPoint::Static(p) => p.coords,
+ BeamPoint::FromParticle(id) => q.fixed_rows::<N>(id * N).into(),
+ }
+ });
(a - b).norm() - self.length
}