Real
Simple_spacer::active_springs_stiffness () const
{
- return range_stiffness (0, springs_.size ());
+ Real stiff = range_stiffness (0, springs_.size ());
+ if (isinf (stiff))
+ {
+ /*
+ all springs are inactive. Take the stiffness of the
+ latest spring to block.
+ */
+
+ Real max_block_force = -infinity_f;
+ int max_i = -1;
+ for (int i=0; i < springs_.size (); i++)
+ {
+ if (springs_[i].block_force_ > max_block_force)
+ {
+ max_i = i;
+ max_block_force = springs_[i].block_force_;
+ }
+ }
+
+ stiff = springs_[max_i].hooke_;
+ }
+ return stiff;
}
void
if (conf < line_len_)
{
- force_ += (line_len_ - conf) * active_springs_stiffness ();
+ force_ += (line_len_ - conf) * active_springs_stiffness ();
break;
}
else
"are connected by @var{count-1} springs, and an arbitrary number of rods "
"Springs have the format (ideal, hooke) and rods (idx1, idx2, distance) "
"@var{length} is a number, @var{ragged} a boolean "
- "Return: a list containing the force (#f for non-satisfied constraints)"
- "followed by positions of the objects."
+ "Return: a list containing the force (#f for non-satisfied constraints) "
+ "followed by the @var{spring-count}+1 positions of the objects. "
)
{
- SCM_ASSERT_TYPE (scm_ilength (springs) >= 0, springs, SCM_ARG1, __FUNCTION__, "list of springs");
+ int len = scm_ilength (springs);
+ if (len == 0)
+ return scm_list_2 (scm_from_double (0.0), scm_from_double (0.0));
+
+ SCM_ASSERT_TYPE (len >= 0, springs, SCM_ARG1, __FUNCTION__, "list of springs");
SCM_ASSERT_TYPE (scm_ilength (rods) >= 0, rods, SCM_ARG2, __FUNCTION__, "list of rods");
SCM_ASSERT_TYPE (scm_is_number (length) || length == SCM_BOOL_F,
length, SCM_ARG3, __FUNCTION__, "number or #f");
+
bool is_ragged = ragged == SCM_BOOL_T;
Simple_spacer spacer;
for (SCM s = springs; ly_c_pair_p (s); s = ly_cdr (s))
for (SCM s = rods; ly_c_pair_p (s); s = ly_cdr (s))
{
SCM entry = ly_car (s);
- int l = scm_to_int (ly_car (s));
- int r = scm_to_int (ly_cadr (s));
- entry = ly_cddr (s);
+ int l = scm_to_int (ly_car (entry));
+ int r = scm_to_int (ly_cadr (entry));
+ entry = ly_cddr (entry);
- Real distance = scm_to_double (ly_car (s));
+ Real distance = scm_to_double (ly_car (entry));
spacer.add_rod (l, r, distance);
}
+ spacer.line_len_ = scm_to_double (length);
+
if (is_ragged)
spacer.my_solve_natural_len ();
else
- {
- spacer.line_len_ = scm_to_double (length);
-
- spacer.my_solve_linelen ();
- }
+ spacer.my_solve_linelen ();
Array<Real> posns;
posns.push (0.0);
posns.push (posns.top() + l);
}
- SCM force_return = scm_from_double (spacer.force_);
+ SCM force_return = SCM_BOOL_F;
if (is_ragged)
{
Real len = posns.top ();
if (spacer.line_len_ - len >= 0)
force_return = scm_from_double ((spacer.line_len_ - len)
* spacer.active_springs_stiffness ());
- else
- force_return = SCM_BOOL_F;
}
-
+ else if (not isinf (spacer.force_)
+ && spacer.is_active ())
+ {
+ force_return = scm_from_double (spacer.force_);
+ }
+
SCM retval= SCM_EOL;
for (int i = posns.size(); i--;)
{
bool
Spring_description::is_sane () const
{
- return (hooke_ > 0) && !isinf (ideal_) && !isnan (ideal_);
+ return (hooke_ > 0)
+ && ideal_ > 0
+ && !isinf (ideal_) && !isnan (ideal_);
}
Real