Category talk:Jq-turtle: Difference between revisions
Content added Content deleted
(minx maxx miny maxy) |
|||
Line 10: | Line 10: | ||
<pre> |
<pre> |
||
# The turtle's state: {svg, up, angle} |
# The turtle's state: {svg, up, angle, x, y, minx, maxx, miny, maxy} |
||
# Angle: |
# Angle: |
||
Line 25: | Line 25: | ||
# $start : [$x, $y] |
# $start : [$x, $y] |
||
def turtle($start): |
def turtle($start): |
||
def mm: .minx = .x | .miny = .y | .maxx = .x | .maxy = .y; |
|||
$start |
$start |
||
| if type == "array" |
| if type == "array" |
||
then "M \($start|join(","))" |
|||
⚫ | |||
else turtle([0,0]) |
|||
end |
|||
⚫ | |||
| mm ; |
|||
def turtleUp: .up=true; |
def turtleUp: .up=true; |
||
def turtleDown: .up=false; |
def turtleDown: .up=false; |
||
def minmax: |
|||
.minx = ([.minx, .x]|min) |
|||
| .miny = ([.miny, .y]|min) |
|||
| .maxx = ([.maxx, .x]|max) |
|||
| .maxy = ([.maxy, .y]|max) ; |
|||
# Move to $xy = [$x,$y] without changing orientation |
# Move to $xy = [$x,$y] without changing orientation |
||
def turtleMove($xy): |
def turtleMove($xy): |
||
$xy as [$x, $y] |
$xy as [$x, $y] |
||
| . |
| .x = $x | .y = $y |
||
| .svg += "M \($x),\($y)" |
|||
| minmax; |
|||
# Move to $xy = [$x,$y] in SVG co-ordinates and change orientation to ($angle % 360) degrees, |
# Move to $xy = [$x,$y] in SVG co-ordinates and change orientation to ($angle % 360) degrees, |
||
Line 43: | Line 56: | ||
then $xy as [$x, $y] |
then $xy as [$x, $y] |
||
| .svg += "M \($x),\($y)" |
| .svg += "M \($x),\($y)" |
||
| .x = $x | .y = $y |
|||
| minmax |
|||
else . |
else . |
||
end |
end |
||
| .angle = ($angle % 360); |
| .angle = ($angle % 360); |
||
def turtleForward($d): |
def turtleForward($d): |
||
def rnd: 1000*.|round/1000; |
def rnd: 1000*.|round/1000; |
||
if .up |
if .up |
||
then if .angle== 0 then .svg += " m \($d),0" |
then if .angle== 0 then .svg += " m \($d),0" | .x += $d |
||
elif .angle== 90 then .svg += " m 0,-\($d)" |
elif .angle== 90 then .svg += " m 0,-\($d)" | .y -= $d |
||
elif .angle==180 then .svg += " m -\($d),0" |
elif .angle==180 then .svg += " m -\($d),0" | .x -= $d |
||
elif .angle==270 then .svg += " m 0,\($d)" |
elif .angle==270 then .svg += " m 0,\($d)" | .y += $d |
||
else ($d * (.angle|cosDegrees |
else ($d * (.angle|cosDegrees)) as $dx |
||
| ($d * (.angle|sinDegrees |
| ($d * (.angle|sinDegrees) * -1) as $dy |
||
| .svg += " m\($dx),\($dy)" |
| .svg += " m\($dx|rnd),\($dy|rnd)\n" |
||
| .x += $dx |
|||
| .y += $dy |
|||
end |
end |
||
else if .angle== 0 then .svg += " h \($d)" |
else if .angle== 0 then .svg += " h \($d)" | .x += $d |
||
elif .angle== 90 then .svg += " v -\($d)" |
elif .angle== 90 then .svg += " v -\($d)" | .y -= $d |
||
elif .angle==180 then .svg += " h -\($d)" |
elif .angle==180 then .svg += " h -\($d)" | .x -= $d |
||
elif .angle==270 then .svg += " v \($d)" |
elif .angle==270 then .svg += " v \($d)" | .y += $d |
||
else ($d * (.angle|cosDegrees |
else ($d * (.angle|cosDegrees)) as $dx |
||
| ($d * (.angle|sinDegrees |
| ($d * (.angle|sinDegrees) * -1) as $dy |
||
| .svg += " l\($dx),\($dy)" |
| .svg += " l\($dx|rnd),\($dy|rnd)\n" |
||
| .x += $dx |
|||
| .y += $dy |
|||
end |
end |
||
end |
end |
||
| minmax; |
|||
def turtleRotate($angle): .angle = (360 + (.angle + $angle)) % 360; |
def turtleRotate($angle): .angle = (360 + (.angle + $angle)) % 360; |
||
def turtleArcRight($r): |
def turtleArcRight($r): |
||
if .angle== 0 then .svg += " a\($r),\($r) 0 0 1 \($r),\($r)" |
if .angle== 0 then .svg += " a\($r),\($r) 0 0 1 \($r),\($r)" | .x += $r | .y += $r |
||
elif .angle== 90 then .svg += " a\($r),\($r) 0 0 1 \($r),-\($r)" |
elif .angle== 90 then .svg += " a\($r),\($r) 0 0 1 \($r),-\($r)" | .x += $r | .y -= $r |
||
elif .angle==180 then .svg += " a\($r),\($r) 0 0 1 -\($r),-\($r)" |
elif .angle==180 then .svg += " a\($r),\($r) 0 0 1 -\($r),-\($r)"| .x -= $r | .y -= $r |
||
elif .angle==270 then .svg += " a\($r),\($r) 0 0 1 -\($r),\($r)" |
elif .angle==270 then .svg += " a\($r),\($r) 0 0 1 -\($r),\($r)" | .x -= $r | .y += $r |
||
else "turtleArcRight at \(.angle) not yet supported" | error |
else "turtleArcRight at \(.angle) not yet supported" | error |
||
end |
end |
||
| minmax |
|||
| turtleRotate(-90); |
| turtleRotate(-90); |
||
def turtleArcLeft($r): |
def turtleArcLeft($r): |
||
if .angle== 0 then .svg += " a\($r),\($r) 0 0 0 \($r),-\($r)" |
if .angle== 0 then .svg += " a\($r),\($r) 0 0 0 \($r),-\($r)" | .x += $r | .y -= $r |
||
elif .angle== 90 then .svg += " a\($r),\($r) 0 0 0 -\($r),-\($r)" |
elif .angle== 90 then .svg += " a\($r),\($r) 0 0 0 -\($r),-\($r)"| .x -= $r | .y -= $r |
||
elif .angle==180 then .svg += " a\($r),\($r) 0 0 0 -\($r),\($r)" |
elif .angle==180 then .svg += " a\($r),\($r) 0 0 0 -\($r),\($r)" | .x -= $r | .y += $r |
||
elif .angle==270 then .svg += " a\($r),\($r) 0 0 0 \($r),\($r)" |
elif .angle==270 then .svg += " a\($r),\($r) 0 0 0 \($r),\($r)" | .x += $r | .y += $r |
||
else "turtleArcRight at \(.angle) not yet supported" | error |
else "turtleArcRight at \(.angle) not yet supported" | error |
||
end |
end |
||
| minmax |
|||
| turtleRotate(90); |
| turtleRotate(90); |
||
############################################################################ |
|||
def svg($size): |
def svg($size): |
||
Line 94: | Line 116: | ||
., |
., |
||
"</svg>"; |
"</svg>"; |
||
def path($fill; $stroke; $width): |
def path($fill; $stroke; $width): |
||
"<path fill=\"\($fill)\" stroke=\"\($stroke)\" stroke-width=\" |
"<path fill=\"\($fill)\" stroke=\"\($stroke)\" stroke-width=\"\($width)\" d=\"\(.svg)\" />"; |
||
def draw($size): |
def draw($size): |
||
path("none"; "red"; 1) | svg($size) |
path("none"; "red"; 1) | svg($size); |
||
</pre> |
</pre> |
Latest revision as of 23:39, 16 January 2022
turtle.jq - turtle graphics with some ancillary SVG convenience functions.
To include these turtle graphics definitions, download the page contents (minus this preamble) into a file and include it using an appropriate `include` directive, e.g.
include "turtle" {search: "."};
For an illustration of how to use the functions defined here, see Koch_curve.
# The turtle's state: {svg, up, angle, x, y, minx, maxx, miny, maxy} # Angle: # => = 0 degrees # ^ = 90 degrees # <= = 180 degrees # v = 270 degrees def pi: 4 * (1|atan); def a2radians: 2 * pi * ./360; def cosDegrees: a2radians|cos; def sinDegrees: a2radians|sin; # $start : [$x, $y] def turtle($start): def mm: .minx = .x | .miny = .y | .maxx = .x | .maxy = .y; $start | if type == "array" then "M \($start|join(","))" else turtle([0,0]) end | {svg: ., up:true, angle:0, x: $start[0], y: $start[1] } | mm ; def turtleUp: .up=true; def turtleDown: .up=false; def minmax: .minx = ([.minx, .x]|min) | .miny = ([.miny, .y]|min) | .maxx = ([.maxx, .x]|max) | .maxy = ([.maxy, .y]|max) ; # Move to $xy = [$x,$y] without changing orientation def turtleMove($xy): $xy as [$x, $y] | .x = $x | .y = $y | .svg += "M \($x),\($y)" | minmax; # Move to $xy = [$x,$y] in SVG co-ordinates and change orientation to ($angle % 360) degrees, # but if $xy is not an array, then just adjust the orientation. def turtleMove($xy; $angle): if $xy|type == "array" then $xy as [$x, $y] | .svg += "M \($x),\($y)" | .x = $x | .y = $y | minmax else . end | .angle = ($angle % 360); def turtleForward($d): def rnd: 1000*.|round/1000; if .up then if .angle== 0 then .svg += " m \($d),0" | .x += $d elif .angle== 90 then .svg += " m 0,-\($d)" | .y -= $d elif .angle==180 then .svg += " m -\($d),0" | .x -= $d elif .angle==270 then .svg += " m 0,\($d)" | .y += $d else ($d * (.angle|cosDegrees)) as $dx | ($d * (.angle|sinDegrees) * -1) as $dy | .svg += " m\($dx|rnd),\($dy|rnd)\n" | .x += $dx | .y += $dy end else if .angle== 0 then .svg += " h \($d)" | .x += $d elif .angle== 90 then .svg += " v -\($d)" | .y -= $d elif .angle==180 then .svg += " h -\($d)" | .x -= $d elif .angle==270 then .svg += " v \($d)" | .y += $d else ($d * (.angle|cosDegrees)) as $dx | ($d * (.angle|sinDegrees) * -1) as $dy | .svg += " l\($dx|rnd),\($dy|rnd)\n" | .x += $dx | .y += $dy end end | minmax; def turtleRotate($angle): .angle = (360 + (.angle + $angle)) % 360; def turtleArcRight($r): if .angle== 0 then .svg += " a\($r),\($r) 0 0 1 \($r),\($r)" | .x += $r | .y += $r elif .angle== 90 then .svg += " a\($r),\($r) 0 0 1 \($r),-\($r)" | .x += $r | .y -= $r elif .angle==180 then .svg += " a\($r),\($r) 0 0 1 -\($r),-\($r)"| .x -= $r | .y -= $r elif .angle==270 then .svg += " a\($r),\($r) 0 0 1 -\($r),\($r)" | .x -= $r | .y += $r else "turtleArcRight at \(.angle) not yet supported" | error end | minmax | turtleRotate(-90); def turtleArcLeft($r): if .angle== 0 then .svg += " a\($r),\($r) 0 0 0 \($r),-\($r)" | .x += $r | .y -= $r elif .angle== 90 then .svg += " a\($r),\($r) 0 0 0 -\($r),-\($r)"| .x -= $r | .y -= $r elif .angle==180 then .svg += " a\($r),\($r) 0 0 0 -\($r),\($r)" | .x -= $r | .y += $r elif .angle==270 then .svg += " a\($r),\($r) 0 0 0 \($r),\($r)" | .x += $r | .y += $r else "turtleArcRight at \(.angle) not yet supported" | error end | minmax | turtleRotate(90); def svg($size): "<svg viewBox=\"0 0 \($size) \($size)\" xmlns=\"http://www.w3.org/2000/svg\">", ., "</svg>"; def path($fill; $stroke; $width): "<path fill=\"\($fill)\" stroke=\"\($stroke)\" stroke-width=\"\($width)\" d=\"\(.svg)\" />"; def draw($size): path("none"; "red"; 1) | svg($size);