- XLogo
Imagine a very elastic grid. Undeformed it appears as a regular lattice of squares. Apply a function and each vertex is deformed from its original position. The grid appears stretched or twisted.
The grid has corner co-ordinate values of [1,1] [1,-1] [-1,-1] [-1,1]
You can alter the mesh size of the grid by changing the :Size varible shown in red in the Go procedure.
You can also comment out one line of code to draw only horizontal or vertical
lines.
To New
# set default screen, pen and turtle values
ResetAll SetScreenSize [400 400] HideTurtle
SetSC Black SetPC Green SetPS 1 PenUp
End
To GridPos :I :J
Make "Rect Function :I :J
Output List 180*First :Rect 180*Last :Rect
End
To Function :X :Y
Output List :X :Y # unchanged
End
To Go
New
Make "Size 19 # increase (eg 29) for finer grid
For [L 0 1] [
For (List "I Minus 1 1 2/:Size) [PenUp
For (List "J Minus 1 1 2/:Size) [
If :L=0 [SetPos GridPos :I :J PenDown] # vertical lines
If :L=1 [SetPos GridPos :J :I PenDown] # horizontal lines
]]]
End
Copy and paste to replace the Function procedure with one of
the following functions which stretch and distort the grid.
Increase the grid Size to 29 for more detail.
To Function :X :Y
If :X< 0 [Make
"XSign Minus 1][Make "XSign 1]
If :Y< 0 [Make
"YSign Minus 1][Make "YSign 1]
Make "X Power :X 2
Make "Y Power :Y 2
Output List :XSign*:X :YSign*:Y
End
To Function :X :Y
Make "X :X + 0.05 * Sin 360* :Y
Make "Y :Y + 0.05 * Cos 360* :X
Output List :X :Y
End
Add in the following two procedures which allow the use of polar coordinates to stretch and twist the grid. The first converts polar to rectangular (PtoR), the second rectangular to polar (RtoP) co-ordinates.
To PtoR :RadDist :Theta
# convert polar to rectangular co-ordinates
LocalMake "X :RadDist *Sin :Theta
LocalMake "Y :RadDist *Cos :Theta
Output List :X :Y
End
To RtoP :X :Y
# convert rectangular to polar co-ordinates
LocalMake "Dist Sqrt ((Power :X 2) +(Power :Y 2))
If :X<0 [Output List :Dist 180 +ATan :Y/:X] [
# else :X >0
If :Y<0 [Output List :Dist 360 +ATan :Y/:X]
[Output List :Dist ATan :Y/:X]]
# else :X =0
If :Y<=0 [Output List :Dist 270] [Output List :Dist 90]
End
Then, copy and paste to replace the Function procedure with one of the following functions.
To Function :X :Y
Make "Polar RtoP :X :Y
Make "RadDist First :Polar Make "Theta Last :Polar
If :RadDist <1 [
Make "RadDist Power :RadDist 0.4] # change 0.4 to 2
Output PtoR :RadDist :Theta
End
To Function :X :Y
Make "Polar RtoP :X :Y
Make "RadDist First :Polar Make "Theta Last :Polar
If :RadDist <1 [
Make "Theta :Theta- 100*(1-:RadDist)] # change 100 to 200
Output PtoR :RadDist :Theta
End
To Function :X :Y
Make "Polar RtoP :X :Y
Make "RadDist First :Polar Make "Theta Last :Polar
Make "RadDist Power :RadDist 0.4
Output PtoR :RadDist :Theta
End
Here is an alternative rectangular to polar converter, using trigonometry instead of a second turtle to calculate the angle. It's a bit more mathematical, as ArcTan must be modified for each quadrant. Also, you have to ensure you never divide by zero.
To RtoP :X :Y
# convert rectangular to polar co-ordinates
LocalMake "Dist Sqrt ((Power :X 2) +(Power :Y 2))
If :X<0 [Output List :Dist 180 +ATan :Y/:X] [
# else :X >0
If :Y<0 [Output List :Dist 360 +ATan :Y/:X]
[Output List :Dist ATan :Y/:X]]
# else :X =0
If :Y<=0 [Output List :Dist 270] [Output List :Dist 90]
End