]> git.donarmstrong.com Git - lilypond.git/blob - lily/slur-bezier-bow.cc
patch::: 1.3.64.jcn1
[lilypond.git] / lily / slur-bezier-bow.cc
1 /*
2   slur-bezier-bow.cc -- implement Slur_bezier_bow
3
4   source file of the GNU LilyPond music typesetter
5
6   (c) 2000  Jan Nieuwenhuizen <janneke@gnu.org>
7 */
8
9 #include "debug.hh"
10 #include "paper-def.hh"
11 #include "slur-bezier-bow.hh"
12 #include "main.hh"
13
14 Slur_bezier_bow::Slur_bezier_bow (Array<Offset> encompass, Direction dir)
15   : Bezier_bow (encompass, dir)
16 {
17 }
18
19 void
20 Slur_bezier_bow::blow_fit ()
21 {
22   Real len = curve_.control_[3][X_AXIS]; 
23   Real h = curve_.control_[1][Y_AXIS] * fit_factor () / len;
24   curve_.control_[1][Y_AXIS] = h * len;
25   curve_.control_[2][Y_AXIS] = h * len;  
26   curve_.assert_sanity ();
27 }
28
29
30 Real
31 Slur_bezier_bow::enclosed_area_f () const
32 {
33   Real a = 0;
34   for (int i=0; i < encompass_.size (); i++)
35     {
36       Interval x;
37       Interval y;
38       if (i == 0)
39         {
40           x = Interval (0, encompass_[1][X_AXIS] / 2);
41           y = Interval (0,
42                         curve_.get_other_coordinate (X_AXIS,
43                                                      encompass_[1][X_AXIS]
44                                                      / 2));
45         }
46       else if (i == encompass_.size () - 1)
47         {
48           x = Interval ((encompass_[i-1][X_AXIS] + encompass_[i][X_AXIS])/2, 
49                         encompass_[i][X_AXIS]);
50           y = Interval (0,
51                         (curve_.get_other_coordinate (X_AXIS,
52                                                       (x[MIN] + x[MAX]) / 2)));
53         }
54       else
55         {
56           x = Interval ((encompass_[i-1][X_AXIS] + encompass_[i][X_AXIS]) / 2, 
57                         (encompass_[i][X_AXIS] + encompass_[i+1][X_AXIS]) / 2);
58           y = Interval (encompass_[i][Y_AXIS],
59                         (curve_.get_other_coordinate (X_AXIS, x[MIN])
60                          + curve_.get_other_coordinate (X_AXIS,
61                                                         (x[MIN] + x[MAX]) / 2)
62                          + curve_.get_other_coordinate (X_AXIS, x[MAX])) / 3);
63         }
64       
65       Real da = x.length () * y.length ();
66       a += da;
67     }
68   return a;
69 }
70
71 Array<Real>
72 Slur_bezier_bow::area_x_gradients_array (Real area)
73 {
74   Real len = curve_.control_[3][X_AXIS]; 
75   Real grow = len / 10.0;
76   Array<Real> da (2);
77   for (int i=0; i < 2; i++)
78     {
79       Real r = curve_.control_[i+1][X_AXIS];
80       curve_.control_[i+1][X_AXIS] += grow;
81       da[i] = (enclosed_area_f () - area) / grow;
82       curve_.control_[i+1][X_AXIS] = r; 
83     }
84   return da;
85 }
86
87 void
88 Slur_bezier_bow::minimise_enclosed_area (Paper_def* paper_l,
89                                          Real default_height)
90 {
91   Real length = curve_.control_[3][X_AXIS]; 
92   Real sb = paper_l->get_var ("slur_beautiful");
93   Real beautiful = length * default_height * sb;
94
95   DEBUG_OUT << to_str ("Beautiful: %f\n", beautiful);
96   DEBUG_OUT << to_str ("Length: %f\n", length);
97   DEBUG_OUT << to_str ("D-height: %f\n", default_height);
98   DEBUG_OUT << to_str ("FitFac: %f\n", fit_factor ());
99
100   if (fit_factor () > 1.0)
101     blow_fit ();
102   
103   Real pct_c0 = paper_l->get_var ("bezier_pct_c0");
104   Real pct_c3 = paper_l->get_var ("bezier_pct_c3");
105   Real pct_in_max = paper_l->get_var ("bezier_pct_in_max");
106   Real pct_out_max = paper_l->get_var ("bezier_pct_out_max");
107   Real steps = paper_l->get_var ("bezier_area_steps");
108
109   for (int i=0; i < steps; i++)
110     {
111       Real area = enclosed_area_f ();
112       if (!i)
113         DEBUG_OUT << to_str ("Init area: %f\n", area);
114
115       if (area <= beautiful)
116         break;
117
118       Array<Real> da = area_x_gradients_array (area);
119
120       // urg
121       Real pct = pct_c0 + pct_c3 * length * length * length;
122       pct *= (steps - i) / steps;
123       if (da[0] > 0 || da[1] < 0)
124         pct = pct <? pct_out_max;
125       else
126         pct = pct <? pct_in_max;
127
128       Real u = (abs (curve_.control_[1][X_AXIS] / da[0])
129                 <? abs ((curve_.control_[3][X_AXIS]
130                          - curve_.control_[2][X_AXIS]) / da[1]));
131
132       DEBUG_OUT << to_str ("pct: %f\n", pct);
133       DEBUG_OUT << to_str ("u: %f\n", u);
134
135       DEBUG_OUT << to_str ("da: (%f, %f)\n", da[0], da[1]);
136       DEBUG_OUT << to_str ("da*u: (%f, %f)\n", da[0]*u*pct, da[1]*u*pct);
137       DEBUG_OUT << to_str ("cx: (%f, %f)\n", curve_.control_[1][X_AXIS],
138                            curve_.control_[2][X_AXIS]);
139
140       curve_.control_[1][X_AXIS] -= da[0] * u * pct;
141       curve_.control_[2][X_AXIS] -= da[1] * u * pct;
142     }
143
144   Real area = enclosed_area_f ();
145   DEBUG_OUT << to_str ("Exarea: %f\n", area);
146 }
147
148
149
150 /*
151   max ( encompass.y / curve.y )
152   
153  */
154 Real
155 Slur_bezier_bow::fit_factor () const
156 {
157   Real x1 = encompass_[0][X_AXIS];
158   Real x2 = encompass_.top ()[X_AXIS];
159
160   Real factor = 0.0;
161   for (int i=1; i < encompass_.size ()-1; i++)
162     {
163       if (encompass_[i][X_AXIS] > x1 && encompass_[i][X_AXIS] < x2)
164         {
165          Real y = curve_.get_other_coordinate (X_AXIS, encompass_[i][X_AXIS]);
166          if (y>0)
167            {
168              Real f = encompass_[i][Y_AXIS] / y;
169              factor = factor >? f;
170            }
171         }
172     }
173
174
175   return factor;
176 }
177
178
179
180