2 slur-bezier-bow.cc -- implement Slur_bezier_bow
4 source file of the GNU LilyPond music typesetter
6 (c) 2000--2001 Jan Nieuwenhuizen <janneke@gnu.org>
10 #include "paper-def.hh"
11 #include "slur-bezier-bow.hh"
14 Slur_bezier_bow::Slur_bezier_bow (Array
<Offset
> encompass
, Direction dir
,
21 encompass_
= encompass
;
24 Real w
= encompass_
.top ()[X_AXIS
] - encompass_
[0][X_AXIS
];
25 curve_
= slur_shape (w
, h_inf
, r_0
);
29 Slur_bezier_bow::get_bezier () const
38 rv
.translate (origin_
);
44 Slur_bezier_bow::to_canonical_form ()
46 origin_
= encompass_
[0];
47 translate (&encompass_
, -origin_
);
49 Offset delta
= encompass_
.top () - encompass_
[0];
50 alpha_
= delta
.arg ();
52 rotate (&encompass_
, -alpha_
);
55 scale (&encompass_
, 1, -1);
58 while (encompass_
.size () > 1 && encompass_
[1][X_AXIS
] <= 0.0)
60 programming_error ("Degenerate bow: infinite steepness reqd");
64 Real l
= encompass_
.top ()[X_AXIS
];
65 while (encompass_
.size () > 1 && encompass_
.top (1)[X_AXIS
] >= l
)
67 programming_error ("Degenerate bow: infinite steepness reqd");
68 encompass_
.del (encompass_
.size ()-2);
75 Slur_bezier_bow::blow_fit ()
77 Real len
= curve_
.control_
[3][X_AXIS
];
78 Real h
= curve_
.control_
[1][Y_AXIS
] * fit_factor () / len
;
79 curve_
.control_
[1][Y_AXIS
] = h
* len
;
80 curve_
.control_
[2][Y_AXIS
] = h
* len
;
81 curve_
.assert_sanity ();
86 Slur_bezier_bow::enclosed_area_f () const
89 for (int i
=0; i
< encompass_
.size (); i
++)
95 x
= Interval (0, encompass_
[1][X_AXIS
] / 2);
97 curve_
.get_other_coordinate (X_AXIS
,
101 else if (i
== encompass_
.size () - 1)
103 x
= Interval ((encompass_
[i
-1][X_AXIS
] + encompass_
[i
][X_AXIS
])/2,
104 encompass_
[i
][X_AXIS
]);
106 (curve_
.get_other_coordinate (X_AXIS
,
107 (x
[MIN
] + x
[MAX
]) / 2)));
111 x
= Interval ((encompass_
[i
-1][X_AXIS
] + encompass_
[i
][X_AXIS
]) / 2,
112 (encompass_
[i
][X_AXIS
] + encompass_
[i
+1][X_AXIS
]) / 2);
113 y
= Interval (encompass_
[i
][Y_AXIS
],
114 (curve_
.get_other_coordinate (X_AXIS
, x
[MIN
])
115 + curve_
.get_other_coordinate (X_AXIS
,
116 (x
[MIN
] + x
[MAX
]) / 2)
117 + curve_
.get_other_coordinate (X_AXIS
, x
[MAX
])) / 3);
120 Real da
= x
.length () * y
.length ();
127 Slur_bezier_bow::area_x_gradients_array (Real area
)
129 Real len
= curve_
.control_
[3][X_AXIS
];
130 Real grow
= len
/ 10.0;
132 for (int i
=0; i
< 2; i
++)
134 Real r
= curve_
.control_
[i
+1][X_AXIS
];
135 curve_
.control_
[i
+1][X_AXIS
] += grow
;
136 da
[i
] = (enclosed_area_f () - area
) / grow
;
137 curve_
.control_
[i
+1][X_AXIS
] = r
;
143 ugh, should have another look, and use a regular optimization
144 algorithm, instead of this homebrew.
147 Slur_bezier_bow::minimise_enclosed_area (Real beauty
,
150 Real length
= curve_
.control_
[3][X_AXIS
];
151 Real beautiful
= beauty
* length
* slur_height (length
, h_inf_
, r_0_
);
154 if (fit_factor () > 1.0)
157 Real pct_c0
= gh_scm2double (gh_cdr (scm_assoc (ly_symbol2scm ("bezier-pct-c0"), bezier_props
)));
158 Real pct_c3
= gh_scm2double (gh_cdr (scm_assoc (ly_symbol2scm ("bezier-pct-c3"), bezier_props
)));
159 Real pct_in_max
= gh_scm2double (gh_cdr (scm_assoc (ly_symbol2scm ("bezier-pct-in-max"), bezier_props
)));
160 Real pct_out_max
= gh_scm2double (gh_cdr (scm_assoc (ly_symbol2scm ("bezier-pct-out-max"), bezier_props
)));
161 Real steps
= gh_scm2double (gh_cdr (scm_assoc (ly_symbol2scm ("bezier-area-steps"),bezier_props
)));
163 for (int i
=0; i
< steps
; i
++)
165 Real area
= enclosed_area_f ();
166 if (area
<= beautiful
)
169 Array
<Real
> da
= area_x_gradients_array (area
);
172 Real pct
= pct_c0
+ pct_c3
* length
* length
* length
;
173 pct
*= (steps
- i
) / steps
;
174 if (da
[0] > 0 || da
[1] < 0)
175 pct
= pct
<? pct_out_max
;
177 pct
= pct
<? pct_in_max
;
179 Real u
= (abs (curve_
.control_
[1][X_AXIS
] / da
[0])
180 <? abs ((curve_
.control_
[3][X_AXIS
]
181 - curve_
.control_
[2][X_AXIS
]) / da
[1]));
183 curve_
.control_
[1][X_AXIS
] -= da
[0] * u
* pct
;
184 curve_
.control_
[2][X_AXIS
] -= da
[1] * u
* pct
;
191 max (encompass.y / curve.y)
195 Slur_bezier_bow::fit_factor () const
197 Real x1
= encompass_
[0][X_AXIS
];
198 Real x2
= encompass_
.top ()[X_AXIS
];
201 for (int i
=1; i
< encompass_
.size ()-1; i
++)
203 if (encompass_
[i
][X_AXIS
] > x1
&& encompass_
[i
][X_AXIS
] < x2
)
205 Real y
= curve_
.get_other_coordinate (X_AXIS
, encompass_
[i
][X_AXIS
]);
208 Real f
= encompass_
[i
][Y_AXIS
] / y
;
209 factor
= factor
>? f
;