#lang racket/base

; Functions to draw charges / emblems
; Each method takes 4 parameters:
; - the width and height of the area on which the charge is drawn
; - the charge color and field color on which the charge is drawn

(require
  racket/math
  "../../graphics/vectorial.rkt"
  "../../base-generation/random.rkt"
  "../../base-generation/distribution.rkt")

; Two kind of charges are distinguished here.
; The small charges are simple symbols and try to fill the area.
; The large charges have positions for additional small charges on them.

(provide
  large-charge
  small-charge)

; Small charges
; Circle
(define (small:circle width height charge-color field-color)
  (define radius (/ (min width height) 2))
  (circle
    #:center (point (/ width 2) (/ height 2))
    #:radius radius
    #:attributes (at-fill-color charge-color)))

; Ring - a circle with a circle inside
(define (small:ring width height charge-color field-color)
  (define radius (/ (min width height) 2))
  (group
    (circle
      #:center (point (/ width 2) (/ height 2))
      #:radius radius
      #:attributes (at-fill-color charge-color))
    (circle
      #:center (point (/ width 2) (/ height 2))
      #:radius (/ radius 2)
      #:attributes (at-fill-color field-color))))

; Star maker
; This function takes the number of points and returns a small charge function
; The heavy? parameters indicates if the star should generate heavy branches or thin branches
(define (star-maker nb-points heavy?)
  (lambda (width height charge-color field-color)
    (define radius (/ (min width height) 2))
    (define center (point (/ width 2) (/ height 2)))
    (define a (/ pi nb-points))
    (define ratio
      (cond
        ((eq? 3 nb-points) 1/3)
        ((and (not (eq? 4 nb-points)) heavy?)
         (/ (sqrt (+ 1 (expt (tan a) 2)))
            (+ 1 (* (tan a) (tan (* 2 a))))))
        (#t (/ 1 (+ 1 (* 2 (cos a)))))
        ))
    (star
      #:nb-points nb-points
      #:radius radius
      #:center center
      #:ratio ratio
      #:attributes (at-fill-color charge-color))))

; Definitions of star charges
(define small:star-3 (star-maker 3 #f))
(define small:star-4 (star-maker 4 #f))
(define small:star-5 (star-maker 5 #f))
(define small:star-6 (star-maker 6 #f))
(define small:star-thin-7 (star-maker 7 #f))
(define small:star-heavy-7 (star-maker 7 #t))
(define small:star-thin-8 (star-maker 8 #f))
(define small:star-heavy-8 (star-maker 8 #t))
(define small:star-thin-9 (star-maker 9 #f))
(define small:star-heavy-9 (star-maker 9 #t))
(define small:star-thin-10 (star-maker 10 #f))
(define small:star-heavy-10 (star-maker 10 #t))
(define small:star-thin-12 (star-maker 12 #f))
(define small:star-heavy-12 (star-maker 12 #t))
(define small:star-thin-20 (star-maker 20 #f))

; Greek cross (+)
(define (small:greek-cross width height charge-color field-color)
  (define cross-size (min width height))
  (define cross-width (/ cross-size 3))
  (group
    (rectangle
      #:width cross-width
      #:height cross-size
      #:top-left (point (/ (- width cross-width) 2) (/ (- height cross-size) 2))
      #:attributes (at-fill-color charge-color))
    (rectangle
      #:width cross-size
      #:height cross-width
      #:top-left (point (/ (- width cross-size) 2) (/ (- height cross-width) 2))
      #:attributes (at-fill-color charge-color))
    ))

; St. Andrew cross / small saltire (x)
(define (small:andrew-cross width height charge-color field-color)
  (define cross-size (min width height))
  (define r (/ cross-size 4))
  (define offset-x (/ (- width cross-size) 2))
  (define offset-y (/ (- height cross-size) 2))
  (polygon
    #:attributes (at-fill-color charge-color)
    (point (+ r offset-x) offset-y)
    (point (/ width 2) (+ offset-y r))
    (point (+ (/ width 2) r) offset-y)
    (point (+ cross-size offset-x) (+ offset-y r))
    (point (+ (/ width 2) r) (/ height 2))
    (point (+ cross-size offset-x) (+ (/ height 2) r))
    (point (+ (/ width 2) r) (+ cross-size offset-y))
    (point (/ width 2) (+ (/ height 2) r))
    (point (+ r offset-x) (+ cross-size offset-y))
    (point offset-x (+ (/ height 2) r))
    (point (+ r offset-x) (/ height 2))
    (point offset-x (+ offset-y r))))

; Crescent
; The crescent is 33 width, 40 height and a group is used to scale it to the right size
(define (small:crescent width height charge-color field-color)
  (define area-scaling (min (/ width 40) (/ height 40)))
  (define area-translation (point (/ (- width (* 40 area-scaling)) 2) (/ (- height (* 40 area-scaling)) 2)))
  (group
    #:attributes
    (at-transforms
      (translate area-translation)
      (scale area-scaling)
      (translate (point 3.5 0)))
    (path
      #:attributes (at-fill-color charge-color)
      (move-to (point 33 5))
      (arc-to
        #:radius-point (point 20 20)
        #:x-axis-rotation 0
        #:large-arc? #t
        #:sweep? #f
        #:end (point 33 35))
      (arc-to
        #:radius-point (point 16 16)
        #:x-axis-rotation 0
        #:large-arc? #t
        #:sweep? #t
        #:end (point 33 5))
      (close-path))))

; Apply a random rotation to a small:charge
(define (small:rotate width height charge)
  (define angle (random:from-vector (vector 0 45 90 135 180 225 270 315)))
  (define center (point (/ width 2) (/ height 2)))
  (group
    #:attributes (at-rotate angle center)
    charge))

; Draw a small charge
(define (small-charge width height charge-color field-color)
  ; List of function and if they can be rotated
  (define func+rotate?
      (vector
        (cons small:circle #f) (cons small:ring #f)
        (cons small:star-3 #t) (cons small:star-4 #t) (cons small:star-5 #t) (cons small:star-6 #t)
        (cons small:star-thin-7 #t) (cons small:star-heavy-7 #t) (cons small:star-thin-8 #t) (cons small:star-heavy-8 #t)
        (cons small:star-thin-9 #t) (cons small:star-heavy-9 #t) (cons small:star-thin-10 #t) (cons small:star-heavy-10 #t)
        (cons small:star-thin-12 #t) (cons small:star-heavy-12 #t) (cons small:star-thin-20 #t)
        (cons small:greek-cross #f) (cons small:andrew-cross #f)
        (cons small:crescent #t)
        ))
  (define choice (random:from-vector func+rotate?))
  (define charge ((car choice) width height charge-color field-color))
  (if (cdr choice)
      (small:rotate width height charge)
      charge))

;;;;;;
; Large charges
; Large charges have variations that are applied above the pattern
; The variation signature depends on the pattern

; Common variation: nothing more (empty group)
(define (large:variation:no-more . args)
  (group))

; Cross
; Inner cross variation
(define (large:cross:inner-cross
          width height charge-color field-color cross-width)
  (define inner-cross-width (/ cross-width 3))
  (group
    (rectangle
        #:width inner-cross-width
        #:height height
        #:top-left (point (/ (- width inner-cross-width) 2) 0)
        #:attributes (at-fill-color field-color))
    (rectangle
      #:width width
      #:height inner-cross-width
      #:top-left (point 0 (/ (- height inner-cross-width) 2))
      #:attributes (at-fill-color field-color))))

; Small inner charge, located at the crossing of the rectangles
(define (large:cross:small-inner-charge
          width height charge-color field-color cross-width)
  (group
    #:attributes (at-translate (point (/ (- width cross-width) 2) (/ (- height cross-width) 2)))
    (small-charge cross-width cross-width field-color charge-color)))

; Big inner charge, inside a rectangle centered on the cross
(define (large:cross:big-inner-charge
          width height charge-color field-color cross-width)
  (define size-rect (* cross-width 2.5))
  (define size-bonus (* cross-width 2))
  (group
    (rectangle
      #:width size-rect
      #:height size-rect
      #:top-left (point (/ (- width size-rect) 2) (/ (- height size-rect) 2))
      #:attributes (at-fill-color charge-color))
    (group
      #:attributes (at-translate (point (/ (- width size-bonus) 2) (/ (- height size-bonus) 2)))
      (small-charge size-bonus size-bonus field-color charge-color))))

; One outer charge, in one of the quadrants defined by the cross
(define (large:cross:one-outer-charge
          width height charge-color field-color cross-width)
  (define area-width (/ (- width cross-width) 4))
  (define area-height (/ (- height cross-width) 4))
  (define possible-position
    (vector
      (point (/ area-width 2) (/ area-height 2))
      (point (/ (+ width cross-width area-width) 2) (/ area-height 2))
      (point (/ area-width 2) (/ (+ height cross-width area-height) 2))
      (point (/ (+ width cross-width area-width) 2) (/ (+ height cross-width area-height) 2))))
  (define position (random:from-vector possible-position))
  (group
    #:attributes (at-translate position)
    (small-charge area-width area-height charge-color field-color)))

; Four outer charges, one in every quadrant defined by the cross
(define (large:cross:four-outer-charges
          width height charge-color field-color cross-width)
  (define area-width (/ (- width cross-width) 4))
  (define area-height (/ (- height cross-width) 4))
  (define same-charge? (random:boolean))
  (define first-charge (small-charge area-width area-height charge-color field-color))
  (define translations
    (list
      (point (/ area-width 2) (/ area-height 2))
      (point (/ (+ width cross-width area-width) 2) (/ area-height 2))
      (point (/ area-width 2) (/ (+ height cross-width area-height) 2))
      (point (/ (+ width cross-width area-width) 2) (/ (+ height cross-width area-height) 2))))
  (apply group
    (map
      (lambda (tr)
        (group
          #:attributes (at-translate tr)
          (if same-charge?
              first-charge
              (small-charge area-width area-height charge-color field-color))))
      translations)))

; Cross charge
; Distribution of variations
(define large:cross:variation-distribution
  (distribution
    (cons large:variation:no-more 5)
    (cons large:cross:inner-cross 1)
    (cons large:cross:small-inner-charge 1)
    (cons large:cross:big-inner-charge 1)
    (cons large:cross:one-outer-charge 1)
    (cons large:cross:four-outer-charges 1)))
;
(define (large:cross width height charge-color field-color)
  (define variation (distribution-generate large:cross:variation-distribution))
  (define cross-width (* 2/10 (min width height)))
  (group
    ; Main pattern
    (rectangle
      #:width cross-width
      #:height height
      #:top-left (point (/ (- width cross-width) 2) 0)
      #:attributes (at-fill-color charge-color))
    (rectangle
      #:width width
      #:height cross-width
      #:top-left (point 0 (/ (- height cross-width) 2))
      #:attributes (at-fill-color charge-color))
    ; Variation
    (variation width height charge-color field-color cross-width)))

; Lozenge

; Inner charge variation, a small charge located insize the lozenge
(define (large:lozenge:inner-charge
          width height charge-color field-color offset)
  (define wref (- width offset offset))
  (define href (- height offset offset))
  (define lc (/ (* wref href) (+ wref href)))
  (group
    #:attributes (at-translate (point (/ (- width lc) 2) (/ (- height lc) 2)))
    (small-charge lc lc field-color charge-color)))

; Lozenge charge
; Distribution of variations
(define large:lozenge:variation-distribution
  (distribution
    (cons large:variation:no-more 2)
    (cons large:lozenge:inner-charge 1)))
;
(define (large:lozenge width height charge-color field-color)
  (define variation (distribution-generate large:lozenge:variation-distribution))
  (define lref (min width height))
  (define offset (if (random:boolean) (* lref 1/10) 0))
  (group
    ; Main pattern
    (polygon
      #:attributes (at-fill-color charge-color)
      (point offset (/ height 2))
      (point (/ width 2) offset)
      (point (- width offset) (/ height 2))
      (point (/ width 2) (- height offset)))
    ; Variation
    (variation width height charge-color field-color offset)))

; Fess (horizontal bar)

; Inner pattern variation - a rectangle inside the rectangle
(define (large:fess:inner-pattern
          width height charge-color field-color fess-size)
  (define inner-size (* fess-size (random:from-vector (vector 1/2 1/3 1/4))))
  (rectangle
    #:width width
    #:height inner-size
    #:top-left (point 0 (/ (- height inner-size) 2))
    #:attributes (at-fill-color field-color)))

; Inner charge - a small charge inside the rectangle
(define (large:fess:inner-charge
          width height charge-color field-color fess-size)
  (define offset (* fess-size 1/10))
  (group
    #:attributes (at-translate (point offset (+ offset (/ (- height fess-size) 2))))
    (small-charge (- width (* 2 offset)) (- fess-size (* 2 offset)) field-color charge-color)))

; Surrounding charge - add a thinner rectangle next to each side of the pattern
(define (large:fess:surrounding-pattern
          width height charge-color field-color fess-size)
  (define pattern-size (* height 1/20))
  (group
    (rectangle
      #:width width
      #:height pattern-size
      #:top-left (point 0 (- (/ height 2) (/ fess-size 2) (* 2 pattern-size)))
      #:attributes (at-fill-color charge-color))
    (rectangle
      #:width width
      #:height pattern-size
      #:top-left (point 0 (+ (/ height 2) (/ fess-size 2) pattern-size))
      #:attributes (at-fill-color charge-color))))

; Fess charge
; Distribution of variations
(define large:fess:variation-distribution
  (distribution
    (cons large:variation:no-more 3)
    (cons large:fess:inner-pattern 1)
    (cons large:fess:inner-charge 1)
    (cons large:fess:surrounding-pattern 1)))
;
(define (large:fess width height charge-color field-color)
  (define variation (distribution-generate large:fess:variation-distribution))
  (define ratio (random:from-vector (vector 1/5 1/4 1/3 1/2)))
  (define size (* height ratio))
  (group
    (rectangle
      #:width width
      #:height size
      #:top-left (point 0 (/ (- height size) 2))
      #:attributes (at-fill-color charge-color))
    (variation width height charge-color field-color size)))

; Pale (vertical bar)

; Inner pattern variation - a rectangle inside the rectangle
(define (large:pale:inner-pattern
          width height charge-color field-color pale-size)
  (define inner-size (* pale-size (random:from-vector (vector 1/2 1/3 1/4))))
  (rectangle
    #:width inner-size
    #:height height
    #:top-left (point (/ (- width inner-size) 2) 0)
    #:attributes (at-fill-color field-color)))

; Inner charge - a small charge inside the rectangle
(define (large:pale:inner-charge
          width height charge-color field-color pale-size)
  (define offset (* pale-size 1/10))
  (group
    #:attributes (at-translate (point (+ offset (/ (- width pale-size) 2)) offset))
    (small-charge (- pale-size (* 2 offset)) (- height (* 2 offset)) field-color charge-color)))

; Surrounding charge - add a thinner rectangle next to each side of the pattern
(define (large:pale:surrounding-pattern
          width height charge-color field-color pale-size)
  (define pattern-size (* width 1/20))
  (group
    (rectangle
      #:width pattern-size
      #:height height
      #:top-left (point (- (/ width 2) (/ pale-size 2) (* 2 pattern-size)) 0)
      #:attributes (at-fill-color charge-color))
    (rectangle
      #:width pattern-size
      #:height height
      #:top-left (point (+ (/ width 2) (/ pale-size 2) pattern-size) 0)
      #:attributes (at-fill-color charge-color))))

; Pale charge
; Distribution of variations
(define large:pale:variation-distribution
  (distribution
    (cons large:variation:no-more 3)
    (cons large:pale:inner-pattern 1)
    (cons large:pale:inner-charge 1)
    (cons large:pale:surrounding-pattern 1)))
;
(define (large:pale width height charge-color field-color)
  (define variation (distribution-generate large:pale:variation-distribution))
  (define ratio (random:from-vector (vector 1/5 1/4 1/3 1/2)))
  (define size (* width ratio))
  (group
    (rectangle
      #:width size
      #:height height
      #:top-left (point (/ (- width size) 2) 0)
      #:attributes (at-fill-color charge-color))
    (variation width height charge-color field-color size)))

; Disc

; Variation - filled with a small charge
(define (large:disc:charged
          width height charge-color field-color radius)
  (group
    #:attributes
    (at-translate
      (point
        (- (/ width 2) (* radius (/ 1 (sqrt 2))))
        (- (/ height 2) (* radius (/ 1 (sqrt 2))))))
      (small-charge (* radius (sqrt 2)) (* radius (sqrt 2)) field-color charge-color)))

; Disc charge
; Distribution of variations
(define large:disc:variation-distribution
  (distribution
    (cons large:variation:no-more 1)
    (cons large:disc:charged 2)))
;
(define (large:disc width height charge-color field-color)
  (define variation (distribution-generate large:disc:variation-distribution))
  (define radius (* (min width height) 1/3))
  (group
    (circle
      #:center (point (/ width 2) (/ height 2))
      #:radius radius
      #:attributes (at-fill-color charge-color))
    (variation width height charge-color field-color radius)))

; Border

; Inner charge variation - a small charge located insize the bordered area
(define (large:border:inner-charge
          width height charge-color field-color border-width)
  (group
    #:attributes (at-translate (point (* 2 border-width) (* 2 border-width)))
    (small-charge (- width (* 4 border-width)) (- height (* 4 border-width)) charge-color field-color)))

; Border charge
; Distribution of variations
(define large:border:variation-distribution
  (distribution
    (cons large:variation:no-more 2)
    (cons large:border:inner-charge 1)))
;
(define (large:border width height charge-color field-color)
  (define variation (distribution-generate large:border:variation-distribution))
  (define border-width (* 1/10 (min width height)))
  (group
    ; Main pattern
    (rectangle
      #:width width
      #:height border-width
      #:attributes (at-fill-color charge-color))
    (rectangle
      #:width border-width
      #:height height
      #:attributes (at-fill-color charge-color))
    (rectangle
      #:width width
      #:height border-width
      #:top-left (point 0 (- height border-width))
      #:attributes (at-fill-color charge-color))
    (rectangle
      #:width border-width
      #:height height
      #:top-left (point (- width border-width) 0)
      #:attributes (at-fill-color charge-color))
    ; Variation
    (variation width height charge-color field-color border-width)))

; Saltire
; Note: the 1/2-character parameters are:
; - w: width of the area
; - h: height of the area
; - sw: saltire width
; - rw: width of the rectangle generating the saltire (by moving it from one corner to the opposite)
; - rh: height of the rectangle generating the saltire

; Inner saltire variation - a saltire inside the saltire
(define (large:saltire:inner-saltire
          w h charge-color field-color
          sw rw rh)
  (polygon
    #:attributes (at-fill-color charge-color)
    (point 0 0) (point (/ rw 2) 0) (point (/ w 2) (- (/ h 2) (/ rh 2))) (point (- w (/ rw 2)) 0)
    (point w 0) (point w (/ rh 2)) (point (+ (/ w 2) (/ rw 2)) (/ h 2)) (point w (- h (/ rh 2)))
    (point w h) (point (- w (/ rw 2)) h) (point (/ w 2) (+ (/ h 2) (/ rh 2))) (point (/ rw 2) h)
    (point 0 h) (point 0 (- h (/ rh 2))) (point (- (/ w 2) (/ rw 2)) (/ h 2)) (point 0 (/ rh 2))
  ))

; Small inner charge - a charge at the center of the saltire
(define (large:saltire:small-inner-charge
          w h charge-color field-color
          sw rw rh)
  (define ratio 9/10)
  (group
    #:attributes (at-translate (point (- (/ w 2) (* ratio rw)) (- (/ h 2) (* ratio rh))))
    (small-charge (* ratio 2 rw) (* ratio 2 rh) field-color charge-color)))

; Cross inner charge - several identical charges inside the saltire
(define (large:saltire:cross-inner-charge
          w h charge-color field-color
          sw rw rh)
  (define charge (small-charge rw rh field-color charge-color))
  (define theta (atan (/ h w)))
  (define D (sqrt (+ (* w w) (* h h))))
  (define (draw n lst)
    (define offset-x (* n (cos theta) 1/6 D))
    (define offset-y (* n (sin theta) 1/6 D))
    (if (<= n 0)
        lst
        (draw (- n 1)
          (append
            (list
              (group
                #:attributes
                (at-translate
                  (point (- offset-x (/ rw 2))
                         (- offset-y (/ rh 2))))
                charge)
              (group
                #:attributes
                (at-translate
                  (point (- offset-x (/ rw 2))
                         (- h offset-y (/ rh 2))))
                charge))
            lst))))
  (apply group (draw 5 (list))))

; One outer charge - a charge in one of the sectors defined by the saltire
(define (large:saltire:one-outer-charge
          w h charge-color field-color
          sw rw rh)
  ; Size of the charge
  (define nw (/ (* rw (- h (* rh 2))) (* rh 2)))
  (define nh (/ (* rh (- w (* rw 2))) (* rw 2)))
  (define e 1/10)
  (define area-width-dexter (/ (* (- 1 e) nw h) (+ nw h)))
  (define area-width-chief (/ (* (- 1 e) nh w) (+ nh w)))
  (define area-width (min area-width-dexter area-width-chief))
  ; Translation
  (define translation
    (random:from-vector
      (vector
        (point (- (/ w 2) (/ area-width 2)) (* e nh))
        (point (* e nw) (- (/ h 2) (/ area-width 2)))
        (point (- (/ w 2) (/ area-width 2)) (- h (* e nh) area-width))
        (point (- w (* e nw) area-width) (- (/ h 2) (/ area-width 2))))))
  ;
  (group
    #:attributes (at-translate translation)
    (small-charge area-width area-width charge-color field-color)))

; Four outer charges - one in each sector define by the saltire
(define (large:saltire:four-outer-charges
          w h charge-color field-color
          sw rw rh)
  ; Size of the charge
  (define nw (/ (* rw (- h (* rh 2))) (* rh 2)))
  (define nh (/ (* rh (- w (* rw 2))) (* rw 2)))
  (define e 1/10)
  (define area-width-dexter (/ (* (- 1 e) nw h) (+ nw h)))
  (define area-width-chief (/ (* (- 1 e) nh w) (+ nh w)))
  (define area-width (min area-width-dexter area-width-chief))
  ; Translation
  (define translations
    (list
      (point (- (/ w 2) (/ area-width 2)) (* e nh))
      (point (* e nw) (- (/ h 2) (/ area-width 2)))
      (point (- (/ w 2) (/ area-width 2)) (- h (* e nh) area-width))
      (point (- w (* e nw) area-width) (- (/ h 2) (/ area-width 2)))))
  ; Charges
  (define same-charge? (random:boolean))
  (define first-charge (small-charge area-width area-width charge-color field-color))
  ;
  (apply group
    (map
      (lambda (tr)
        (group
          #:attributes (at-translate tr)
          (if same-charge?
              first-charge
              (small-charge area-width area-width charge-color field-color))))
      translations)))

; Saltire charge
; Distribution of variations
(define large:saltire:variation-distribution
  (distribution
    (cons large:variation:no-more 5)
    (cons large:saltire:inner-saltire 1)
    (cons large:saltire:small-inner-charge 1)
    (cons large:saltire:cross-inner-charge 1)
    (cons large:saltire:one-outer-charge 1)
    (cons large:saltire:four-outer-charges 1)))
;
(define (large:saltire w h charge-color field-color)
  (define variation (distribution-generate large:saltire:variation-distribution))
  ; Saltire parameters
  (define sw (* 2/10 (min w h)))
  (define r (/ sw (sqrt (+ (* w w) (* h h)))))
  (define rw (* r w))
  (define rh (* r h))
  ;
  (group
    ; Pattern
    (polygon
      #:attributes (at-fill-color charge-color)
      (point 0 0) (point rw 0) (point (/ w 2) (- (/ h 2) rh)) (point (- w rw) 0)
      (point w 0) (point w rh) (point (+ (/ w 2) rw) (/ h 2)) (point w (- h rh))
      (point w h) (point (- w rw) h) (point (/ w 2) (+ (/ h 2) rh)) (point rw h)
      (point 0 h) (point 0 (- h rh)) (point (- (/ w 2) rw) (/ h 2)) (point 0 rh))
    ; Variation
    (variation w h charge-color field-color sw rw rh)))

; Small charge alone
(define (large:single-small width height charge-color field-color)
  (define scaling (random:from-vector (vector 4/10 6/10 8/10)))
  (group
    #:attributes
    (at-transforms
      (translate (point (/ (* (- 1 scaling) width) 2) (/ (* (- 1 scaling) height) 2)))
      (scale scaling))
    (small-charge width height charge-color field-color)))

; Distribution of large charges
(define large-charge:distribution
  (distribution
    (cons large:single-small 6)
    (cons large:cross 3)
    (cons large:lozenge 2)
    (cons large:fess 1)
    (cons large:pale 1)
    (cons large:disc 1)
    (cons large:border 1)
    (cons large:saltire 1)))

; Choose a large charge at random
(define (large-charge width height charge-color field-color)
  ((distribution-generate large-charge:distribution)
   width height charge-color field-color))
