X-Git-Url: https://git.donarmstrong.com/?a=blobdiff_plain;f=lily%2Fspring.cc;h=f57695bfd732ec50f821465a570a088547eaf9d8;hb=794dcbdb52faf4292036cd1b0270a956cf4316a3;hp=1f250546db354d31f41a7cfb344a011281af7524;hpb=157d98c1870868bf59c1691577444e3c3d533bc4;p=lilypond.git diff --git a/lily/spring.cc b/lily/spring.cc index 1f250546db..f57695bfd7 100644 --- a/lily/spring.cc +++ b/lily/spring.cc @@ -3,7 +3,7 @@ source file of the GNU LilyPond music typesetter - (c) 2007 Joe Neeman + (c) 2007--2009 Joe Neeman */ #include "spring.hh" @@ -32,10 +32,18 @@ Spring::Spring (Real dist, Real min_dist) void Spring::update_blocking_force () { - if (distance_ == min_distance_) - blocking_force_ = 0.0; + if (min_distance_ > distance_) + blocking_force_ = (min_distance_ - distance_) / inverse_stretch_strength_; else blocking_force_ = (min_distance_ - distance_) / inverse_compress_strength_; + + // If the spring is fixed, it's not clear what the natural value + // of blocking_force_ would be. -infinity_f works fine for now. + if (isnan (blocking_force_) || blocking_force_ == infinity_f) + blocking_force_ = -infinity_f; + + if (blocking_force_ >= 0) + inverse_compress_strength_ = 0; } /* scale a spring, but in a way that doesn't violate min_distance */ @@ -43,8 +51,9 @@ void Spring::operator*= (Real r) { distance_ = max (min_distance_, distance_ * r); - inverse_compress_strength_ = distance_ - min_distance_; + inverse_compress_strength_ = max (0.0, distance_ - min_distance_); inverse_stretch_strength_ *= 0.8; + update_blocking_force (); } bool @@ -90,7 +99,6 @@ Spring::set_distance (Real d) programming_error ("insane spring distance requested, ignoring it"); else { - min_distance_ = min (min_distance_, d); distance_ = d; update_blocking_force (); } @@ -104,11 +112,16 @@ Spring::set_min_distance (Real d) else { min_distance_ = d; - distance_ = max (distance_, min_distance_); update_blocking_force (); } } +void +Spring::ensure_min_distance (Real d) +{ + set_min_distance (max (d, min_distance_)); +} + void Spring::set_inverse_stretch_strength (Real f) { @@ -116,6 +129,8 @@ Spring::set_inverse_stretch_strength (Real f) programming_error ("insane spring constant"); else inverse_stretch_strength_ = f; + + update_blocking_force (); } void @@ -147,8 +162,9 @@ Spring::set_blocking_force (Real f) void Spring::set_default_strength () { - inverse_compress_strength_ = distance_ - min_distance_; - inverse_stretch_strength_ = distance_ - min_distance_; + inverse_compress_strength_ = (distance_ >= min_distance_) ? distance_ - min_distance_ : 0; + inverse_stretch_strength_ = distance_; + update_blocking_force (); } Real @@ -157,11 +173,15 @@ Spring::length (Real f) const Real force = max (f, blocking_force_); Real inv_k = force < 0.0 ? inverse_compress_strength_ : inverse_stretch_strength_; - if (isinf (force)) + if (force == infinity_f) { programming_error ("cruelty to springs"); force = 0.0; } - return distance_ + force * inv_k; + // There is a corner case here: if min_distance_ is larger than + // distance_ but the spring is fixed, then inv_k will be zero + // and we need to make sure that we return min_distance_. + return max (min_distance_, distance_ + force * inv_k); } +