lilypond-user
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

drawing curves in markup (was: draw-line)


From: Kevin Barry
Subject: drawing curves in markup (was: draw-line)
Date: Tue, 17 Mar 2015 14:52:55 +0000

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) }
}

reply via email to

[Prev in Thread] Current Thread [Next in Thread]