- 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