+ double inv_hooke = 0;
+ double cur_len = configuration_length (force_);
+
+ fits_ = true;
+ for (vsize i=0; i < springs_.size (); i++)
+ inv_hooke += springs_[i].inverse_stretch_strength ();
+
+ if (inv_hooke == 0.0) /* avoid division by zero. If springs are infinitely stiff */
+ return 0.0; /* anyway, then it makes no difference what the force is */
+
+ assert (cur_len <= line_len_);
+ return (line_len_ - cur_len) / inv_hooke + force_;
+}
+
+Real
+Simple_spacer::compress_line ()
+{
+ double inv_hooke = 0;
+ double cur_len = configuration_length (force_);
+ double cur_force = force_;
+ bool compressed = false;
+
+ /* just because we are in compress_line () doesn't mean that the line
+ will actually be compressed (as in, a negative force) because
+ we start out with a stretched line. Here, we check whether we
+ will be compressed or stretched (so we know which spring constant to use) */
+ if (configuration_length (0.0) > line_len_)
+ {
+ cur_force = 0.0;
+ cur_len = configuration_length (0.0);
+ compressed = true;
+ }
+
+ fits_ = true;
+ for (vsize i=0; i < springs_.size (); i++)
+ inv_hooke += compressed
+ ? springs_[i].inverse_compress_strength ()
+ : springs_[i].inverse_stretch_strength ();
+
+ assert (line_len_ <= cur_len);
+
+ vector<Spring> sorted_springs = springs_;
+ sort (sorted_springs.begin (), sorted_springs.end (), greater<Spring> ());
+
+ for (vsize i = 0; i < sorted_springs.size (); i++)
+ {
+ Spring sp = sorted_springs[i];
+
+ assert (sp.blocking_force () <= cur_force);
+ if (isinf (sp.blocking_force ()))
+ break;
+
+ double block_dist = (cur_force - sp.blocking_force ()) * inv_hooke;
+ if (cur_len - block_dist < line_len_)
+ {
+ cur_force += (line_len_ - cur_len) / inv_hooke;
+ cur_len = line_len_;
+
+ /*
+ Paranoia check.
+ */
+ assert (fabs (configuration_length (cur_force) - cur_len) < 1e-6);
+ return cur_force;
+ }
+
+ cur_len -= block_dist;
+ inv_hooke -= sp.inverse_compress_strength ();
+ cur_force = sp.blocking_force ();
+ }
+
+ fits_ = false;
+ return cur_force;