Page 1 of 1

Pretty Pictures with "The Rose" Algorithm

Posted: Mon Dec 23, 2013 12:40 pm
by CalamityJames
I've written this program several times since the late 1980s (in Applesoft Basic for the Apple ][, TML Basic for the Apple IIgs, Visual Basic for the PC). Now here is my Pure Basic version. It uses simple algorithm to produce a remarkable variety of images. I hope it's of interest.

Image

Code: Select all

;"The Rose" Algorithm by Peter Maurer of AT & T (see "A Rose is a Rose" 
;in the American Mathematical Monthly Vol 94 No 7 (Aug - Sept 1987) pp 631 - 645)
;http://www.jstor.org/stable/2322215

;Program by Terry Morris

EnableExplicit

Enumeration ; gadgets
  #CanvasGadget
EndEnumeration

#MAIN_WINDOW = 0

Global ProgName.s = "The Rose"
Global BackColour.i, ForeColour.i
Global EventId.i, Multiplier.i
Global CentreX.i, CentreY.i, N.i, D.i, Quit.i, Z.i

CompilerIf #PB_Compiler_OS = #PB_OS_Windows
  Procedure CentreAnyFormInWorkArea(WindowNo.i)
    Protected WindowTop.i, WindowLeft.i, WindowWidth.i, WindowHeight.i, ReturnValue.i, WorkAreaRect.RECT
    Protected SpareHeight.i, SpareWidth.i, WorkAreaHeight.i, WorkAreaWidth.i, WindowRect.rect
    ReturnValue = SystemParametersInfo_(#SPI_GETWORKAREA, 0, @WorkAreaRect, 0)
    GetWindowRect_(WindowID(WindowNo),@WindowRect)
    WindowWidth = WindowRect\right - WindowRect\left
    WindowHeight = WindowRect\bottom - WindowRect\top
    WorkAreaHeight = WorkAreaRect\Bottom - WorkAreaRect\Top
    WorkAreaWidth = WorkAreaRect\Right - WorkAreaRect\Left
    SpareHeight = Int((WorkAreaHeight - WindowHeight) / 2)
    SpareWidth = Int((WorkAreaWidth - WindowWidth) / 2)
    WindowTop = WorkAreaRect\Top + SpareHeight
    WindowLeft = WorkAreaRect\Left + SpareWidth
    ReturnValue = MoveWindow_(WindowID(WindowNo), WindowLeft, WindowTop, WindowWidth, WindowHeight, 0)
  EndProcedure
CompilerEndIf

Procedure Initialize()
CentreX = WindowWidth(#MAIN_WINDOW) / 2 ; Get horizontal centre.
CentreY = WindowHeight(#MAIN_WINDOW) / 2    ; Get vertical centre
Multiplier = CentreX - 5
If Multiplier > (CentreY - 5)
  Multiplier = CentreY - 5
EndIf
EndProcedure

Procedure DrawPatternAlgorithmC(Cx.i, Cy.i, Mult.i)
Protected TT.i, t.f, c.i, OldX.i, OldY.i, Theta.i, NewX.i, NewY.i
Protected X.f, r.f
StartDrawing(CanvasOutput(#CanvasGadget))
Box(0, 0, OutputWidth(), OutputHeight(), BackColour)
StopDrawing()
Repeat
  Theta = TT
  r = Sin(2 * #PI * N * Theta/Z) ; Corrects error
  t = 2 * #PI * Theta/Z          ; in article
  OldX = Cx + Int(r * Cos(t) * Mult)
  OldY = Cy - Int(r * Sin(t) * Mult)
  Repeat
    Theta = Mod(Theta + D, Z)
    X = Radian(Mod(N * Theta, Z))
    r = Sin(X)
    t = Radian(Theta)
    NewX = Cx + Int(r * Cos(t) * Mult)
    NewY = Cy - Int(r * Sin(t) * Mult)
    StartDrawing(CanvasOutput(#CanvasGadget))
    LineXY(OldX, OldY, NewX, NewY, ForeColour)
    StopDrawing()
    c + 1
    OldX = NewX: OldY = NewY
  Until Theta = TT Or Quit = #True
  TT + 1
Until C>= Z Or Quit = #True
EndProcedure

Procedure DrawPatternsInThread(*Value)
  ForeColour = RGB(Random(255,129),Random(255,128),Random(255,128))
  Z = 360
  N = 4: D = 43
  DrawPatternAlgorithmC(CentreX, CentreY, Multiplier)
  Delay(3000)
  N = 5: D = 97
  DrawPatternAlgorithmC(CentreX, CentreY, Multiplier)
  Delay(3000)
  N = 6: D = 72
  DrawPatternAlgorithmC(CentreX, CentreY, Multiplier)
  Delay(3000)
  N = 4: D = 120
  DrawPatternAlgorithmC(CentreX, CentreY, Multiplier)
  Delay(3000)
  z = 359: N = 90: D = 90
  DrawPatternAlgorithmC(CentreX, CentreY, Multiplier)
  Delay(3000)
  N = 40: D = 89
  DrawPatternAlgorithmC(CentreX, CentreY, Multiplier)
  Delay(3000)
  Repeat
  Z = Random (360, 359)
  N = Random(Z - 1, 1)
  D = Random(Z- 1, 1)
  ForeColour = RGB(Random(255,129),Random(255,128),Random(255,128))
  DrawPatternAlgorithmC(CentreX, CentreY, Multiplier)
  Delay(3000)
Until Quit = #True  
EndProcedure

If OpenWindow(#MAIN_WINDOW, 600, 100, 600, 600, ProgName, #PB_Window_SystemMenu | #PB_Window_SizeGadget | #PB_Window_MinimizeGadget |#PB_Window_TitleBar | #PB_Window_MaximizeGadget | #PB_Window_Invisible | #PB_Window_ScreenCentered)
  CompilerIf #PB_Compiler_OS = #PB_OS_Windows
    CentreAnyFormInWorkArea(#MAIN_WINDOW)
  CompilerEndIf
  ExamineDesktops()
  CanvasGadget(#CanvasGadget, 0, 0, DesktopWidth(0), DesktopHeight(0))
  Initialize()
  CreateThread(@DrawPatternsInThread(),0)
  HideWindow(#MAIN_WINDOW, #False)
Repeat  
  EventID = WaitWindowEvent()
   Select EventId
      Case #PB_Event_SizeWindow
        Initialize()  
    EndSelect
 Until EventID = #PB_Event_CloseWindow 
 Quit = #True
EndIf

Re: Pretty Pictures with "The Rose" Algorithm

Posted: Mon Dec 23, 2013 1:17 pm
by wilbert

Re: Pretty Pictures with "The Rose" Algorithm

Posted: Mon Dec 23, 2013 1:25 pm
by CalamityJames
Or the Meccanograph, which came much earlier than the Spirograph (http://www.meccanopedia.com/wiki/index. ... lan_01.jpg)

Re: Pretty Pictures with "The Rose" Algorithm

Posted: Mon Dec 23, 2013 1:26 pm
by luis
Really pretty, I had a plastic spirograph, always found it fascinating. I will use this, thank you :)

Re: Pretty Pictures with "The Rose" Algorithm

Posted: Mon Dec 23, 2013 3:34 pm
by davido
Hi Terry,

Very nice demonstration, rather better than I recalled it.

Pure nostalgia.

Thank you very much for sharing. :D

Re: Pretty Pictures with "The Rose" Algorithm

Posted: Mon Dec 23, 2013 5:50 pm
by deeproot
Nice indeed!! :D

Re: Pretty Pictures with "The Rose" Algorithm

Posted: Mon Dec 23, 2013 7:04 pm
by BasicallyPure
I like it.
I started to write a spirograph program once but never finished it.
Now I don't have to.

thanks,
BP

Re: Pretty Pictures with "The Rose" Algorithm

Posted: Mon Dec 23, 2013 7:33 pm
by charvista
Fascinating.

Re: Pretty Pictures with "The Rose" Algorithm

Posted: Mon Dec 23, 2013 8:05 pm
by Lord
Look at this in ShowCase: http://www.purearea.net/pb/showcase/show.php?id=339
It's called "Zykloide".

Re: Pretty Pictures with "The Rose" Algorithm

Posted: Thu Dec 26, 2013 4:46 pm
by Kwai chang caine
Very very nice :shock:
Thanks 8)