2 simple-spacer.cc -- implement Simple_spacer
4 source file of the GNU LilyPond music typesetter
6 (c) 1999 Han-Wen Nienhuys <hanwen@cs.uu.nl>
9 - add support for different stretch/shrink constants?
10 - Use force as a minimizing function, and use it to discourage mixes of
17 #include "simple-spacer.hh"
18 #include "paper-column.hh"
22 #include "column-x-positions.hh"
23 #include "dimensions.hh"
25 Simple_spacer::Simple_spacer ()
29 default_space_f_
= 20 PT
;
30 compression_energy_factor_f_
= 3.0;
34 Simple_spacer::add_rod (int l
, int r
, Real dist
)
36 if (isinf (dist
) || isnan (dist
))
38 programming_error ("Weird minimum distance. Ignoring");
43 Real c
= range_stiffness (l
,r
);
44 Real d
= range_ideal_len (l
,r
);
45 Real block_stretch
= dist
- d
;
47 Real block_force
= c
* block_stretch
;
48 force_f_
= force_f_
>? block_force
;
50 for (int i
=l
; i
< r
; i
++)
51 springs_
[i
].block_force_f_
= block_force
>?
52 springs_
[i
].block_force_f_
;
56 Simple_spacer::range_ideal_len (int l
, int r
) const
59 for (int i
=l
; i
< r
; i
++)
60 d
+= springs_
[i
].ideal_f_
;
65 Simple_spacer::range_stiffness (int l
, int r
) const
68 for (int i
=l
; i
< r
; i
++)
69 den
+= 1 / springs_
[i
].hooke_f_
;
75 Simple_spacer::active_blocking_force () const
77 Real bf
= - infinity_f
;
78 for (int i
=0; i
< springs_
.size (); i
++)
79 if (springs_
[i
].active_b_
)
81 bf
= bf
>? springs_
[i
].block_force_f_
;
87 Simple_spacer::active_springs_stiffness () const
90 for (int i
=0; i
< springs_
.size (); i
++)
91 if (springs_
[i
].active_b_
)
93 den
+= 1 / springs_
[i
].hooke_f_
;
99 Simple_spacer::set_active_states ()
102 // force is only copied.
103 for (int i
=0 ; i
<springs_
.size (); i
++)
104 if (springs_
[i
].block_force_f_
>= force_f_
)
105 springs_
[i
].active_b_
= false;
109 Simple_spacer::configuration_length () const
112 for (int i
=0; i
< springs_
.size (); i
++)
113 l
+= springs_
[i
].length (force_f_
);
119 Spring_description::length (Real f
) const
123 return ideal_f_
+ f
/ hooke_f_
;
127 Simple_spacer::active_b () const
129 for (int i
=0; i
< springs_
.size (); i
++)
130 if (springs_
[i
].active_b_
)
136 Simple_spacer::my_solve_linelen ()
140 force_f_
= active_blocking_force ();
141 Real conf
= configuration_length ();
143 if (conf
< line_len_f_
)
145 force_f_
+= (line_len_f_
- conf
) * active_springs_stiffness ();
149 set_active_states ();
155 Simple_spacer::my_solve_natural_len ()
159 force_f_
= active_blocking_force () >? 0.0;
161 if (force_f_
< 1e-8) // ugh.,
164 set_active_states ();
169 Simple_spacer::add_columns (Link_array
<Paper_column
> cols
)
171 for (int i
=0; i
< cols
.size () - 1; i
++)
173 Paper_column
* c
= cols
[i
];
174 Column_spring
*to_next
= 0;
175 for (int j
=0; !to_next
&& j
< c
->spring_arr_drul_
[RIGHT
].size( ); j
++)
177 Column_spring
&sp
= c
->spring_arr_drul_
[RIGHT
] [j
];
178 if (sp
.other_l_
!= cols
[i
+1])
184 Spring_description desc
;
187 desc
.hooke_f_
= to_next
->strength_f_
;
188 desc
.ideal_f_
= to_next
->distance_f_
;
193 desc
.ideal_f_
= default_space_f_
;
198 programming_error ("Insane spring.");
202 desc
.block_force_f_
= - desc
.hooke_f_
* desc
.ideal_f_
; // block at distance 0
203 springs_
.push (desc
);
206 for (int i
=0; i
< cols
.size () - 1; i
++)
208 Array
<Column_rod
> * rods
= &cols
[i
]->minimal_dists_arr_drul_
[RIGHT
];
209 for (int j
=0; j
< rods
->size( ); j
++)
211 int oi
= cols
.find_i (rods
->elem (j
).other_l_
);
214 add_rod (i
, oi
, rods
->elem (j
).distance_f_
);
220 my_solve_natural_len ();
226 Simple_spacer::solve (Column_x_positions
*positions
) const
228 positions
->energy_f_
= energy_f (); // abs (force_f_);
229 positions
->force_f_
= force_f_
;
231 positions
->config_
.push (indent_f_
);
232 for (int i
=0; i
<springs_
.size (); i
++)
234 positions
->config_
.push (positions
->config_
.top () + springs_
[i
].length (force_f_
));
237 positions
->satisfies_constraints_b_
= (line_len_f_
< 0) || active_b ();
242 Spring_description::Spring_description( )
247 block_force_f_
= 0.0;
251 Spring_description::energy_f (Real force
) const
253 Real stretch
= (force
>? block_force_f_
) / hooke_f_
;
254 Real e
= 0.5 * stretch
* stretch
* hooke_f_
;
259 Spring_description::sane_b () const
261 return (hooke_f_
> 0) && ! isinf (ideal_f_
) && !isnan (ideal_f_
);
266 Simple_spacer::energy_f () const
270 for (int i
=0; i
<springs_
.size (); i
++)
272 e
+= springs_
[i
].energy_f (force_f_
);
276 e
*= compression_energy_factor_f_
;