I was playing around with drawing regular polygons, which led to creating a new markup command with several configurable options. (Some of these options are inherited via the built-in \polygon command.)

There might be a few things to tighten up, but I believe it is in a pretty workable state. I wish optional parameters existed for markup commands. If they did, then a user could just specify the number of sides and omit the size. The default size would be something that matches the font height, so the shape would naturally fit in with the surrounding text.


-- Aaron Hill
\version "2.25.13"

\paper {
  #(set-paper-size "a6")
  top-margin = 1\cm
  left-margin = 1\cm
  tagline = #f
}

#(define pi 3.14159265359)

#(define-markup-command
  (regularPolygon layout props
    sides axis size)
  (integer? number? number?)
  #:properties ((twist 0)
                (angularity 0))
  (if (< sides 3)
    (begin
      (ly:warning "you must specify at least three sides.")
      (set! sides 3)))

  (define (build-polygon radius measuring?)
    (let* (
      (side-length (* 2 radius (sin (/ pi sides))))
      (max-radius (* 1/2 side-length (/ 1 (tan (/ pi sides)))))
      (min-radius (* radius
        (/ (sin (* pi (/ (- sides 2) (* 6 sides))))
          (sin (* pi (/ (- (* 5 sides) 4) (* 6 sides)))))))

      (star? (< 0 angularity))
      (pt-count (* sides (if star? 2 1)))
      (thetas (map
        (lambda (n)
          (cons n
            (* (- (/ n pt-count) (/ 1 2 sides) 1/4
                  (if measuring? 0 (* twist (/ 1 2 sides))))
              2 pi)))
        (iota pt-count)))
      (cpts (map
        (lambda (theta)
          (make-polar
            (if (and star? (odd? (car theta)))
              (interval-index (cons max-radius min-radius)
                (1+ (* 2 (1- angularity))))
              radius)
            (cdr theta)))
        thetas))
      (rpts (map
        (lambda (cpt)
          (cons (real-part cpt) (imag-part cpt)))
          cpts)))
      (interpret-markup layout
        (if measuring?
          (cons '((thickness . 0)) props)
          props)
        (make-polygon-markup rpts))))

  (let*  ((prescaled (build-polygon 1 #t))
          (pre-extent
            (ly:stencil-extent prescaled axis))
          (radius
            (/ size (interval-length pre-extent)))
          (rescaled (build-polygon radius #f))
          (aligned-to-baseline
            (ly:stencil-aligned-to
              rescaled Y DOWN))
          (aligned-to-left-edge
            (ly:stencil-aligned-to
              aligned-to-baseline X LEFT)))
    aligned-to-left-edge))

foo = \markup {
  \override #'(filled . #f)
  {
    \regularPolygon #3 #Y #2
    \regularPolygon #4 #Y #2
    \regularPolygon #5 #Y #2
    \regularPolygon #6 #Y #2
    \regularPolygon #7 #Y #2
  }
}

fooo = \markup \column {
  \override #'(twist . -1) \foo
  \override #'(twist . -0.75) \foo
  \override #'(twist . -0.5) \foo
  \override #'(twist . -0.25) \foo
  \override #'(twist . 0) \foo
  \override #'(twist . 0.25) \foo
  \override #'(twist . 0.5) \foo
  \override #'(twist . 0.75) \foo
  \override #'(twist . 1) \foo
}

\markup {
  \fooo
  \override #'(angularity . 0.5) \fooo
  \override #'(angularity . 1) \fooo
}

starBase = \markup {
  \override #'(angularity . 0.8)
  \override #'(thickness . 12)
  \regularPolygon #17 #X #40
}

star = \markup \overlay {
  \with-color #yellow \starBase
  \with-color #red \override #'(filled . #f) \starBase
}

\markup \general-align #X #LEFT \overlay {
  \general-align #X #CENTER \vcenter \star
  \rotate #15 \general-align #X #CENTER \vcenter
  \fontsize #6 \override #'(style . outline) \whiteout
  \center-column {
    \larger \bold \line { Lorem Ipsum! }
    \italic \line { (dolor sit amet) }
  }
}

Attachment: regular-polygon.pdf
Description: Adobe PDF document

Reply via email to