Skip to content

Instantly share code, notes, and snippets.

@bakgatviooldoos
Created December 5, 2024 13:00
Show Gist options
  • Save bakgatviooldoos/36e810cd00587384f3f7c4822e4c1278 to your computer and use it in GitHub Desktop.
Save bakgatviooldoos/36e810cd00587384f3f7c4822e4c1278 to your computer and use it in GitHub Desktop.
Christmas Globe, Racket Advent 2024
#lang racket
(require
racket/gui
"helpers.rkt")
(provide
epicycles-renderer%)
(define (fourier-sample θ zs)
(for/sum ([(z t) (in-indexed (in-list zs))])
(* z (exp (* t θ)))))
; discrete forward fourier transform
(define (dft xs)
(define N (length xs))
(for/list ([k (in-range N)])
(define θ (* -2i pi k (/ N)))
(fourier-sample θ xs)))
(define epicycles-renderer%
(class gif-renderer%
(init
width
height
coords
mainview?
recorded?)
(super-new
[width width]
[height height]
[mainview? mainview?]
[recorded? recorded?])
(define N (length coords))
(define zs+ts (sort (map cons (dft coords) (range N))
> #:key (compose1 magnitude car)))
(define points (list))
(define cursor #false)
(define/public (get-cursor) cursor)
(define/public (sample! ticks)
(define θ (* +2i pi ticks (/ N)))
(points
. set!
. (for/list ([z+t (in-list zs+ts)]
#:do [(match-define (cons z t) z+t)])
(* z (exp (* t θ)) (/ N)))))
(sample! 0)
(define (draw-epicycles . dcs)
(sends dcs set-brush "white" 'transparent)
(sends dcs set-pen "skyblue" 1 'solid)
(for/fold ([cx (/ width 2)] [cy (/ height 2)]
[lx 0] [ly 0]
#:result
(set! cursor (make-rectangular (+ cx lx) (+ cy ly))))
([point (in-list points)])
(define r (magnitude point))
(define-values (cx′ cy′) (values (+ lx cx) (+ ly cy)))
(sends dcs draw-ellipse (- cx′ r) (- cy′ r) (* 2 r) (* 2 r))
(sends dcs draw-line cx cy cx′ cy′)
(define-values (lx′ ly′) (values (real-part point) (imag-part point)))
(values cx′ cy′ lx′ ly′)))
(define/override (paint canvas dc [bm* #false])
(super paint draw-epicycles canvas dc bm*))))
#lang racket
(require
racket/gui mrlib/gif)
(provide
either
complex-parts ω norm
sends
gif-renderer%
fetch/scale-coords
render-gif!)
(define (either x y)
(if (zero? (random 0 2)) x y))
; components of complex number z
(define (complex-parts z)
(values (real-part z) (imag-part z)))
(define ω magnitude)
; complex -> unit vector
(define (norm z) (if (zero? z) 0 (/ z (ω z))))
(define-syntax-rule
(sends objs msg ...)
#;becomes
(for ([obj (in-list objs)])
(send obj msg ...)))
(define gif-renderer%
(class object%
(super-new)
(init
mainview?
recorded?)
(init-field
width height)
(define scenes (list))
(define recording? recorded?)
(define cacheview? mainview?)
(define/public (get-scenes) scenes)
(define/public (paint render* canvas dc [bm* #false])
(cond
[(not recording?) (render* dc)]
[else
(define bm (bm* . or . (send canvas make-bitmap width height)))
(define bm-dc (new bitmap-dc% [bitmap bm]))
(render* dc bm-dc)
(when cacheview?
(scenes
. set!
. `(,bm . ,scenes)))
(values bm)]))))
(define (render-gif! filepath scenes #:chunks [chunks #false])
(thread
(thunk
(cond
[(not chunks)
(write-animated-gif
#;bitmaps (reverse scenes)
#;delay-cseconds 1
#;filename filepath
#:one-at-a-time? #true
#:loop? #true
#:last-frame-delay 100)]
[else
(define total (length scenes))
(define size (exact-floor (/ total chunks)))
(define chunked
(let loop ([chunked (list)]
[scenes (reverse scenes)]
[remains total])
(cond
[(zero? remains) (reverse chunked)]
[(<= remains size)
(reverse (cons scenes chunked))]
[else
(loop
(cons (take scenes size) chunked)
(drop scenes size)
(- remains size))])))
(for ([chunk (in-list chunked)]
[posn (in-naturals)])
(write-animated-gif
#;bitmaps chunk
#;delay-cseconds 1
#;filename (~a posn "-" filepath)
#:one-at-a-time? #true
#:loop? #true
#:last-frame-delay 100))]))))
(define (fetch/scale-coords filename radius)
(with-input-from-file filename
(thunk
(define the-coords
(for/list ([point (in-lines)]
#:when (non-empty-string? point))
(string->number
(~a (string-replace point "," "+") "i"))))
(define center
(for/fold ([x-min +inf.0] [x-max -inf.0]
[y-min +inf.0] [y-max -inf.0]
#:result
(make-rectangular
(/ (+ x-max x-min) 2)
(/ (+ y-max y-min) 2)))
([coord (in-list the-coords)]
#:do [(define-values (real imag)
(complex-parts coord))])
(values
(min x-min real) (max x-max real)
(min y-min imag) (max y-max imag))))
(define centered
(map (lambda (z) (- z center)) the-coords))
(define scale
(/ radius (ω (argmax ω centered))))
(map (lambda (z) (* z scale)) centered))))
456.39801025390625,413.1969909667969
458.3300476074219,410.7043151855469
460.2321472167969,408.18865966796875
462.1019287109375,405.6489562988281
463.94073486328125,403.08673095703125
465.74713134765625,400.50152587890625
467.521484375,397.89422607421875
469.2633056640625,395.2651062011719
470.9720153808594,392.61431884765625
472.64813232421875,389.94281005859375
474.2900390625,387.2501525878906
475.8994140625,384.5379333496094
477.4734191894531,381.8050231933594
479.0143127441406,379.05328369140625
480.51995849609375,376.2821350097656
481.99139404296875,373.49267578125
483.4277038574219,370.6849670410156
484.8286437988281,367.8594055175781
486.1946716308594,365.016845703125
487.5240783691406,362.15692138671875
488.8186950683594,359.2811279296875
490.07598876953125,356.3887939453125
491.2976989746094,353.4812927246094
492.4825744628906,350.5585632324219
493.63055419921875,347.62115478515625
494.7423400878906,344.6698303222656
495.8157958984375,341.7043762207031
496.8530578613281,338.7260437011719
497.85198974609375,335.7346496582031
498.81365966796875,332.7310791015625
499.738037109375,329.7157897949219
500.62322998046875,326.6888122558594
501.47174072265625,323.65130615234375
502.28076171875,320.60308837890625
503.0519714355469,317.5450439453125
503.7854309082031,314.4777526855469
504.479736328125,311.4013366699219
505.1352844238281,308.3164367675781
505.75225830078125,305.2236022949219
506.3305969238281,302.123291015625
506.869873046875,299.0159606933594
507.3702697753906,295.9021301269531
507.83184814453125,292.78228759765625
508.2546081542969,289.656982421875
508.6380920410156,286.526611328125
508.98284912109375,283.3917236328125
509.2887268066406,280.2528076171875
509.55535888671875,277.1103210449219
509.7832946777344,273.96478271484375
509.97235107421875,270.8166809082031
510.1224365234375,267.6664733886719
510.23406982421875,264.5146789550781
510.3067321777344,261.36175537109375
510.3409729003906,258.2081298828125
510.3365173339844,255.05435180664062
510.2937316894531,251.90086364746094
510.21234130859375,248.74813842773438
510.0922546386719,245.59664916992188
509.9332275390625,242.44686889648438
509.73541259765625,239.29930114746094
509.4987487792969,236.15438842773438
509.22314453125,233.0126953125
508.90863037109375,229.8746337890625
508.5551452636719,226.74072265625
508.1627502441406,223.6114501953125
507.7314147949219,220.48731994628906
507.2610778808594,217.36880493164062
506.7518615722656,214.25640869140625
506.20379638671875,211.15060424804688
505.6169128417969,208.0519256591797
504.99127197265625,204.96083068847656
504.326904296875,201.8778076171875
503.62396240234375,198.80335998535156
502.8824462890625,195.7379913330078
502.1025695800781,192.68215942382812
501.28436279296875,189.63636779785156
500.4280090332031,186.60105895996094
499.5335693359375,183.57679748535156
498.60125732421875,180.56396484375
497.6311340332031,177.56309509277344
496.62347412109375,174.57461547851562
495.578369140625,171.59906005859375
494.4959716796875,168.63682556152344
493.3764953613281,165.6884002685547
492.22015380859375,162.7542724609375
491.02685546875,159.83494567871094
489.797119140625,156.93080139160156
488.5310363769531,154.04229736328125
487.22894287109375,151.1698760986328
485.8909912109375,148.31396484375
484.51739501953125,145.47503662109375
483.1083984375,142.6535186767578
481.66424560546875,139.84979248046875
480.1852722167969,137.0643310546875
478.6714782714844,134.29759216308594
477.1231384277344,131.5500030517578
475.54071044921875,128.8219985961914
473.9244079589844,126.11386108398438
472.2745056152344,123.42609405517578
470.59130859375,120.75904083251953
468.87506103515625,118.11309814453125
467.12603759765625,115.48873138427734
465.3443603515625,112.88644409179688
463.5304870605469,110.30647277832031
461.6846923828125,107.74925994873047
459.807373046875,105.21510314941406
457.8987121582031,102.70440673828125
455.9591064453125,100.21756744384766
453.9888610839844,97.75495147705078
451.9880065917969,95.3171615600586
449.9571228027344,92.90431213378906
447.89654541015625,90.51676177978516
445.80657958984375,88.1549072265625
443.68756103515625,85.819091796875
441.53985595703125,83.50965881347656
439.363525390625,81.22710418701172
437.1590881347656,78.97174072265625
434.9269104003906,76.7437744140625
432.6673583984375,74.54359436035156
430.3807373046875,72.37158203125
428.06744384765625,70.22797393798828
425.72784423828125,68.1131362915039
423.36199951171875,66.02770233154297
420.9704895019531,63.9716682434082
418.55377197265625,61.94541931152344
416.11212158203125,59.94922637939453
413.6459655761719,57.983402252197266
411.1556091308594,56.0483283996582
408.6414489746094,54.144351959228516
406.1037292480469,52.271854400634766
403.5429382324219,50.43098068237305
400.95953369140625,48.622032165527344
398.3538818359375,46.84528350830078
395.7263488769531,45.1010627746582
393.0773010253906,43.38963317871094
390.4071350097656,41.71133804321289
387.7161865234375,40.066612243652344
385.0049743652344,38.45549392700195
382.27392578125,36.878273010253906
379.52337646484375,35.335235595703125
376.75384521484375,33.82661437988281
373.9656066894531,32.35269355773926
371.15924072265625,30.913686752319336
368.3350830078125,29.509963989257812
365.4934997558594,28.141799926757812
362.6350402832031,26.80928611755371
359.7601013183594,25.51268196105957
356.8691711425781,24.252174377441406
353.9626770019531,23.027969360351562
351.0410461425781,21.840312957763672
348.1047668457031,20.689373016357422
345.1542663574219,19.57537841796875
342.1900634765625,18.49849510192871
339.2125244140625,17.45890998840332
336.2221984863281,16.45678997039795
333.2194519042969,15.492415428161621
330.204833984375,14.565834045410156
327.1788635253906,13.677192687988281
324.14190673828125,12.8266019821167
321.0945739746094,12.014220237731934
318.0372619628906,11.240138053894043
314.970458984375,10.504490852355957
311.8947448730469,9.807373046875
308.8104553222656,9.148852348327637
305.7182312011719,8.529040813446045
302.6183776855469,7.947983741760254
299.5115966796875,7.405755043029785
296.39825439453125,6.90239143371582
293.2788391113281,6.437933444976807
290.1538391113281,6.012396812438965
287.0238952636719,5.625817775726318
283.8893127441406,5.278173923492432
280.7506408691406,4.969526052474976
277.6083984375,4.699931383132935
274.4630126953125,4.469241619110107
271.315185546875,4.277415990829468
268.1650390625,4.124379873275757
265.0133972167969,4.0100789070129395
261.8605041503906,3.9344213008880615
258.70697021484375,3.897312879562378
255.55316162109375,3.8988027572631836
252.39967346191406,3.938741445541382
249.24681091308594,4.017463445663452
246.09523010253906,4.13485050201416
242.94532775878906,4.291009187698364
239.79754638671875,4.4860923290252686
236.6524658203125,4.719978094100952
233.51052856445312,4.992902040481567
230.3721923828125,5.3047051429748535
227.23797607421875,5.65553092956543
224.1083526611328,6.045342922210693
220.9839324951172,6.474022388458252
217.86502075195312,6.941827297210693
214.75216674804688,7.4482574462890625
211.64593505859375,7.993959903717041
208.5467071533203,8.578161239624023
205.45516967773438,9.201305389404297
202.37155151367188,9.863105773925781
199.2964630126953,10.563322067260742
196.23052978515625,11.302372932434082
193.1740264892578,12.07956600189209
190.1275177001953,12.895121574401855
187.0914764404297,13.748974800109863
184.06634521484375,14.640625953674316
181.05276489257812,15.570351600646973
178.05101013183594,16.5378475189209
175.06163024902344,17.542720794677734
172.08511352539062,18.585227966308594
172.15672302246094,19.86944007873535
174.92813110351562,21.37455940246582
177.67877197265625,22.917396545410156
180.40951538085938,24.495241165161133
183.1202392578125,26.10717010498047
185.811767578125,27.750974655151367
188.484375,29.425363540649414
191.1382598876953,31.129234313964844
193.77407836914062,32.861013412475586
196.39205932617188,34.6195182800293
198.9926300048828,36.40372085571289
201.57611083984375,38.21261215209961
204.142822265625,40.04521179199219
206.69309997558594,41.90068054199219
209.22723388671875,43.778076171875
211.7455291748047,45.6766357421875
214.2482452392578,47.59559631347656
216.73580932617188,49.53429412841797
219.2084197998047,51.49202346801758
221.66603088378906,53.46856689453125
224.10946655273438,55.46257781982422
226.53872680664062,57.473793029785156
228.9541015625,59.5016975402832
231.3558349609375,61.545745849609375
233.7440185546875,63.605560302734375
236.1184539794922,65.6812744140625
238.47988891601562,67.77176666259766
240.82852172851562,69.87663269042969
243.16455078125,71.99541473388672
245.4881591796875,74.12791442871094
247.79872131347656,76.27445983886719
250.09722900390625,78.43387603759766
252.3839569091797,80.60587310791016
254.6588592529297,82.79006958007812
256.9213409423828,84.9873046875
259.17242431640625,87.19615936279297
261.4123229980469,89.41637420654297
263.6405334472656,91.64830780029297
265.8572692871094,93.8916244506836
268.063232421875,96.1456069946289
270.25811767578125,98.41031646728516
272.44158935546875,100.68600463867188
274.6146545410156,102.9716796875
276.7769775390625,105.26749420166016
278.92822265625,107.57367706298828
281.06939697265625,109.88924407958984
283.1998596191406,112.21469116210938
285.3197326660156,114.54972076416016
287.4298400878906,116.89363861083984
289.5290832519531,119.24735260009766
291.6183776855469,121.6097640991211
293.69775390625,123.98091888427734
295.7666320800781,126.361328125
297.8260803222656,128.74982452392578
299.87506103515625,131.1474151611328
301.9144592285156,133.55311584472656
303.9440612792969,135.967041015625
305.9635925292969,138.3894805908203
307.9740295410156,140.8193817138672
309.973876953125,143.25808715820312
311.96478271484375,145.70399475097656
313.9455261230469,148.158203125
315.9171142578125,150.61984252929688
317.87896728515625,153.08914184570312
319.83123779296875,155.5660858154297
321.7742614746094,158.05026245117188
323.70733642578125,160.54208374023438
325.6316223144531,163.0408172607422
327.5457458496094,165.54733276367188
329.4512634277344,168.0603790283203
331.3464660644531,170.58126831054688
333.2331848144531,173.1084747314453
335.1096496582031,175.64329528808594
336.9775390625,178.18446350097656
338.8353271484375,180.73300170898438
340.6844482421875,183.287841796875
342.5235595703125,185.84991455078125
344.3539733886719,188.41822814941406
346.17437744140625,190.9935760498047
347.98602294921875,193.57513427734375
349.7876892089844,196.16366577148438
351.58056640625,198.75823974609375
353.3634948730469,201.35977172851562
355.1375732421875,203.96717834472656
356.90167236328125,206.58152770996094
358.656982421875,209.20169067382812
360.402099609375,211.8286895751953
362.13848876953125,214.46139526367188
363.8645935058594,217.1009063720703
365.5821228027344,219.74607849121094
367.2890625,222.3980255126953
368.9874572753906,225.0554656982422
370.6752014160156,227.7197265625
372.354248046875,230.38937377929688
374.0227966308594,233.06568908691406
375.682373046875,235.7474822998047
377.3315124511719,238.435791015625
378.971435546875,241.1296844482422
380.6010437011719,243.829833984375
382.2210998535156,246.53558349609375
383.83099365234375,249.24754333496094
385.43115234375,251.9652862548828
387.02117919921875,254.6888885498047
388.6011047363281,257.41845703125
390.1710510253906,260.1537170410156
391.7304992675781,262.8950500488281
393.2801208496094,265.64190673828125
394.8188781738281,268.3948669433594
396.347900390625,271.1531982421875
397.86566162109375,273.91778564453125
399.3738708496094,276.6875915527344
400.87042236328125,279.46368408203125
402.3573913574219,282.2449645996094
403.83245849609375,285.0325012207031
405.2977294921875,287.82525634765625
406.751220703125,290.6241455078125
408.1944580078125,293.4283142089844
409.6259460449219,296.23846435546875
411.0469055175781,299.0541687011719
412.4560546875,301.87554931640625
413.854248046875,304.7024841308594
415.24072265625,307.5351867675781
416.6158142089844,310.3734436035156
417.9791259765625,313.2174072265625
419.33062744140625,316.0668640136719
420.67034912109375,318.9219665527344
421.9979248046875,321.7826843261719
423.3135681152344,324.6490173339844
424.6167297363281,327.52099609375
425.9078369140625,330.39849853515625
427.1860656738281,333.2815856933594
428.4520263671875,336.17010498046875
429.7049255371094,339.06451416015625
430.9451904296875,341.964111328125
432.172119140625,344.8695373535156
433.38616943359375,347.7802429199219
434.5865783691406,350.69671630859375
435.7737121582031,353.61859130859375
436.94696044921875,356.5460205078125
438.1065979003906,359.4788513183594
439.2521057128906,362.4172668457031
440.3833923339844,365.3609619140625
441.50054931640625,368.3103332519531
442.6028747558594,371.2652893066406
443.69091796875,374.2253723144531
444.76348876953125,377.1912536621094
445.8217468261719,380.1621398925781
446.8643493652344,383.1385803222656
447.891357421875,386.1206359863281
448.9017333984375,389.108154296875
449.8976135253906,392.1006164550781
450.8767395019531,395.0985107421875
451.83935546875,398.1019287109375
452.7853088378906,401.11041259765625
453.7144470214844,404.12432861328125
454.6264343261719,407.143310546875
455.52105712890625,410.1675720214844
221.0030059814453,165.33700561523438
218.84774780273438,163.02938842773438
216.67910766601562,160.73434448242188
214.49708557128906,158.4520263671875
212.3008575439453,156.18336486816406
210.09121704101562,153.92776489257812
207.86814880371094,151.68540954589844
205.63084411621094,149.45724487304688
203.38014221191406,147.2426300048828
201.11582946777344,145.04193115234375
198.83741760253906,142.8558349609375
196.5456085205078,140.68377685546875
194.23989868164062,138.5264892578125
191.9203643798828,136.38406372070312
189.58741760253906,134.25625610351562
187.24021911621094,132.14418029785156
184.87954711914062,130.0471649169922
182.50511169433594,127.96574401855469
180.1167449951172,125.90034484863281
177.71498107910156,123.85051727294922
175.2989501953125,121.81754302978516
172.86953735351562,119.80058288574219
170.4261932373047,117.80052185058594
167.9691162109375,115.81732177734375
165.4984893798828,113.85107421875
163.01385498046875,111.90253448486328
160.51589965820312,109.97109985351562
158.00376892089844,108.05815887451172
155.47840881347656,106.1626968383789
152.93896484375,104.28614044189453
150.38624572753906,102.42769622802734
147.81961059570312,100.58849334716797
145.23965454101562,98.76805114746094
142.6461181640625,96.96700286865234
140.03887939453125,95.18584442138672
137.4181671142578,93.4245834350586
134.7841796875,91.68324279785156
132.1367950439453,89.96234893798828
129.47596740722656,88.26229858398438
126.80181121826172,86.58326721191406
124.11441802978516,84.92552185058594
121.41383361816406,83.28936004638672
118.7000961303711,81.6750717163086
115.97327423095703,80.08299255371094
113.23346710205078,78.51343536376953
110.48069763183594,76.96662902832031
107.71510314941406,75.44290924072266
104.936767578125,73.94258880615234
102.14575958251953,72.4659423828125
99.34219360351562,71.01329040527344
96.52616882324219,69.58495330810547
93.69773864746094,68.1813735961914
90.85702514648438,66.80277252197266
88.43014526367188,68.43931579589844
86.09152221679688,70.56085205078125
83.77934265136719,72.7112045288086
81.4942398071289,74.89027404785156
79.23625183105469,77.09746551513672
77.0057373046875,79.33238983154297
74.80303955078125,81.59471893310547
72.62848663330078,83.88414764404297
70.48248291015625,86.20036315917969
68.3655776977539,88.54318237304688
66.27781677246094,90.91201782226562
64.21954727172852,93.30651092529297
62.191070556640625,95.72630310058594
60.192726135253906,98.1710205078125
58.22492218017578,100.64041900634766
56.288116455078125,103.1341781616211
54.38237380981445,105.6517562866211
52.50798797607422,108.19279479980469
50.66526412963867,110.75688171386719
48.854515075683594,113.34361267089844
47.0763053894043,115.95283508300781
45.330745697021484,118.58404541015625
43.6180419921875,121.23670959472656
41.938446044921875,123.91048431396484
40.292240142822266,126.60493469238281
38.67984390258789,129.31979370117188
37.1016731262207,132.05465698242188
35.55772399902344,134.80897521972656
34.04822540283203,137.5823211669922
32.57341766357422,140.37428283691406
31.13374137878418,143.1844940185547
29.729576110839844,146.0126953125
28.360872268676758,148.85813903808594
27.027812957763672,151.7205047607422
25.730636596679688,154.59927368164062
24.46993064880371,157.49423217773438
23.245716094970703,160.4048309326172
22.05803871154785,163.33045959472656
20.90704917907715,166.27076721191406
19.79316520690918,169.22532653808594
18.716781616210938,172.19374084472656
17.67764663696289,175.17539978027344
16.675912857055664,178.1698455810547
15.711974143981934,181.17666625976562
14.786224365234375,184.1954345703125
13.898316383361816,187.22560119628906
13.048393249511719,190.26657104492188
12.237051010131836,193.31809997558594
11.464188575744629,196.37962341308594
10.729634284973145,199.4505157470703
10.033621788024902,202.53041076660156
9.376769065856934,205.61886596679688
8.758440494537354,208.71531677246094
8.178704738616943,211.81918334960938
7.6382904052734375,214.93016052246094
7.136784076690674,218.04763793945312
6.674219608306885,221.17112731933594
6.251107692718506,224.30020141601562
5.866685390472412,227.4342498779297
5.521190166473389,230.57284545898438
5.214840888977051,233.71551513671875
4.9476845264434814,236.86170959472656
4.719500303268433,240.01097106933594
4.5302557945251465,243.16287231445312
4.379911422729492,246.3168182373047
4.268803358078003,249.4723663330078
4.195882320404053,252.62908935546875
4.161863803863525,255.7864532470703
4.166672945022583,258.94403076171875
4.209815263748169,262.1012878417969
4.291766405105591,265.25775146484375
4.412703990936279,268.41302490234375
4.57236909866333,271.5664978027344
4.770810604095459,274.7178039550781
5.0084919929504395,277.8664245605469
5.285196781158447,281.0118103027344
5.60075569152832,284.1535339355469
5.955461502075195,287.2911376953125
6.349388122558594,290.42401123046875
6.782145023345947,293.5517272949219
7.254042148590088,296.6738586425781
7.765068054199219,299.7897644042969
8.31479787826538,302.8990478515625
8.903717517852783,306.0012512207031
9.531415939331055,309.09576416015625
10.197696685791016,312.18218994140625
10.903060913085938,315.2599792480469
11.646699905395508,318.32867431640625
12.429071426391602,321.3877868652344
13.249771118164062,324.43682861328125
14.10863971710205,327.47528076171875
15.005857467651367,330.502685546875
15.940747261047363,333.5186767578125
16.913941383361816,336.5224914550781
17.924449920654297,339.51397705078125
18.972824096679688,342.492431640625
20.058284759521484,345.4574890136719
21.181129455566406,348.4086608886719
22.340808868408203,351.3455505371094
23.537403106689453,354.267578125
24.7705135345459,357.17437744140625
26.040063858032227,360.06549072265625
27.34572982788086,362.9404296875
28.68739891052246,365.79876708984375
30.064716339111328,368.64007568359375
31.477575302124023,371.4638977050781
32.92559051513672,374.2698669433594
34.4086799621582,377.0574645996094
35.926395416259766,379.8262939453125
37.478736877441406,382.575927734375
39.065120697021484,385.3060302734375
40.68567657470703,388.0159912109375
42.33964920043945,390.7057189941406
44.027286529541016,393.3743591308594
45.74774932861328,396.0220642089844
47.50139236450195,398.6478576660156
49.287296295166016,401.25177001953125
51.105690002441406,403.8332214355469
52.955848693847656,406.3919372558594
54.837764739990234,408.92742919921875
56.7509765625,411.4393005371094
58.695228576660156,413.92730712890625
60.67032241821289,416.3908996582031
62.67557144165039,418.82989501953125
64.71124649047852,421.24365234375
66.76580810546875,423.57965087890625
67.77133178710938,420.5865478515625
68.79204559326172,417.5984191894531
69.82879638671875,414.615966796875
70.88038635253906,411.6386413574219
71.947509765625,408.6668701171875
73.02928161621094,405.7003479003906
74.12600708007812,402.73944091796875
75.23723602294922,399.7838134765625
76.36290740966797,396.8337097167969
77.50289154052734,393.88916015625
78.6568603515625,390.9499816894531
79.82503509521484,388.01641845703125
81.00663757324219,385.0882873535156
82.2023696899414,382.1658630371094
83.41116333007812,379.24884033203125
84.63380432128906,376.3376159667969
85.8693618774414,373.4317932128906
87.11831665039062,370.5317077636719
88.3801040649414,367.6372375488281
89.65486907958984,364.7484130859375
90.94242095947266,361.8652648925781
92.24250030517578,358.9878234863281
93.55538940429688,356.1160888671875
94.88041687011719,353.25
96.21819305419922,350.3898620605469
97.56782531738281,347.53521728515625
98.93009185791016,344.6866455078125
100.30401611328125,341.84368896484375
101.69032287597656,339.0066833496094
103.08826446533203,336.1754150390625
104.49823760986328,333.35015869140625
105.91983795166016,330.53070068359375
107.35327911376953,327.71722412109375
108.79822540283203,324.9097595214844
110.25484466552734,322.108154296875
111.72296905517578,319.3126525878906
113.20244598388672,316.5232238769531
114.69343566894531,313.73980712890625
116.19569396972656,310.9624938964844
117.70933532714844,308.19140625
119.23417663574219,305.4263916015625
120.77031707763672,302.6676330566406
122.31753540039062,299.9151611328125
123.87598419189453,297.1689758300781
125.44554901123047,294.4291076660156
127.02617645263672,291.6957092285156
128.61798095703125,288.9687194824219
130.22068786621094,286.24810791015625
131.83462524414062,283.53424072265625
133.45932006835938,280.8266906738281
135.09544372558594,278.12603759765625
136.74221801757812,275.4319152832031
138.40028381347656,272.74468994140625
140.06927490234375,270.064208984375
141.74917602539062,267.3906555175781
143.44036865234375,264.72412109375
145.142333984375,262.0645446777344
146.85565185546875,259.4122314453125
148.57998657226562,256.7670593261719
150.3153076171875,254.1290283203125
152.06207275390625,251.49868774414062
153.81991577148438,248.8756561279297
155.58892822265625,246.2601318359375
157.3695068359375,243.6524658203125
159.16127014160156,241.05252075195312
160.96432495117188,238.4603729248047
162.7791748046875,235.8764190673828
164.60546875,233.30062866210938
166.4433135986328,230.73304748535156
168.29287719726562,228.17381286621094
170.15443420410156,225.62344360351562
172.02789306640625,223.08163452148438
173.91329956054688,220.54873657226562
175.8107452392578,218.02496337890625
177.7205047607422,215.51036071777344
179.64285278320312,213.00534057617188
181.57766723632812,210.51002502441406
183.52516174316406,208.02456665039062
185.4855194091797,205.54920959472656
187.4588623046875,203.084228515625
189.44541931152344,200.6298828125
191.44541931152344,198.1864471435547
193.458984375,195.75428771972656
195.4864959716797,193.33358764648438
197.52806091308594,190.9248046875
199.58396911621094,188.52825927734375
201.65452575683594,186.14425659179688
203.73992919921875,183.77334594726562
205.84046936035156,181.41590881347656
207.9567413330078,179.0724334716797
210.0890350341797,176.7435302734375
212.2374725341797,174.42967224121094
214.40257263183594,172.13125610351562
216.58499145507812,169.84933471679688
218.78500366210938,167.58445739746094
267.63800048828125,222.7270050048828
265.5039978027344,225.04981994628906
263.3918762207031,227.39256286621094
261.3011779785156,229.7544403076172
259.23162841796875,232.13485717773438
257.1827392578125,234.5330810546875
255.15383911132812,236.94827270507812
253.14454650878906,239.37977600097656
251.15443420410156,241.82699584960938
249.18313598632812,244.28941345214844
247.23031616210938,246.76651000976562
245.29562377929688,249.25779724121094
243.37875366210938,251.7628173828125
241.47940063476562,254.28114318847656
239.59725952148438,256.81236267089844
237.7320556640625,259.3560791015625
235.883544921875,261.9119567871094
234.05145263671875,264.4796447753906
232.23558044433594,267.0588073730469
230.4356689453125,269.6491394042969
228.65155029296875,272.2503967285156
226.88299560546875,274.86224365234375
225.1298370361328,277.48443603515625
223.39183044433594,280.11669921875
221.66905212402344,282.75897216796875
219.9613494873047,285.4110107421875
218.26840209960938,288.0724792480469
216.59005737304688,290.7431945800781
214.9261932373047,293.4229431152344
213.27691650390625,296.1116943359375
211.64210510253906,298.8092956542969
210.02146911621094,301.5154113769531
208.41490173339844,304.2298889160156
206.82260131835938,306.9527893066406
205.2444305419922,309.6838684082031
203.68011474609375,312.4229431152344
202.12953186035156,315.1697998046875
200.59324645996094,317.9246826171875
199.07064819335938,320.6871337890625
197.56167602539062,323.4570617675781
196.06671142578125,326.23455810546875
194.5854949951172,329.0194396972656
193.1177978515625,331.81146240234375
191.6640625,334.61077880859375
190.22406005859375,337.41717529296875
188.79754638671875,340.23046875
187.3850555419922,343.0508117675781
185.98623657226562,345.87799072265625
184.6009979248047,348.7118225097656
183.2299346923828,351.55255126953125
181.8725128173828,354.3998107910156
180.52880859375,357.2535705566406
179.19940185546875,360.1140441894531
177.88368225097656,362.9808044433594
176.58203125,365.85400390625
175.29464721679688,368.7336120605469
174.02113342285156,371.619384765625
172.76210021972656,374.5115051269531
171.51731872558594,377.4097595214844
170.28668212890625,380.3141174316406
169.07095336914062,383.2247009277344
167.86952209472656,386.1412048339844
166.6828155517578,389.06378173828125
165.51109313964844,391.9923400878906
164.3539581298828,394.92669677734375
163.21218872070312,397.8670959472656
162.08546447753906,400.81329345703125
160.97381591796875,403.7651672363281
159.87808227539062,406.7230224609375
158.797607421875,409.6864929199219
157.73294067382812,412.6556701660156
156.68441772460938,415.6305847167969
155.65170288085938,418.61102294921875
154.63548278808594,421.59710693359375
153.63577270507812,424.5887756347656
152.6523895263672,427.58587646484375
151.6863250732422,430.58856201171875
150.73724365234375,433.5966796875
149.8052215576172,436.610107421875
148.89117431640625,439.6290283203125
147.99481201171875,442.6532897949219
147.1162567138672,445.6827392578125
146.25640869140625,448.7175598144531
145.4150848388672,451.7575988769531
144.59242248535156,454.8027038574219
143.7891845703125,457.8529968261719
143.0055389404297,460.9084167480469
142.24151611328125,463.96875
141.49754333496094,467.0340576171875
140.7745819091797,470.1044006347656
140.0723114013672,473.1795349121094
139.3911590576172,476.2593994140625
138.7316436767578,479.3439636230469
140.21253967285156,481.4315185546875
143.01734924316406,482.87457275390625
145.8397674560547,484.28289794921875
148.6795654296875,485.65582275390625
151.53646850585938,486.9927978515625
154.40966796875,488.2943420410156
157.29898071289062,489.5597229003906
160.20407104492188,490.7885437011719
163.12416076660156,491.9811706542969
166.0590057373047,493.13714599609375
169.0082244873047,494.2558288574219
171.97108459472656,495.33782958984375
174.94728088378906,496.38262939453125
177.93653869628906,497.3895263671875
180.9380645751953,498.3591613769531
183.9514617919922,499.291259765625
186.97653198242188,500.184814453125
190.01248168945312,501.0405578613281
193.05889892578125,501.8583679199219
196.11538696289062,502.63763427734375
199.18145751953125,503.3782653808594
202.2565460205078,504.08062744140625
205.3401641845703,504.7445983886719
208.43186950683594,505.3694152832031
211.53123474121094,505.9554138183594
214.63766479492188,506.5028076171875
217.75062561035156,507.0115051269531
220.8697967529297,507.4808349609375
223.9945526123047,507.9111633300781
227.12440490722656,508.3026428222656
230.25888061523438,508.65533447265625
233.3975372314453,508.96905517578125
236.53988647460938,509.2432556152344
239.6853485107422,509.4786071777344
242.83349609375,509.6751403808594
245.98377990722656,509.83294677734375
249.1358184814453,509.95196533203125
252.28907775878906,510.0321350097656
255.4430694580078,510.0733337402344
258.5973205566406,510.0760498046875
261.7514343261719,510.0403137207031
264.90478515625,509.9659118652344
268.0570068359375,509.852783203125
271.2076110839844,509.700927734375
274.3561096191406,509.51019287109375
277.50201416015625,509.28057861328125
280.6448669433594,509.0120849609375
283.7840881347656,508.7047119140625
286.9192199707031,508.35791015625
290.0498352050781,507.97216796875
293.17535400390625,507.5475158691406
296.2953796386719,507.0838928222656
299.40936279296875,506.5814208984375
302.5168151855469,506.0401306152344
305.6173095703125,505.4600830078125
308.710205078125,504.8408203125
311.7950744628906,504.182861328125
314.8714599609375,503.4862976074219
317.9389343261719,502.7513427734375
320.9969177246094,501.97808837890625
324.04498291015625,501.1664123535156
327.08245849609375,500.316162109375
330.109130859375,499.4279479980469
333.1243896484375,498.5019836425781
336.12786865234375,497.5383605957031
339.1189270019531,496.5368957519531
342.09710693359375,495.4977111816406
345.0620422363281,494.42138671875
348.0133361816406,493.30810546875
350.9504699707031,492.1580505371094
353.8726806640625,490.9706726074219
356.7799072265625,489.7469177246094
359.6716613769531,488.487060546875
362.5475158691406,487.1913146972656
365.4066467285156,485.859130859375
368.24896240234375,484.49139404296875
371.07403564453125,483.08843994140625
373.8814697265625,481.6505432128906
376.6704406738281,480.17706298828125
378.88275146484375,478.4159851074219
378.20654296875,475.3350524902344
377.51806640625,472.2568359375
376.8149719238281,469.1819152832031
376.09942626953125,466.1098327636719
375.37115478515625,463.040771484375
374.6285400390625,459.9751281738281
373.873779296875,456.9124755859375
373.10540771484375,453.8531799316406
372.3236999511719,450.79730224609375
371.5298156738281,447.7445373535156
370.72149658203125,444.6955871582031
369.9007873535156,441.6499938964844
369.0672607421875,438.6078186035156
368.21966552734375,435.5695495605469
367.36004638671875,432.53466796875
366.4866027832031,429.5037536621094
365.6001892089844,426.4765625
364.7015075683594,423.4529724121094
363.78839111328125,420.4337158203125
362.86328125,417.41815185546875
361.9247131347656,414.40673828125
360.97296142578125,411.39947509765625
360.0091857910156,408.39599609375
359.0308837890625,405.3973693847656
358.04058837890625,402.4025573730469
357.0369873046875,399.41217041015625
356.0201721191406,396.42626953125
354.9913330078125,393.4444580078125
353.9479675292969,390.46771240234375
352.8927307128906,387.4952087402344
351.8241271972656,384.5274658203125
350.742431640625,381.5644226074219
349.6485290527344,378.60589599609375
348.5403747558594,375.65264892578125
347.42041015625,372.7038879394531
346.2867431640625,369.76043701171875
345.1404113769531,366.8218078613281
343.98138427734375,363.8881530761719
342.8086853027344,360.9599914550781
341.62420654296875,358.0364990234375
340.42535400390625,355.1189270019531
339.2145690917969,352.206298828125
337.9903564453125,349.29925537109375
336.75323486328125,346.39764404296875
335.50372314453125,343.50146484375
334.2403259277344,340.6111755371094
332.9652099609375,337.7261657714844
331.6757507324219,334.8475036621094
330.3743591308594,331.97418212890625
329.0594787597656,329.1070556640625
327.73187255859375,326.2457580566406
326.3914489746094,323.39044189453125
325.0376281738281,320.54144287109375
323.67169189453125,317.6982727050781
322.29168701171875,314.8619079589844
320.89990234375,312.0312194824219
319.493896484375,309.2076416015625
318.075927734375,306.3900146484375
316.644287109375,303.579345703125
315.2001953125,300.7751159667969
313.74285888671875,297.9776611328125
312.27252197265625,295.1870422363281
310.7894592285156,292.40313720703125
309.2929382324219,289.62652587890625
307.7840881347656,286.8564453125
306.2613525390625,284.09405517578125
304.7266540527344,281.33831787109375
303.177734375,278.5905456542969
301.6170654296875,275.849365234375
300.04193115234375,273.1164855957031
298.4551086425781,270.39044189453125
296.85400390625,267.6727600097656
295.24090576171875,264.96209716796875
293.6138000488281,262.2599792480469
291.9744567871094,259.5650939941406
290.3211975097656,256.8787841796875
288.6556091308594,254.2001190185547
286.9761657714844,251.5301055908203
285.2843017578125,248.86788940429688
283.5785827636719,246.21456909179688
281.86053466796875,243.56932067871094
280.12847900390625,240.93310546875
278.3840637207031,238.3050537109375
276.62567138671875,235.6864776611328
274.85491943359375,233.07608032226562
273.0699768066406,230.4753875732422
271.2729187011719,227.8831024169922
269.46142578125,225.30084228515625
#lang racket
(require
math/number-theory
"helpers.rkt")
(provide
integrate/reflect)
; the change in position from the point to the point of intersection along the line
(define (Δ-to-contact point line radius)
(define-values (x y) (complex-parts point))
(define slope
(let-values ([(lx ly) (complex-parts line)])
(if (zero? lx) +inf.0 (/ ly lx))))
; r^2 = (x + Δ)^2 + (y + Δ·slope)^2
; r^2 = x^2 + 2x·Δ + Δ^2 + y^2 + 2y·Δ·slope + (Δ·slope)^2
; 0 = Δ^2·(slope^2 + 1) + 2Δ·(x + y·slope) + x^2 + y^2 - r^2
; my math might be off here, but I'm winging it
(cond
[(infinite? slope)
(define Δy
(argmin
abs (quadratic-solutions
#;a= 1
#;b= (* 2 y)
#;c= (+ (* x x) (* y y) (- (* radius radius))))))
(make-rectangular 0 Δy)]
[else
(define Δx
(argmin
abs (quadratic-solutions
#;a= (+ (* slope slope) 1)
#;b= (* 2 (+ x (* y slope)))
#;c= (+ (* x x) (* y y) (- (* radius radius))))))
(make-rectangular Δx (* slope Δx))]))
(define (reflect axis line)
(define ^axis (norm axis))
(define /line (/ line ^axis))
(* ^axis (- /line (* 2 (real-part /line)))))
(define (integrate/reflect
pos vel dt
#:acceleration [acc 0+0i]
#:dampening [dmp 0.999]
#:boundary [rad 100])
; semi-implicit euler-integration
; preserves energy okay-ish for this type of thing
(define vel′ (+ (* acc dt) (* dmp vel)))
(define pos′ (+ (* vel′ dt) pos))
(cond
[(< (ω pos′) rad) (values pos′ vel′)]
[else
; the change in position to intersect with the ring (radius=R)
(define Δcontact (Δ-to-contact pos vel′ rad))
; point of intersection
(define intersect (+ pos Δcontact))
; reflected velocity vector
(define reflector (reflect intersect vel′))
; complement of the ratio of change to intersection over the total change in position
(define remaining (- 1 (/ (ω Δcontact) (ω (- pos′ pos)))))
; reflected position
(define reflected (+ intersect (* dt remaining reflector)))
(values reflected reflector)]))
#lang racket
(require
racket/gui pict
"reflect.rkt"
"fourier.rkt"
"helpers.rkt")
(struct snowflake [pos vel bitmap])
(define flake-gd0
(pict->bitmap
(filled-ellipse 4 2 #:color "gold" #:draw-border? #false)))
(define flake-gd1
(pict->bitmap
(filled-ellipse 4 3 #:color "orange" #:draw-border? #false)))
(define flake-rd0
(pict->bitmap
(filled-ellipse 2 4 #:color "indianred" #:draw-border? #false)))
(define flake-rd1
(pict->bitmap
(filled-ellipse 3 4 #:color "red" #:draw-border? #false)))
(define flake-gr0
(pict->bitmap
(filled-ellipse 4 3 #:color "green" #:draw-border? #false)))
(define flake-gr1
(pict->bitmap
(filled-ellipse 4 4 #:color "seagreen" #:draw-border? #false)))
(define flake-pp0
(pict->bitmap
(filled-ellipse 4 4 #:color "purple" #:draw-border? #false)))
(define (flake-gd)
(either flake-gd0 flake-gd1))
(define (flake-rd)
(either flake-rd0 flake-rd1))
(define (flake-gr)
(either flake-gr0 flake-gr1))
(define (flake-pr)
(either flake-pp0 flake-rd1))
(define (make-racket-christmas-scene radius)
(define coords (fetch/scale-coords "racket-logo.txt" radius))
(define split-areas
(for/fold ([prev (car coords)]
[areas (list 0)]
#:result (reverse areas))
([next (in-list coords)])
(define change (- next prev))
(cond
[(< 4 (magnitude change))
(values next `(0 . ,areas))]
[else
(values
next `(,(+ (car areas) 1) . ,(cdr areas)))])))
(values coords split-areas `(,flake-gd ,flake-rd ,flake-gr ,flake-gd)))
(define snow-globe-renderer%
(class gif-renderer%
(init
width height radius
[recorded? #false])
(super-new
[width width]
[height height]
[recorded? recorded?])
(define-values (flake-posns areas flake-bms)
(make-racket-christmas-scene radius))
(define ori (make-rectangular (/ width 2) (/ height 2)))
(define rad radius)
(define feeding (length flake-posns))
(define dynamic '())
(define static '())
(define cursor ori)
(define trails '())
(define breach 20)
(define border (pict->bitmap (ellipse (* 2 (+ breach radius))
(* 2 (+ breach radius)))))
(define epicycles
(new epicycles-renderer%
[width width]
[height height]
[coords flake-posns]
[mainview? #false]
[recorded? #true]))
(define/public (sample! ticks dt)
(send epicycles sample! ticks)
(cond
[(zero? feeding)
(set! trails (cons (snowflake cursor 0+0i (flake-pr)) trails))
(set! trails (take trails (min 30 (length trails))))
(set! dynamic (for/list ([flake (in-list dynamic)])
(match-define (snowflake pos vel bm) flake)
(define-values (pos′ vel′)
(integrate/reflect
(- pos ori) vel dt
#:boundary (+ rad breach)
#:acceleration 0+0.98i))
(snowflake (+ pos′ ori) vel′ bm)))]
[else
(set! feeding (- feeding 1))
(cond
[(zero? (car areas))
(set! areas (cdr areas))
(set! flake-bms (cdr flake-bms))]
[else
(set! areas (cons (- (car areas) 1) (cdr areas)))])
(define vel (* (either +i -i) (random 1 40) (norm (- cursor ori))))
(define new-flake (snowflake cursor vel {(car flake-bms)}))
(if (equal? flake-gr (car flake-bms))
(set! static (cons new-flake static))
(set! dynamic (cons new-flake dynamic)))]))
(define (draw-flakes . dcs)
(sends dcs draw-bitmap border
(- (/ width 2) (+ rad breach))
(- (/ height 2) (+ rad breach)))
(for ([flake (in-sequences (in-list dynamic) (in-list static) (in-list trails))]
#:do [(define-values (x y) (complex-parts (snowflake-pos flake)))])
(sends dcs draw-bitmap (snowflake-bitmap flake) x y)))
(define/override (paint canvas dc)
(define bm* (send epicycles paint canvas dc))
(set! cursor (send epicycles get-cursor))
(super paint draw-flakes canvas dc bm*))))
(define now current-inexact-milliseconds)
(define (run-snow-globe
#:width [width 400]
#:height [height 400]
#:radius [radius 110]
#:msecs-per-frame [frame-time 90]
#:save-gif-to-file [save-to-file #false])
(define the-frame
(new (class frame%
(super-new [label "epicycles"]
[width width]
[height width])
(define running? #true)
(define/public (is-running?)
running?)
(define/augment (on-close)
(set! running? #false)))))
(define snow-globe
(new snow-globe-renderer%
[width width]
[height height]
[radius radius]
[mainview? #true]
[recorded? #true]))
(define the-canvas
(new canvas%
[parent the-frame]
[paint-callback
(lambda (canvas dc)
(send snow-globe paint canvas dc))]))
(send the-frame create-status-line)
(send the-frame show #true)
(sleep/yield 1)
(let loop ([ticks 1] [refresh? #true] [previous (now)])
(send the-frame set-status-text (format "ticks: ~a" ticks))
(define frame-start (now))
(define dt (/ (- frame-start previous)
1000.0))
(send snow-globe sample! ticks dt)
(send the-canvas refresh)
(define time-pass (- (now) frame-start))
(define time-wait (/ (max 0 (- frame-time time-pass))
1000.0))
(sleep/yield time-wait)
(cond
[(= 3600 ticks)
(send the-frame set-status-text
(format "completed epicycles (~a ticks)" ticks))
(when save-to-file
(sync
(render-gif! save-to-file (send snow-globe get-scenes) #:chunks 10)))]
[else
(when (send the-frame is-running?)
(loop (+ ticks 1) (not refresh?) frame-start))])))
(run-snow-globe
#:msecs-per-frame 90
#:save-gif-to-file "merry-xmas.gif")
@bakgatviooldoos
Copy link
Author

bakgatviooldoos commented Dec 5, 2024

long-merry-xmas

This is a compressed version of the ideal.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment