2 simple-spacer.cc -- implement Simple_spacer
4 source file of the GNU LilyPond music typesetter
6 (c) 1999--2001 Han-Wen Nienhuys <hanwen@cs.uu.nl>
9 - add support for different stretch/shrink constants?
14 #include <libc-extension.hh>
16 #include "simple-spacer.hh"
17 #include "paper-column.hh"
21 #include "column-x-positions.hh"
22 #include "spaceable-element.hh"
23 #include "dimensions.hh"
25 Simple_spacer::Simple_spacer ()
29 default_space_f_
= 20 PT
;
33 Simple_spacer::add_rod (int l
, int r
, Real dist
)
35 if (isinf (dist
) || isnan (dist
))
37 programming_error ("Weird minimum distance. Ignoring");
42 Real c
= range_stiffness (l
,r
);
43 Real d
= range_ideal_len (l
,r
);
44 Real block_stretch
= dist
- d
;
46 Real block_force
= c
* block_stretch
;
47 force_f_
= force_f_
>? block_force
;
49 for (int i
=l
; i
< r
; i
++)
50 springs_
[i
].block_force_f_
= block_force
>?
51 springs_
[i
].block_force_f_
;
55 Simple_spacer::range_ideal_len (int l
, int r
) const
58 for (int i
=l
; i
< r
; i
++)
59 d
+= springs_
[i
].ideal_f_
;
64 Simple_spacer::range_stiffness (int l
, int r
) const
67 for (int i
=l
; i
< r
; i
++)
68 den
+= 1 / springs_
[i
].hooke_f_
;
74 Simple_spacer::active_blocking_force () const
76 Real bf
= - infinity_f
;
77 for (int i
=0; i
< springs_
.size (); i
++)
78 if (springs_
[i
].active_b_
)
80 bf
= bf
>? springs_
[i
].block_force_f_
;
86 Simple_spacer::active_springs_stiffness () const
89 for (int i
=0; i
< springs_
.size (); i
++)
90 if (springs_
[i
].active_b_
)
92 den
+= 1 / springs_
[i
].hooke_f_
;
98 Simple_spacer::set_active_states ()
101 // force is only copied.
102 for (int i
=0 ; i
<springs_
.size (); i
++)
103 if (springs_
[i
].block_force_f_
>= force_f_
)
104 springs_
[i
].active_b_
= false;
108 Simple_spacer::configuration_length () const
111 for (int i
=0; i
< springs_
.size (); i
++)
112 l
+= springs_
[i
].length (force_f_
);
118 Spring_description::length (Real f
) const
122 return ideal_f_
+ f
/ hooke_f_
;
126 Simple_spacer::active_b () const
128 for (int i
=0; i
< springs_
.size (); i
++)
129 if (springs_
[i
].active_b_
)
135 Simple_spacer::my_solve_linelen ()
139 force_f_
= active_blocking_force ();
140 Real conf
= configuration_length ();
142 if (conf
< line_len_f_
)
144 force_f_
+= (line_len_f_
- conf
) * active_springs_stiffness ();
148 set_active_states ();
154 Simple_spacer::my_solve_natural_len ()
158 force_f_
= active_blocking_force () >? 0.0;
160 if (force_f_
< 1e-8) // ugh.,
163 set_active_states ();
168 Simple_spacer::add_columns (Link_array
<Grob
> cols
)
170 for (int i
=0; i
< cols
.size () - 1; i
++)
172 SCM spring_params
= SCM_UNDEFINED
;
173 for (SCM s
= Spaceable_grob::get_ideal_distances (cols
[i
]);
174 spring_params
== SCM_UNDEFINED
&& gh_pair_p (s
);
177 Grob
*other
= unsmob_grob (gh_caar (s
));
178 if (other
!= cols
[i
+1])
181 spring_params
= gh_cdar (s
);
184 Spring_description desc
;
185 if (spring_params
!= SCM_UNDEFINED
)
187 desc
.ideal_f_
= gh_scm2double (gh_car (spring_params
));
188 desc
.hooke_f_
= gh_scm2double (gh_cdr (spring_params
));
192 programming_error ("No spring between adjacent columns");
194 desc
.ideal_f_
= default_space_f_
;
199 programming_error ("Insane spring found. Setting to unit spring.");
204 desc
.block_force_f_
= - desc
.hooke_f_
* desc
.ideal_f_
; // block at distance 0
205 springs_
.push (desc
);
208 for (int i
=0; i
< cols
.size () - 1; i
++)
210 for (SCM s
= Spaceable_grob::get_minimum_distances (cols
[i
]);
211 gh_pair_p (s
); s
= gh_cdr (s
))
213 Grob
* other
= unsmob_grob (gh_caar (s
));
214 int oi
= cols
.find_i (other
);
217 add_rod (i
, oi
, gh_scm2double (gh_cdar (s
)));
223 TODO: should support natural length on only the last line.
226 my_solve_natural_len ();
232 Simple_spacer::solve (Column_x_positions
*positions
) const
234 positions
->force_f_
= force_f_
;
236 positions
->config_
.push (indent_f_
);
237 for (int i
=0; i
<springs_
.size (); i
++)
239 positions
->config_
.push (positions
->config_
.top () + springs_
[i
].length (force_f_
));
242 positions
->satisfies_constraints_b_
= (line_len_f_
< 0) || active_b ();
247 Spring_description::Spring_description ()
252 block_force_f_
= 0.0;
257 Spring_description::sane_b () const
259 return (hooke_f_
> 0) && ! isinf (ideal_f_
) && !isnan (ideal_f_
);