|
From: | Lukas-Fabian Moser |
Subject: | Re: Questions about HorizontalBracket |
Date: | Sun, 13 Sep 2020 19:22:13 +0200 |
User-agent: | Mozilla/5.0 (X11; Linux x86_64; rv:68.0) Gecko/20100101 Thunderbird/68.10.0 |
Hi Francesco,
I’m trying to use HorizontalBracket to annotate the intervals between notes of a scale. The example (perhaps not minimal, but almost working) attached shows something very close to what I want to achieve. However there are a few things that need to be fixed, or improved: 1) the brackets remain outside the staff no matter how I fiddle with staff- padding and padding properties, while I would like them to stay closer to the notes; 2) I cannot find an (obvious and) automatic way to have the ends of a bracket to align with the center of the note heads. I found a manual workaround by setting the shorten-pair property, which is a far from being an optimal solution; 3) is there a way to create a V-shaped bracket? The hack I came up with is ugly; 4) to have brackets both above and below the notes I have used two voices, one with the notes hidden. Is there a faster/less verbose way to obtain the same result? Besides these, it would be nice (but not essential) to have these bracket to also follow the slope of an interval.
LilyPond's horizontal brackets are not very flexible, as far as I know. But it occurred to me that for everything you listed, the necessary mechanisms are in LilyPond as part of the mechanism typesetting slurs: 1), 2) is automatic for slurs, 3) is a matter of distorting a slur to a simple three-point line, and 4) is possible by virtue of the \=... construct.
Hence, how about:
\version "2.21.0"
% Some routines for calculating with 2D vectors (given as scheme
pairs)
#(define (vector-sum v w)
(cons (+ (car v) (car w))
(+ (cdr v) (cdr w))))
#(define (vector-factor factor v)
(cons (* (car v) factor)
(* (cdr v) factor)))
#(define (scalar-product v w)
(+ (* (car v) (car w))
(* (cdr v) (cdr w))))
#(define (midpoint p1 p2)
(vector-factor 1/2 (vector-sum p1 p2)))
#(define (normal p q)
; yields a normal vector to the line from p to q.
; the length of the normal vector will be proportional to
; the distance [pq].
(cons (- (cdr p) (cdr q))
(- (car q) (car p))))
#(define (side v normal start)
; A line through "start" with fixed normal vector "normal" cuts
the plane
; into two half-planes. This function returns
; 0 if v lies on the line itself,
; +1 if v lies in the half plane that the normal vector points
to,
; -1 otherwise.
(let ((dist (- (scalar-product normal v)
(scalar-product normal start))))
(cond ((> dist 0) 1) ; is there no "sgn" function in
guile?!
((< dist 0) -1)
(else 0))
))
% Shortcuts for using pairs inside a \markup \path ...
#(define (moveto p) (list 'moveto (car p) (cdr p)))
#(define (lineto p) (list 'lineto (car p) (cdr p)))
VShapeSlur =
\tweak stencil
#(lambda (grob)
(let* ((control-points (ly:grob-property grob 'control-points))
(start (first control-points))
(1st-directional-point (second control-points))
(2nd-directional-point (third control-points))
(stop (fourth control-points)))
(grob-interpret-markup grob #{
\markup {
\path #0.1 #(list (moveto start)
(lineto (midpoint 1st-directional-point
2nd-directional-point))
(lineto stop))
} #})))
\etc
bracketSlur =
\tweak stencil
#(lambda (grob)
(let* ((control-points (ly:grob-property grob 'control-points))
(start (first control-points))
(1st-directional-point (second control-points))
(stop (fourth control-points))
(normal (normal start stop))
(scaled-normal
(vector-factor
(* 0.075 (side 1st-directional-point normal start))
normal)))
(grob-interpret-markup grob #{
\markup {
\path #0.1
#(list (moveto start)
(lineto (vector-sum start scaled-normal))
(lineto (vector-sum stop scaled-normal))
(lineto stop))
} #})))
\etc
\relative c' {
c1 \bracketSlur ( d) e \bracketSlur( f g a g f')
c,1 \VShapeSlur ( d) e \VShapeSlur( f g a g f')
}
\relative c' {
c4 \VShapeSlur \=0_( \VShapeSlur \=1^( d e \bracketSlur \=2_(
f\=1) e d\=2) c b\=0)
}
Best
Lukas
[Prev in Thread] | Current Thread | [Next in Thread] |