Just as a follow up to Stephen's question: for analytic examples I have to
draw curved lines all the time, usually with arrow-heads attached at the
end, so I made a function to do it given just the coordinates of the
desired destination. Using curveto is very slow because of all the trial
and error with control points, and if you do this often it becomes draining
(rather like fixing slurs before the awesome \shape function was
introduced).

The code with some examples is at the end of this mail. If I knew more
about mathematics I might know how to calculate the tangent to a bezier
curve at the end point (to know how much to rotate the arrowhead) and the
function wouldn't be such a hack. Anyway it seems to work well enough in
most situations where I need it. If it could be improved perhaps a snippet
could be made. Also I didn't really know how to retrieve the 'direction
property of the TextScript grob that is made from the markup, but somehow
simply specifying direction as a potential property seemed to work. *shrug*.

By the way, does it bug anybody else that the arrow heads in markup and the
arrow heads that can be attached to glissandi aren't the same? I really
hate it...

Kevin

\version "2.18.2"

#(define-markup-command (draw-curved-line layout props points)
   (number-pair?)
   #:properties ((thickness 0.25)
                 (curviness 1)
                 (direction 1))
   (define (square x) (* x x))
   (define (movefrom xy ang len)
     (cons (+ (car xy) (* len (cos ang)))
       (+ (cdr xy) (* len (sin ang)))))
   (let* ((x (car points))
          (y (cdr points))
          (distance (sqrt (+ (square x) (square y))))
          (ang (atan y x))
          (len-scale (* 0.1 curviness))
          (wid-scale (* distance 0.2 curviness))
          (diva-distance (* distance (- 0.382 len-scale)))
          (divb-distance (* distance (+ 0.618 len-scale)))
          (diva (movefrom '(0 . 0) ang diva-distance))
          (divb (movefrom '(0 . 0) ang divb-distance))
          (perp-ang (+ (degrees->radians (* direction 90)) ang))
          (beza (movefrom diva perp-ang wid-scale))
          (bezb (movefrom divb perp-ang wid-scale)))
     (interpret-markup layout props
       (markup #:path thickness (list (list 'curveto
                                        (car beza)
                                        (cdr beza)
                                        (car bezb)
                                        (cdr bezb)
                                        x
                                        y))))))

#(define-markup-command (draw-curved-arrow layout props points)
   (number-pair?)
   #:properties ((thickness 0.25)
                 (curviness 1)
                 (direction 1))
   (define (radians->degrees x)
     (/ (* 180 x) 3.14159))
   (let* ((x (car points))
          (y (cdr points))
          (ang (atan y x))
          (curve-scale (+ (* 8 curviness) (* 28 (sqrt curviness))))
          (rotang (- (radians->degrees ang) (* curve-scale direction))))
     (interpret-markup layout props
       #{
         \markup { \combine \draw-curved-line #points
                   \translate #(cons (+ x 0.5) y)
                   \rotate #rotang
                   \arrow-head #X #RIGHT ##t }
       #})))

% examples of usage
\relative {
  b'1_\markup { \draw-curved-arrow #'(5 . 10) }
  % change the 'curviness property to make the line more or less curved
  b_\markup { \override #'(curviness . 5) \draw-curved-arrow #'(8 . 0) }
  b_\markup { \override #'(curviness . 0) \draw-curved-arrow #'(8 . 3) }
  b^\markup { \draw-curved-arrow #'(10 . 10) }
  b_\markup { \draw-curved-arrow #'(5 . 5) }
  b_\markup { \override #'(curviness . 3) \draw-curved-arrow #'(5 . 5) }
}
_______________________________________________
lilypond-user mailing list
lilypond-user@gnu.org
https://lists.gnu.org/mailman/listinfo/lilypond-user

Reply via email to