2 slur-bezier-bow.cc -- implement Slur_bezier_bow
4 source file of the GNU LilyPond music typesetter
6 (c) 2000--2004 Jan Nieuwenhuizen <janneke@gnu.org>
10 #include "paper-def.hh"
11 #include "slur-bezier-bow.hh"
13 Slur_bezier_bow::Slur_bezier_bow (Array
<Offset
> encompass
, Direction dir
,
20 encompass_
= encompass
;
23 Real w
= encompass_
.top ()[X_AXIS
] - encompass_
[0][X_AXIS
];
24 curve_
= slur_shape (w
, h_inf
, r_0
);
28 Slur_bezier_bow::get_bezier () const
37 rv
.translate (origin_
);
43 Slur_bezier_bow::to_canonical_form ()
45 origin_
= encompass_
[0];
46 translate (&encompass_
, -origin_
);
48 Offset delta
= encompass_
.top () - encompass_
[0];
49 alpha_
= delta
.arg ();
51 rotate (&encompass_
, -alpha_
);
54 scale (&encompass_
, 1, -1);
57 while (encompass_
.size () > 1 && encompass_
[1][X_AXIS
] <= 0.0)
59 programming_error ("Degenerate bow: infinite steepness reqd");
63 Real l
= encompass_
.top ()[X_AXIS
];
64 while (encompass_
.size () > 1 && encompass_
.top (1)[X_AXIS
] >= l
)
66 programming_error ("Degenerate bow: infinite steepness reqd");
67 encompass_
.del (encompass_
.size ()-2);
74 Slur_bezier_bow::blow_fit ()
76 Real len
= curve_
.control_
[3][X_AXIS
];
77 Real h
= curve_
.control_
[1][Y_AXIS
] * fit_factor () / len
;
78 curve_
.control_
[1][Y_AXIS
] = h
* len
;
79 curve_
.control_
[2][Y_AXIS
] = h
* len
;
80 curve_
.assert_sanity ();
85 Slur_bezier_bow::get_enclosed_area () const
88 for (int i
=0; i
< encompass_
.size (); i
++)
94 x
= Interval (0, encompass_
[1][X_AXIS
] / 2);
96 curve_
.get_other_coordinate (X_AXIS
,
100 else if (i
== encompass_
.size () - 1)
102 x
= Interval ((encompass_
[i
-1][X_AXIS
] + encompass_
[i
][X_AXIS
])/2,
103 encompass_
[i
][X_AXIS
]);
105 (curve_
.get_other_coordinate (X_AXIS
,
106 (x
[MIN
] + x
[MAX
]) / 2)));
110 x
= Interval ((encompass_
[i
-1][X_AXIS
] + encompass_
[i
][X_AXIS
]) / 2,
111 (encompass_
[i
][X_AXIS
] + encompass_
[i
+1][X_AXIS
]) / 2);
112 y
= Interval (encompass_
[i
][Y_AXIS
],
113 (curve_
.get_other_coordinate (X_AXIS
, x
[MIN
])
114 + curve_
.get_other_coordinate (X_AXIS
,
115 (x
[MIN
] + x
[MAX
]) / 2)
116 + curve_
.get_other_coordinate (X_AXIS
, x
[MAX
])) / 3);
119 Real da
= x
.length () * y
.length ();
126 Slur_bezier_bow::area_x_gradientses (Real area
)
128 Real len
= curve_
.control_
[3][X_AXIS
];
129 Real grow
= len
/ 10.0;
131 for (int i
=0; i
< 2; i
++)
133 Real r
= curve_
.control_
[i
+1][X_AXIS
];
134 curve_
.control_
[i
+1][X_AXIS
] += grow
;
135 da
[i
] = (get_enclosed_area () - area
) / grow
;
136 curve_
.control_
[i
+1][X_AXIS
] = r
;
142 ugh, should have another look, and use a regular optimization
143 algorithm, instead of this homebrew.
146 Slur_bezier_bow::minimise_enclosed_area (Real beauty
,
149 Real length
= curve_
.control_
[3][X_AXIS
];
150 Real beautiful
= beauty
* length
* slur_height (length
, h_inf_
, r_0_
);
153 if (fit_factor () > 1.0)
156 Real pct_c0
= gh_scm2double (ly_cdr (scm_assoc (ly_symbol2scm ("bezier-pct-c0"), bezier_props
)));
157 Real pct_c3
= gh_scm2double (ly_cdr (scm_assoc (ly_symbol2scm ("bezier-pct-c3"), bezier_props
)));
158 Real pct_in_max
= gh_scm2double (ly_cdr (scm_assoc (ly_symbol2scm ("bezier-pct-in-max"), bezier_props
)));
159 Real pct_out_max
= gh_scm2double (ly_cdr (scm_assoc (ly_symbol2scm ("bezier-pct-out-max"), bezier_props
)));
160 Real steps
= gh_scm2double (ly_cdr (scm_assoc (ly_symbol2scm ("bezier-area-steps"),bezier_props
)));
162 for (int i
=0; i
< steps
; i
++)
164 Real area
= get_enclosed_area ();
165 if (area
<= beautiful
)
168 Array
<Real
> da
= area_x_gradientses (area
);
171 Real pct
= pct_c0
+ pct_c3
* length
* length
* length
;
172 pct
*= (steps
- i
) / steps
;
173 if (da
[0] > 0 || da
[1] < 0)
174 pct
= pct
<? pct_out_max
;
176 pct
= pct
<? pct_in_max
;
178 Real u
= (abs (curve_
.control_
[1][X_AXIS
] / da
[0])
179 <? abs ((curve_
.control_
[3][X_AXIS
]
180 - curve_
.control_
[2][X_AXIS
]) / da
[1]));
182 curve_
.control_
[1][X_AXIS
] -= da
[0] * u
* pct
;
183 curve_
.control_
[2][X_AXIS
] -= da
[1] * u
* pct
;
190 max (encompass.y / curve.y)
194 Slur_bezier_bow::fit_factor () const
196 Real x1
= encompass_
[0][X_AXIS
];
197 Real x2
= encompass_
.top ()[X_AXIS
];
200 for (int i
=1; i
< encompass_
.size ()-1; i
++)
202 if (encompass_
[i
][X_AXIS
] > x1
&& encompass_
[i
][X_AXIS
] < x2
)
204 Real y
= curve_
.get_other_coordinate (X_AXIS
, encompass_
[i
][X_AXIS
]);
207 Real f
= encompass_
[i
][Y_AXIS
] / y
;
208 factor
= factor
>? f
;