lilypond-user
[Top][All Lists]

## Re: How to calculate visible vertical beam-height

 From: Thomas Morley Subject: Re: How to calculate visible vertical beam-height Date: Sun, 2 Jun 2019 19:17:58 +0200

```Am So., 2. Juni 2019 um 17:26 Uhr schrieb <address@hidden>:
>
> --------
> Thomas Morley:
> ...
> > I'm interested in a formula how the length of the red line changes
> > with different blot-diameters.
> ...
> > \version "2.19.82"
> >
> > #(define-markup-command (beam layout props width slope thickness)
> >   (number? number? number?)
> >   #:properties ((blot #f))
> >   (let* ((y (* slope width))
> >          (yext (cons (min 0 y) (max 0 y)))
> >          (half (/ thickness 2)))
> >
> >     (ly:make-stencil
> >      `(polygon ',(list
> >                   0 (/ thickness -2)
> >                   width (+ (* width slope)  (/ thickness -2))
> >                   width (+ (* width slope)  (/ thickness 2))
> >                   0 (/ thickness 2))
> >                ,(or blot (ly:output-def-lookup layout 'blot-diameter))
> >                #t)
> >      (cons 0 width)
> >      (cons (+ (- half) (car yext))
> >            (+ half (cdr yext))))))
> >
> > \markup {
> >   \overlay {
> >     \override #'(blot . 0) \beam #5 #1 #2
> >     \translate #'(1 . 0) \with-color #red \draw-line #'(0 . 2)
> >   }
> >
> >   \overlay {
> >     \override #'(blot . 2) \beam #5 #1 #2
> >     \translate #'(2.35 . 0) \with-color #red \draw-line #'(0 . 4.7)
> >   }
> > }
>
> Which seems to be drawn as (in postscript):
> /draw_polygon % fill? x(n) y(n) x(n-1) y(n-1) ... x(0) y(0) n blot
> {
>         setlinewidth %set to blot
>
>         0 setlinecap
>         1 setlinejoin
>
>         3 1 roll
>         /polygon_x
>         currentpoint
>         /polygon_y exch def
>         def
>         rmoveto % x(0) y(0)
>         { polygon_x polygon_y vector_add lineto } repeat % n times
>         closepath
>         stroke_and_fill?
> } bind def
>
> So, you defines four points makeing up a filled closed polygon.
> You then draw a line with linewidth = blot or blot-diamer, through
> thoose points.
>
> Let
>  x1 = 0
>  x2 = width
>  ya = - thickness/2
>  yb =   thickness/2
>  h  = width * slope
>
> The points are
>  (x1, ya)
>  (x1, yb)
>  (x2, ya+h)
>  (x2, yb+h)
>
> I.e.
>  thickness = height (in y-direction) of beam without any blot
>  slope is tan(angle of beam inclination), i.e. 1 => 45°
>  blot = the linewidth of a line (path in postscript jargon) through
>       the above points, i.e. adding to thickness
>
> As one can see, the polygon have four corners and is an
> parallelogram, i.e. top/bottom sides are parallel to each
> other and the same for left/right siedes.
>
> Then you make the parallelogram lines thicker, thereby extending
> the filled area blot/2 units outwards, parallel to the sides.
> Round at the corner, and straight along the sides.
>
> But since blot is a linewidth, not a y-height as for the thickness,
> the blot/2 distance from the polygon side to the final extent, it
> is measured at 90° to the parallelogram side, which is inclined at an
> angle = atan(slope). If you draw a line (A) representing the blot/2
> extension, you'll see that it is also inclined at the same angle;
> if you look at the top side and if slope > 0, the line A is inclined
> upwards to the left.
>
> So the extension is blot/2 at 90° (normal) to the polygon side.
> To get from a polygon side point p1 up in y-direction, we divide
> it into two actions:
>
>  . from p1 going normal to poly-side blot/2 units to the line edge
>    point p2
>
>  . the from p2, along the line edge, to the final "straight above p1
>    point" p3
>
> since lines p1-p2 and p2-p3 are at 90° angle to each other, we can use
> trigonymetry to find the length of the line p1-p3.
>
> we know that (by makeing some drawings):
>  length of line p1-p2 / length of line p1-p3 =
>  cos( our inclination angle ) = cos(atan(slope))
>
> So bacically:
>  length of p1-p3 = length p1-p2 / cos(atan(slope))
>
> and finally:
>  total height = thickness + blot / cos(atan(slope))
>
> Well, you can't blame me for guessing.
>
> Regards,
> /Karl Hammar

Hi Karl,

many thinks for your detailed explanations.

First I translated your
>  total height = thickness + blot / cos(atan(slope))
into guile, making for:
(+ thick (/ blot (cos (atan slope))))

Though, guile has sometimes problems with trigonemetric procedures if
the angle gets close to multiples of PI/4. I was beaten by this
problem before.
Thus I used our builtin functions ly:directed and ly:angle, making for:
(+ thick (/ blot (car (ly:directed (ly:angle (cons 1 slope))))))
The test-code below compares the two codings. The results are almost
identical, unless slope is 0.89, i.e. the angle is closer to 45°
Admittedly the difference is minimal and PI/2 will never reached with
this polygon-coding.

Anyway, here a _test_-coding:
`visible-beam-thickness´ conses the two codings. The markup-command
produces debugging-output, the polygon and two lines.
The blue one takes the values from your coding. The green one mines.
If someone else is interested for own codings, the relevant parts can
be catched easily, I suppose.

#(define (visible-beam-thickness blot slope thick)
(cons
(+ thick (/ blot (car (ly:directed (ly:angle (cons 1 slope))))))
(+ thick (/ blot (cos (atan slope))))))

#(define-markup-command (beam layout props width slope thickness)
(number? number? number?)
#:properties ((blot #f))
(let* ((y (* slope width))
(yext (cons (min 0 y) (max 0 y)))
(half (/ thickness 2))
(call-test (visible-beam-thickness blot slope thickness))
(harm (car call-test))
(karl (cdr call-test)))

(format #t "\nkarl: ~a\tharm: ~a\tdifference: ~a"
karl
harm
(- karl harm))

(ly:make-stencil
`(polygon ',(list
0 (/ thickness -2)
width (+ (* width slope)  (/ thickness -2))
width (+ (* width slope)  (/ thickness 2))
0 (/ thickness 2))
,(or blot (ly:output-def-lookup layout 'blot-diameter))
#t)
(cons 0 width)
(cons (+ (- half) (car yext))
(+ half (cdr yext))))
(ly:stencil-translate
(stencil-with-color
(interpret-markup layout props
(make-override-markup '(thickness . 0)
(make-draw-line-markup
(cons 0 harm))))
green)
(cons
(/ width 2)
(- (* (/ width 2) slope) (/ harm 2))))
(ly:stencil-translate
(stencil-with-color
(interpret-markup layout props
(make-override-markup '(thickness . 0)
(make-draw-line-markup
(cons 0 karl))))
blue)
(cons
(1+ (/ width 2))
(- (* (1+ (/ width 2)) slope) (/ karl 2)))))))

\markup {
\override #'(blot . 0.1) \beam #5 #1 #2
\override #'(blot . 0.1) \beam #5 #0.89 #2
\override #'(blot . 2) \beam #5 #2 #2
\override #'(blot . 2) \beam #5 #-2 #2
\override #'(blot . 2) \beam #5 #0 #2
\override #'(blot . 2) \beam #5 #0 #1.1
\override #'(blot . 0.05) \beam #5 #0.01 #1.1
}

I think we can take this problem as solved.

Thanks a lot,
Harm

```